@@ -342,21 +342,21 @@ void Compiler::fgPerNodeLocalVarLiveness(GenTree* tree)
342342 fgCurMemoryDef |= memoryKindSet (GcHeap, ByrefExposed);
343343 fgCurMemoryHavoc |= memoryKindSet (GcHeap, ByrefExposed);
344344 }
345- }
346345
347- // If this is a p/invoke unmanaged call or if this is a tail-call
346+ // If this is a p/invoke unmanaged call or if this is a tail-call via helper,
348347 // and we have an unmanaged p/invoke call in the method,
349348 // then we're going to run the p/invoke epilog.
350349 // So we mark the FrameRoot as used by this instruction.
351350 // This ensures that the block->bbVarUse will contain
352351 // the FrameRoot local var if is it a tracked variable.
353352
354- if ((tree->AsCall ()->IsUnmanaged () || tree->AsCall ()->IsTailCall ()) && compMethodRequiresPInvokeFrame ())
353+ if ((tree->AsCall ()->IsUnmanaged () || tree->AsCall ()->IsTailCallViaJitHelper ()) &&
354+ compMethodRequiresPInvokeFrame ())
355355 {
356356 assert ((!opts.ShouldUsePInvokeHelpers ()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
357357 if (!opts.ShouldUsePInvokeHelpers ())
358358 {
359- /* Get the TCB local and mark it as used */
359+ // Get the FrameRoot local and mark it as used.
360360
361361 noway_assert (info.compLvFrameListRoot < lvaCount);
362362
@@ -373,6 +373,7 @@ void Compiler::fgPerNodeLocalVarLiveness(GenTree* tree)
373373 }
374374
375375 break ;
376+ }
376377
377378 default :
378379
@@ -504,7 +505,7 @@ void Compiler::fgPerBlockLocalVarLiveness()
504505 }
505506 }
506507
507- /* Get the TCB local and mark it as used */
508+ // Mark the FrameListRoot as used, if applicable.
508509
509510 if (block->bbJumpKind == BBJ_RETURN && compMethodRequiresPInvokeFrame ())
510511 {
@@ -513,13 +514,22 @@ void Compiler::fgPerBlockLocalVarLiveness()
513514 {
514515 noway_assert (info.compLvFrameListRoot < lvaCount);
515516
516- LclVarDsc* varDsc = &lvaTable[info.compLvFrameListRoot ];
517-
518- if (varDsc->lvTracked )
517+ // 32-bit targets always pop the frame in the epilog.
518+ // For 64-bit targets, we only do this in the epilog for IL stubs;
519+ // for non-IL stubs the frame is popped after every PInvoke call.
520+ CLANG_FORMAT_COMMENT_ANCHOR;
521+ #ifdef TARGET_64BIT
522+ if (opts.jitFlags ->IsSet (JitFlags::JIT_FLAG_IL_STUB))
523+ #endif
519524 {
520- if (!VarSetOps::IsMember (this , fgCurDefSet, varDsc->lvVarIndex ))
525+ LclVarDsc* varDsc = &lvaTable[info.compLvFrameListRoot ];
526+
527+ if (varDsc->lvTracked )
521528 {
522- VarSetOps::AddElemD (this , fgCurUseSet, varDsc->lvVarIndex );
529+ if (!VarSetOps::IsMember (this , fgCurDefSet, varDsc->lvVarIndex ))
530+ {
531+ VarSetOps::AddElemD (this , fgCurUseSet, varDsc->lvVarIndex );
532+ }
523533 }
524534 }
525535 }
@@ -1437,16 +1447,16 @@ void Compiler::fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call)
14371447{
14381448 assert (call != nullptr );
14391449
1440- // If this is a tail-call and we have any unmanaged p/invoke calls in
1441- // the method then we're going to run the p/invoke epilog
1450+ // If this is a tail-call via helper, and we have any unmanaged p/invoke calls in
1451+ // the method, then we're going to run the p/invoke epilog
14421452 // So we mark the FrameRoot as used by this instruction.
14431453 // This ensure that this variable is kept alive at the tail-call
1444- if (call->IsTailCall () && compMethodRequiresPInvokeFrame ())
1454+ if (call->IsTailCallViaJitHelper () && compMethodRequiresPInvokeFrame ())
14451455 {
14461456 assert ((!opts.ShouldUsePInvokeHelpers ()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
14471457 if (!opts.ShouldUsePInvokeHelpers ())
14481458 {
1449- /* Get the TCB local and make it live */
1459+ // Get the FrameListRoot local and make it live.
14501460
14511461 noway_assert (info.compLvFrameListRoot < lvaCount);
14521462
@@ -1465,7 +1475,7 @@ void Compiler::fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call)
14651475 /* Is this call to unmanaged code? */
14661476 if (call->IsUnmanaged () && compMethodRequiresPInvokeFrame ())
14671477 {
1468- /* Get the TCB local and make it live */
1478+ // Get the FrameListRoot local and make it live.
14691479 assert ((!opts.ShouldUsePInvokeHelpers ()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
14701480 if (!opts.ShouldUsePInvokeHelpers ())
14711481 {
0 commit comments