Do not insert gcstress interrupt instruction at call to JIT_RareDisableHelper
authorRahul Kumar <rahku@microsoft.com>
Fri, 22 Jul 2016 19:48:55 +0000 (12:48 -0700)
committerRahul Kumar <rahku@microsoft.com>
Tue, 26 Jul 2016 02:09:01 +0000 (19:09 -0700)
src/vm/gccover.cpp

index 3220cddd8ebbc2f30ffcc83aa053f71e5e20d6e7..41dc094e9415cc10d77f9f792e7dc14e89d29b5b 100644 (file)
@@ -37,6 +37,7 @@
 
 MethodDesc* AsMethodDesc(size_t addr);
 static SLOT getTargetOfCall(SLOT instrPtr, PCONTEXT regs, SLOT*nextInstr);
+bool isCallToStopForGCJitHelper(SLOT instrPtr);
 #if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
 static void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID codeStart);
 static bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 stopOffset, LPVOID codeStart);
@@ -911,7 +912,11 @@ bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 sto
             if (instrLen == 2)
                 *((WORD*)instrPtr)  = INTERRUPT_INSTR;
             else
-                *((DWORD*)instrPtr) = INTERRUPT_INSTR_32;
+            {
+                // Do not replace with gcstress interrupt instruction at call to JIT_RareDisableHelper
+                if(!isCallToStopForGCJitHelper(instrPtr))
+                    *((DWORD*)instrPtr) = INTERRUPT_INSTR_32;
+            }
 
             instrPtr += instrLen;
 #elif defined(_TARGET_ARM64_)
@@ -920,8 +925,10 @@ bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 sto
                          *((DWORD*)instrPtr) != INTERRUPT_INSTR_CALL &&
                          *((DWORD*)instrPtr) != INTERRUPT_INSTR_PROTECT_RET);
             }
-
-            *((DWORD*)instrPtr) = INTERRUPT_INSTR;
+            
+            // Do not replace with gcstress interrupt instruction at call to JIT_RareDisableHelper
+            if(!isCallToStopForGCJitHelper(instrPtr))
+                *((DWORD*)instrPtr) = INTERRUPT_INSTR;
             instrPtr += 4;
 #endif
 
@@ -940,6 +947,57 @@ bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 sto
 }
 #endif
 
+// Is this a call instruction to JIT_RareDisableHelper()
+// We cannot insert GCStress instruction at this call
+// For arm64 & arm (R2R) call to jithelpers happens via a stub.
+// For other architectures call does not happen via stub.
+// For other architecures we can get the target directly by calling getTargetOfCall().
+// This is not the case for arm64/arm so need to decode the stub
+// instruction to find the actual jithelper target. 
+// For other architecture we detect call to JIT_RareDisableHelper 
+// in function OnGcCoverageInterrupt() since getTargetOfCall() can
+// get the actual jithelper target.
+bool isCallToStopForGCJitHelper(SLOT instrPtr)
+{
+#if defined(_TARGET_ARM64_)    
+   if (((*reinterpret_cast<DWORD*>(instrPtr)) & 0xFC000000) == 0x94000000) // Do we have a BL instruction?
+   {
+       // call through immediate
+       int imm26 = ((*((DWORD*)instrPtr)) & 0x03FFFFFF)<<2;
+       // SignExtend the immediate value.
+       imm26 = (imm26 << 4) >> 4;
+       DWORD* target = (DWORD*) (instrPtr + imm26);
+       // Call to jithelpers happens via jumpstub
+       if(*target == 0x58000050 /* ldr xip0, PC+8*/ && *(target+1) == 0xd61f0200 /* br xip0 */)
+       {
+           // get the actual jithelper target
+           target = *(((DWORD**)target) + 1);
+           if((TADDR)target == GetEEFuncEntryPoint(JIT_RareDisableHelper))
+           {
+               return true;
+           }
+       }
+   }
+#elif defined(_TARGET_ARM_)
+    if((instrPtr[1] & 0xf8) == 0xf0 && (instrPtr[3] & 0xc0) == 0xc0) // call using imm
+    {
+        int imm32 = GetThumb2BlRel24((UINT16 *)instrPtr);
+        WORD* target = (WORD*) (instrPtr + 4 + imm32);
+        // Is target a stub
+        if(*target == 0xf8df && *(target+1) == 0xf000) // ldr pc, [pc+4]
+        {
+            //get actual target
+            target = *((WORD**)target + 1);
+            if((TADDR)target == GetEEFuncEntryPoint(JIT_RareDisableHelper))
+            {
+                return true;
+            }
+        }
+    }
+#endif
+   return false;
+}
+
 static size_t getRegVal(unsigned regNum, PCONTEXT regs)
 {
     return *getRegAddr(regNum, regs);