void Compiler::fgInlineAppendStatements(InlineInfo* inlineInfo, BasicBlock* block, GenTreePtr stmtAfter)
{
- // If this inlinee was passed a generic context but didn't look at
- // it, we can decrement the "generic context was used" ref count.
+ // If this inlinee was passed a runtime lookup generic context and
+ // ignores it, we can decrement the "generic context was used" ref
+ // count, because we created a new lookup tree and incremented the
+ // count when we imported the type parameter argument to pass to
+ // the inlinee. See corresponding logic in impImportCall that
+ // checks the sig for CORINFO_CALLCONV_PARAMTYPE.
+ //
+ // Does this method require a context (type) parameter?
if ((inlineInfo->inlineCandidateInfo->methInfo.args.callConv & CORINFO_CALLCONV_PARAMTYPE) != 0)
{
- // Did the context require the caller to perform a runtime lookup?
+ // Did the computation of that parameter require the
+ // caller to perform a runtime lookup?
if (inlineInfo->inlineCandidateInfo->exactContextNeedsRuntimeLookup)
{
- // Fetch the temp for the generic context
+ // Fetch the temp for the generic context as it would
+ // appear in the inlinee's body.
const unsigned typeCtxtArg = inlineInfo->typeContextArg;
const unsigned tmpNum = inlineInfo->lclTmpNum[typeCtxtArg];
// Was it used in the inline body?
if (tmpNum == BAD_VAR_NUM)
{
- // No, so the runtime lookup is not needed.
+ // No -- so the associated runtime lookup is not needed
+ // and also no longer provides evidence that the generic
+ // context should be kept alive.
JITDUMP("Inlinee ignores runtime lookup generics context\n");
assert(lvaGenericsContextUseCount > 0);
lvaGenericsContextUseCount--;
GenTreeArgList* args = nullptr;
CORINFO_THIS_TRANSFORM constraintCallThisTransform = CORINFO_NO_THIS_TRANSFORM;
CORINFO_CONTEXT_HANDLE exactContextHnd = nullptr;
- BOOL exactContextNeedsRuntimeLookup = FALSE;
+ bool exactContextNeedsRuntimeLookup = false;
bool canTailCall = true;
const char* szCanTailCallFailReason = nullptr;
int tailCall = prefixFlags & PREFIX_TAILCALL;
// Work out what sort of call we're making.
// Dispense with virtual calls implemented via LDVIRTFTN immediately.
- constraintCallThisTransform = callInfo->thisTransform;
-
+ constraintCallThisTransform = callInfo->thisTransform;
exactContextHnd = callInfo->contextHandle;
- exactContextNeedsRuntimeLookup = callInfo->exactContextNeedsRuntimeLookup;
+ exactContextNeedsRuntimeLookup = callInfo->exactContextNeedsRuntimeLookup == TRUE;
// Recursive call is treaded as a loop to the begining of the method.
if (methHnd == info.compMethodHnd)
#endif // defined(DEBUG) || defined(INLINE_DATA)
// Is it an inline candidate?
- impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup == TRUE, callInfo);
+ impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo);
}
// append the call node.
#endif // defined(DEBUG) || defined(INLINE_DATA)
// Is it an inline candidate?
- impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup == TRUE, callInfo);
+ impMarkInlineCandidate(call, exactContextHnd, exactContextNeedsRuntimeLookup, callInfo);
}
DONE_CALL: