summaryrefslogtreecommitdiff
path: root/src/jit/inline.cpp
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2018-12-06 09:03:31 -0800
committerGitHub <noreply@github.com>2018-12-06 09:03:31 -0800
commit045f470f71cfcedf3eb7ff248f25bf29619d9a88 (patch)
tree3acf9d6d7cb154803725c16f4de68b90a0a62233 /src/jit/inline.cpp
parent7454475cd4f5575d2a2db3879bb164609e8bd6ad (diff)
downloadcoreclr-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.cpp12
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));