2. For JIT64/AMD64 only: Next for non-IL stubs, the InlinedCallFrame is 'pushed' by setting `Thread->m_pFrame` to point to the InlinedCallFrame (recall that the per-frame initialization already set `InlinedCallFrame->m_pNext` to point to the previous top). For IL stubs this step is accomplished in the per-frame initialization.
3. The Frame is made active by setting `InlinedCallFrame->m_pCallerReturnAddress`.
4. The code then toggles the GC mode by setting `Thread->m_fPreemptiveGCDisabled = 0`.
-5. Starting now, no GC pointers may be live in registers.
+5. Starting now, no GC pointers may be live in registers. RyuJit LSRA meets this requirement by adding special refPositon `RefTypeKillGCRefs` before unmanaged calls and special helpers.
6. Then comes the actual call/PInvoke.
7. The GC mode is set back by setting `Thread->m_fPreemptiveGCDisabled = 1`.
8. Then we check to see if `g_TrapReturningThreads` is set (non-zero). If it is, we call `CORINFO_HELP_STOP_FOR_GC`.
}
}
- /* GC refs cannot be enregistered accross an unmanaged call */
-
// TODO: we should generate the code for saving to/restoring
// from the inlined N/Direct frame instead.
}
}
- if (tree->IsCall() && (tree->gtFlags & GTF_CALL_UNMANAGED) != 0)
+ if (killGCRefs(tree))
{
RefPosition* pos = newRefPosition((Interval*)nullptr, currentLoc, RefTypeKillGCRefs, tree,
(allRegs(TYP_REF) & ~RBM_ARG_REGS));
return false;
}
+//------------------------------------------------------------------------
+// killGCRefs:
+// Given some tree node return does it need all GC refs to be spilled from
+// callee save registers.
+//
+// Arguments:
+// tree - the tree for which we ask about gc refs.
+//
+// Return Value:
+// true - tree kills GC refs on callee save registers
+// false - tree doesn't affect GC refs on callee save registers
+bool LinearScan::killGCRefs(GenTree* tree)
+{
+ if (tree->IsCall())
+ {
+ if ((tree->gtFlags & GTF_CALL_UNMANAGED) != 0)
+ {
+ return true;
+ }
+
+ if (tree->AsCall()->gtCallMethHnd == compiler->eeFindHelper(CORINFO_HELP_JIT_PINVOKE_BEGIN))
+ {
+ assert(compiler->opts.ShouldUsePInvokeHelpers());
+ return true;
+ }
+ }
+ return false;
+}
+
//----------------------------------------------------------------------------
// defineNewInternalTemp: Defines a ref position for an internal temp.
//
// Given some tree node add refpositions for all the registers this node kills
bool buildKillPositionsForNode(GenTree* tree, LsraLocation currentLoc);
+ bool killGCRefs(GenTree* tree);
+
regMaskTP allRegs(RegisterType rt);
regMaskTP allRegs(GenTree* tree);
regMaskTP allMultiRegCallNodeRegs(GenTreeCall* tree);