diff options
author | Andy Ayers <andya@microsoft.com> | 2018-12-06 09:03:31 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-06 09:03:31 -0800 |
commit | 045f470f71cfcedf3eb7ff248f25bf29619d9a88 (patch) | |
tree | 3acf9d6d7cb154803725c16f4de68b90a0a62233 /src/jit/inline.cpp | |
parent | 7454475cd4f5575d2a2db3879bb164609e8bd6ad (diff) | |
download | coreclr-045f470f71cfcedf3eb7ff248f25bf29619d9a88.tar.gz coreclr-045f470f71cfcedf3eb7ff248f25bf29619d9a88.tar.bz2 coreclr-045f470f71cfcedf3eb7ff248f25bf29619d9a88.zip |
Guarded devirtualization foundations (#21270)
Lay the groundwork for guarded devirtualization of virtual and interface
calls in the jit.
Introduce the notion of a guarded devirtualization candidate and identify
these if regular devirtualization fails. Use simple heuristics to produce
a class to guess for. Require that the method that would be invoked if the class
guess is correct be a plausible inline candidate.
Generalize the calli transformer to become an indirect call transformer.
This runs after importation because it needs to introduce control flow and
runs before inlining so that the new direct calls it introduces can be inlined.
Implement the transformation to duplicate the call site, devirtualize on the side
where the class is now known exactly, and turn the resulting direct call into an
inline candidate.
Add a motivation and design document.
Diffstat (limited to 'src/jit/inline.cpp')
-rw-r--r-- | src/jit/inline.cpp | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/jit/inline.cpp b/src/jit/inline.cpp index a1064762ce..f523d2abbe 100644 --- a/src/jit/inline.cpp +++ b/src/jit/inline.cpp @@ -337,6 +337,7 @@ InlineContext::InlineContext(InlineStrategy* strategy) , m_CodeSizeEstimate(0) , m_Success(true) , m_Devirtualized(false) + , m_Guarded(false) , m_Unboxed(false) #if defined(DEBUG) || defined(INLINE_DATA) , m_Policy(nullptr) @@ -397,18 +398,19 @@ void InlineContext::Dump(unsigned indent) const char* inlineReason = InlGetObservationString(m_Observation); const char* inlineResult = m_Success ? "" : "FAILED: "; const char* devirtualized = m_Devirtualized ? " devirt" : ""; + const char* guarded = m_Guarded ? " guarded" : ""; const char* unboxed = m_Unboxed ? " unboxed" : ""; if (m_Offset == BAD_IL_OFFSET) { - printf("%*s[%u IL=???? TR=%06u %08X] [%s%s%s%s] %s\n", indent, "", m_Ordinal, m_TreeID, calleeToken, - inlineResult, inlineReason, devirtualized, unboxed, calleeName); + printf("%*s[%u IL=???? TR=%06u %08X] [%s%s%s%s%s] %s\n", indent, "", m_Ordinal, m_TreeID, calleeToken, + inlineResult, inlineReason, guarded, devirtualized, unboxed, calleeName); } else { IL_OFFSET offset = jitGetILoffs(m_Offset); - printf("%*s[%u IL=%04d TR=%06u %08X] [%s%s%s%s] %s\n", indent, "", m_Ordinal, offset, m_TreeID, calleeToken, - inlineResult, inlineReason, devirtualized, unboxed, calleeName); + printf("%*s[%u IL=%04d TR=%06u %08X] [%s%s%s%s%s] %s\n", indent, "", m_Ordinal, offset, m_TreeID, + calleeToken, inlineResult, inlineReason, guarded, devirtualized, unboxed, calleeName); } } @@ -1205,6 +1207,7 @@ InlineContext* InlineStrategy::NewSuccess(InlineInfo* inlineInfo) calleeContext->m_Observation = inlineInfo->inlineResult->GetObservation(); calleeContext->m_Success = true; calleeContext->m_Devirtualized = originalCall->IsDevirtualized(); + calleeContext->m_Guarded = originalCall->IsGuarded(); calleeContext->m_Unboxed = originalCall->IsUnboxed(); #if defined(DEBUG) || defined(INLINE_DATA) @@ -1266,6 +1269,7 @@ InlineContext* InlineStrategy::NewFailure(GenTreeStmt* stmt, InlineResult* inlin failedContext->m_Callee = inlineResult->GetCallee(); failedContext->m_Success = false; failedContext->m_Devirtualized = originalCall->IsDevirtualized(); + failedContext->m_Guarded = originalCall->IsGuarded(); failedContext->m_Unboxed = originalCall->IsUnboxed(); assert(InlIsValidObservation(failedContext->m_Observation)); |