Fix for missing GC ref map record on ARM64 for the X8 register (dotnet/coreclr#22309)
authorTomáš Rylek <trylek@microsoft.com>
Thu, 31 Jan 2019 19:23:38 +0000 (20:23 +0100)
committerGitHub <noreply@github.com>
Thu, 31 Jan 2019 19:23:38 +0000 (20:23 +0100)
GC stress testing revealed a deficiency in GC ref map on ARM64 - we weren't
emitting the entry corresponding to the X8 return buffer address because
a recent refactoring changed its location in the transition block. This change
generalizes transition block by exposing a new function

GetOffsetOfFirstGCRefMapSlot()

that returns the same value as

GetOffsetOfArgumentRegisters()

except on ARM64 where it returns the offset of the X8 register in the
transition block (above the callee-saved registers and 8-byte padding i.e.
at position 13 corresponding to offset 0x68, or
GetOffsetOfArgumentRegisters() - 8).

Thanks

Tomas

Commit migrated from https://github.com/dotnet/coreclr/commit/d4d3af17d582a16e88b58789b116adcd2e07b605

src/coreclr/src/vm/callingconvention.h
src/coreclr/src/vm/compile.cpp
src/coreclr/src/vm/frames.cpp

index 295db1f..e70e31f 100644 (file)
@@ -142,6 +142,16 @@ struct TransitionBlock
         LIMITED_METHOD_CONTRACT;
         return offsetof(TransitionBlock, m_x8RetBuffReg);
     }
+    
+    static int GetOffsetOfFirstGCRefMapSlot()
+    {
+        return GetOffsetOfRetBuffArgReg();
+    }
+#else
+    static int GetOffsetOfFirstGCRefMapSlot()
+    {
+        return GetOffsetOfArgumentRegisters();
+    }
 #endif
 
     static BYTE GetOffsetOfArgs()
index cd78e1c..bebe403 100644 (file)
@@ -1013,7 +1013,7 @@ void CEECompileInfo::GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, GCRefMapBuilde
 
     nStackSlots = nStackBytes / sizeof(TADDR) + NUM_ARGUMENT_REGISTERS;
 #else
-    nStackSlots = (sizeof(TransitionBlock) + nStackBytes - TransitionBlock::GetOffsetOfArgumentRegisters()) / TARGET_POINTER_SIZE;
+    nStackSlots = (sizeof(TransitionBlock) + nStackBytes - TransitionBlock::GetOffsetOfFirstGCRefMapSlot()) / TARGET_POINTER_SIZE;
 #endif
 
     for (UINT pos = 0; pos < nStackSlots; pos++)
@@ -1025,7 +1025,7 @@ void CEECompileInfo::GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, GCRefMapBuilde
             (TransitionBlock::GetOffsetOfArgumentRegisters() + ARGUMENTREGISTERS_SIZE - (pos + 1) * sizeof(TADDR)) :
             (TransitionBlock::GetOffsetOfArgs() + (pos - NUM_ARGUMENT_REGISTERS) * sizeof(TADDR));
 #else
-        ofs = TransitionBlock::GetOffsetOfArgumentRegisters() + pos * TARGET_POINTER_SIZE;
+        ofs = TransitionBlock::GetOffsetOfFirstGCRefMapSlot() + pos * TARGET_POINTER_SIZE;
 #endif
 
         CORCOMPILE_GCREFMAP_TOKENS token = *(CORCOMPILE_GCREFMAP_TOKENS *)(pFrame + ofs);
@@ -1068,7 +1068,7 @@ void CEECompileInfo::GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, GCRefMapBuilde
             (TransitionBlock::GetOffsetOfArgumentRegisters() + ARGUMENTREGISTERS_SIZE - (pos + 1) * sizeof(TADDR)) :
             (TransitionBlock::GetOffsetOfArgs() + (pos - NUM_ARGUMENT_REGISTERS) * sizeof(TADDR));
 #else
-        ofs = TransitionBlock::GetOffsetOfArgumentRegisters() + pos * TARGET_POINTER_SIZE;
+        ofs = TransitionBlock::GetOffsetOfFirstGCRefMapSlot() + pos * TARGET_POINTER_SIZE;
 #endif
 
         if (token != 0)
index 73c4d56..af41def 100644 (file)
@@ -1330,7 +1330,7 @@ void TransitionFrame::PromoteCallerStackUsingGCRefMap(promote_func* fn, ScanCont
             (TransitionBlock::GetOffsetOfArgumentRegisters() + ARGUMENTREGISTERS_SIZE - (pos + 1) * sizeof(TADDR)) :
             (TransitionBlock::GetOffsetOfArgs() + (pos - NUM_ARGUMENT_REGISTERS) * sizeof(TADDR));
 #else
-        ofs = TransitionBlock::GetOffsetOfArgumentRegisters() + pos * sizeof(TADDR);
+        ofs = TransitionBlock::GetOffsetOfFirstGCRefMapSlot() + pos * sizeof(TADDR);
 #endif
 
         PTR_TADDR ppObj = dac_cast<PTR_TADDR>(pTransitionBlock + ofs);