Skip to content

Commit 516f061

Browse files
authored
[release/7.0-rc1] Improve DOTNET_JitDisasm and introduce DOTNET_JitDisasmSummary (#74392)
* [release/7.0-rc1] Improve DOTNET_JitDisasm and introduce DOTNET_JitDisasmSummary * Update jitconfig.cpp
1 parent 7193b90 commit 516f061

File tree

7 files changed

+133
-90
lines changed

7 files changed

+133
-90
lines changed

docs/design/features/OsrDetailsAndDebugging.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ Note if a Tier0 method is recursive and has loops there can be some interesting
338338

339339
### Seeing which OSR methods are created
340340

341-
* `DOTNET_DumpJittedMethods=1` will specially mark OSR methods with the inspiring IL offsets.
341+
* `DOTNET_JitDisasmSummary=1` will specially mark OSR methods with the inspiring IL offsets.
342342

343343
For example, running a libraries test with some stressful OSR settings, there ended up being 699 OSR methods jitted out of 160675 total methods. Grepping for OSR in the dump output, the last few lines were:
344344

src/coreclr/jit/codegencommon.cpp

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,31 +1887,9 @@ void CodeGen::genGenerateMachineCode()
18871887

18881888
if (compiler->fgHaveProfileData())
18891889
{
1890-
const char* pgoKind;
1891-
switch (compiler->fgPgoSource)
1892-
{
1893-
case ICorJitInfo::PgoSource::Static:
1894-
pgoKind = "Static";
1895-
break;
1896-
case ICorJitInfo::PgoSource::Dynamic:
1897-
pgoKind = "Dynamic";
1898-
break;
1899-
case ICorJitInfo::PgoSource::Blend:
1900-
pgoKind = "Blend";
1901-
break;
1902-
case ICorJitInfo::PgoSource::Text:
1903-
pgoKind = "Textual";
1904-
break;
1905-
case ICorJitInfo::PgoSource::Sampling:
1906-
pgoKind = "Sample-based";
1907-
break;
1908-
default:
1909-
pgoKind = "Unknown";
1910-
break;
1911-
}
1912-
1913-
printf("; with %s PGO: edge weights are %s, and fgCalledCount is " FMT_WT "\n", pgoKind,
1914-
compiler->fgHaveValidEdgeWeights ? "valid" : "invalid", compiler->fgCalledCount);
1890+
printf("; with %s: edge weights are %s, and fgCalledCount is " FMT_WT "\n",
1891+
compiler->compGetPgoSourceName(), compiler->fgHaveValidEdgeWeights ? "valid" : "invalid",
1892+
compiler->fgCalledCount);
19151893
}
19161894

19171895
if (compiler->fgPgoFailReason != nullptr)

src/coreclr/jit/compiler.cpp

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ extern ICorJitHost* g_jitHost;
3434
#define COLUMN_FLAGS (COLUMN_KINDS + 32)
3535
#endif
3636

37-
#if defined(DEBUG)
3837
unsigned Compiler::jitTotalMethodCompiled = 0;
39-
#endif // defined(DEBUG)
4038

4139
#if defined(DEBUG)
4240
LONG Compiler::jitNestingLevel = 0;
@@ -4082,8 +4080,9 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
40824080
//
40834081
const char* Compiler::compGetTieringName(bool wantShortName) const
40844082
{
4085-
const bool tier0 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0);
4086-
const bool tier1 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1);
4083+
const bool tier0 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0);
4084+
const bool tier1 = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1);
4085+
const bool instrumenting = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR);
40874086

40884087
if (!opts.compMinOptsIsSet)
40894088
{
@@ -4097,13 +4096,13 @@ const char* Compiler::compGetTieringName(bool wantShortName) const
40974096

40984097
if (tier0)
40994098
{
4100-
return "Tier0";
4099+
return instrumenting ? "Instrumented Tier0" : "Tier0";
41014100
}
41024101
else if (tier1)
41034102
{
41044103
if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_OSR))
41054104
{
4106-
return "Tier1-OSR";
4105+
return instrumenting ? "Instrumented Tier1-OSR" : "Tier1-OSR";
41074106
}
41084107
else
41094108
{
@@ -4149,6 +4148,31 @@ const char* Compiler::compGetTieringName(bool wantShortName) const
41494148
}
41504149
}
41514150

4151+
//------------------------------------------------------------------------
4152+
// compGetPgoSourceName: get a string describing PGO source
4153+
//
4154+
// Returns:
4155+
// String describing describing PGO source (e.g. Dynamic, Static, etc)
4156+
//
4157+
const char* Compiler::compGetPgoSourceName() const
4158+
{
4159+
switch (fgPgoSource)
4160+
{
4161+
case ICorJitInfo::PgoSource::Static:
4162+
return "Static PGO";
4163+
case ICorJitInfo::PgoSource::Dynamic:
4164+
return "Dynamic PGO";
4165+
case ICorJitInfo::PgoSource::Blend:
4166+
return "Blend PGO";
4167+
case ICorJitInfo::PgoSource::Text:
4168+
return "Textual PGO";
4169+
case ICorJitInfo::PgoSource::Sampling:
4170+
return "Sample-based PGO";
4171+
default:
4172+
return "";
4173+
}
4174+
}
4175+
41524176
//------------------------------------------------------------------------
41534177
// compGetStressMessage: get a string describing jitstress capability
41544178
// for this method
@@ -5106,9 +5130,31 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
51065130
compJitTelemetry.NotifyEndOfCompilation();
51075131
#endif
51085132

5109-
#if defined(DEBUG)
5110-
++Compiler::jitTotalMethodCompiled;
5111-
#endif // defined(DEBUG)
5133+
unsigned methodsCompiled = (unsigned)InterlockedIncrement((LONG*)&Compiler::jitTotalMethodCompiled);
5134+
5135+
if (JitConfig.JitDisasmSummary() && !compIsForInlining())
5136+
{
5137+
char osrBuffer[20] = {0};
5138+
if (opts.IsOSR())
5139+
{
5140+
// Tiering name already includes "OSR", we just want the IL offset
5141+
sprintf_s(osrBuffer, 20, " @0x%x", info.compILEntry);
5142+
}
5143+
5144+
#ifdef DEBUG
5145+
const char* fullName = info.compFullName;
5146+
#else
5147+
const char* fullName = eeGetMethodFullName(info.compMethodHnd);
5148+
#endif
5149+
5150+
char debugPart[128] = {0};
5151+
INDEBUG(sprintf_s(debugPart, 128, ", hash=0x%08x%s", info.compMethodHash(), compGetStressMessage()));
5152+
5153+
const bool hasProf = fgHaveProfileData();
5154+
printf("%4d: JIT compiled %s [%s%s%s%s, IL size=%u, code size=%u%s]\n", methodsCompiled, fullName,
5155+
compGetTieringName(), osrBuffer, hasProf ? " with " : "", hasProf ? compGetPgoSourceName() : "",
5156+
info.compILCodeSize, *methodCodeSize, debugPart);
5157+
}
51125158

51135159
compFunctionTraceEnd(*methodCodePtr, *methodCodeSize, false);
51145160
JITDUMP("Method code size: %d\n", (unsigned)(*methodCodeSize));
@@ -6710,24 +6756,6 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr,
67106756
}
67116757

67126758
#ifdef DEBUG
6713-
if ((JitConfig.DumpJittedMethods() == 1) && !compIsForInlining())
6714-
{
6715-
enum
6716-
{
6717-
BUFSIZE = 20
6718-
};
6719-
char osrBuffer[BUFSIZE] = {0};
6720-
if (opts.IsOSR())
6721-
{
6722-
// Tiering name already includes "OSR", we just want the IL offset
6723-
//
6724-
sprintf_s(osrBuffer, BUFSIZE, " @0x%x", info.compILEntry);
6725-
}
6726-
6727-
printf("Compiling %4d %s::%s, IL size = %u, hash=0x%08x %s%s%s\n", Compiler::jitTotalMethodCompiled,
6728-
info.compClassName, info.compMethodName, info.compILCodeSize, info.compMethodHash(),
6729-
compGetTieringName(), osrBuffer, compGetStressMessage());
6730-
}
67316759
if (compIsForInlining())
67326760
{
67336761
compGenTreeID = impInlineInfo->InlinerCompiler->compGenTreeID;

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4145,9 +4145,7 @@ class Compiler
41454145
regNumber getCallArgIntRegister(regNumber floatReg);
41464146
regNumber getCallArgFloatRegister(regNumber intReg);
41474147

4148-
#if defined(DEBUG)
41494148
static unsigned jitTotalMethodCompiled;
4150-
#endif
41514149

41524150
#ifdef DEBUG
41534151
static LONG jitNestingLevel;
@@ -9472,6 +9470,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
94729470
}
94739471

94749472
const char* compGetTieringName(bool wantShortName = false) const;
9473+
const char* compGetPgoSourceName() const;
94759474
const char* compGetStressMessage() const;
94769475

94779476
codeOptimize compCodeOpt() const

src/coreclr/jit/jitconfig.cpp

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@ void JitConfigValues::MethodSet::initialize(const WCHAR* list, ICorJitHost* host
4444
bool isQuoted = false; // true while parsing inside a quote "this-is-a-quoted-region"
4545
MethodName currentName; // Buffer used while parsing the current entry
4646

47-
currentName.m_next = nullptr;
48-
currentName.m_methodNameStart = -1;
49-
currentName.m_methodNameLen = -1;
50-
currentName.m_methodNameWildcardAtEnd = false;
51-
currentName.m_classNameStart = -1;
52-
currentName.m_classNameLen = -1;
53-
currentName.m_classNameWildcardAtEnd = false;
54-
currentName.m_numArgs = -1;
47+
currentName.m_next = nullptr;
48+
currentName.m_methodNameStart = -1;
49+
currentName.m_methodNameLen = -1;
50+
currentName.m_methodNameWildcardAtStart = false;
51+
currentName.m_methodNameWildcardAtEnd = false;
52+
currentName.m_classNameStart = -1;
53+
currentName.m_classNameLen = -1;
54+
currentName.m_classNameWildcardAtEnd = false;
55+
currentName.m_numArgs = -1;
5556

5657
enum State
5758
{
@@ -202,21 +203,31 @@ void JitConfigValues::MethodSet::initialize(const WCHAR* list, ICorJitHost* host
202203
}
203204

204205
// Is the first character a wildcard?
205-
if (m_list[currentName.m_methodNameStart] == WILD_CHAR)
206+
if (m_list[currentName.m_methodNameStart] == WILD_CHAR && currentName.m_methodNameLen == 1)
206207
{
207208
// The method name is a full wildcard; mark it as such.
208209
currentName.m_methodNameStart = -1;
209210
currentName.m_methodNameLen = -1;
210211
}
211-
// Is there a wildcard at the end of the method name?
212-
//
213-
else if (m_list[currentName.m_methodNameStart + currentName.m_methodNameLen - 1] == WILD_CHAR)
212+
else
214213
{
215-
// i.e. class:foo*, will match any method that starts with "foo"
216-
217-
// Remove the trailing WILD_CHAR from method name
218-
currentName.m_methodNameLen--; // backup for WILD_CHAR
219-
currentName.m_methodNameWildcardAtEnd = true;
214+
// Is there a wildcard at the start of the method name?
215+
if (m_list[currentName.m_methodNameStart] == WILD_CHAR)
216+
{
217+
// i.e. class:*foo, will match any method that ends with "foo"
218+
// Remove the leading WILD_CHAR from method name
219+
currentName.m_methodNameStart++;
220+
currentName.m_methodNameLen--;
221+
currentName.m_methodNameWildcardAtStart = true;
222+
}
223+
// Is there a wildcard at the end of the method name?
224+
if (m_list[currentName.m_methodNameStart + currentName.m_methodNameLen - 1] == WILD_CHAR)
225+
{
226+
// i.e. class:foo*, will match any method that starts with "foo"
227+
// Remove the trailing WILD_CHAR from method name
228+
currentName.m_methodNameLen--; // backup for WILD_CHAR
229+
currentName.m_methodNameWildcardAtEnd = true;
230+
}
220231
}
221232

222233
// should we expect an ARG_LIST?
@@ -309,11 +320,35 @@ void JitConfigValues::MethodSet::destroy(ICorJitHost* host)
309320
m_names = nullptr;
310321
}
311322

312-
static bool matchesName(const char* const name, int nameLen, bool wildcardAtEnd, const char* const s2)
323+
// strstr that is length-limited, this implementation is not intended to be used on hot paths
324+
static size_t strnstr(const char* pSrc, size_t srcSize, const char* needle, size_t needleSize)
325+
{
326+
if (srcSize < needleSize)
327+
{
328+
return -1;
329+
}
330+
331+
for (size_t srcPos = 0; srcPos <= srcSize - needleSize; srcPos++)
332+
{
333+
if (strncmp(pSrc + srcPos, needle, needleSize) == 0)
334+
{
335+
return srcPos;
336+
}
337+
}
338+
return -1;
339+
}
340+
341+
static bool matchesName(
342+
const char* const name, int nameLen, bool wildcardAtStart, bool wildcardAtEnd, const char* const s2)
313343
{
314-
// 's2' must start with 'nameLen' characters of 'name'
315-
if (strncmp(name, s2, nameLen) != 0)
344+
if (wildcardAtStart && (int)strnstr(s2, strlen(s2), name, nameLen) == -1)
345+
{
346+
return false;
347+
}
348+
349+
if (!wildcardAtStart && strncmp(name, s2, nameLen) != 0)
316350
{
351+
// 's2' must start with 'nameLen' characters of 'name'
317352
return false;
318353
}
319354

@@ -346,12 +381,14 @@ bool JitConfigValues::MethodSet::contains(const char* methodName,
346381
if (name->m_methodNameStart != -1)
347382
{
348383
const char* expectedMethodName = &m_list[name->m_methodNameStart];
349-
if (!matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtEnd, methodName))
384+
if (!matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtStart,
385+
name->m_methodNameWildcardAtEnd, methodName))
350386
{
351387
// C++ embeds the class name into the method name; deal with that here.
352388
const char* colon = strchr(methodName, ':');
353389
if (colon != nullptr && colon[1] == ':' &&
354-
matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtEnd, methodName))
390+
matchesName(expectedMethodName, name->m_methodNameLen, name->m_methodNameWildcardAtStart,
391+
name->m_methodNameWildcardAtEnd, methodName))
355392
{
356393
int classLen = (int)(colon - methodName);
357394
if (name->m_classNameStart == -1 ||
@@ -367,8 +404,7 @@ bool JitConfigValues::MethodSet::contains(const char* methodName,
367404

368405
// If m_classNameStart is valid, check for a mismatch
369406
if (className == nullptr || name->m_classNameStart == -1 ||
370-
matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, name->m_classNameWildcardAtEnd,
371-
className))
407+
matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, false, false, className))
372408
{
373409
return true;
374410
}
@@ -379,8 +415,8 @@ bool JitConfigValues::MethodSet::contains(const char* methodName,
379415
if (nsSep != nullptr && nsSep != className)
380416
{
381417
const char* onlyClass = nsSep[-1] == '.' ? nsSep : &nsSep[1];
382-
if (matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, name->m_classNameWildcardAtEnd,
383-
onlyClass))
418+
if (matchesName(&m_list[name->m_classNameStart], name->m_classNameLen, false,
419+
name->m_classNameWildcardAtEnd, onlyClass))
384420
{
385421
return true;
386422
}

src/coreclr/jit/jitconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class JitConfigValues
2020
MethodName* m_next;
2121
int m_methodNameStart;
2222
int m_methodNameLen;
23+
bool m_methodNameWildcardAtStart;
2324
bool m_methodNameWildcardAtEnd;
2425
int m_classNameStart;
2526
int m_classNameLen;

src/coreclr/jit/jitconfigvalues.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,14 @@ CONFIG_INTEGER(DiffableDasm, W("JitDiffableDasm"), 0) // Make the disas
2626
CONFIG_INTEGER(JitDasmWithAddress, W("JitDasmWithAddress"), 0) // Print the process address next to each instruction of
2727
// the disassembly
2828
CONFIG_INTEGER(DisplayLoopHoistStats, W("JitLoopHoistStats"), 0) // Display JIT loop hoisting statistics
29-
CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics
30-
// If set to "1", display the stats in textual format.
31-
// If set to "2", display the stats in csv format.
32-
// If set to "3", display the stats in summarize format.
33-
// Recommended to use with JitStdOutFile flag.
34-
CONFIG_STRING(JitLsraOrdering, W("JitLsraOrdering")) // LSRA heuristics ordering
35-
CONFIG_INTEGER(DumpJittedMethods, W("DumpJittedMethods"), 0) // Prints all jitted methods to the console
36-
CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by
37-
// RyuJIT where possible
29+
CONFIG_INTEGER(DisplayLsraStats, W("JitLsraStats"), 0) // Display JIT Linear Scan Register Allocator statistics
30+
// If set to "1", display the stats in textual format.
31+
// If set to "2", display the stats in csv format.
32+
// If set to "3", display the stats in summarize format.
33+
// Recommended to use with JitStdOutFile flag.
34+
CONFIG_STRING(JitLsraOrdering, W("JitLsraOrdering")) // LSRA heuristics ordering
35+
CONFIG_INTEGER(EnablePCRelAddr, W("JitEnablePCRelAddr"), 1) // Whether absolute addr be encoded as PC-rel offset by
36+
// RyuJIT where possible
3837
CONFIG_INTEGER(JitAssertOnMaxRAPasses, W("JitAssertOnMaxRAPasses"), 0)
3938
CONFIG_INTEGER(JitBreakEmitOutputInstr, W("JitBreakEmitOutputInstr"), -1)
4039
CONFIG_INTEGER(JitBreakMorphTree, W("JitBreakMorphTree"), 0xffffffff)
@@ -257,6 +256,8 @@ CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // En
257256
CONFIG_METHODSET(JitDisasm, W("JitDisasm"))
258257
#endif // !defined(DEBUG)
259258

259+
CONFIG_INTEGER(JitDisasmSummary, W("JitDisasmSummary"), 0) // Prints all jitted methods to the console
260+
260261
CONFIG_INTEGER(RichDebugInfo, W("RichDebugInfo"), 0) // If 1, keep rich debug info and report it back to the EE
261262

262263
#ifdef DEBUG

0 commit comments

Comments
 (0)