Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
stub devirt gets null check; handle GT_RET_EXPR
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyAyersMS committed Feb 3, 2017
1 parent 56f702a commit 0d17370
Showing 1 changed file with 33 additions and 5 deletions.
38 changes: 33 additions & 5 deletions src/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18392,6 +18392,24 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
break;
}

case GT_RET_EXPR:
{
// If we see a RET_EXPR, then obj is the return value from
// an inlineable call. Use the declared return type to
// devirtualize. Note if/when we inline we may get an even
// better type -- so there are opportunities for
// downstream devirtualization that we'll miss right now.
GenTreeCall* objFromCall = obj->gtRetExpr.gtInlineCandidate->AsCall();
InlineCandidateInfo* inlInfo = objFromCall->gtInlineCandidateInfo;
if (inlInfo != nullptr)
{
assert(inlInfo->methInfo.args.retType == CORINFO_TYPE_CLASS);
objClass = inlInfo->methInfo.args.retTypeClass;
}

break;
}

default:
{
break;
Expand Down Expand Up @@ -18509,17 +18527,21 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
if (objClassIsFinal || derivedMethodIsFinal)
{
JITDUMP("!!! Inlining ok, no restrictions, final; can devirtualize\n");
const bool wasStubCall = call->IsVirtualStub();

// Make the updates.
call->gtFlags &= ~GTF_CALL_VIRT_VTABLE;
call->gtFlags &= ~GTF_CALL_VIRT_STUB;
call->gtCallMethHnd = derivedMethod;

// Need to update call info too. This is fragile
// but hopefully the derived method conforms to
// the base in most other ways.
callInfo->hMethod = derivedMethod;
callInfo->methodFlags = derivedMethodAttribs;
// Stub calls include an implicit null check, which we
// now need to make explicit. Not sure yet if we can
// restrict this to just a subset or need to do it for all,
// so will do it for all.
if (wasStubCall)
{
call->gtFlags |= GTF_CALL_NULLCHECK;
}

// Clear the inline candidate info (may be non-null since
// it's a union field used for other things by virtual
Expand All @@ -18535,6 +18557,12 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
}
#endif

// Need to update call info too. This is fragile
// but hopefully the derived method conforms to
// the base in most other ways.
callInfo->hMethod = derivedMethod;
callInfo->methodFlags = derivedMethodAttribs;

// Note this may not equal objClass, if there is a
// final method that objClass inherits.
CORINFO_CLASS_HANDLE derivedClass = info.compCompHnd->getMethodClass(derivedMethod);
Expand Down

0 comments on commit 0d17370

Please sign in to comment.