diff options
Diffstat (limited to 'src/jit/inline.cpp')
-rw-r--r-- | src/jit/inline.cpp | 138 |
1 files changed, 101 insertions, 37 deletions
diff --git a/src/jit/inline.cpp b/src/jit/inline.cpp index deccc0e84b..05fcf1c6b9 100644 --- a/src/jit/inline.cpp +++ b/src/jit/inline.cpp @@ -447,7 +447,7 @@ void InlineContext::DumpData(unsigned indent) else if (m_Success) { const char* inlineReason = InlGetObservationString(m_Observation); - printf("%*s%u,\"%s\",\"%s\"", indent, "", m_Ordinal, inlineReason, calleeName); + printf("%*s%u,\"%s\",\"%s\",", indent, "", m_Ordinal, inlineReason, calleeName); m_Policy->DumpData(jitstdout); printf("\n"); } @@ -500,14 +500,25 @@ void InlineContext::DumpXml(FILE* file, unsigned indent) fprintf(file, "%*s<Offset>%u</Offset>\n", indent + 2, "", offset); fprintf(file, "%*s<Reason>%s</Reason>\n", indent + 2, "", inlineReason); - // Optionally, dump data about the last inline - if ((JitConfig.JitInlineDumpData() != 0) && (this == m_InlineStrategy->GetLastContext())) + // Optionally, dump data about the inline + const int dumpDataSetting = JitConfig.JitInlineDumpData(); + + // JitInlineDumpData=1 -- dump data plus deltas for last inline only + if ((dumpDataSetting == 1) && (this == m_InlineStrategy->GetLastContext())) { fprintf(file, "%*s<Data>", indent + 2, ""); m_InlineStrategy->DumpDataContents(file); fprintf(file, "</Data>\n"); } + // JitInlineDumpData=2 -- dump data for all inlines, no deltas + if ((dumpDataSetting == 2) && (m_Policy != nullptr)) + { + fprintf(file, "%*s<Data>", indent + 2, ""); + m_Policy->DumpData(file); + fprintf(file, "</Data>\n"); + } + newIndent = indent + 2; } @@ -646,10 +657,11 @@ void InlineResult::Report() m_Reported = true; #ifdef DEBUG - const char* callee = nullptr; + const char* callee = nullptr; + const bool showInlines = (JitConfig.JitPrintInlinedMethods() == 1); // Optionally dump the result - if (VERBOSE) + if (VERBOSE || showInlines) { const char* format = "INLINER: during '%s' result '%s' reason '%s' for '%s' calling '%s'\n"; const char* caller = (m_Caller == nullptr) ? "n/a" : m_RootCompiler->eeGetMethodFullName(m_Caller); @@ -689,12 +701,18 @@ void InlineResult::Report() #ifdef DEBUG + const char* obsString = InlGetObservationString(obs); + if (VERBOSE) { - const char* obsString = InlGetObservationString(obs); JITDUMP("\nINLINER: Marking %s as NOINLINE because of %s\n", callee, obsString); } + if (showInlines) + { + printf("Marking %s as NOINLINE because of %s\n", callee, obsString); + } + #endif // DEBUG COMP_HANDLE comp = m_RootCompiler->info.compCompHnd; @@ -740,6 +758,7 @@ InlineStrategy::InlineStrategy(Compiler* compiler) , m_HasForceViaDiscretionary(false) #if defined(DEBUG) || defined(INLINE_DATA) , m_MethodXmlFilePosition(0) + , m_Random(nullptr) #endif // defined(DEBUG) || defined(INLINE_DATA) { @@ -1155,10 +1174,10 @@ InlineContext* InlineStrategy::NewRoot() InlineContext* InlineStrategy::NewSuccess(InlineInfo* inlineInfo) { InlineContext* calleeContext = new (m_Compiler, CMK_Inlining) InlineContext(this); - GenTree* stmt = inlineInfo->iciStmt; + GenTreeStmt* stmt = inlineInfo->iciStmt; BYTE* calleeIL = inlineInfo->inlineCandidateInfo->methInfo.ILCode; unsigned calleeILSize = inlineInfo->inlineCandidateInfo->methInfo.ILCodeSize; - InlineContext* parentContext = stmt->gtStmt.gtInlineContext; + InlineContext* parentContext = stmt->gtInlineContext; noway_assert(parentContext != nullptr); @@ -1213,35 +1232,22 @@ InlineContext* InlineStrategy::NewSuccess(InlineInfo* inlineInfo) // A new InlineContext for diagnostic purposes, or nullptr if // the desired context could not be created. -InlineContext* InlineStrategy::NewFailure(GenTree* stmt, InlineResult* inlineResult) +InlineContext* InlineStrategy::NewFailure(GenTreeStmt* stmt, InlineResult* inlineResult) { - // Check for a parent context first. We may insert new statements - // between the caller and callee that do not pick up either's - // context, and these statements may have calls that we later - // examine and fail to inline. - // - // See fgInlinePrependStatements for examples. - - InlineContext* parentContext = stmt->gtStmt.gtInlineContext; - - if (parentContext == nullptr) - { - // Assume for now this is a failure to inline a call in a - // statement inserted between caller and callee. Just ignore - // it for the time being. - - return nullptr; - } - + // Check for a parent context first. We should now have a parent + // context for all statements. + InlineContext* parentContext = stmt->gtInlineContext; + assert(parentContext != nullptr); InlineContext* failedContext = new (m_Compiler, CMK_Inlining) InlineContext(this); - failedContext->m_Parent = parentContext; - // Push on front here will put siblings in reverse lexical - // order which we undo in the dumper + // Pushing the new context on the front of the parent child list + // will put siblings in reverse lexical order which we undo in the + // dumper. + failedContext->m_Parent = parentContext; failedContext->m_Sibling = parentContext->m_Child; parentContext->m_Child = failedContext; failedContext->m_Child = nullptr; - failedContext->m_Offset = stmt->AsStmt()->gtStmtILoffsx; + failedContext->m_Offset = stmt->gtStmtILoffsx; failedContext->m_Observation = inlineResult->GetObservation(); failedContext->m_Callee = inlineResult->GetCallee(); failedContext->m_Success = false; @@ -1354,7 +1360,7 @@ void InlineStrategy::DumpDataEnsurePolicyIsSet() // successful policy, so fake one up. if (m_LastSuccessfulPolicy == nullptr) { - const bool isPrejitRoot = (opts.eeFlags & CORJIT_FLG_PREJIT) != 0; + const bool isPrejitRoot = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT); m_LastSuccessfulPolicy = InlinePolicy::GetPolicy(m_Compiler, isPrejitRoot); // Add in a bit of data.... @@ -1388,7 +1394,7 @@ void InlineStrategy::DumpDataHeader(FILE* file) void InlineStrategy::DumpDataSchema(FILE* file) { DumpDataEnsurePolicyIsSet(); - fprintf(file, "Method,Version,HotSize,ColdSize,JitTime,SizeEstimate,TimeEstimate"); + fprintf(file, "Method,Version,HotSize,ColdSize,JitTime,SizeEstimate,TimeEstimate,"); m_LastSuccessfulPolicy->DumpSchema(file); } @@ -1424,7 +1430,7 @@ void InlineStrategy::DumpDataContents(FILE* file) microsecondsSpentJitting = (unsigned)((counts / countsPerSec) * 1000 * 1000); } - fprintf(file, "%08X,%u,%u,%u,%u,%d,%d", currentMethodToken, m_InlineCount, info.compTotalHotCodeSize, + fprintf(file, "%08X,%u,%u,%u,%u,%d,%d,", currentMethodToken, m_InlineCount, info.compTotalHotCodeSize, info.compTotalColdCodeSize, microsecondsSpentJitting, m_CurrentSizeEstimate / 10, m_CurrentTimeEstimate); m_LastSuccessfulPolicy->DumpData(file); } @@ -1461,10 +1467,22 @@ void InlineStrategy::DumpXml(FILE* file, unsigned indent) fprintf(file, "<InlineForest>\n"); fprintf(file, "<Policy>%s</Policy>\n", m_LastSuccessfulPolicy->GetName()); - if (JitConfig.JitInlineDumpData() != 0) + const int dumpDataSetting = JitConfig.JitInlineDumpData(); + if (dumpDataSetting != 0) { fprintf(file, "<DataSchema>"); - DumpDataSchema(file); + + if (dumpDataSetting == 1) + { + // JitInlineDumpData=1 -- dump schema for data plus deltas + DumpDataSchema(file); + } + else if (dumpDataSetting == 2) + { + // JitInlineDumpData=2 -- dump schema for data only + m_LastSuccessfulPolicy->DumpSchema(file); + } + fprintf(file, "</DataSchema>\n"); } @@ -1484,7 +1502,7 @@ void InlineStrategy::DumpXml(FILE* file, unsigned indent) const Compiler::Info& info = m_Compiler->info; const Compiler::Options& opts = m_Compiler->opts; - const bool isPrejitRoot = (opts.eeFlags & CORJIT_FLG_PREJIT) != 0; + const bool isPrejitRoot = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT); const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0; // We'd really like the method identifier to be unique and @@ -1589,6 +1607,52 @@ void InlineStrategy::FinalizeXml(FILE* file) ReplayPolicy::FinalizeXml(); } +//------------------------------------------------------------------------ +// GetRandom: setup or access random state +// +// Return Value: +// New or pre-existing random state. +// +// Notes: +// Random state is kept per jit compilation request. Seed is partially +// specified externally (via stress or policy setting) and partially +// specified internally via method hash. + +CLRRandom* InlineStrategy::GetRandom() +{ + if (m_Random == nullptr) + { + int externalSeed = 0; + +#ifdef DEBUG + + if (m_Compiler->compRandomInlineStress()) + { + externalSeed = getJitStressLevel(); + } + +#endif // DEBUG + + int randomPolicyFlag = JitConfig.JitInlinePolicyRandom(); + if (randomPolicyFlag != 0) + { + externalSeed = randomPolicyFlag; + } + + int internalSeed = m_Compiler->info.compMethodHash(); + + assert(externalSeed != 0); + assert(internalSeed != 0); + + int seed = externalSeed ^ internalSeed; + + m_Random = new (m_Compiler, CMK_Inlining) CLRRandom(); + m_Random->Init(seed); + } + + return m_Random; +} + #endif // defined(DEBUG) || defined(INLINE_DATA) //------------------------------------------------------------------------ |