diff options
author | Andy Ayers <andya@microsoft.com> | 2021-02-17 19:43:47 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-17 19:43:47 +0300 |
commit | 701e029c330a6844f1e91c6760b93872ee106108 (patch) | |
tree | 06338e6d973e6fbdf7137c5b56bb7083fa2070d9 /src/coreclr/ToolBox | |
parent | 9195df699fe25d2e752c2bc350c16dc199f02f7a (diff) |
Add MCS verb to dump jit flags histogram (#48281)
Useful for determining what sorts of jit compilations are found in an SPMI
collection.
Diffstat (limited to 'src/coreclr/ToolBox')
8 files changed, 220 insertions, 0 deletions
diff --git a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt b/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt index 8524fe8faec..e928c48d0ca 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 d7c519e9021..e3b01e3b204 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 74ca6374914..8bcf0da11d1 100644 --- a/src/coreclr/ToolBox/superpmi/mcs/commandline.h +++ b/src/coreclr/ToolBox/superpmi/mcs/commandline.h @@ -23,6 +23,7 @@ public: , actionDumpMap(false) , actionDumpToc(false) , actionFracture(false) + , actionJitFlags(false) , actionILDump(false) , actionInteg(false) , actionMerge(false) @@ -51,6 +52,7 @@ public: 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 f8a007075bc..34313a577bb 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 00000000000..26379ce6771 --- /dev/null +++ b/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp @@ -0,0 +1,83 @@ +// +// 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 "spmidumphelper.h" + +int verbJitFlags::DoWork(const char* nameOfInput) +{ + MethodContextIterator mci; + if (!mci.Initialize(nameOfInput)) + return -1; + + LightWeightMap<unsigned long long, unsigned> flagMap; + unsigned mcCount = 0; + + 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); + } + + mcCount++; + } + + if (!mci.Destroy()) + return -1; + + 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* pFlags = flagMap.GetRawKeys(); + + for (unsigned int i = 0; i < count; i++) + { + const unsigned long long flags = *pFlags++; + const int index = flagMap.GetIndex(flags); + const unsigned appearances = flagMap.GetItem(index); + + printf("%016llx %8u %7.2f%% %s\n", flags, appearances, 100.0 * ((double) appearances / mcCount), SpmiDumpHelper::DumpJitFlags(flags).c_str()); + + for (unsigned int bit = 0; bit < 64; bit++) + { + if (flags & (1ull << bit)) + { + appearancesPerBit[bit] += appearances; + } + } + } + + 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<<bit).c_str()); + } + } + + 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 00000000000..495b0b84700 --- /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 summary of jit flags values +//---------------------------------------------------------- +#ifndef _verbJitFlags +#define _verbJitFlags + +class verbJitFlags +{ +public: + static int DoWork(const char* nameOfInput); +}; + +#endif diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp index ea545729b91..b2d8ac7fd36 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp @@ -206,3 +206,91 @@ std::string SpmiDumpHelper::DumpCorInfoFlag(CorInfoFlag flags) return s; } + +std::string SpmiDumpHelper::DumpJitFlags(CORJIT_FLAGS corJitFlags) +{ + return DumpJitFlags(corJitFlags.GetFlagsRaw()); +} + +std::string SpmiDumpHelper::DumpJitFlags(unsigned long long flags) +{ + std::string s(""); + +#define AddFlag(__name)\ + if (flags & (1ull << CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_ ## __name)) { \ + s += std::string(" ") + std::string(#__name); \ + flags &= ~(1ull << CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_ ## __name); } + + // Note some flags are target dependent, but we want to + // be target-agnostic. So we use numbers for the few + // flags that are not universally defined. + +#define AddFlagNumeric(__name, __val)\ + if (flags & (1ull << __val)) { \ + s += std::string(" ") + std::string(#__name); \ + flags &= ~(1ull <<__val); } + + AddFlag(SPEED_OPT); + AddFlag(SIZE_OPT); + AddFlag(DEBUG_CODE); + AddFlag(DEBUG_EnC); + AddFlag(DEBUG_INFO); + AddFlag(MIN_OPT); + + AddFlag(MCJIT_BACKGROUND); + + // x86 only + // + AddFlagNumeric(PINVOKE_RESTORE_ESP, 8); + AddFlagNumeric(TARGET_P4, 9); + AddFlagNumeric(USE_FCOMI, 10); + AddFlagNumeric(USE_CMOV, 11); + + AddFlag(OSR); + AddFlag(ALT_JIT); + + AddFlagNumeric(FEATURE_SIMD, 17); + + AddFlag(MAKEFINALCODE); + AddFlag(READYTORUN); + AddFlag(PROF_ENTERLEAVE); + + AddFlag(PROF_NO_PINVOKE_INLINE); + AddFlag(SKIP_VERIFICATION); + AddFlag(PREJIT); + AddFlag(RELOC); + AddFlag(IMPORT_ONLY); + AddFlag(IL_STUB); + AddFlag(PROCSPLIT); + AddFlag(BBINSTR); + AddFlag(BBOPT); + AddFlag(FRAMED); + + AddFlag(PUBLISH_SECRET_PARAM); + + AddFlag(SAMPLING_JIT_BACKGROUND); + AddFlag(USE_PINVOKE_HELPERS); + AddFlag(REVERSE_PINVOKE); + AddFlag(TRACK_TRANSITIONS); + AddFlag(TIER0); + AddFlag(TIER1); + + // arm32 only + // + AddFlagNumeric(RELATIVE_CODE_RELOCS, 41); + + AddFlag(NO_INLINING); + +#undef AddFlag +#undef AddFlagNumeric + + if (flags != 0) + { + char buffer[MAX_BUFFER_SIZE]; + sprintf_s(buffer, MAX_BUFFER_SIZE, " Unknown jit flags-%016llX", flags); + s += std::string(buffer); + } + + return s; +} + diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h b/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h index 977efc70c69..213d0baa381 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h +++ b/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h @@ -49,6 +49,9 @@ public: static std::string DumpCorInfoFlag(CorInfoFlag flags); + static std::string DumpJitFlags(CORJIT_FLAGS corJitFlags); + static std::string DumpJitFlags(unsigned long long rawFlags); + private: static void FormatAgnostic_CORINFO_SIG_INST_Element( |