From 1b7f0ffa9e4bc16177faf987f3175966d14fe82d Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Sun, 14 Feb 2021 09:51:43 -0800 Subject: [PATCH 1/2] Add MCS verb to dump jit flags histogram Useful for determining what sorts of jit compilations are found in an SPMI collection. --- .../ToolBox/superpmi/mcs/CMakeLists.txt | 1 + .../ToolBox/superpmi/mcs/commandline.cpp | 20 ++++ .../ToolBox/superpmi/mcs/commandline.h | 2 + src/coreclr/ToolBox/superpmi/mcs/mcs.cpp | 5 + .../ToolBox/superpmi/mcs/verbjitflags.cpp | 111 ++++++++++++++++++ .../ToolBox/superpmi/mcs/verbjitflags.h | 18 +++ 6 files changed, 157 insertions(+) create mode 100644 src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp create mode 100644 src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h diff --git a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt b/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt index 8524fe8faec70b..e928c48d0cad24 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt +++ b/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt @@ -21,6 +21,7 @@ set(MCS_SOURCES verbdumpmap.cpp verbdumptoc.cpp verbfracture.cpp + verbjitflags.cpp verbildump.cpp verbinteg.cpp verbmerge.cpp diff --git a/src/coreclr/ToolBox/superpmi/mcs/commandline.cpp b/src/coreclr/ToolBox/superpmi/mcs/commandline.cpp index d7c519e90214d4..e3b01e3b20454b 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/commandline.cpp +++ b/src/coreclr/ToolBox/superpmi/mcs/commandline.cpp @@ -130,6 +130,10 @@ void CommandLine::DumpHelp(const char* program) printf(" to the mch file.\n"); printf(" e.g. '-toc a.mch' creates a.mch.mct\n"); printf("\n"); + printf(" -jitflags inputfile\n"); + printf(" Summarize interesting jitflags for the method contexts\n"); + printf(" e.g. '-jitflags a.mch'\n"); + printf("\n"); printf("Range descriptions are either a single number, or a text file with .mcl extension\n"); printf("containing a sorted list of line delimited numbers.\n"); printf(" e.g. -strip 2 a.mc b.mc\n"); @@ -235,6 +239,12 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o) foundVerb = true; o->actionDumpToc = true; } + else if ((_strnicmp(&argv[i][1], "jitflags", argLen) == 0)) + { + tempLen = strlen(argv[i]); + foundVerb = true; + o->actionJitFlags = true; + } else if ((_strnicmp(&argv[i][1], "ildump", argLen) == 0)) { tempLen = strlen(argv[i]); @@ -551,6 +561,16 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o) } return true; } + if (o->actionJitFlags) + { + if (!foundFile1) + { + LogError("CommandLine::Parse() '-jitFlags' needs one input."); + DumpHelp(argv[0]); + return false; + } + return true; + } if (o->actionILDump) { if (!foundFile1) diff --git a/src/coreclr/ToolBox/superpmi/mcs/commandline.h b/src/coreclr/ToolBox/superpmi/mcs/commandline.h index 74ca637491406b..8bcf0da11d1e99 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/commandline.h +++ b/src/coreclr/ToolBox/superpmi/mcs/commandline.h @@ -23,6 +23,7 @@ class CommandLine , actionDumpMap(false) , actionDumpToc(false) , actionFracture(false) + , actionJitFlags(false) , actionILDump(false) , actionInteg(false) , actionMerge(false) @@ -51,6 +52,7 @@ class CommandLine bool actionDumpMap; bool actionDumpToc; bool actionFracture; + bool actionJitFlags; bool actionILDump; bool actionInteg; bool actionMerge; diff --git a/src/coreclr/ToolBox/superpmi/mcs/mcs.cpp b/src/coreclr/ToolBox/superpmi/mcs/mcs.cpp index f8a007075bc0c7..34313a577bb11b 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/mcs.cpp +++ b/src/coreclr/ToolBox/superpmi/mcs/mcs.cpp @@ -12,6 +12,7 @@ #include "verbfracture.h" #include "verbdumpmap.h" #include "verbdumptoc.h" +#include "verbjitflags.h" #include "verbildump.h" #include "verbtoc.h" #include "verbremovedup.h" @@ -102,6 +103,10 @@ int __cdecl main(int argc, char* argv[]) { exitCode = verbPrintJITEEVersion::DoWork(); } + if (o.actionJitFlags) + { + exitCode = verbJitFlags::DoWork(o.nameOfFile1); + } Logger::Shutdown(); return exitCode; diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp new file mode 100644 index 00000000000000..866ad79ff2d6d5 --- /dev/null +++ b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp @@ -0,0 +1,111 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#include "standardpch.h" +#include "verbjitflags.h" +#include "methodcontext.h" +#include "methodcontextiterator.h" +#include "errorhandling.h" +#include "corjitflags.h" + +int verbJitFlags::DoWork(const char* nameOfInput) +{ + MethodContextIterator mci; + if (!mci.Initialize(nameOfInput)) + return -1; + + LightWeightMap flagMap; + + while (mci.MoveNext()) + { + MethodContext* mc = mci.Current(); + CORJIT_FLAGS corJitFlags; + mc->repGetJitFlags(&corJitFlags, sizeof(corJitFlags)); + unsigned long long rawFlags = corJitFlags.GetFlagsRaw(); + + int index = flagMap.GetIndex(rawFlags); + if (index == -1) + { + flagMap.Add(rawFlags, 1); + } + else + { + int oldVal = flagMap.GetItem(index); + flagMap.Update(index, oldVal + 1); + } + } + + if (!mci.Destroy()) + return -1; + + printf("%16s,%8s, parsed\n", "bits", "count"); + + const unsigned int count = flagMap.GetCount(); + unsigned long long* pFlag = flagMap.GetRawKeys(); + for (unsigned int i = 0; i < count; i++) + { + const unsigned long long flag = *pFlag++; + const int index = flagMap.GetIndex(flag); + + printf("%016llx,%8u", flag, flagMap.GetItem(index)); + + for (int flagBit = 63; flagBit >= 0; flagBit--) + { + if (((flag >> flagBit) & 1ull) == 1ull) + { + switch (flagBit) + { + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SPEED_OPT: printf(", SPEED_OPT"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SIZE_OPT: printf(", SIZE_OPT"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_DEBUG_CODE: printf(", DEBUG_CODE"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_DEBUG_EnC: printf(", DEBUG_EnC"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_DEBUG_INFO: printf(", DEBUG_INFO"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MIN_OPT: printf(", MIN_OPT"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MCJIT_BACKGROUND: printf(", MCJIT_BACKGROUND"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_OSR: printf(", OSR"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_ALT_JIT: printf(", ALT_JIT"); break; + + case 17: printf(", FEATURE_SIMD"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MAKEFINALCODE: printf(", MAKEFINALCODE"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_READYTORUN: printf(", READYTORUN"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PROF_ENTERLEAVE: printf(", PROF_ENTERLEAVE"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE: printf(", NO_PINVOKE_INLINE"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SKIP_VERIFICATION: printf(", SKIP_VERIFICATION"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PREJIT: printf(", PREJIT"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_RELOC: printf(", RELOC"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_IMPORT_ONLY: printf(", IMPORT_ONLY"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_IL_STUB: printf(", IL_STUB"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PROCSPLIT: printf(", PROCSPLIT"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBINSTR: printf(", BBINSTR"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBOPT: printf(", BBOPT"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_FRAMED: printf(", FRAMED"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PUBLISH_SECRET_PARAM: printf(", PUBLISH_SECRET_PARAM"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND: printf(", SAMPLING_JIT_BACKGROUND"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_USE_PINVOKE_HELPERS: printf(", USE_PINVOKE_HELPERS"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_REVERSE_PINVOKE: printf(", REVERSE_PINVOKE"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TRACK_TRANSITIONS: printf(", TRACK_TRANSITIONS"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TIER0: printf(", TIER0"); break; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TIER1: printf(", TIER1"); break; + + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_NO_INLINING: printf(", NO_INLINING"); break; + default: + printf(", ?_%02u_?", flagBit); + break; + } + } + } + + printf("\n"); + } + + return 0; +} + diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h new file mode 100644 index 00000000000000..63d0b2e2b6bce0 --- /dev/null +++ b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +//---------------------------------------------------------- +// verbJitFlags.h - verb that prints sumary of jit flags values +//---------------------------------------------------------- +#ifndef _verbJitFlags +#define _verbJitFlags + +class verbJitFlags +{ +public: + static int DoWork(const char* nameOfInput); +}; + +#endif From 1e972dddeb73a0706385f58c7d5d3efd6ebbd1a1 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Tue, 16 Feb 2021 19:17:28 -0800 Subject: [PATCH 2/2] revise per feedback --- .../ToolBox/superpmi/mcs/verbjitflags.cpp | 80 ++++++----------- .../ToolBox/superpmi/mcs/verbjitflags.h | 2 +- .../superpmi-shared/spmidumphelper.cpp | 88 +++++++++++++++++++ .../superpmi/superpmi-shared/spmidumphelper.h | 3 + 4 files changed, 118 insertions(+), 55 deletions(-) diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp index 866ad79ff2d6d5..26379ce6771d0e 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp +++ b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp @@ -8,7 +8,7 @@ #include "methodcontext.h" #include "methodcontextiterator.h" #include "errorhandling.h" -#include "corjitflags.h" +#include "spmidumphelper.h" int verbJitFlags::DoWork(const char* nameOfInput) { @@ -17,6 +17,7 @@ int verbJitFlags::DoWork(const char* nameOfInput) return -1; LightWeightMap flagMap; + unsigned mcCount = 0; while (mci.MoveNext()) { @@ -35,75 +36,46 @@ int verbJitFlags::DoWork(const char* nameOfInput) int oldVal = flagMap.GetItem(index); flagMap.Update(index, oldVal + 1); } + + mcCount++; } if (!mci.Destroy()) return -1; - printf("%16s,%8s, parsed\n", "bits", "count"); + printf("\nGrouped Flag Appearances (%u contexts)\n\n", mcCount); + printf("%-16s %8s %8s parsed\n", "bits", "count", "percent"); + + unsigned appearancesPerBit[64] = {}; const unsigned int count = flagMap.GetCount(); - unsigned long long* pFlag = flagMap.GetRawKeys(); + unsigned long long* pFlags = flagMap.GetRawKeys(); + for (unsigned int i = 0; i < count; i++) { - const unsigned long long flag = *pFlag++; - const int index = flagMap.GetIndex(flag); + const unsigned long long flags = *pFlags++; + const int index = flagMap.GetIndex(flags); + const unsigned appearances = flagMap.GetItem(index); - printf("%016llx,%8u", flag, flagMap.GetItem(index)); + printf("%016llx %8u %7.2f%% %s\n", flags, appearances, 100.0 * ((double) appearances / mcCount), SpmiDumpHelper::DumpJitFlags(flags).c_str()); - for (int flagBit = 63; flagBit >= 0; flagBit--) + for (unsigned int bit = 0; bit < 64; bit++) { - if (((flag >> flagBit) & 1ull) == 1ull) + if (flags & (1ull << bit)) { - switch (flagBit) - { - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SPEED_OPT: printf(", SPEED_OPT"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SIZE_OPT: printf(", SIZE_OPT"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_DEBUG_CODE: printf(", DEBUG_CODE"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_DEBUG_EnC: printf(", DEBUG_EnC"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_DEBUG_INFO: printf(", DEBUG_INFO"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MIN_OPT: printf(", MIN_OPT"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MCJIT_BACKGROUND: printf(", MCJIT_BACKGROUND"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_OSR: printf(", OSR"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_ALT_JIT: printf(", ALT_JIT"); break; - - case 17: printf(", FEATURE_SIMD"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MAKEFINALCODE: printf(", MAKEFINALCODE"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_READYTORUN: printf(", READYTORUN"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PROF_ENTERLEAVE: printf(", PROF_ENTERLEAVE"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE: printf(", NO_PINVOKE_INLINE"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SKIP_VERIFICATION: printf(", SKIP_VERIFICATION"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PREJIT: printf(", PREJIT"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_RELOC: printf(", RELOC"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_IMPORT_ONLY: printf(", IMPORT_ONLY"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_IL_STUB: printf(", IL_STUB"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PROCSPLIT: printf(", PROCSPLIT"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBINSTR: printf(", BBINSTR"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBOPT: printf(", BBOPT"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_FRAMED: printf(", FRAMED"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PUBLISH_SECRET_PARAM: printf(", PUBLISH_SECRET_PARAM"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND: printf(", SAMPLING_JIT_BACKGROUND"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_USE_PINVOKE_HELPERS: printf(", USE_PINVOKE_HELPERS"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_REVERSE_PINVOKE: printf(", REVERSE_PINVOKE"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TRACK_TRANSITIONS: printf(", TRACK_TRANSITIONS"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TIER0: printf(", TIER0"); break; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TIER1: printf(", TIER1"); break; - - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_NO_INLINING: printf(", NO_INLINING"); break; - default: - printf(", ?_%02u_?", flagBit); - break; - } + appearancesPerBit[bit] += appearances; } } + } - printf("\n"); + printf("\nIndividual Flag Appearances\n\n"); + for (unsigned int bit = 0; bit < 64; bit++) + { + unsigned perBit = appearancesPerBit[bit]; + if (perBit > 0) + { + printf("%8u %7.2f%% %s\n", perBit, 100.0 * (double) perBit / mcCount, SpmiDumpHelper::DumpJitFlags(1ull<