@@ -110,9 +110,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
110
110
{
111
111
if (IsTargetAbi(CORINFO_NATIVEAOT_ABI))
112
112
{
113
- // See comment in impCheckForPInvokeCall
114
- BasicBlock* block = compIsForInlining() ? impInlineInfo->iciBlock : compCurBB;
115
- if (info.compCompHnd->convertPInvokeCalliToCall(pResolvedToken, !impCanPInvokeInlineCallSite(block)))
113
+ if (info.compCompHnd->convertPInvokeCalliToCall(pResolvedToken, !impCanPInvokeInlineCallSite(compCurBB)))
116
114
{
117
115
eeGetCallInfo(pResolvedToken, nullptr, CORINFO_CALLINFO_ALLOWINSTPARAM, callInfo);
118
116
return impImportCall(CEE_CALL, pResolvedToken, nullptr, nullptr, prefixFlags, callInfo, rawILOffset);
@@ -633,17 +631,9 @@ var_types Compiler::impImportCall(OPCODE opcode,
633
631
}
634
632
635
633
//--------------------------- Inline NDirect ------------------------------
636
-
637
- // For inline cases we technically should look at both the current
638
- // block and the call site block (or just the latter if we've
639
- // fused the EH trees). However the block-related checks pertain to
640
- // EH and we currently won't inline a method with EH. So for
641
- // inlinees, just checking the call site block is sufficient.
642
- {
643
- // New lexical block here to avoid compilation errors because of GOTOs.
644
- BasicBlock* block = compIsForInlining() ? impInlineInfo->iciBlock : compCurBB;
645
- impCheckForPInvokeCall(call->AsCall(), methHnd, sig, mflags, block);
646
- }
634
+ // If this is a call to a PInvoke method, we may be able to inline the invocation frame.
635
+ //
636
+ impCheckForPInvokeCall(call->AsCall(), methHnd, sig, mflags, compCurBB);
647
637
648
638
#ifdef UNIX_X86_ABI
649
639
// On Unix x86 we use caller-cleaned convention.
@@ -6366,8 +6356,7 @@ bool Compiler::impCanPInvokeInline()
6366
6356
// from a call to see if the call qualifies as an inline pinvoke.
6367
6357
//
6368
6358
// Arguments:
6369
- // block - block containing the call, or for inlinees, block
6370
- // containing the call being inlined
6359
+ // block - block containing the call
6371
6360
//
6372
6361
// Return Value:
6373
6362
// true if this call can legally qualify as an inline pinvoke, false otherwise
@@ -6384,9 +6373,9 @@ bool Compiler::impCanPInvokeInline()
6384
6373
// TODO-CQ: The inlining frame no longer has a GSCookie, so the common on this
6385
6374
// restriction is out of date. However, given that there is a comment
6386
6375
// about protecting the framelet, I'm not confident about what this
6387
- // is actually protecteing , so I don't want to remove this
6376
+ // is actually protecting , so I don't want to remove this
6388
6377
// restriction without further analysis analysis.
6389
- // * We disable pinvoke inlini1ng inside handlers since the GSCookie
6378
+ // * We disable pinvoke inlining inside handlers since the GSCookie
6390
6379
// is in the inlined Frame (see
6391
6380
// CORINFO_EE_INFO::InlinedCallFrameInfo::offsetOfGSCookie), but
6392
6381
// this would not protect framelets/return-address of handlers.
@@ -6401,49 +6390,53 @@ bool Compiler::impCanPInvokeInlineCallSite(BasicBlock* block)
6401
6390
return false;
6402
6391
}
6403
6392
6404
- // The remaining limitations do not apply to NativeAOT
6405
- if (IsTargetAbi(CORINFO_NATIVEAOT_ABI))
6406
- {
6407
- return true;
6408
- }
6409
-
6410
- // The VM assumes that the PInvoke frame in IL Stub is only going to be used
6411
- // for the PInvoke target call. The PInvoke frame cannot be reused by marshalling helper
6412
- // calls (see InlinedCallFrame::GetActualInteropMethodDesc and related stackwalking code).
6413
- if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB))
6393
+ // The following limitations do not apply to NativeAOT
6394
+ //
6395
+ if (!IsTargetAbi(CORINFO_NATIVEAOT_ABI))
6414
6396
{
6415
- return false;
6416
- }
6397
+ // The VM assumes that the PInvoke frame in IL Stub is only going to be used
6398
+ // for the PInvoke target call. The PInvoke frame cannot be reused by marshalling helper
6399
+ // calls (see InlinedCallFrame::GetActualInteropMethodDesc and related stackwalking code).
6400
+ if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IL_STUB))
6401
+ {
6402
+ return false;
6403
+ }
6417
6404
6418
6405
#ifdef USE_PER_FRAME_PINVOKE_INIT
6419
- // For platforms that use per-P/Invoke InlinedCallFrame initialization,
6420
- // we can't inline P/Invokes inside of try blocks where we can resume execution in the same function.
6421
- // The runtime can correctly unwind out of an InlinedCallFrame and out of managed code. However,
6422
- // it cannot correctly unwind out of an InlinedCallFrame and stop at that frame without also unwinding
6423
- // at least one managed frame. In particular, the runtime struggles to restore non-volatile registers
6424
- // from the top-most unmanaged call before the InlinedCallFrame. As a result, the runtime does not support
6425
- // re-entering the same method frame as the InlinedCallFrame after an exception in unmanaged code.
6426
- if (block->hasTryIndex())
6427
- {
6428
- // Check if this block's try block or any containing try blocks have catch handlers.
6429
- // If any of the containing try blocks have catch handlers,
6430
- // we cannot inline a P/Invoke for reasons above. If the handler is a fault or finally handler,
6431
- // we can inline a P/Invoke into this block in the try since the code will not resume execution
6432
- // in the same method after throwing an exception if only fault or finally handlers are executed.
6433
- for (unsigned int ehIndex = block->getTryIndex(); ehIndex != EHblkDsc::NO_ENCLOSING_INDEX;
6434
- ehIndex = ehGetEnclosingTryIndex(ehIndex))
6435
- {
6436
- if (ehGetDsc(ehIndex)->HasCatchHandler())
6406
+ // For platforms that use per-P/Invoke InlinedCallFrame initialization,
6407
+ // we can't inline P/Invokes inside of try blocks where we can resume execution in the same function.
6408
+ // The runtime can correctly unwind out of an InlinedCallFrame and out of managed code. However,
6409
+ // it cannot correctly unwind out of an InlinedCallFrame and stop at that frame without also unwinding
6410
+ // at least one managed frame. In particular, the runtime struggles to restore non-volatile registers
6411
+ // from the top-most unmanaged call before the InlinedCallFrame. As a result, the runtime does not support
6412
+ // re-entering the same method frame as the InlinedCallFrame after an exception in unmanaged code.
6413
+ if (block->hasTryIndex())
6414
+ {
6415
+ // Check if this block's try block or any containing try blocks have catch handlers.
6416
+ // If any of the containing try blocks have catch handlers,
6417
+ // we cannot inline a P/Invoke for reasons above. If the handler is a fault or finally handler,
6418
+ // we can inline a P/Invoke into this block in the try since the code will not resume execution
6419
+ // in the same method after throwing an exception if only fault or finally handlers are executed.
6420
+ for (unsigned int ehIndex = block->getTryIndex(); ehIndex != EHblkDsc::NO_ENCLOSING_INDEX;
6421
+ ehIndex = ehGetEnclosingTryIndex(ehIndex))
6437
6422
{
6438
- return false;
6423
+ if (ehGetDsc(ehIndex)->HasCatchHandler())
6424
+ {
6425
+ return false;
6426
+ }
6439
6427
}
6440
6428
}
6429
+ #endif // USE_PER_FRAME_PINVOKE_INIT
6430
+ }
6441
6431
6432
+ if (!compIsForInlining())
6433
+ {
6442
6434
return true;
6443
6435
}
6444
- #endif // USE_PER_FRAME_PINVOKE_INIT
6445
6436
6446
- return true;
6437
+ // If inlining, verify conditions for the call site block too.
6438
+ //
6439
+ return impInlineRoot()->impCanPInvokeInlineCallSite(impInlineInfo->iciBlock);
6447
6440
}
6448
6441
6449
6442
//------------------------------------------------------------------------
@@ -6455,8 +6448,7 @@ bool Compiler::impCanPInvokeInlineCallSite(BasicBlock* block)
6455
6448
// methHnd - handle for the method being called (may be null)
6456
6449
// sig - signature of the method being called
6457
6450
// mflags - method flags for the method being called
6458
- // block - block containing the call, or for inlinees, block
6459
- // containing the call being inlined
6451
+ // block - block containing the call
6460
6452
//
6461
6453
// Notes:
6462
6454
// Sets GTF_CALL_M_PINVOKE on the call for pinvokes.
@@ -6554,7 +6546,11 @@ void Compiler::impCheckForPInvokeCall(
6554
6546
// Size-speed tradeoff: don't use inline pinvoke at rarely
6555
6547
// executed call sites. The non-inline version is more
6556
6548
// compact.
6557
- if (block->isRunRarely())
6549
+ //
6550
+ // Zero-diff quirk: the first clause below should simply be block->isRunRarely()
6551
+ //
6552
+ if ((!compIsForInlining() && block->isRunRarely()) ||
6553
+ (compIsForInlining() && impInlineInfo->iciBlock->isRunRarely()))
6558
6554
{
6559
6555
return;
6560
6556
}
@@ -7742,9 +7738,7 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
7742
7738
7743
7739
if (methAttr & CORINFO_FLG_PINVOKE)
7744
7740
{
7745
- // See comment in impCheckForPInvokeCall
7746
- BasicBlock* block = compIsForInlining() ? impInlineInfo->iciBlock : compCurBB;
7747
- if (!impCanPInvokeInlineCallSite(block))
7741
+ if (!impCanPInvokeInlineCallSite(compCurBB))
7748
7742
{
7749
7743
inlineResult->NoteFatal(InlineObservation::CALLSITE_PINVOKE_EH);
7750
7744
return;
0 commit comments