Emit the hash for callees, and check it during replay.
Capture the root method name, and do a simple Xml-safe conversion.
Add a missing newline to the banner message announcing that the replay
policy is in effect.
m_Sibling->DumpXml(file, indent);
}
- Compiler* compiler = m_InlineStrategy->GetCompiler();
-
- mdMethodDef calleeToken =
- compiler->info.compCompHnd->getMethodDefFromMethod(m_Callee);
-
const bool isRoot = m_Parent == nullptr;
const bool hasChild = m_Child != nullptr;
const char* inlineType = m_Success ? "Inline" : "FailedInline";
if (!isRoot)
{
+ Compiler* compiler = m_InlineStrategy->GetCompiler();
+
+ mdMethodDef calleeToken =
+ compiler->info.compCompHnd->getMethodDefFromMethod(m_Callee);
+ unsigned calleeHash =
+ compiler->info.compCompHnd->getMethodHash(m_Callee);
+
const char* inlineReason = InlGetObservationString(m_Observation);
int offset = -1;
fprintf(file, "%*s<%s>\n", indent, "", inlineType);
fprintf(file, "%*s<Token>%u</Token>\n", indent + 2, "", calleeToken);
+ fprintf(file, "%*s<Hash>%u</Hash>\n", indent + 2, "", calleeHash);
fprintf(file, "%*s<Offset>%u</Offset>\n", indent + 2, "", offset);
fprintf(file, "%*s<Reason>%s</Reason>\n", indent + 2, "", inlineReason);
newIndent = indent + 2;
microsecondsSpentJitting = (unsigned) ((counts / countsPerSec) * 1000 * 1000);
}
+ // Get method name just for root method, to make it a bit easier
+ // to search for things in the inline xml.
+ const char* methodName = info.compCompHnd->getMethodName(info.compMethodHnd, nullptr);
+
+ // Cheap xml quoting for values. Only < and & are troublemakers,
+ // but change > for symmetry.
+ //
+ // Ok to truncate name, just ensure it's null terminated.
+ char buf[64];
+ strncpy(buf, methodName, sizeof(buf));
+ buf[sizeof(buf)-1] = 0;
+
+ for (int i = 0; i < sizeof(buf); i++)
+ {
+ switch (buf[i])
+ {
+ case '<':
+ buf[i] = '[';
+ break;
+ case '>':
+ buf[i] = ']';
+ break;
+ case '&':
+ buf[i] = '#';
+ break;
+ default:
+ break;
+ }
+ }
+
fprintf(file, "%*s<Method>\n", indent, "");
fprintf(file, "%*s<Token>%u</Token>\n", indent + 2, "", currentMethodToken);
fprintf(file, "%*s<Hash>%u</Hash>\n", indent + 2, "", hash);
+ fprintf(file, "%*s<Name>%s</Name>\n", indent + 2, "", buf);
fprintf(file, "%*s<InlineCount>%u</InlineCount>\n", indent + 2, "", m_InlineCount);
fprintf(file, "%*s<HotSize>%u</HotSize>\n", indent + 2, "", info.compTotalHotCodeSize);
fprintf(file, "%*s<ColdSize>%u</ColdSize>\n", indent + 2, "", info.compTotalColdCodeSize);
// Nope, open it up.
const wchar_t* replayFileName = JitConfig.JitInlineReplayFile();
s_ReplayFile = _wfopen(replayFileName, W("r"));
- fprintf(stderr, "*** %s inlines from %ws",
+ fprintf(stderr, "*** %s inlines from %ws\n",
s_ReplayFile == nullptr ? "Unable to replay" : "Replaying",
replayFileName);
s_WroteReplayBanner = true;
// File pointer should be pointing at the parent context level.
// See if we see an inline entry for this context.
//
- // Token we're looking for.
+ // Token and Hash we're looking for.
mdMethodDef contextToken =
m_RootCompiler->info.compCompHnd->getMethodDefFromMethod(
context->GetCallee());
+ unsigned contextHash =
+ m_RootCompiler->info.compCompHnd->getMethodHash(
+ context->GetCallee());
- return FindInline(contextToken);
+ return FindInline(contextToken, contextHash);
}
//------------------------------------------------------------------------
//
// Arguments:
// token -- token describing the inline
+// hash -- hash describing the inline
//
// ReturnValue:
// true if the inline entry was found
// Assumes file position has just been set by a successful call to
// FindMethod or FindContext.
//
-// Token will not be sufficiently unique to identify a particular
-// inline, if there are multiple calls to the same method.
+// Token and Hash will not be sufficiently unique to identify a
+// particular inline, if there are multiple calls to the same
+// method.
-bool ReplayPolicy::FindInline(unsigned token)
+bool ReplayPolicy::FindInline(unsigned token, unsigned hash)
{
char buffer[256];
bool foundInline = false;
unsigned inlineToken = 0;
int count = sscanf(buffer, " <Token>%u</Token> ", &inlineToken);
- // Need a secondary check here for callsite
- // ID... offset or similar. Hash would be nice too.
+ // Need a secondary check here for callsite.
+ // ...offset or similar.
if ((count != 1) || (inlineToken != token))
{
continue;
}
+ // Get next line
+ if (fgets(buffer, sizeof(buffer), s_ReplayFile) == nullptr)
+ {
+ break;
+ }
+
+ unsigned inlineHash = 0;
+ count = sscanf(buffer, " <Hash>%u</Hash> ", &inlineHash);
+
+ // Need a secondary check here for callsite ID
+ // ... offset or similar.
+ if ((count != 1) || (inlineHash != hash))
+ {
+ continue;
+ }
+
// We're good!
foundInline = true;
break;
bool ReplayPolicy::FindInline(CORINFO_METHOD_HANDLE callee)
{
- // Token we're looking for
+ // Token and Hash we're looking for
mdMethodDef calleeToken =
m_RootCompiler->info.compCompHnd->getMethodDefFromMethod(callee);
+ unsigned calleeHash =
+ m_RootCompiler->info.compCompHnd->getMethodHash(callee);
- bool foundInline = FindInline(calleeToken);
+ bool foundInline = FindInline(calleeToken, calleeHash);
return foundInline;
}
bool FindMethod();
bool FindContext(InlineContext* context);
bool FindInline(CORINFO_METHOD_HANDLE callee);
- bool FindInline(unsigned token);
+ bool FindInline(unsigned token, unsigned hash);
static bool s_WroteReplayBanner;
static FILE* s_ReplayFile;