@@ -1026,7 +1026,8 @@ var_types Compiler::impImportCall(OPCODE opcode,
1026
1026
INDEBUG(call->AsCall()->gtRawILOffset = rawILOffset);
1027
1027
1028
1028
// Is it an inline candidate?
1029
- impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo);
1029
+ impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo,
1030
+ compInlineContext);
1030
1031
}
1031
1032
1032
1033
// append the call node.
@@ -1236,7 +1237,20 @@ var_types Compiler::impImportCall(OPCODE opcode,
1236
1237
INDEBUG(call->AsCall()->gtRawILOffset = rawILOffset);
1237
1238
1238
1239
// Is it an inline candidate?
1239
- impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo);
1240
+ impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo, compInlineContext);
1241
+
1242
+ // If the call is virtual, record the inliner's context for possible use during late devirt inlining.
1243
+ // Also record the generics context if there is any.
1244
+ //
1245
+ if (call->AsCall()->IsVirtual() && (call->AsCall()->gtCallType != CT_INDIRECT))
1246
+ {
1247
+ JITDUMP("\nSaving generic context %p and inline context %p for call [%06u]\n", dspPtr(exactContextHnd),
1248
+ dspPtr(compInlineContext), dspTreeID(call->AsCall()));
1249
+ LateDevirtualizationInfo* const info = new (this, CMK_Inlining) LateDevirtualizationInfo;
1250
+ info->exactContextHnd = exactContextHnd;
1251
+ info->inlinersContext = compInlineContext;
1252
+ call->AsCall()->gtLateDevirtualizationInfo = info;
1253
+ }
1240
1254
}
1241
1255
1242
1256
// Extra checks for tail calls and tail recursion.
@@ -1427,22 +1441,6 @@ var_types Compiler::impImportCall(OPCODE opcode,
1427
1441
}
1428
1442
else
1429
1443
{
1430
- // If the call is virtual, and has a generics context, and is not going to have a class probe,
1431
- // record the context for possible use during late devirt.
1432
- //
1433
- // If we ever want to devirt at Tier0, and/or see issues where OSR methods under PGO lose
1434
- // important devirtualizations, we'll want to allow both a class probe and a captured context.
1435
- //
1436
- if (origCall->IsVirtual() && (origCall->gtCallType != CT_INDIRECT) && (exactContextHnd != nullptr) &&
1437
- (origCall->gtHandleHistogramProfileCandidateInfo == nullptr))
1438
- {
1439
- JITDUMP("\nSaving context %p for call [%06u]\n", dspPtr(exactContextHnd), dspTreeID(origCall));
1440
- origCall->gtCallMoreFlags |= GTF_CALL_M_HAS_LATE_DEVIRT_INFO;
1441
- LateDevirtualizationInfo* const info = new (this, CMK_Inlining) LateDevirtualizationInfo;
1442
- info->exactContextHnd = exactContextHnd;
1443
- origCall->gtLateDevirtualizationInfo = info;
1444
- }
1445
-
1446
1444
if (isFatPointerCandidate)
1447
1445
{
1448
1446
// fatPointer candidates should be in statements of the form call() or var = call().
@@ -7451,6 +7449,7 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call,
7451
7449
// exactContextHnd -- context handle for inlining
7452
7450
// exactContextNeedsRuntimeLookup -- true if context required runtime lookup
7453
7451
// callInfo -- call info from VM
7452
+ // inlinersContext -- the inliner's context
7454
7453
//
7455
7454
// Notes:
7456
7455
// Mostly a wrapper for impMarkInlineCandidateHelper that also undoes
@@ -7460,7 +7459,8 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call,
7460
7459
void Compiler::impMarkInlineCandidate(GenTree* callNode,
7461
7460
CORINFO_CONTEXT_HANDLE exactContextHnd,
7462
7461
bool exactContextNeedsRuntimeLookup,
7463
- CORINFO_CALL_INFO* callInfo)
7462
+ CORINFO_CALL_INFO* callInfo,
7463
+ InlineContext* inlinersContext)
7464
7464
{
7465
7465
if (!opts.OptEnabled(CLFLG_INLINING))
7466
7466
{
@@ -7483,7 +7483,7 @@ void Compiler::impMarkInlineCandidate(GenTree* callNode,
7483
7483
7484
7484
// Do the actual evaluation
7485
7485
impMarkInlineCandidateHelper(call, candidateId, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo,
7486
- &inlineResult);
7486
+ inlinersContext, &inlineResult);
7487
7487
// Ignore non-inlineable candidates
7488
7488
// TODO: Consider keeping them to just devirtualize without inlining, at least for interface
7489
7489
// calls on NativeAOT, but that requires more changes elsewhere too.
@@ -7506,7 +7506,8 @@ void Compiler::impMarkInlineCandidate(GenTree* callNode,
7506
7506
const uint8_t candidatesCount = call->GetInlineCandidatesCount();
7507
7507
assert(candidatesCount <= 1);
7508
7508
InlineResult inlineResult(this, call, nullptr, "impMarkInlineCandidate");
7509
- impMarkInlineCandidateHelper(call, 0, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo, &inlineResult);
7509
+ impMarkInlineCandidateHelper(call, 0, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo,
7510
+ inlinersContext, &inlineResult);
7510
7511
}
7511
7512
7512
7513
// If this call is an inline candidate or is not a guarded devirtualization
@@ -7539,6 +7540,7 @@ void Compiler::impMarkInlineCandidate(GenTree* callNode,
7539
7540
// exactContextHnd -- context handle for inlining
7540
7541
// exactContextNeedsRuntimeLookup -- true if context required runtime lookup
7541
7542
// callInfo -- call info from VM
7543
+ // inlinersContext -- the inliner's context
7542
7544
//
7543
7545
// Notes:
7544
7546
// If callNode is an inline candidate, this method sets the flag
@@ -7555,6 +7557,7 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
7555
7557
CORINFO_CONTEXT_HANDLE exactContextHnd,
7556
7558
bool exactContextNeedsRuntimeLookup,
7557
7559
CORINFO_CALL_INFO* callInfo,
7560
+ InlineContext* inlinersContext,
7558
7561
InlineResult* inlineResult)
7559
7562
{
7560
7563
// Let the strategy know there's another call
@@ -7749,7 +7752,8 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
7749
7752
}
7750
7753
7751
7754
InlineCandidateInfo* inlineCandidateInfo = nullptr;
7752
- impCheckCanInline(call, candidateIndex, fncHandle, methAttr, exactContextHnd, &inlineCandidateInfo, inlineResult);
7755
+ impCheckCanInline(call, candidateIndex, fncHandle, methAttr, exactContextHnd, inlinersContext, &inlineCandidateInfo,
7756
+ inlineResult);
7753
7757
7754
7758
if (inlineResult->IsFailure())
7755
7759
{
@@ -8378,7 +8382,6 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
8378
8382
// it's a union field used for other things by virtual
8379
8383
// stubs)
8380
8384
call->ClearInlineInfo();
8381
- call->gtCallMoreFlags &= ~GTF_CALL_M_HAS_LATE_DEVIRT_INFO;
8382
8385
8383
8386
#if defined(DEBUG)
8384
8387
if (verbose)
@@ -9057,6 +9060,7 @@ bool Compiler::impTailCallRetTypeCompatible(bool allowWideni
9057
9060
// fncHandle - method that will be called
9058
9061
// methAttr - attributes for the method
9059
9062
// exactContextHnd - exact context for the method
9063
+ // inlinersContext - the inliner's context
9060
9064
// ppInlineCandidateInfo [out] - information needed later for inlining
9061
9065
// inlineResult - result of ongoing inline evaluation
9062
9066
//
@@ -9069,6 +9073,7 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
9069
9073
CORINFO_METHOD_HANDLE fncHandle,
9070
9074
unsigned methAttr,
9071
9075
CORINFO_CONTEXT_HANDLE exactContextHnd,
9076
+ InlineContext* inlinersContext,
9072
9077
InlineCandidateInfo** ppInlineCandidateInfo,
9073
9078
InlineResult* inlineResult)
9074
9079
{
@@ -9083,6 +9088,7 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
9083
9088
CORINFO_METHOD_HANDLE fncHandle;
9084
9089
unsigned methAttr;
9085
9090
CORINFO_CONTEXT_HANDLE exactContextHnd;
9091
+ InlineContext* inlinersContext;
9086
9092
InlineResult* result;
9087
9093
InlineCandidateInfo** ppInlineCandidateInfo;
9088
9094
} param;
@@ -9094,6 +9100,7 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
9094
9100
param.fncHandle = fncHandle;
9095
9101
param.methAttr = methAttr;
9096
9102
param.exactContextHnd = (exactContextHnd != nullptr) ? exactContextHnd : MAKE_METHODCONTEXT(fncHandle);
9103
+ param.inlinersContext = inlinersContext;
9097
9104
param.result = inlineResult;
9098
9105
param.ppInlineCandidateInfo = ppInlineCandidateInfo;
9099
9106
@@ -9244,7 +9251,7 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
9244
9251
pInfo->methAttr = pParam->methAttr;
9245
9252
pInfo->initClassResult = initClassResult;
9246
9253
pInfo->exactContextNeedsRuntimeLookup = false;
9247
- pInfo->inlinersContext = pParam->pThis->compInlineContext ;
9254
+ pInfo->inlinersContext = pParam->inlinersContext ;
9248
9255
9249
9256
// Note exactContextNeedsRuntimeLookup is reset later on,
9250
9257
// over in impMarkInlineCandidate.
0 commit comments