diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index b48a1727065eb..cdfbf9acfa34b 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -5552,13 +5552,15 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call) BlockRange().InsertBefore(call, newThisAddr, newThis, thisArgNode); #if !defined(TARGET_XARCH) - // Keep delegate alive if the target can't do an indirect call with an immediate operand - // and only in fully interruptible code. if (comp->GetInterruptible()) { - GenTree* baseClone = comp->gtCloneExpr(base); - GenTree* keepBaseAlive = comp->gtNewKeepAliveNode(baseClone); - BlockRange().InsertBefore(call, baseClone, keepBaseAlive); + // If the target's backend doesn't support indirect calls with immediate operands (contained) + // and the method is marked as interruptible, we need to insert a GT_START_NONGC before the call. + // to keep the delegate object alive while we're obtaining the function pointer. + // Since the actual call is effectively a safe point, we don't need to insert any additional + // NOPs to prevent the GC starvation in single-block methods. + GenTree* startNonGCNode = new (comp, GT_START_NONGC) GenTree(GT_START_NONGC, TYP_VOID); + BlockRange().InsertBefore(newThisAddr, startNonGCNode); } #endif