From b8a6343623e73dc5fec894c065aeaa3fe0cfea69 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 13:41:21 +0100 Subject: [PATCH 01/23] JIT: Add a unified mechanism to track metadata/metrics about the compilation Adds a JIT-EE API to report metadata back to the EE side about the JIT compilation, and adds support for saving these metrics as part of SPMI runs. Switches a number of adhoc metrics to use this scheme. --- src/coreclr/inc/corinfo.h | 6 + src/coreclr/inc/icorjitinfoimpl_generated.h | 4 + src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/jit/CMakeLists.txt | 3 + src/coreclr/jit/ICorJitInfo_names_generated.h | 1 + .../jit/ICorJitInfo_wrapper_generated.hpp | 9 ++ src/coreclr/jit/codegencommon.cpp | 8 +- src/coreclr/jit/compiler.cpp | 41 +++-- src/coreclr/jit/compiler.h | 14 +- src/coreclr/jit/emit.cpp | 2 +- src/coreclr/jit/emitxarch.cpp | 4 +- src/coreclr/jit/fgbasic.cpp | 3 +- src/coreclr/jit/jitmetadata.cpp | 41 +++++ src/coreclr/jit/jitmetadata.h | 29 ++++ src/coreclr/jit/jitmetadatalist.h | 31 ++++ src/coreclr/jit/loopcloning.cpp | 8 +- src/coreclr/jit/lsra.cpp | 2 +- src/coreclr/jit/optimizer.cpp | 10 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 6 + .../JitInterface/CorInfoImpl_generated.cs | 153 ++++++++++-------- .../ThunkGenerator/ThunkInput.txt | 1 + .../aot/jitinterface/jitinterface_generated.h | 10 ++ .../superpmi-shared/compileresult.cpp | 2 + .../superpmi/superpmi-shared/compileresult.h | 11 ++ .../superpmi-shared/jitmetadatalist.h | 1 + .../superpmi-shim-collector/icorjitinfo.cpp | 6 + .../icorjitinfo_generated.cpp | 8 + .../icorjitinfo_generated.cpp | 7 + .../tools/superpmi/superpmi/fileio.cpp | 20 +++ src/coreclr/tools/superpmi/superpmi/fileio.h | 4 + .../tools/superpmi/superpmi/icorjitinfo.cpp | 33 ++++ .../tools/superpmi/superpmi/jitinstance.cpp | 1 + .../tools/superpmi/superpmi/jitinstance.h | 1 + .../tools/superpmi/superpmi/superpmi.cpp | 55 ++++++- src/coreclr/vm/jitinterface.cpp | 21 +++ src/coreclr/vm/jitinterface.h | 2 + 36 files changed, 437 insertions(+), 131 deletions(-) create mode 100644 src/coreclr/jit/jitmetadata.cpp create mode 100644 src/coreclr/jit/jitmetadata.h create mode 100644 src/coreclr/jit/jitmetadatalist.h create mode 100644 src/coreclr/tools/superpmi/superpmi-shared/jitmetadatalist.h diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 86680d6e20c91e..ac83351a8da30e 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2916,6 +2916,12 @@ class ICorStaticInfo uint32_t numMappings // [IN] Number of rich mappings ) = 0; + // Report back some metadata about the compilation to the EE -- for + // example, metrics about the compilation. + virtual void reportMetadata( + const char* key, + const void* value) = 0; + /*-------------------------- Misc ---------------------------------------*/ // Used to allocate memory that needs to handed to the EE. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 8dd993f5b47829..8a14cdb0f99f1e 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -438,6 +438,10 @@ void reportRichMappings( ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings) override; +void reportMetadata( + const char* key, + const void* value) override; + void* allocateArray( size_t cBytes) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 6355fc20dd0fd5..646f1b169330a2 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 0fb71692-0ee6-4914-88a8-6446e45f23e8 */ - 0x0fb71692, - 0x0ee6, - 0x4914, - {0x88, 0xa8, 0x64, 0x46, 0xe4, 0x5f, 0x23, 0xe8} +constexpr GUID JITEEVersionIdentifier = { /* 1f30d12b-38f1-4f1e-a08a-831def882aa4 */ + 0x1f30d12b, + 0x38f1, + 0x4f1e, + {0xa0, 0x8a, 0x83, 0x1d, 0xef, 0x88, 0x2a, 0xa4} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index aa660321075890..ae08a27e4c00aa 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -137,6 +137,7 @@ set( JIT_SOURCES jitconfig.cpp jiteh.cpp jithashtable.cpp + jitmetadata.cpp lclmorph.cpp lclvars.cpp likelyclass.cpp @@ -334,6 +335,8 @@ set( JIT_HEADERS jitexpandarray.h jitgcinfo.h jithashtable.h + jitmetadata.h + jitmetadatalist.h jitpch.h jitstd.h lir.h diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index 5fe1f716d474b8..3908d4bcdc4be2 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -108,6 +108,7 @@ DEF_CLR_API(setBoundaries) DEF_CLR_API(getVars) DEF_CLR_API(setVars) DEF_CLR_API(reportRichMappings) +DEF_CLR_API(reportMetadata) DEF_CLR_API(allocateArray) DEF_CLR_API(freeArray) DEF_CLR_API(getArgNext) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index cae9b5d7b39e59..cb4442df3810cd 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -1028,6 +1028,15 @@ void WrapICorJitInfo::reportRichMappings( API_LEAVE(reportRichMappings); } +void WrapICorJitInfo::reportMetadata( + const char* key, + const void* value) +{ + API_ENTER(reportMetadata); + wrapHnd->reportMetadata(key, value); + API_LEAVE(reportMetadata); +} + void* WrapICorJitInfo::allocateArray( size_t cBytes) { diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 825837fe45ef50..29b911f3160e5b 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -315,10 +315,8 @@ void CodeGen::genPrepForCompiler() } } VarSetOps::AssignNoCopy(compiler, genLastLiveSet, VarSetOps::MakeEmpty(compiler)); - genLastLiveMask = RBM_NONE; -#ifdef DEBUG - compiler->fgBBcountAtCodegen = compiler->fgBBcount; -#endif + genLastLiveMask = RBM_NONE; + compiler->Metrics.BasicBlocksAtCodegen = compiler->fgBBcount; } //------------------------------------------------------------------------ @@ -2042,7 +2040,7 @@ void CodeGen::genEmitMachineCode() printf("; Total bytes of code %d, prolog size %d, PerfScore %.2f, instruction count %d, allocated bytes for " "code %d", - codeSize, prologSize, compiler->info.compPerfScore, instrCount, + codeSize, prologSize, compiler->Metrics.PerfScore, instrCount, GetEmitter()->emitTotalHotCodeSize + GetEmitter()->emitTotalColdCodeSize); if (dspMetrics) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index c351419687fbf3..8363c1eeb7575d 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1793,9 +1793,10 @@ void Compiler::compInit(ArenaAllocator* pAlloc, info.compMethodName = eeGetMethodName(methodHnd); info.compClassName = eeGetClassName(info.compClassHnd); info.compFullName = eeGetMethodFullName(methodHnd); - info.compPerfScore = 0.0; info.compMethodSuperPMIIndex = g_jitHost->getIntConfigValue(W("SuperPMIMethodContextNumber"), -1); + + JitMetadata::report(this, JitMetadataName::MethodFullName, info.compFullName); #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS #if defined(DEBUG) @@ -1860,11 +1861,9 @@ void Compiler::compInit(ArenaAllocator* pAlloc, lvMemoryPerSsaData = SsaDefArray(); - // - // Initialize all the per-method statistics gathering data structures. - // - - optLoopsCloned = 0; +// +// Initialize all the per-method statistics gathering data structures. +// #if LOOP_HOIST_STATS m_loopsConsidered = 0; @@ -1965,6 +1964,8 @@ void Compiler::compInit(ArenaAllocator* pAlloc, compUsesThrowHelper = false; m_preferredInitCctor = CORINFO_HELP_UNDEF; + + new (&Metrics, jitstd::placement_t()) JitMetrics(); } /***************************************************************************** @@ -5212,7 +5213,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl #ifdef DEBUG if (JitConfig.JitMetrics() > 0) { - sprintf_s(metricPart, 128, ", perfScore=%.2f, numCse=%u", info.compPerfScore, optCSEcount); + sprintf_s(metricPart, 128, ", perfScore=%.2f, numCse=%u", Metrics.PerfScore, optCSEcount); } #endif @@ -5222,6 +5223,8 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl info.compILCodeSize, *methodCodeSize, debugPart, metricPart); } + INDEBUG(Metrics.report(this)); + compFunctionTraceEnd(*methodCodePtr, *methodCodeSize, false); JITDUMP("Method code size: %d\n", (unsigned)(*methodCodeSize)); @@ -5416,7 +5419,7 @@ PhaseStatus Compiler::placeLoopAlignInstructions() { block->SetFlags(BBF_LOOP_ALIGN); BitVecOps::AddElemD(&loopTraits, alignedLoops, loop->GetIndex()); - INDEBUG(loopAlignCandidates++); + Metrics.LoopAlignmentCandidates++; BasicBlock* prev = block->Prev(); // shouldAlignLoop should have guaranteed these properties. @@ -5465,7 +5468,7 @@ PhaseStatus Compiler::placeLoopAlignInstructions() } } - JITDUMP("Found %u candidates for loop alignment\n", loopAlignCandidates); + JITDUMP("Found %d candidates for loop alignment\n", Metrics.LoopAlignmentCandidates); return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -6438,6 +6441,8 @@ void Compiler::compCompileFinish() compArenaAllocator->finishMemStats(); memAllocHist.record((unsigned)((compArenaAllocator->getTotalBytesAllocated() + 1023) / 1024)); memUsedHist.record((unsigned)((compArenaAllocator->getTotalBytesUsed() + 1023) / 1024)); + + Metrics.BytesAllocated = (int64_t)compArenaAllocator->getTotalBytesUsed(); } #ifdef DEBUG @@ -6621,7 +6626,7 @@ void Compiler::compCompileFinish() printf(" %3d |", optCallCount); printf(" %3d |", optIndirectCallCount); - printf(" %3d |", fgBBcountAtCodegen); + printf(" %3d |", Metrics.BasicBlocksAtCodegen); printf(" %3d |", lvaCount); if (opts.MinOpts()) @@ -6634,13 +6639,13 @@ void Compiler::compCompileFinish() printf(" %3d |", optCSEcount); } - if (info.compPerfScore < 9999.995) + if (Metrics.PerfScore < 9999.995) { - printf(" %7.2f |", info.compPerfScore); + printf(" %7.2f |", Metrics.PerfScore); } else { - printf(" %7.0f |", info.compPerfScore); + printf(" %7.0f |", Metrics.PerfScore); } printf(" %4d |", info.compMethodInfo->ILCodeSize); @@ -7146,6 +7151,8 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, opts.disAsm = false; } + INDEBUG(JitMetadata::report(this, JitMetadataName::TieringName, compGetTieringName(true))); + #if COUNT_BASIC_BLOCKS bbCntTable.record(fgBBcount); @@ -9074,12 +9081,12 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) fprintf(s_csvFile, "%u,", comp->info.compILCodeSize); fprintf(s_csvFile, "%u,", comp->fgBBcount); fprintf(s_csvFile, "%u,", comp->opts.MinOpts()); - fprintf(s_csvFile, "%u,", comp->optNumNaturalLoopsFound); - fprintf(s_csvFile, "%u,", comp->optLoopsCloned); + fprintf(s_csvFile, "%d,", comp->Metrics.LoopsFoundDuringOpts); + fprintf(s_csvFile, "%d,", comp->Metrics.LoopsCloned); #if FEATURE_LOOP_ALIGN #ifdef DEBUG - fprintf(s_csvFile, "%u,", comp->loopAlignCandidates); - fprintf(s_csvFile, "%u,", comp->loopsAligned); + fprintf(s_csvFile, "%d,", comp->Metrics.LoopAlignmentCandidates); + fprintf(s_csvFile, "%d,", comp->Metrics.LoopsAligned); #endif // DEBUG #endif // FEATURE_LOOP_ALIGN unsigned __int64 totCycles = 0; diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index a18fee959436b4..eff322512c6c41 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -65,6 +65,8 @@ inline var_types genActualType(T value); #include "simd.h" #include "simdashwintrinsic.h" +#include "jitmetadata.h" + /***************************************************************************** * Forward declarations */ @@ -4960,7 +4962,6 @@ class Compiler unsigned fgEdgeCount; // # of control flow edges between the BBs unsigned fgBBcount; // # of BBs in the method (in the linked list that starts with fgFirstBB) #ifdef DEBUG - unsigned fgBBcountAtCodegen; // # of BBs in the method at the start of codegen jitstd::vector* fgBBOrder; // ordered vector of BBs #endif // Used as a quick check for whether loop alignment should look for natural loops. @@ -4989,7 +4990,6 @@ class Compiler // 2. All loop exits where bbIsHandlerBeg(exit) is false have only loop predecessors. // bool optLoopsCanonical; - unsigned optNumNaturalLoopsFound; // Number of natural loops found in the loop finding phase bool fgBBVarSetsInited; @@ -6828,16 +6828,11 @@ class Compiler public: bool fgHasLoops; -#ifdef DEBUG - unsigned loopAlignCandidates; // number of candidates identified by placeLoopAlignInstructions - unsigned loopsAligned; // number of loops actually aligned -#endif // DEBUG protected: unsigned optCallCount; // number of calls made in the method unsigned optIndirectCallCount; // number of virtual, interface and indirect calls made in the method unsigned optNativeCallCount; // number of Pinvoke/Native calls made in the method - unsigned optLoopsCloned; // number of loops cloned in the current method. #ifdef DEBUG void optCheckPreds(); @@ -10142,7 +10137,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX const char* compMethodName; const char* compClassName; const char* compFullName; - double compPerfScore; int compMethodSuperPMIIndex; // useful when debugging under SuperPMI #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS @@ -10981,7 +10975,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // test attributes are satisfied. void JitTestCheckSSA(); // SSA builder tests. void JitTestCheckVN(); // Value numbering tests. -#endif // DEBUG + + JitMetrics Metrics; +#endif // DEBUG FieldSeqStore* m_fieldSeqStore; diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index d3ac84e7919a1d..ecbfe659be1034 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -4393,7 +4393,7 @@ size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp) float insExeCost = insEvaluateExecutionCost(id); // All compPerfScore calculations must be performed using doubles double insPerfScore = (double)(ig->igWeight / (double)BB_UNITY_WEIGHT) * insExeCost; - emitComp->info.compPerfScore += insPerfScore; + emitComp->Metrics.PerfScore += insPerfScore; ig->igPerfScore += insPerfScore; #endif // defined(DEBUG) || defined(LATE_DISASM) diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 9e80da3bfaf9ab..d429f0d261f7a2 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -12475,10 +12475,10 @@ BYTE* emitter::emitOutputAlign(insGroup* ig, instrDesc* id, BYTE* dst) assert(paddingToAdd == paddingNeeded); } } - - emitComp->loopsAligned++; #endif + emitComp->Metrics.LoopsAligned++; + #ifdef DEBUG // Under STRESS_EMITTER, if this is the 'align' before the 'jmp' instruction, // then add "int3" instruction. Since int3 takes 1 byte, we would only add diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 9ba1d20cd4bd6b..ef876477cc5a64 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -49,8 +49,7 @@ void Compiler::fgInit() fgBBcount = 0; #ifdef DEBUG - fgBBcountAtCodegen = 0; - fgBBOrder = nullptr; + fgBBOrder = nullptr; #endif // DEBUG fgMightHaveNaturalLoops = false; diff --git a/src/coreclr/jit/jitmetadata.cpp b/src/coreclr/jit/jitmetadata.cpp new file mode 100644 index 00000000000000..917c7c54f67cd5 --- /dev/null +++ b/src/coreclr/jit/jitmetadata.cpp @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "jitpch.h" +#include "jitmetadata.h" + +#ifdef DEBUG + +const char* JitMetadata::getName(JitMetadataName name) +{ + switch (name) + { +#define JITMETADATA(name, type, flags) \ + case JitMetadataName::name: \ + return #name; +#include "jitmetadatalist.h" + + default: + unreached(); + } +} + +void JitMetadata::report(Compiler* comp, JitMetadataName name, const void* data) +{ + comp->info.compCompHnd->reportMetadata(getName(name), data); +} + +template +static void reportValue(Compiler* comp, const char* key, T value) +{ + comp->info.compCompHnd->reportMetadata(key, &value); +} + +void JitMetrics::report(Compiler* comp) +{ +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) reportValue(comp, #name, name); +#include "jitmetadatalist.h" +} + +#endif diff --git a/src/coreclr/jit/jitmetadata.h b/src/coreclr/jit/jitmetadata.h new file mode 100644 index 00000000000000..c713582fac5484 --- /dev/null +++ b/src/coreclr/jit/jitmetadata.h @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +class Compiler; + +enum class JitMetadataName +{ +#define JITMETADATA(name, type, flags) name, +#include "jitmetadatalist.h" +}; + +class JitMetadata +{ +public: + static const char* getName(JitMetadataName name); + static void report(Compiler* comp, JitMetadataName name, const void* data); +}; + +class JitMetrics +{ +public: +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) type name = 0; +#include "jitmetadatalist.h" + + void report(Compiler* comp); +}; diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h new file mode 100644 index 00000000000000..23a6940b770cab --- /dev/null +++ b/src/coreclr/jit/jitmetadatalist.h @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// clang-format off + +#ifdef JITMETADATA +#define JITMETADATAINFO(name, type, flags) JITMETADATA(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) JITMETADATA(name, type, flags) +#endif + +#if !defined(JITMETADATAINFO) || !defined(JITMETADATAMETRIC) +#error Define JITMETADATAINFO and JITMETADATAMETRIC before including this file. +#endif + +// Name, type flags +JITMETADATAINFO(MethodFullName, const char*, 0) +JITMETADATAINFO(TieringName, const char*, 0) +JITMETADATAINFO(MethodOptimized, bool, 0) +JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) +JITMETADATAMETRIC(LoopsCloned, int, 0) +JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) +JITMETADATAMETRIC(LoopsAligned, int, 0) +JITMETADATAMETRIC(BytesAllocated, int64_t, 0) +JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) + +#undef JITMETADATA +#undef JITMETADATAINFO +#undef JITMETADATAMETRIC + +// clang-format on diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index ca4c2572fa41d9..96cd8bff015939 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -2955,19 +2955,19 @@ PhaseStatus Compiler::optCloneLoops() #endif #endif - assert(optLoopsCloned == 0); // It should be initialized, but not yet changed. + assert(Metrics.LoopsCloned == 0); // It should be initialized, but not yet changed. for (FlowGraphNaturalLoop* loop : m_loops->InReversePostOrder()) { if (context.GetLoopOptInfo(loop->GetIndex()) != nullptr) { - optLoopsCloned++; + Metrics.LoopsCloned++; context.OptimizeConditions(loop->GetIndex() DEBUGARG(verbose)); context.OptimizeBlockConditions(loop->GetIndex() DEBUGARG(verbose)); optCloneLoop(loop, &context); } } - if (optLoopsCloned > 0) + if (Metrics.LoopsCloned > 0) { fgInvalidateDfsTree(); m_dfsTree = fgComputeDfs(); @@ -2986,7 +2986,7 @@ PhaseStatus Compiler::optCloneLoops() #ifdef DEBUG if (verbose) { - printf("Loops cloned: %d\n", optLoopsCloned); + printf("Loops cloned: %d\n", Metrics.LoopsCloned); printf("Loops statically optimized: %d\n", optStaticallyOptimizedLoops); printf("After loop cloning:\n"); fgDispBasicBlocks(/*dumpTrees*/ true); diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 04ca6149c9fc36..9ca1d59ed7a5e2 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -10096,7 +10096,7 @@ void LinearScan::dumpLsraStatsCsv(FILE* file) { fprintf(file, ",%u", sumStats[statIndex]); } - fprintf(file, ",%.2f\n", compiler->info.compPerfScore); + fprintf(file, ",%.2f\n", compiler->Metrics.PerfScore); } // ----------------------------------------------------------- diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index c1362b987aab73..c70ba9b0273ec1 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -21,13 +21,7 @@ void Compiler::optInit() { fgHasLoops = false; - optLoopsCanonical = false; - optNumNaturalLoopsFound = 0; - -#ifdef DEBUG - loopAlignCandidates = 0; - loopsAligned = 0; -#endif + optLoopsCanonical = false; /* Keep track of the number of calls and indirect calls made by this method */ optCallCount = 0; @@ -2668,7 +2662,7 @@ PhaseStatus Compiler::optFindLoopsPhase() optFindAndScaleGeneralLoopBlocks(); } - optNumNaturalLoopsFound = (unsigned)m_loops->NumLoops(); + Metrics.LoopsFoundDuringOpts = (int)m_loops->NumLoops(); return PhaseStatus::MODIFIED_EVERYTHING; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 2e72a18def7713..d1bd90f1688f4c 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3156,6 +3156,12 @@ private void reportRichMappings(InlineTreeNode* inlineTree, uint numInlineTree, Marshal.FreeHGlobal((IntPtr)mappings); } +#pragma warning disable CA1822 // Mark members as static + private void reportMetadata(byte* key, void* value) +#pragma warning restore CA1822 // Mark members as static + { + } + #pragma warning disable CA1822 // Mark members as static private void* allocateArray(UIntPtr cBytes) #pragma warning restore CA1822 // Mark members as static diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 13844628bb8639..2e4e617b40b9b7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1547,6 +1547,20 @@ private static void _reportRichMappings(IntPtr thisHandle, IntPtr* ppException, } } + [UnmanagedCallersOnly] + private static void _reportMetadata(IntPtr thisHandle, IntPtr* ppException, byte* key, void* value) + { + var _this = GetThis(thisHandle); + try + { + _this.reportMetadata(key, value); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + } + } + [UnmanagedCallersOnly] private static void* _allocateArray(IntPtr thisHandle, IntPtr* ppException, UIntPtr cBytes) { @@ -2551,7 +2565,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 172); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2657,74 +2671,75 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[101] = (delegate* unmanaged)&_getVars; callbacks[102] = (delegate* unmanaged)&_setVars; callbacks[103] = (delegate* unmanaged)&_reportRichMappings; - callbacks[104] = (delegate* unmanaged)&_allocateArray; - callbacks[105] = (delegate* unmanaged)&_freeArray; - callbacks[106] = (delegate* unmanaged)&_getArgNext; - callbacks[107] = (delegate* unmanaged)&_getArgType; - callbacks[108] = (delegate* unmanaged)&_getExactClasses; - callbacks[109] = (delegate* unmanaged)&_getArgClass; - callbacks[110] = (delegate* unmanaged)&_getHFAType; - callbacks[111] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[112] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[113] = (delegate* unmanaged)&_getEEInfo; - callbacks[114] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[115] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[116] = (delegate* unmanaged)&_printMethodName; - callbacks[117] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[118] = (delegate* unmanaged)&_getMethodHash; - callbacks[119] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[120] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[121] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; - callbacks[122] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[123] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[124] = (delegate* unmanaged)&_getHelperFtn; - callbacks[125] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[126] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[127] = (delegate* unmanaged)&_getMethodSync; - callbacks[128] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[129] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[130] = (delegate* unmanaged)&_embedClassHandle; - callbacks[131] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[132] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[133] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[134] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[135] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[136] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[137] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[138] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[139] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[140] = (delegate* unmanaged)&_getCallInfo; - callbacks[141] = (delegate* unmanaged)&_getClassDomainID; - callbacks[142] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[143] = (delegate* unmanaged)&_getObjectContent; - callbacks[144] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[145] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[146] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[147] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[148] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[149] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[150] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[151] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[152] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[153] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[154] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[155] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[156] = (delegate* unmanaged)&_allocMem; - callbacks[157] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[158] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[159] = (delegate* unmanaged)&_allocGCInfo; - callbacks[160] = (delegate* unmanaged)&_setEHcount; - callbacks[161] = (delegate* unmanaged)&_setEHinfo; - callbacks[162] = (delegate* unmanaged)&_logMsg; - callbacks[163] = (delegate* unmanaged)&_doAssert; - callbacks[164] = (delegate* unmanaged)&_reportFatalError; - callbacks[165] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[166] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[167] = (delegate* unmanaged)&_recordCallSite; - callbacks[168] = (delegate* unmanaged)&_recordRelocation; - callbacks[169] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[170] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[171] = (delegate* unmanaged)&_getJitFlags; + callbacks[104] = (delegate* unmanaged)&_reportMetadata; + callbacks[105] = (delegate* unmanaged)&_allocateArray; + callbacks[106] = (delegate* unmanaged)&_freeArray; + callbacks[107] = (delegate* unmanaged)&_getArgNext; + callbacks[108] = (delegate* unmanaged)&_getArgType; + callbacks[109] = (delegate* unmanaged)&_getExactClasses; + callbacks[110] = (delegate* unmanaged)&_getArgClass; + callbacks[111] = (delegate* unmanaged)&_getHFAType; + callbacks[112] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[113] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[114] = (delegate* unmanaged)&_getEEInfo; + callbacks[115] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[116] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[117] = (delegate* unmanaged)&_printMethodName; + callbacks[118] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[119] = (delegate* unmanaged)&_getMethodHash; + callbacks[120] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[121] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[122] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; + callbacks[123] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[124] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[125] = (delegate* unmanaged)&_getHelperFtn; + callbacks[126] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[127] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[128] = (delegate* unmanaged)&_getMethodSync; + callbacks[129] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[130] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[131] = (delegate* unmanaged)&_embedClassHandle; + callbacks[132] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[133] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[134] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[135] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[136] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[137] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[138] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[139] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[140] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[141] = (delegate* unmanaged)&_getCallInfo; + callbacks[142] = (delegate* unmanaged)&_getClassDomainID; + callbacks[143] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[144] = (delegate* unmanaged)&_getObjectContent; + callbacks[145] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[146] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[147] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[148] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[149] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[150] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[151] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[152] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[153] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[154] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[155] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[156] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[157] = (delegate* unmanaged)&_allocMem; + callbacks[158] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[159] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[160] = (delegate* unmanaged)&_allocGCInfo; + callbacks[161] = (delegate* unmanaged)&_setEHcount; + callbacks[162] = (delegate* unmanaged)&_setEHinfo; + callbacks[163] = (delegate* unmanaged)&_logMsg; + callbacks[164] = (delegate* unmanaged)&_doAssert; + callbacks[165] = (delegate* unmanaged)&_reportFatalError; + callbacks[166] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[167] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[168] = (delegate* unmanaged)&_recordCallSite; + callbacks[169] = (delegate* unmanaged)&_recordRelocation; + callbacks[170] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[171] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[172] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 3407e4e3a87c9a..4b7a3589abdf72 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -266,6 +266,7 @@ FUNCTIONS void getVars(CORINFO_METHOD_HANDLE ftn, uint32_t* cVars, ICorDebugInfo::ILVarInfo** vars, bool* extendOthers) void setVars(CORINFO_METHOD_HANDLE ftn, uint32_t cVars, ICorDebugInfo::NativeVarInfo* vars) void reportRichMappings(ICorDebugInfo::InlineTreeNode* inlineTreeNodes, uint32_t numInlineTreeNodes, ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings) + void reportMetadata(const char* key, const void* value) void*allocateArray(size_t cBytes); void freeArray(void*array); CORINFO_ARG_LIST_HANDLE getArgNext(CORINFO_ARG_LIST_HANDLE args); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 5d659488b29257..6b17b4a552ffde 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -115,6 +115,7 @@ struct JitInterfaceCallbacks void (* getVars)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, uint32_t* cVars, ICorDebugInfo::ILVarInfo** vars, bool* extendOthers); void (* setVars)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, uint32_t cVars, ICorDebugInfo::NativeVarInfo* vars); void (* reportRichMappings)(void * thisHandle, CorInfoExceptionClass** ppException, ICorDebugInfo::InlineTreeNode* inlineTreeNodes, uint32_t numInlineTreeNodes, ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings); + void (* reportMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, const char* key, const void* value); void* (* allocateArray)(void * thisHandle, CorInfoExceptionClass** ppException, size_t cBytes); void (* freeArray)(void * thisHandle, CorInfoExceptionClass** ppException, void* array); CORINFO_ARG_LIST_HANDLE (* getArgNext)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_ARG_LIST_HANDLE args); @@ -1214,6 +1215,15 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; } + virtual void reportMetadata( + const char* key, + const void* value) +{ + CorInfoExceptionClass* pException = nullptr; + _callbacks->reportMetadata(_thisHandle, &pException, key, value); + if (pException != nullptr) throw pException; +} + virtual void* allocateArray( size_t cBytes) { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp index 3c6653c41a1c3a..29dc4738ec2b27 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp @@ -32,6 +32,8 @@ CompileResult::CompileResult() allocGCInfoDets.retval = nullptr; allocGCInfoDets.size = 0; + MethodFullName = nullptr; + MethodName = nullptr; memoryTracker = nullptr; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h index b7be4dcd89279e..aecbd39db1f3e7 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h @@ -121,6 +121,8 @@ class CompileResult void dmpSetVars(DWORD key, const Agnostic_SetVars& value); bool repSetVars(CORINFO_METHOD_HANDLE* ftn, ULONG32* cVars, ICorDebugInfo::NativeVarInfo** vars); + void recMetadata(const char* key, const void* value); + void recSetPatchpointInfo(PatchpointInfo* patchpointInfo); void dmpSetPatchpointInfo(DWORD key, const Agnostic_SetPatchpointInfo& value); bool repSetPatchpointInfo(PatchpointInfo** patchpointInfo); @@ -215,6 +217,15 @@ class CompileResult #define DENSELWM(map, value) DenseLightWeightMap* map; #include "crlwmlist.h" +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) type name; +#include "jitmetadatalist.h" + + // Reported method name from JIT (not available with release JIT) + const char* MethodName; + // Reported method full name from JIT (not available with release JIT) + const char* MethodFullName; + // not persisted to disk. public: LightWeightMap* CallTargetTypes; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/jitmetadatalist.h b/src/coreclr/tools/superpmi/superpmi-shared/jitmetadatalist.h new file mode 100644 index 00000000000000..f43f4300d73a1a --- /dev/null +++ b/src/coreclr/tools/superpmi/superpmi-shared/jitmetadatalist.h @@ -0,0 +1 @@ +#include "../../../jit/jitmetadatalist.h" diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 47c50535e450f1..5d95ff65b6950a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1193,6 +1193,12 @@ void interceptor_ICJI::reportRichMappings(ICorDebugInfo::InlineTreeNode* inli original_ICorJitInfo->reportRichMappings(inlineTreeNodes, numInlineTreeNodes, mappings, numMappings); } +void interceptor_ICJI::reportMetadata(const char* key, const void* value) +{ + mc->cr->AddCall("reportMetadata"); + original_ICorJitInfo->reportMetadata(key, value); +} + /*-------------------------- Misc ---------------------------------------*/ // Used to allocate memory that needs to handed to the EE. // For eg, use this to allocated memory for reporting debug info, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 0f69dfae4a08c6..ed2dd8c79c4194 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -845,6 +845,14 @@ void interceptor_ICJI::reportRichMappings( original_ICorJitInfo->reportRichMappings(inlineTreeNodes, numInlineTreeNodes, mappings, numMappings); } +void interceptor_ICJI::reportMetadata( + const char* key, + const void* value) +{ + mcs->AddCall("reportMetadata"); + original_ICorJitInfo->reportMetadata(key, value); +} + void* interceptor_ICJI::allocateArray( size_t cBytes) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 02bef7b549aca0..6242fb8b055ed7 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -741,6 +741,13 @@ void interceptor_ICJI::reportRichMappings( original_ICorJitInfo->reportRichMappings(inlineTreeNodes, numInlineTreeNodes, mappings, numMappings); } +void interceptor_ICJI::reportMetadata( + const char* key, + const void* value) +{ + original_ICorJitInfo->reportMetadata(key, value); +} + void* interceptor_ICJI::allocateArray( size_t cBytes) { diff --git a/src/coreclr/tools/superpmi/superpmi/fileio.cpp b/src/coreclr/tools/superpmi/superpmi/fileio.cpp index ed16485a038e8a..5fe03666208339 100644 --- a/src/coreclr/tools/superpmi/superpmi/fileio.cpp +++ b/src/coreclr/tools/superpmi/superpmi/fileio.cpp @@ -41,6 +41,26 @@ bool FileWriter::Printf(const char* fmt, ...) } } +bool FileWriter::Print(const char* value) +{ + return Printf("%s", value); +} + +bool FileWriter::Print(int value) +{ + return Printf("%d", value); +} + +bool FileWriter::Print(int64_t value) +{ + return Printf("%lld", value); +} + +bool FileWriter::Print(double value) +{ + return Printf("%f", value); +} + bool FileWriter::CreateNew(const char* path, FileWriter* fw) { FileHandle handle(CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); diff --git a/src/coreclr/tools/superpmi/superpmi/fileio.h b/src/coreclr/tools/superpmi/superpmi/fileio.h index a88e74d6ee00c5..16ceaf87bd6148 100644 --- a/src/coreclr/tools/superpmi/superpmi/fileio.h +++ b/src/coreclr/tools/superpmi/superpmi/fileio.h @@ -94,6 +94,10 @@ class FileWriter } bool Printf(const char* fmt, ...); + bool Print(const char* value); + bool Print(int value); + bool Print(int64_t value); + bool Print(double value); static bool CreateNew(const char* path, FileWriter* fw); }; diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 15c17173abdda4..c2fdb967d67ca7 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1027,6 +1027,39 @@ void MyICJI::reportRichMappings( freeArray(mappings); } +void MyICJI::reportMetadata(const char* key, const void* value) +{ + jitInstance->mc->cr->AddCall("reportMetadata"); + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) \ + if (strcmp(key, #name) == 0) \ + { \ + memcpy(&jitInstance->mc->cr->##name, value, sizeof(type)); \ + return; \ + } + + if (strcmp(key, "MethodFullName") == 0) + { + const char* str = static_cast(value); + size_t len = strlen(str); + char* buf = static_cast(jitInstance->mc->cr->allocateMemory(len + 1)); + memcpy(buf, str, len + 1); + jitInstance->mc->cr->MethodFullName = buf; + return; + } + + if (strcmp(key, "MethodName") == 0) + { + const char* str = static_cast(value); + size_t len = strlen(str); + char* buf = static_cast(jitInstance->mc->cr->allocateMemory(len + 1)); + memcpy(buf, str, len + 1); + jitInstance->mc->cr->MethodName = buf; + return; + } +} + /*-------------------------- Misc ---------------------------------------*/ // Used to allocate memory that needs to handed to the EE. diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp index 7c55db51af20cf..93191588cc00c3 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp @@ -411,6 +411,7 @@ ReplayResults JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcI pParam->pThis->mc->cr->recMessageLog(jitResult == CORJIT_OK ? "Successful Compile" : "Successful Compile (BADCODE)"); pParam->results.NumCodeBytes = NCodeSizeBlock; + pParam->results.CompileResults = pParam->pThis->mc->cr; } else { diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.h b/src/coreclr/tools/superpmi/superpmi/jitinstance.h index 03e283c1d5b62d..b13fe46d641f40 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.h +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.h @@ -22,6 +22,7 @@ struct ReplayResults bool IsMinOpts = false; uint32_t NumCodeBytes = 0; uint64_t NumExecutedInstructions = 0; + CompileResult* CompileResults = nullptr; }; class JitInstance diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index 4ac03d18ce9a6d..792ad0c9d0cd11 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -137,42 +137,81 @@ static const char* ResultToString(ReplayResult result) } } -static bool PrintDiffsCsvHeader(FileWriter& fw) +static void PrintDiffsCsvHeader(FileWriter& fw) { - return fw.Printf("Context,Context size,Base result,Diff result,MinOpts,Has diff,Base size,Diff size,Base instructions,Diff instructions\n"); + fw.Print("Context,Context size,Method name,Method full name,Base result,Diff result,MinOpts,Has diff,Base size,Diff size,Base instructions,Diff instructions"); + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) fw.Print(",Base " #name ",Diff " #name); + +#include "jitmetadatalist.h" + + fw.Print("%s\n"); } -static bool PrintDiffsCsvRow( +static void PrintDiffsCsvRow( FileWriter& fw, int context, uint32_t contextSize, const ReplayResults& baseRes, const ReplayResults& diffRes, bool hasDiff) { - return fw.Printf("%d,%u,%s,%s,%s,%s,%u,%u,%lld,%lld\n", + fw.Printf( + "%d,%u,\"%s\",\"%s\",%s,%s,%s,%s,%u,%u,%lld,%lld", context, contextSize, + baseRes.CompileResults->MethodName == nullptr ? "" : baseRes.CompileResults->MethodName, + baseRes.CompileResults->MethodFullName == nullptr ? "" : baseRes.CompileResults->MethodFullName, ResultToString(baseRes.Result), ResultToString(diffRes.Result), baseRes.IsMinOpts ? "True" : "False", hasDiff ? "True" : "False", baseRes.NumCodeBytes, diffRes.NumCodeBytes, baseRes.NumExecutedInstructions, diffRes.NumExecutedInstructions); + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) \ + fw.Print(","); \ + fw.Print(baseRes.CompileResults->##name); \ + fw.Print(","); \ + fw.Print(diffRes.CompileResults->##name); + +#include "jitmetadatalist.h" + + fw.Print("\n"); } -static bool PrintReplayCsvHeader(FileWriter& fw) +static void PrintReplayCsvHeader(FileWriter& fw) { - return fw.Printf("Context,Context size,Result,MinOpts,Size,Instructions\n"); + fw.Printf("Context,Context size,Method name,Method full name,Result,MinOpts,Size,Instructions\n"); + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) fw.Print("," #name); + +#include "jitmetadatalist.h" + + fw.Print("\n"); } -static bool PrintReplayCsvRow( +static void PrintReplayCsvRow( FileWriter& fw, int context, uint32_t contextSize, const ReplayResults& res) { - return fw.Printf("%d,%u,%s,%s,%u,%lld\n", + fw.Printf("%d,%u,\"%s\",\"%s\",%s,%s,%s,%s,%u,%lld", context, contextSize, + res.CompileResults->MethodName == nullptr ? "" : res.CompileResults->MethodName, + res.CompileResults->MethodFullName == nullptr ? "" : res.CompileResults->MethodFullName, ResultToString(res.Result), res.IsMinOpts ? "True" : "False", res.NumCodeBytes, res.NumExecutedInstructions); + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) \ + fw.Print(","); \ + fw.Print(res.CompileResults->##name); + +#include "jitmetadatalist.h" + + fw.Print("\n"); } // Run superpmi. The return value is as follows: diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 62d69c0fe4ef98..c6031ee224577f 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10956,6 +10956,21 @@ void CEEJitInfo::reportRichMappings( EE_TO_JIT_TRANSITION(); } +void CEEJitInfo::reportMetadata( + const char* key, + const void* value) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + JIT_TO_EE_TRANSITION_LEAF(); + + EE_TO_JIT_TRANSITION_LEAF(); +} + void CEEJitInfo::setPatchpointInfo(PatchpointInfo* patchpointInfo) { CONTRACTL { @@ -14421,6 +14436,12 @@ void CEEInfo::reportRichMappings( UNREACHABLE(); // only called on derived class. } +void CEEInfo::reportMetadata(const char* key, const void* value) +{ + LIMITED_METHOD_CONTRACT; + UNREACHABLE(); // only called on derived class. +} + void CEEInfo::setPatchpointInfo(PatchpointInfo* patchpointInfo) { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 1708a05df5e314..277f39e8a80eac 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -897,6 +897,8 @@ class CEEJitInfo : public CEEInfo ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings) override final; + void reportMetadata(const char* key, const void* value) override final; + void* getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ void ** ppIndirection) override final; /* OUT */ static PCODE getHelperFtnStatic(CorInfoHelpFunc ftnNum); From 6e3cf3ea4bd21d9a74aa629635d656501a27f523 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 14:20:26 +0100 Subject: [PATCH 02/23] Clean ups --- src/coreclr/jit/jitmetadatalist.h | 1 - src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp | 2 +- src/coreclr/tools/superpmi/superpmi-shared/compileresult.h | 4 ++-- src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index 23a6940b770cab..1931fc0b79ae73 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -15,7 +15,6 @@ // Name, type flags JITMETADATAINFO(MethodFullName, const char*, 0) JITMETADATAINFO(TieringName, const char*, 0) -JITMETADATAINFO(MethodOptimized, bool, 0) JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) JITMETADATAMETRIC(LoopsCloned, int, 0) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp index 29dc4738ec2b27..c59b4d7b6ff86f 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp @@ -33,7 +33,7 @@ CompileResult::CompileResult() allocGCInfoDets.size = 0; MethodFullName = nullptr; - MethodName = nullptr; + TieringName = nullptr; memoryTracker = nullptr; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h index aecbd39db1f3e7..72415f1d38f595 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h @@ -221,10 +221,10 @@ class CompileResult #define JITMETADATAMETRIC(name, type, flags) type name; #include "jitmetadatalist.h" - // Reported method name from JIT (not available with release JIT) - const char* MethodName; // Reported method full name from JIT (not available with release JIT) const char* MethodFullName; + // Reported compilation tier from JIT + const char* TieringName; // not persisted to disk. public: diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index c2fdb967d67ca7..f168b4a798f85c 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1049,13 +1049,13 @@ void MyICJI::reportMetadata(const char* key, const void* value) return; } - if (strcmp(key, "MethodName") == 0) + if (strcmp(key, "TieringName") == 0) { const char* str = static_cast(value); size_t len = strlen(str); char* buf = static_cast(jitInstance->mc->cr->allocateMemory(len + 1)); memcpy(buf, str, len + 1); - jitInstance->mc->cr->MethodName = buf; + jitInstance->mc->cr->TieringName = buf; return; } } From 4f7f361c3a145365fac2a953a7c287763fa09e84 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 14:21:45 +0100 Subject: [PATCH 03/23] Nit --- src/coreclr/jit/compiler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 8363c1eeb7575d..5ae1bcc68abc0e 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1861,10 +1861,10 @@ void Compiler::compInit(ArenaAllocator* pAlloc, lvMemoryPerSsaData = SsaDefArray(); -// -// Initialize all the per-method statistics gathering data structures. -// - + // + // Initialize all the per-method statistics gathering data structures. + // + CLANG_FORMAT_COMMENT_ANCHOR; #if LOOP_HOIST_STATS m_loopsConsidered = 0; m_curLoopHasHoistedExpression = false; From ad02f9f5f6b3232076d9bdd7c2c84cc92756a679 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 14:28:17 +0100 Subject: [PATCH 04/23] Further fixing --- src/coreclr/tools/superpmi/superpmi/superpmi.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index 792ad0c9d0cd11..b1a074c6becdd0 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -139,7 +139,7 @@ static const char* ResultToString(ReplayResult result) static void PrintDiffsCsvHeader(FileWriter& fw) { - fw.Print("Context,Context size,Method name,Method full name,Base result,Diff result,MinOpts,Has diff,Base size,Diff size,Base instructions,Diff instructions"); + fw.Print("Context,Context size,Method full name,Tier name,Base result,Diff result,MinOpts,Has diff,Base size,Diff size,Base instructions,Diff instructions"); #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) fw.Print(",Base " #name ",Diff " #name); @@ -157,10 +157,10 @@ static void PrintDiffsCsvRow( bool hasDiff) { fw.Printf( - "%d,%u,\"%s\",\"%s\",%s,%s,%s,%s,%u,%u,%lld,%lld", + "%d,%u,\"%s\",%s,%s,%s,%s,%s,%u,%u,%lld,%lld", context, contextSize, - baseRes.CompileResults->MethodName == nullptr ? "" : baseRes.CompileResults->MethodName, baseRes.CompileResults->MethodFullName == nullptr ? "" : baseRes.CompileResults->MethodFullName, + baseRes.CompileResults->TieringName == nullptr ? "" : baseRes.CompileResults->TieringName, ResultToString(baseRes.Result), ResultToString(diffRes.Result), baseRes.IsMinOpts ? "True" : "False", hasDiff ? "True" : "False", @@ -181,7 +181,7 @@ static void PrintDiffsCsvRow( static void PrintReplayCsvHeader(FileWriter& fw) { - fw.Printf("Context,Context size,Method name,Method full name,Result,MinOpts,Size,Instructions\n"); + fw.Printf("Context,Context size,Method full name,Tier name,Result,MinOpts,Size,Instructions\n"); #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) fw.Print("," #name); @@ -198,8 +198,8 @@ static void PrintReplayCsvRow( { fw.Printf("%d,%u,\"%s\",\"%s\",%s,%s,%s,%s,%u,%lld", context, contextSize, - res.CompileResults->MethodName == nullptr ? "" : res.CompileResults->MethodName, res.CompileResults->MethodFullName == nullptr ? "" : res.CompileResults->MethodFullName, + res.CompileResults->TieringName == nullptr ? "" : res.CompileResults->TieringName, ResultToString(res.Result), res.IsMinOpts ? "True" : "False", res.NumCodeBytes, res.NumExecutedInstructions); From 4018a4c55b3d1c7d61724ee2c98c5988838b082a Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 14:47:17 +0100 Subject: [PATCH 05/23] Fixes --- .../superpmi/superpmi-shared/compileresult.cpp | 4 ++++ .../tools/superpmi/superpmi/icorjitinfo.cpp | 18 ++++++++++-------- .../tools/superpmi/superpmi/superpmi.cpp | 6 +++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp index c59b4d7b6ff86f..ec6e88684060b2 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp @@ -35,6 +35,10 @@ CompileResult::CompileResult() MethodFullName = nullptr; TieringName = nullptr; memoryTracker = nullptr; + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) name = 0; +#include "jitmetadatalist.h" } CompileResult::~CompileResult() diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index f168b4a798f85c..7c7395f8225503 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1031,14 +1031,6 @@ void MyICJI::reportMetadata(const char* key, const void* value) { jitInstance->mc->cr->AddCall("reportMetadata"); -#define JITMETADATAINFO(name, type, flags) -#define JITMETADATAMETRIC(name, type, flags) \ - if (strcmp(key, #name) == 0) \ - { \ - memcpy(&jitInstance->mc->cr->##name, value, sizeof(type)); \ - return; \ - } - if (strcmp(key, "MethodFullName") == 0) { const char* str = static_cast(value); @@ -1058,6 +1050,16 @@ void MyICJI::reportMetadata(const char* key, const void* value) jitInstance->mc->cr->TieringName = buf; return; } + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) \ + if (strcmp(key, #name) == 0) \ + { \ + memcpy(&jitInstance->mc->cr->##name, value, sizeof(type)); \ + return; \ + } + +#include "jitmetadatalist.h" } /*-------------------------- Misc ---------------------------------------*/ diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index b1a074c6becdd0..2cdeaf16f87029 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -146,7 +146,7 @@ static void PrintDiffsCsvHeader(FileWriter& fw) #include "jitmetadatalist.h" - fw.Print("%s\n"); + fw.Print("\n"); } static void PrintDiffsCsvRow( @@ -181,7 +181,7 @@ static void PrintDiffsCsvRow( static void PrintReplayCsvHeader(FileWriter& fw) { - fw.Printf("Context,Context size,Method full name,Tier name,Result,MinOpts,Size,Instructions\n"); + fw.Printf("Context,Context size,Method full name,Tier name,Result,MinOpts,Size,Instructions"); #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) fw.Print("," #name); @@ -196,7 +196,7 @@ static void PrintReplayCsvRow( int context, uint32_t contextSize, const ReplayResults& res) { - fw.Printf("%d,%u,\"%s\",\"%s\",%s,%s,%s,%s,%u,%lld", + fw.Printf("%d,%u,\"%s\",%s,%s,%s,%u,%lld", context, contextSize, res.CompileResults->MethodFullName == nullptr ? "" : res.CompileResults->MethodFullName, res.CompileResults->TieringName == nullptr ? "" : res.CompileResults->TieringName, From a06d6ed68186e19e8db77f5e17ccaf2dc5a4fe6f Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 15:06:58 +0100 Subject: [PATCH 06/23] Allow access in release as well --- src/coreclr/jit/compiler.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index eff322512c6c41..8ead83db738b5a 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -10597,6 +10597,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX static EnregisterStats s_enregisterStats; #endif // TRACK_ENREG_STATS + JitMetrics Metrics; + bool compIsForInlining() const; bool compDonotInline(); @@ -10975,9 +10977,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // test attributes are satisfied. void JitTestCheckSSA(); // SSA builder tests. void JitTestCheckVN(); // Value numbering tests. - - JitMetrics Metrics; -#endif // DEBUG +#endif // DEBUG FieldSeqStore* m_fieldSeqStore; From 867374de6a0529f348968152891d8361d238474a Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 15:47:38 +0100 Subject: [PATCH 07/23] Support writing CSV field names with quotes in them --- .../tools/superpmi/superpmi/fileio.cpp | 51 ++++++++++++++++++- src/coreclr/tools/superpmi/superpmi/fileio.h | 4 +- .../tools/superpmi/superpmi/superpmi.cpp | 12 ++--- 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi/fileio.cpp b/src/coreclr/tools/superpmi/superpmi/fileio.cpp index 5fe03666208339..33125db713aaaa 100644 --- a/src/coreclr/tools/superpmi/superpmi/fileio.cpp +++ b/src/coreclr/tools/superpmi/superpmi/fileio.cpp @@ -41,9 +41,18 @@ bool FileWriter::Printf(const char* fmt, ...) } } +bool FileWriter::Print(const char* value, size_t numChars) +{ + DWORD numWritten; + bool result = + WriteFile(m_file.Get(), value, static_cast(numChars), &numWritten, nullptr) && + (numWritten == static_cast(numChars)); + return result; +} + bool FileWriter::Print(const char* value) { - return Printf("%s", value); + return Print(value, strlen(value)); } bool FileWriter::Print(int value) @@ -61,6 +70,46 @@ bool FileWriter::Print(double value) return Printf("%f", value); } +bool FileWriter::PrintQuotedCsvField(const char* value) +{ + size_t numQuotes = 0; + for (const char* p = value; *p != '\0'; p++) + { + if (*p == '"') + { + numQuotes++; + } + } + + if (numQuotes == 0) + { + return Printf("\"%s\"", value); + } + else + { + size_t len = 2 + strlen(value) + numQuotes; + char* buffer = new char[len]; + + size_t index = 0; + buffer[index++] = '"'; + for (const char* p = value; *p != '\0'; p++) + { + if (*p == '"') + { + buffer[index++] = '"'; + } + buffer[index++] = *p; + } + + buffer[index++] = '"'; + assert(index == len); + + bool result = Print(buffer, len); + delete[] buffer; + return result; + } +} + bool FileWriter::CreateNew(const char* path, FileWriter* fw) { FileHandle handle(CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); diff --git a/src/coreclr/tools/superpmi/superpmi/fileio.h b/src/coreclr/tools/superpmi/superpmi/fileio.h index 16ceaf87bd6148..4a1434f972598a 100644 --- a/src/coreclr/tools/superpmi/superpmi/fileio.h +++ b/src/coreclr/tools/superpmi/superpmi/fileio.h @@ -93,11 +93,13 @@ class FileWriter { } - bool Printf(const char* fmt, ...); + bool Print(const char* value, size_t numChars); bool Print(const char* value); bool Print(int value); bool Print(int64_t value); bool Print(double value); + bool PrintQuotedCsvField(const char* value); + bool Printf(const char* fmt, ...); static bool CreateNew(const char* path, FileWriter* fw); }; diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index 2cdeaf16f87029..b0183a5ebae8a0 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -156,10 +156,10 @@ static void PrintDiffsCsvRow( const ReplayResults& diffRes, bool hasDiff) { + fw.Printf("%d,%u,", context, contextSize); + fw.PrintQuotedCsvField(baseRes.CompileResults->MethodFullName == nullptr ? "" : baseRes.CompileResults->MethodFullName); fw.Printf( - "%d,%u,\"%s\",%s,%s,%s,%s,%s,%u,%u,%lld,%lld", - context, contextSize, - baseRes.CompileResults->MethodFullName == nullptr ? "" : baseRes.CompileResults->MethodFullName, + ",%s,%s,%s,%s,%s,%u,%u,%lld,%lld", baseRes.CompileResults->TieringName == nullptr ? "" : baseRes.CompileResults->TieringName, ResultToString(baseRes.Result), ResultToString(diffRes.Result), baseRes.IsMinOpts ? "True" : "False", @@ -196,9 +196,9 @@ static void PrintReplayCsvRow( int context, uint32_t contextSize, const ReplayResults& res) { - fw.Printf("%d,%u,\"%s\",%s,%s,%s,%u,%lld", - context, contextSize, - res.CompileResults->MethodFullName == nullptr ? "" : res.CompileResults->MethodFullName, + fw.Printf("%d,%u,", context, contextSize); + fw.PrintQuotedCsvField(res.CompileResults->MethodFullName == nullptr ? "" : res.CompileResults->MethodFullName); + fw.Printf(",%s,%s,%s,%u,%lld", res.CompileResults->TieringName == nullptr ? "" : res.CompileResults->TieringName, ResultToString(res.Result), res.IsMinOpts ? "True" : "False", From 3bf7adcb0680b6de9477af81d5fa747e78069c73 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 15:50:00 +0100 Subject: [PATCH 08/23] Fix gcc build --- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp | 2 +- src/coreclr/tools/superpmi/superpmi/superpmi.cpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 646f1b169330a2..6355fc20dd0fd5 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 1f30d12b-38f1-4f1e-a08a-831def882aa4 */ - 0x1f30d12b, - 0x38f1, - 0x4f1e, - {0xa0, 0x8a, 0x83, 0x1d, 0xef, 0x88, 0x2a, 0xa4} +constexpr GUID JITEEVersionIdentifier = { /* 0fb71692-0ee6-4914-88a8-6446e45f23e8 */ + 0x0fb71692, + 0x0ee6, + 0x4914, + {0x88, 0xa8, 0x64, 0x46, 0xe4, 0x5f, 0x23, 0xe8} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 7c7395f8225503..c8ed4b67930d33 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1055,7 +1055,7 @@ void MyICJI::reportMetadata(const char* key, const void* value) #define JITMETADATAMETRIC(name, type, flags) \ if (strcmp(key, #name) == 0) \ { \ - memcpy(&jitInstance->mc->cr->##name, value, sizeof(type)); \ + memcpy(&jitInstance->mc->cr->name, value, sizeof(type)); \ return; \ } diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index b0183a5ebae8a0..1f27ff9c329cb6 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -170,9 +170,9 @@ static void PrintDiffsCsvRow( #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) \ fw.Print(","); \ - fw.Print(baseRes.CompileResults->##name); \ + fw.Print(baseRes.CompileResults->name); \ fw.Print(","); \ - fw.Print(diffRes.CompileResults->##name); + fw.Print(diffRes.CompileResults->name); #include "jitmetadatalist.h" @@ -207,7 +207,7 @@ static void PrintReplayCsvRow( #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) \ fw.Print(","); \ - fw.Print(res.CompileResults->##name); + fw.Print(res.CompileResults->name); #include "jitmetadatalist.h" From e821bbdfb695479134994c25e5cb90b7ffb86155 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 15:51:23 +0100 Subject: [PATCH 09/23] Clean up --- src/coreclr/tools/superpmi/superpmi/fileio.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi/fileio.cpp b/src/coreclr/tools/superpmi/superpmi/fileio.cpp index 33125db713aaaa..e26723de6e3e1e 100644 --- a/src/coreclr/tools/superpmi/superpmi/fileio.cpp +++ b/src/coreclr/tools/superpmi/superpmi/fileio.cpp @@ -27,10 +27,7 @@ bool FileWriter::Printf(const char* fmt, ...) } else { - DWORD numWritten; - bool result = - WriteFile(m_file.Get(), pBuffer, static_cast(printed), &numWritten, nullptr) && - (numWritten == static_cast(printed)); + bool result = Print(pBuffer, static_cast(printed)); if (pBuffer != stackBuffer) delete[] pBuffer; From 1e2a1d99e72fc9732d9f1e6361443627cadcd551 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 17:02:26 +0100 Subject: [PATCH 10/23] Add some more metrics; display them in JITDUMP; really report them at the end --- src/coreclr/jit/compiler.cpp | 8 ++++--- src/coreclr/jit/jitmetadata.cpp | 30 +++++++++++++++++++++++++ src/coreclr/jit/jitmetadata.h | 1 + src/coreclr/jit/jitmetadatalist.h | 7 ++++++ src/coreclr/jit/optcse.cpp | 1 + src/coreclr/jit/optimizer.cpp | 4 ++++ src/coreclr/jit/promotion.cpp | 2 ++ src/coreclr/jit/redundantbranchopts.cpp | 2 ++ src/coreclr/jit/ssabuilder.cpp | 3 +++ 9 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 5ae1bcc68abc0e..11bfac838365e7 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -5223,8 +5223,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl info.compILCodeSize, *methodCodeSize, debugPart, metricPart); } - INDEBUG(Metrics.report(this)); - compFunctionTraceEnd(*methodCodePtr, *methodCodeSize, false); JITDUMP("Method code size: %d\n", (unsigned)(*methodCodeSize)); @@ -6656,9 +6654,13 @@ void Compiler::compCompileFinish() printf(""); // in our logic this causes a flush } + JITDUMP("Final metrics:\n"); + Metrics.report(this); + DBEXEC(verbose, Metrics.dump(this)); + if (verbose) { - printf("****** DONE compiling %s\n", info.compFullName); + printf("\n****** DONE compiling %s\n", info.compFullName); printf(""); // in our logic this causes a flush } diff --git a/src/coreclr/jit/jitmetadata.cpp b/src/coreclr/jit/jitmetadata.cpp index 917c7c54f67cd5..c9930b1752919a 100644 --- a/src/coreclr/jit/jitmetadata.cpp +++ b/src/coreclr/jit/jitmetadata.cpp @@ -38,4 +38,34 @@ void JitMetrics::report(Compiler* comp) #include "jitmetadatalist.h" } +static void printMetric(double value) +{ + printf("%f", value); +} + +static void printMetric(int value) +{ + printf("%d", value); +} + +static void printMetric(int64_t value) +{ + printf("%lld", value); +} + +void JitMetrics::dump(Compiler* comp) +{ + int nameMaxWidth = 0; +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) nameMaxWidth = max(nameMaxWidth, (int)strlen(#name)); +#include "jitmetadatalist.h" + +#define JITMETADATAINFO(name, type, flags) +#define JITMETADATAMETRIC(name, type, flags) \ + printf("%-*s: ", nameMaxWidth + 5, #name); \ + printMetric(name); \ + printf("\n"); +#include "jitmetadatalist.h" +} + #endif diff --git a/src/coreclr/jit/jitmetadata.h b/src/coreclr/jit/jitmetadata.h index c713582fac5484..7b50c4439a691e 100644 --- a/src/coreclr/jit/jitmetadata.h +++ b/src/coreclr/jit/jitmetadata.h @@ -26,4 +26,5 @@ class JitMetrics #include "jitmetadatalist.h" void report(Compiler* comp); + void dump(Compiler* comp); }; diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index 1931fc0b79ae73..9200e788aab19d 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -18,10 +18,17 @@ JITMETADATAINFO(TieringName, const char*, 0) JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) JITMETADATAMETRIC(LoopsCloned, int, 0) +JITMETADATAMETRIC(LoopsUnrolled, int, 0) JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) JITMETADATAMETRIC(LoopsAligned, int, 0) +JITMETADATAMETRIC(VarsInSsa, int, 0) +JITMETADATAMETRIC(HoistedExpressions, int, 0) +JITMETADATAMETRIC(Cses, int, 0) +JITMETADATAMETRIC(RedundantBranchesEliminated, int, 0) +JITMETADATAMETRIC(JumpThreadingsPerformed, int, 0) JITMETADATAMETRIC(BytesAllocated, int64_t, 0) JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) +JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) #undef JITMETADATA #undef JITMETADATAINFO diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index e4b3c9faeff4fb..ffc9557e736a7a 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -4370,6 +4370,7 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate) // Record that we created a new LclVar for use as a CSE temp m_addCSEcount++; m_pCompiler->optCSEcount++; + m_pCompiler->Metrics.Cses++; // Walk all references to this CSE, adding an assignment // to the CSE temp to all defs and changing all refs to diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index c70ba9b0273ec1..69d8750c48e5a1 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -1292,6 +1292,8 @@ PhaseStatus Compiler::optUnrollLoops() { assert(anyIRchange); + Metrics.LoopsUnrolled += unrollCount; + #ifdef DEBUG if (verbose) { @@ -5139,6 +5141,8 @@ void Compiler::optHoistCandidate(GenTree* tree, // Record the hoisted expression in hoistCtxt hoistCtxt->GetHoistedInCurLoop(this)->Set(tree->gtVNPair.GetLiberal(), true); + + Metrics.HoistedExpressions++; } bool Compiler::optVNIsLoopInvariant(ValueNum vn, FlowGraphNaturalLoop* loop, VNSet* loopVnInvariantCache) diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index f66748633a69e3..2f7b1e0b31372c 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -1205,6 +1205,8 @@ class LocalsUseVisitor : public GenTreeVisitor } } + m_compiler->Metrics.PhysicallyPromotedFields += totalNumPromotions; + if (totalNumPromotions <= 0) { return false; diff --git a/src/coreclr/jit/redundantbranchopts.cpp b/src/coreclr/jit/redundantbranchopts.cpp index 3ea6142de4cd3f..9dd9a2959e76a3 100644 --- a/src/coreclr/jit/redundantbranchopts.cpp +++ b/src/coreclr/jit/redundantbranchopts.cpp @@ -927,6 +927,7 @@ bool Compiler::optRedundantBranch(BasicBlock* const block) JITDUMP("\nRedundant branch opt in " FMT_BB ":\n", block->bbNum); fgMorphBlockStmt(block, stmt DEBUGARG(__FUNCTION__)); + Metrics.RedundantBranchesEliminated++; return true; } @@ -1683,6 +1684,7 @@ bool Compiler::optJumpThreadCore(JumpThreadInfo& jti) // We optimized. // + Metrics.JumpThreadingsPerformed++; fgModified = true; return true; } diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index 2072591bcd5a9a..fb8b33aa313294 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -1181,6 +1181,7 @@ void SsaBuilder::RenameVariables() { JITDUMP("*************** In SsaBuilder::RenameVariables()\n"); + m_pCompiler->Metrics.VarsInSsa = 0; // The first thing we do is treat parameters and must-init variables as if they have a // virtual definition before entry -- they start out at SSA name 1. for (unsigned lclNum = 0; lclNum < m_pCompiler->lvaCount; lclNum++) @@ -1190,6 +1191,8 @@ void SsaBuilder::RenameVariables() continue; } + m_pCompiler->Metrics.VarsInSsa++; + LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclNum); assert(varDsc->lvTracked); From d96f2e5b7f977c7884c10d05b928921181014df4 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 17:05:06 +0100 Subject: [PATCH 11/23] Reorder a bit --- src/coreclr/jit/jitmetadatalist.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index 9200e788aab19d..b15193718a70c6 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -15,7 +15,7 @@ // Name, type flags JITMETADATAINFO(MethodFullName, const char*, 0) JITMETADATAINFO(TieringName, const char*, 0) -JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) JITMETADATAMETRIC(LoopsFoundDuringOpts, int, 0) JITMETADATAMETRIC(LoopsCloned, int, 0) JITMETADATAMETRIC(LoopsUnrolled, int, 0) @@ -23,12 +23,12 @@ JITMETADATAMETRIC(LoopAlignmentCandidates, int, 0) JITMETADATAMETRIC(LoopsAligned, int, 0) JITMETADATAMETRIC(VarsInSsa, int, 0) JITMETADATAMETRIC(HoistedExpressions, int, 0) +JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER) +JITMETADATAMETRIC(JumpThreadingsPerformed, int, JIT_METADATA_HIGHER_IS_BETTER) JITMETADATAMETRIC(Cses, int, 0) -JITMETADATAMETRIC(RedundantBranchesEliminated, int, 0) -JITMETADATAMETRIC(JumpThreadingsPerformed, int, 0) -JITMETADATAMETRIC(BytesAllocated, int64_t, 0) JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) -JITMETADATAMETRIC(PhysicallyPromotedFields, int, 0) +JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) +JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) #undef JITMETADATA #undef JITMETADATAINFO From 469c3de09ca29160c05a16ba9b90c65ffb0e0eea Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 17:37:07 +0100 Subject: [PATCH 12/23] Nit --- src/coreclr/tools/superpmi/superpmi/superpmi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index 1f27ff9c329cb6..f0b4b76fcc1c19 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -170,7 +170,7 @@ static void PrintDiffsCsvRow( #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) \ fw.Print(","); \ - fw.Print(baseRes.CompileResults->name); \ + fw.Print(baseRes.CompileResults->name); \ fw.Print(","); \ fw.Print(diffRes.CompileResults->name); From 601cf6b736e7225fe14b099f229ab4b411cec928 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 17:38:06 +0100 Subject: [PATCH 13/23] Update JIT-EE version GUID again --- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 6355fc20dd0fd5..646f1b169330a2 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 0fb71692-0ee6-4914-88a8-6446e45f23e8 */ - 0x0fb71692, - 0x0ee6, - 0x4914, - {0x88, 0xa8, 0x64, 0x46, 0xe4, 0x5f, 0x23, 0xe8} +constexpr GUID JITEEVersionIdentifier = { /* 1f30d12b-38f1-4f1e-a08a-831def882aa4 */ + 0x1f30d12b, + 0x38f1, + 0x4f1e, + {0xa0, 0x8a, 0x83, 0x1d, 0xef, 0x88, 0x2a, 0xa4} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// From 186da27d5c0134b126ac255ca761a505d7a98a49 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 18:33:43 +0100 Subject: [PATCH 14/23] Support fast PerfScore diffs in superpmi.py --- src/coreclr/scripts/superpmi.py | 52 ++++++++++++++----- .../tools/superpmi/superpmi/jitinstance.cpp | 2 +- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index baca765929ce4c..1c1813a0131101 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -1865,8 +1865,8 @@ def aggregate_diff_metrics(details): """ base_minopts = {"Successful compiles": 0, "Missing compiles": 0, "Failing compiles": 0, - "Contexts with diffs": 0, "Diffed code bytes": 0, "Diff executed instructions": 0, - "Diffed contexts": 0} + "Contexts with diffs": 0, "Diffed code bytes": 0, "Diffed PerfScore" : 0.0, + "Diff executed instructions": 0, "Diffed contexts": 0} base_fullopts = base_minopts.copy() diff_minopts = base_minopts.copy() @@ -1910,6 +1910,11 @@ def aggregate_diff_metrics(details): base_dict["Diff executed instructions"] += base_insts diff_dict["Diff executed instructions"] += diff_insts + base_perfscore = float(row["Base PerfScore"]) + diff_perfscore = float(row["Diff PerfScore"]) + base_dict["Diffed PerfScore"] += base_perfscore + diff_dict["Diffed PerfScore"] += diff_perfscore + base_dict["Diffed contexts"] += 1 diff_dict["Diffed contexts"] += 1 @@ -2267,6 +2272,14 @@ def create_exception(): delta_bytes = diff_bytes - base_bytes logging.info("Total bytes of delta: {} ({:.2%} of base)".format(delta_bytes, delta_bytes / base_bytes)) + if "PerfScore" in self.coreclr_args.metrics: + base_perfscore = base_metrics["Overall"]["Diffed PerfScore"] + diff_perfscore = diff_metrics["Overall"]["Diffed PerfScore"] + logging.info("Total PerfScore of base: {}".format(base_perfscore)) + logging.info("Total PerfScore of diff: {}".format(diff_perfscore)) + delta_perfscore = diff_perfscore - base_perfscore + logging.info("Total PerfScore of delta: {} ({:.2%} of base)".format(delta_perfscore, delta_perfscore / base_perfscore)) + try: current_text_diff = text_differences.get_nowait() except: @@ -2290,6 +2303,10 @@ def create_exception(): if self.coreclr_args.metrics: for metric in self.coreclr_args.metrics: command += [ "--metrics", metric ] + + if self.coreclr_args.metrics == ["PerfScore"]: + command += [ "--override-total-base-metric", str(base_perfscore), "--override-total-diff-metric", str(diff_perfscore) ] + elif base_bytes is not None and diff_bytes is not None: command += [ "--override-total-base-metric", str(base_bytes), "--override-total-diff-metric", str(diff_bytes) ] @@ -2668,7 +2685,7 @@ def pick_contexts_to_disassemble(self, diffs): # If there are non-default metrics then we need to disassemble # everything so that jit-analyze can handle those. - if self.coreclr_args.metrics is not None: + if self.coreclr_args.metrics is not None and self.coreclr_args.metrics != ["PerfScore"]: contexts = diffs examples = [] else: @@ -2686,22 +2703,29 @@ def display_subset(message, subset): smallest_contexts = sorted(diffs, key=lambda r: int(r["Context size"]))[:20] display_subset("Smallest {} contexts with binary differences:", smallest_contexts) - # Order by byte-wise improvement, largest improvements first - by_diff_size = sorted(diffs, key=lambda r: int(r["Diff size"]) - int(r["Base size"])) - # 20 top improvements, byte-wise - top_improvements_bytes = by_diff_size[:20] - # 20 top regressions, byte-wise - top_regressions_bytes = by_diff_size[-20:] + if self.coreclr_args.metrics is None: + base_metric_name = "Base size" + diff_metric_name = "Diff size" + else: + base_metric_name = "Base PerfScore" + diff_metric_name = "Diff PerfScore" + + # Order by improvement, largest improvements first + by_diff = sorted(diffs, key=lambda r: float(r[diff_metric_name]) - float(r[base_metric_name])) + # 20 top improvements + top_improvements = by_diff[:20] + # 20 top regressions + top_regressions = by_diff[-20:] - display_subset("Top {} improvements, byte-wise:", top_improvements_bytes) - display_subset("Top {} regressions, byte-wise:", top_regressions_bytes) + display_subset("Top {} improvements:", top_improvements) + display_subset("Top {} regressions:", top_regressions) # Order by percentage-wise size improvement, largest improvements first def diff_pct(r): - base = int(r["Base size"]) + base = float(r[base_metric_name]) if base == 0: return 0 - diff = int(r["Diff size"]) + diff = float(r[diff_metric_name]) return (diff - base) / base by_diff_size_pct = sorted(diffs, key=diff_pct) @@ -2723,7 +2747,7 @@ def diff_pct(r): example_improvements = by_diff_size_pct_examples[:3] example_regressions = by_diff_size_pct_examples[3:][-3:] - contexts = smallest_contexts + top_improvements_bytes + top_regressions_bytes + top_improvements_pct + top_regressions_pct + smallest_zero_size_contexts + example_improvements + example_regressions + contexts = smallest_contexts + top_improvements + top_regressions + top_improvements_pct + top_regressions_pct + smallest_zero_size_contexts + example_improvements + example_regressions examples = example_improvements + example_regressions final_contexts_indices = list(set(int(r["Context"]) for r in contexts)) diff --git a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp index 93191588cc00c3..8eb0e69e8b2e5b 100644 --- a/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp +++ b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp @@ -411,7 +411,6 @@ ReplayResults JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcI pParam->pThis->mc->cr->recMessageLog(jitResult == CORJIT_OK ? "Successful Compile" : "Successful Compile (BADCODE)"); pParam->results.NumCodeBytes = NCodeSizeBlock; - pParam->results.CompileResults = pParam->pThis->mc->cr; } else { @@ -460,6 +459,7 @@ ReplayResults JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcI } mc->cr->secondsToCompile = stj.GetSeconds(); + param.results.CompileResults = mc->cr; UINT64 insCountAfter = 0; Instrumentor_GetInsCount(&insCountAfter); From 1a075c38c6c9dc8b40858928a439921d573f3eac Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 19:59:23 +0100 Subject: [PATCH 15/23] Fix reporting inlinee full name --- src/coreclr/jit/compiler.cpp | 5 ++++- src/coreclr/jit/jitmetadatalist.h | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 11bfac838365e7..b0033d8ba65511 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1796,7 +1796,10 @@ void Compiler::compInit(ArenaAllocator* pAlloc, info.compMethodSuperPMIIndex = g_jitHost->getIntConfigValue(W("SuperPMIMethodContextNumber"), -1); - JitMetadata::report(this, JitMetadataName::MethodFullName, info.compFullName); + if (!compIsForInlining()) + { + JitMetadata::report(this, JitMetadataName::MethodFullName, info.compFullName); + } #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS #if defined(DEBUG) diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index b15193718a70c6..8422d0ac1a81cf 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -9,7 +9,7 @@ #endif #if !defined(JITMETADATAINFO) || !defined(JITMETADATAMETRIC) -#error Define JITMETADATAINFO and JITMETADATAMETRIC before including this file. +#error Define JITMETADATAINFO and JITMETADATAMETRIC before including this file. #endif // Name, type flags @@ -30,8 +30,8 @@ JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) -#undef JITMETADATA -#undef JITMETADATAINFO -#undef JITMETADATAMETRIC +#undef JITMETADATA +#undef JITMETADATAINFO +#undef JITMETADATAMETRIC // clang-format on From a637694389f423f351c3b1c93221196e26d8ce06 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Mon, 19 Feb 2024 22:37:45 +0100 Subject: [PATCH 16/23] Fix a bug in PAL version of _vsnprintf_s --- src/coreclr/pal/src/safecrt/vsprintf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/safecrt/vsprintf.cpp b/src/coreclr/pal/src/safecrt/vsprintf.cpp index b8ff745f563ceb..360222d5dc6798 100644 --- a/src/coreclr/pal/src/safecrt/vsprintf.cpp +++ b/src/coreclr/pal/src/safecrt/vsprintf.cpp @@ -95,7 +95,7 @@ DLLEXPORT int __cdecl _vsnprintf_s ( retvalue = vsnprintf(string, sizeInBytes, format, ap); string[sizeInBytes - 1] = '\0'; /* we allow truncation if count == _TRUNCATE */ - if (retvalue > (int)sizeInBytes && count == _TRUNCATE) + if (retvalue >= (int)sizeInBytes && count == _TRUNCATE) { if (errno == ERANGE) { From 4624ddc5fd7dee0cdff80fd268c39aa13cedc73b Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 Feb 2024 14:02:34 +0100 Subject: [PATCH 17/23] Clean up, add function header comment --- src/coreclr/jit/compiler.cpp | 2 +- src/coreclr/jit/jitmetadata.cpp | 55 ++++++++++++++++++++++++++++++++- src/coreclr/jit/jitmetadata.h | 2 +- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index b0033d8ba65511..c389b78072ea87 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -6659,7 +6659,7 @@ void Compiler::compCompileFinish() JITDUMP("Final metrics:\n"); Metrics.report(this); - DBEXEC(verbose, Metrics.dump(this)); + DBEXEC(verbose, Metrics.dump()); if (verbose) { diff --git a/src/coreclr/jit/jitmetadata.cpp b/src/coreclr/jit/jitmetadata.cpp index c9930b1752919a..754bb532a84401 100644 --- a/src/coreclr/jit/jitmetadata.cpp +++ b/src/coreclr/jit/jitmetadata.cpp @@ -6,6 +6,16 @@ #ifdef DEBUG +//------------------------------------------------------------------------ +// JitMetadata::getName: Get the name corresponding to a JitMetadataName value, +// which can be used to report metadata back to the EE. +// +// Parameters: +// name - The JitMetadataName enum entry +// +// Returns: +// String representation of the name +// const char* JitMetadata::getName(JitMetadataName name) { switch (name) @@ -20,17 +30,39 @@ const char* JitMetadata::getName(JitMetadataName name) } } +//------------------------------------------------------------------------ +// JitMetadata::report: Report metadata back to the EE. +// +// Parameters: +// comp - Compiler instance +// name - Enum entry specifying the metadata name +// data - Pointer to the value to report back +// void JitMetadata::report(Compiler* comp, JitMetadataName name, const void* data) { comp->info.compCompHnd->reportMetadata(getName(name), data); } +//------------------------------------------------------------------------ +// reportValue: Report a specific value back to the EE. +// +// Parameters: +// comp - Compiler instance +// key - The key +// value - Value to report back +// template static void reportValue(Compiler* comp, const char* key, T value) { comp->info.compCompHnd->reportMetadata(key, &value); } +//------------------------------------------------------------------------ +// JitMetrics::report: Report all metrics and their values back to the EE. +// +// Parameters: +// comp - Compiler instance +// void JitMetrics::report(Compiler* comp) { #define JITMETADATAINFO(name, type, flags) @@ -38,22 +70,43 @@ void JitMetrics::report(Compiler* comp) #include "jitmetadatalist.h" } +//------------------------------------------------------------------------ +// printMetric: Print a double metric value to jitstdout. +// +// Parameters: +// value - The value +// static void printMetric(double value) { printf("%f", value); } +//------------------------------------------------------------------------ +// printMetric: Print an int metric value to jitstdout. +// +// Parameters: +// value - The value +// static void printMetric(int value) { printf("%d", value); } +//------------------------------------------------------------------------ +// printMetric: Print an int64_t metric value to jitstdout. +// +// Parameters: +// value - The value +// static void printMetric(int64_t value) { printf("%lld", value); } -void JitMetrics::dump(Compiler* comp) +//------------------------------------------------------------------------ +// JitMetrics::dump: Print the values of all metrics to jitstdout. +// +void JitMetrics::dump() { int nameMaxWidth = 0; #define JITMETADATAINFO(name, type, flags) diff --git a/src/coreclr/jit/jitmetadata.h b/src/coreclr/jit/jitmetadata.h index 7b50c4439a691e..42ce87d0966541 100644 --- a/src/coreclr/jit/jitmetadata.h +++ b/src/coreclr/jit/jitmetadata.h @@ -26,5 +26,5 @@ class JitMetrics #include "jitmetadatalist.h" void report(Compiler* comp); - void dump(Compiler* comp); + void dump(); }; From 7dd107c613598c2d34a16dd84be871fe03b20100 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 Feb 2024 16:06:00 +0100 Subject: [PATCH 18/23] Fix --- src/coreclr/scripts/superpmi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 1c1813a0131101..07a1f4427c7441 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -2272,7 +2272,7 @@ def create_exception(): delta_bytes = diff_bytes - base_bytes logging.info("Total bytes of delta: {} ({:.2%} of base)".format(delta_bytes, delta_bytes / base_bytes)) - if "PerfScore" in self.coreclr_args.metrics: + if self.coreclr_args.metrics is not None and "PerfScore" in self.coreclr_args.metrics: base_perfscore = base_metrics["Overall"]["Diffed PerfScore"] diff_perfscore = diff_metrics["Overall"]["Diffed PerfScore"] logging.info("Total PerfScore of base: {}".format(base_perfscore)) From eca3dd97d454e59c847cb895c6326f460110f3f7 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 Feb 2024 17:20:11 +0100 Subject: [PATCH 19/23] Print PerfScore geomeans --- src/coreclr/scripts/superpmi.py | 42 ++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 07a1f4427c7441..fed8109ac0e790 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -22,6 +22,7 @@ import datetime import locale import logging +import math import os import multiprocessing import platform @@ -1865,7 +1866,8 @@ def aggregate_diff_metrics(details): """ base_minopts = {"Successful compiles": 0, "Missing compiles": 0, "Failing compiles": 0, - "Contexts with diffs": 0, "Diffed code bytes": 0, "Diffed PerfScore" : 0.0, + "Contexts with diffs": 0, "Diffed code bytes": 0, + "Diffed PerfScore" : 0.0, "Relative PerfScore Geomean": 0.0, "Diff executed instructions": 0, "Diffed contexts": 0} base_fullopts = base_minopts.copy() @@ -1915,6 +1917,11 @@ def aggregate_diff_metrics(details): base_dict["Diffed PerfScore"] += base_perfscore diff_dict["Diffed PerfScore"] += diff_perfscore + if base_perfscore > 0: + log_relative_perfscore = math.log(diff_perfscore / base_perfscore) + base_dict["Relative PerfScore Geomean"] += log_relative_perfscore + diff_dict["Relative PerfScore Geomean"] += log_relative_perfscore + base_dict["Diffed contexts"] += 1 diff_dict["Diffed contexts"] += 1 @@ -1930,6 +1937,18 @@ def aggregate_diff_metrics(details): for k in diff_overall.keys(): diff_overall[k] += diff_fullopts[k] + for d in [base_overall, base_minopts, base_fullopts, diff_overall, diff_minopts, diff_fullopts]: + sum_of_logs = d["Relative PerfScore Geomean"] + if d["Diffed contexts"] > 0: + d["Relative PerfScore Geomean"] = math.exp(sum_of_logs / d["Diffed contexts"]) + else: + d["Relative PerfScore Geomean"] = 1 + + if d["Contexts with diffs"] > 0: + d["Relative PerfScore Geomean (Diffs)"] = math.exp(sum_of_logs / d["Contexts with diffs"]) + else: + d["Relative PerfScore Geomean (Diffs)"] = 1 + return ({"Overall": base_overall, "MinOpts": base_minopts, "FullOpts": base_fullopts}, {"Overall": diff_overall, "MinOpts": diff_minopts, "FullOpts": diff_fullopts}) @@ -2271,14 +2290,21 @@ def create_exception(): logging.info("Total bytes of diff: {}".format(diff_bytes)) delta_bytes = diff_bytes - base_bytes logging.info("Total bytes of delta: {} ({:.2%} of base)".format(delta_bytes, delta_bytes / base_bytes)) + logging.info("") + + base_perfscore = base_metrics["Overall"]["Diffed PerfScore"] + diff_perfscore = diff_metrics["Overall"]["Diffed PerfScore"] + logging.info("Total PerfScore of base: {}".format(base_perfscore)) + logging.info("Total PerfScore of diff: {}".format(diff_perfscore)) + delta_perfscore = diff_perfscore - base_perfscore + logging.info("Total PerfScore of delta: {} ({:.2%} of base)".format(delta_perfscore, delta_perfscore / base_perfscore)) + logging.info("") - if self.coreclr_args.metrics is not None and "PerfScore" in self.coreclr_args.metrics: - base_perfscore = base_metrics["Overall"]["Diffed PerfScore"] - diff_perfscore = diff_metrics["Overall"]["Diffed PerfScore"] - logging.info("Total PerfScore of base: {}".format(base_perfscore)) - logging.info("Total PerfScore of diff: {}".format(diff_perfscore)) - delta_perfscore = diff_perfscore - base_perfscore - logging.info("Total PerfScore of delta: {} ({:.2%} of base)".format(delta_perfscore, delta_perfscore / base_perfscore)) + relative_perfscore_geomean = diff_metrics["Overall"]["Relative PerfScore Geomean"] + logging.info("Relative PerfScore Geomean: {:.4%}".format(relative_perfscore_geomean - 1)) + relative_perfscore_geomean_diffs = diff_metrics["Overall"]["Relative PerfScore Geomean (Diffs)"] + logging.info("Relative PerfScore Geomean (Diffs): {:.4%}".format(relative_perfscore_geomean_diffs - 1)) + logging.info("") try: current_text_diff = text_differences.get_nowait() From f8903036671f8f91500f798bcf5debb5c26799fa Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 Feb 2024 17:42:19 +0100 Subject: [PATCH 20/23] Add to report --- src/coreclr/scripts/superpmi.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index fed8109ac0e790..89d5ada34ac201 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -1808,10 +1808,10 @@ def compute_pct(base, diff): else: return 0.0 -def format_pct(pct): +def format_pct(pct, num_decimals = 2): plus_if_positive = "+" if pct > 0 else "" - text = "{}{:.2f}%".format(plus_if_positive, pct) + text = "{}{:.{prec}f}%".format(plus_if_positive, pct, prec=num_decimals) if pct != 0: color = "red" if pct > 0 else "green" return html_color(color, text) @@ -2536,19 +2536,21 @@ def write_pivot_section(row): sum_diff = sum(diff_metrics[row]["Diffed code bytes"] for (_, _, diff_metrics, _, _, _) in asm_diffs) with DetailsSection(write_fh, "{} ({} bytes)".format(row, format_delta(sum_base, sum_diff))): - write_fh.write("|Collection|Base size (bytes)|Diff size (bytes)|\n") - write_fh.write("|---|--:|--:|\n") + write_fh.write("|Collection|Base size (bytes)|Diff size (bytes)|Rel PerfScore Geomean|Rel PerfScore Geomean over Diffs\n") + write_fh.write("|---|--:|--:|--:|--:|\n") for (mch_file, base_metrics, diff_metrics, _, _, _) in asm_diffs: # Exclude this particular row? if not has_diffs(diff_metrics[row]): continue - write_fh.write("|{}|{:,d}|{}|\n".format( + write_fh.write("|{}|{:,d}|{}|{}|{}|\n".format( mch_file, base_metrics[row]["Diffed code bytes"], format_delta( base_metrics[row]["Diffed code bytes"], - diff_metrics[row]["Diffed code bytes"]))) + diff_metrics[row]["Diffed code bytes"]), + format_pct(diff_metrics[row]["Relative PerfScore Geomean"] * 100 - 100, 4), + format_pct(diff_metrics[row]["Relative PerfScore Geomean (Diffs)"] * 100 - 100, 4))) write_top_context_section() write_pivot_section("Overall") From ee5ad8b9cb5a04da348411fe904ab1dc2fe33199 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 Feb 2024 18:00:21 +0100 Subject: [PATCH 21/23] Clean up --- src/coreclr/scripts/superpmi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 89d5ada34ac201..7b10d87fe6ce3c 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -2536,7 +2536,7 @@ def write_pivot_section(row): sum_diff = sum(diff_metrics[row]["Diffed code bytes"] for (_, _, diff_metrics, _, _, _) in asm_diffs) with DetailsSection(write_fh, "{} ({} bytes)".format(row, format_delta(sum_base, sum_diff))): - write_fh.write("|Collection|Base size (bytes)|Diff size (bytes)|Rel PerfScore Geomean|Rel PerfScore Geomean over Diffs\n") + write_fh.write("|Collection|Base size (bytes)|Diff size (bytes)|PerfScore|PerfScore in Diffs\n") write_fh.write("|---|--:|--:|--:|--:|\n") for (mch_file, base_metrics, diff_metrics, _, _, _) in asm_diffs: # Exclude this particular row? @@ -2550,7 +2550,7 @@ def write_pivot_section(row): base_metrics[row]["Diffed code bytes"], diff_metrics[row]["Diffed code bytes"]), format_pct(diff_metrics[row]["Relative PerfScore Geomean"] * 100 - 100, 4), - format_pct(diff_metrics[row]["Relative PerfScore Geomean (Diffs)"] * 100 - 100, 4))) + format_pct(diff_metrics[row]["Relative PerfScore Geomean (Diffs)"] * 100 - 100))) write_top_context_section() write_pivot_section("Overall") From a839f5317d33a1a9a29ed2a298b8a07c26b9cc44 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Tue, 20 Feb 2024 18:18:24 +0100 Subject: [PATCH 22/23] Move overall perfscore change to details --- src/coreclr/scripts/superpmi.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 7b10d87fe6ce3c..29e3801147500a 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -2536,20 +2536,19 @@ def write_pivot_section(row): sum_diff = sum(diff_metrics[row]["Diffed code bytes"] for (_, _, diff_metrics, _, _, _) in asm_diffs) with DetailsSection(write_fh, "{} ({} bytes)".format(row, format_delta(sum_base, sum_diff))): - write_fh.write("|Collection|Base size (bytes)|Diff size (bytes)|PerfScore|PerfScore in Diffs\n") - write_fh.write("|---|--:|--:|--:|--:|\n") + write_fh.write("|Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs\n") + write_fh.write("|---|--:|--:|--:|\n") for (mch_file, base_metrics, diff_metrics, _, _, _) in asm_diffs: # Exclude this particular row? if not has_diffs(diff_metrics[row]): continue - write_fh.write("|{}|{:,d}|{}|{}|{}|\n".format( + write_fh.write("|{}|{:,d}|{}|{}|\n".format( mch_file, base_metrics[row]["Diffed code bytes"], format_delta( base_metrics[row]["Diffed code bytes"], diff_metrics[row]["Diffed code bytes"]), - format_pct(diff_metrics[row]["Relative PerfScore Geomean"] * 100 - 100, 4), format_pct(diff_metrics[row]["Relative PerfScore Geomean (Diffs)"] * 100 - 100))) write_top_context_section() @@ -2569,26 +2568,27 @@ def write_pivot_section(row): with DetailsSection(write_fh, "Details"): if any_diffs: write_fh.write("#### Improvements/regressions per collection\n\n") - write_fh.write("|Collection|Contexts with diffs|Improvements|Regressions|Same size|Improvements (bytes)|Regressions (bytes)|\n") - write_fh.write("|---|--:|--:|--:|--:|--:|--:|\n") + write_fh.write("|Collection|Contexts with diffs|Improvements|Regressions|Same size|Improvements (bytes)|Regressions (bytes)|PerfScore Overall (FullOpts)|\n") + write_fh.write("|---|--:|--:|--:|--:|--:|--:|--:|\n") - def write_row(name, diffs): + def write_row(name, diffs, perfscore_geomean): base_diff_sizes = [(int(r["Base size"]), int(r["Diff size"])) for r in diffs] (num_improvements, num_regressions, num_same, byte_improvements, byte_regressions) = calculate_improvements_regressions(base_diff_sizes) - write_fh.write("|{}|{:,d}|{}|{}|{}|{}|{}|\n".format( + write_fh.write("|{}|{:,d}|{}|{}|{}|{}|{}|{}|\n".format( name, len(diffs), html_color("green", "{:,d}".format(num_improvements)), html_color("red", "{:,d}".format(num_regressions)), html_color("blue", "{:,d}".format(num_same)), html_color("green", "-{:,d}".format(byte_improvements)), - html_color("red", "+{:,d}".format(byte_regressions)))) + html_color("red", "+{:,d}".format(byte_regressions)), + "" if perfscore_geomean is None else format_pct(perfscore_geomean, 4))) - for (mch_file, _, _, diffs, _, _) in asm_diffs: - write_row(mch_file, diffs) + for (mch_file, _, diff_metrics, diffs, _, _) in asm_diffs: + write_row(mch_file, diffs, diff_metrics["FullOpts"]["Relative PerfScore Geomean"] * 100 - 100) if len(asm_diffs) > 1: - write_row("", [r for (_, _, _, diffs, _, _) in asm_diffs for r in diffs]) + write_row("", [r for (_, _, _, diffs, _, _) in asm_diffs for r in diffs], None) write_fh.write("\n---\n\n") From 845bb9ca5eb45f2b4a456b7432e060dbf2f80a90 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 21 Feb 2024 09:37:51 +0100 Subject: [PATCH 23/23] Address feedback --- src/coreclr/inc/corinfo.h | 3 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 3 +- .../jit/ICorJitInfo_wrapper_generated.hpp | 5 +-- src/coreclr/jit/compiler.cpp | 9 ++++-- src/coreclr/jit/jitmetadata.cpp | 32 +++---------------- src/coreclr/jit/jitmetadata.h | 12 +++---- src/coreclr/jit/jitmetadatalist.h | 14 +++++++- src/coreclr/jit/optcse.cpp | 2 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 2 +- .../JitInterface/CorInfoImpl_generated.cs | 6 ++-- .../ThunkGenerator/ThunkInput.txt | 2 +- .../aot/jitinterface/jitinterface_generated.h | 7 ++-- .../superpmi-shim-collector/icorjitinfo.cpp | 4 +-- .../icorjitinfo_generated.cpp | 5 +-- .../icorjitinfo_generated.cpp | 5 +-- .../tools/superpmi/superpmi/icorjitinfo.cpp | 20 +++++------- src/coreclr/vm/jitinterface.cpp | 5 +-- src/coreclr/vm/jitinterface.h | 2 +- 18 files changed, 65 insertions(+), 73 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index ac83351a8da30e..111c6488df073f 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2920,7 +2920,8 @@ class ICorStaticInfo // example, metrics about the compilation. virtual void reportMetadata( const char* key, - const void* value) = 0; + const void* value, + size_t length) = 0; /*-------------------------- Misc ---------------------------------------*/ diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 8a14cdb0f99f1e..46c0c817bad07d 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -440,7 +440,8 @@ void reportRichMappings( void reportMetadata( const char* key, - const void* value) override; + const void* value, + size_t length) override; void* allocateArray( size_t cBytes) override; diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index cb4442df3810cd..1205512fabff0f 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -1030,10 +1030,11 @@ void WrapICorJitInfo::reportRichMappings( void WrapICorJitInfo::reportMetadata( const char* key, - const void* value) + const void* value, + size_t length) { API_ENTER(reportMetadata); - wrapHnd->reportMetadata(key, value); + wrapHnd->reportMetadata(key, value, length); API_LEAVE(reportMetadata); } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index a3a3c380bf8d82..c1417c974a71bc 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1798,7 +1798,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc, if (!compIsForInlining()) { - JitMetadata::report(this, JitMetadataName::MethodFullName, info.compFullName); + JitMetadata::report(this, JitMetadata::MethodFullName, info.compFullName, strlen(info.compFullName)); } #endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS @@ -7156,7 +7156,12 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, opts.disAsm = false; } - INDEBUG(JitMetadata::report(this, JitMetadataName::TieringName, compGetTieringName(true))); +#ifdef DEBUG + { + const char* tieringName = compGetTieringName(true); + JitMetadata::report(this, JitMetadata::TieringName, tieringName, strlen(tieringName)); + } +#endif #if COUNT_BASIC_BLOCKS bbCntTable.record(fgBBcount); diff --git a/src/coreclr/jit/jitmetadata.cpp b/src/coreclr/jit/jitmetadata.cpp index 754bb532a84401..905cdb7317d8bb 100644 --- a/src/coreclr/jit/jitmetadata.cpp +++ b/src/coreclr/jit/jitmetadata.cpp @@ -6,41 +6,17 @@ #ifdef DEBUG -//------------------------------------------------------------------------ -// JitMetadata::getName: Get the name corresponding to a JitMetadataName value, -// which can be used to report metadata back to the EE. -// -// Parameters: -// name - The JitMetadataName enum entry -// -// Returns: -// String representation of the name -// -const char* JitMetadata::getName(JitMetadataName name) -{ - switch (name) - { -#define JITMETADATA(name, type, flags) \ - case JitMetadataName::name: \ - return #name; -#include "jitmetadatalist.h" - - default: - unreached(); - } -} - //------------------------------------------------------------------------ // JitMetadata::report: Report metadata back to the EE. // // Parameters: // comp - Compiler instance -// name - Enum entry specifying the metadata name +// key - Key name of metadata // data - Pointer to the value to report back // -void JitMetadata::report(Compiler* comp, JitMetadataName name, const void* data) +void JitMetadata::report(Compiler* comp, const char* key, const void* data, size_t length) { - comp->info.compCompHnd->reportMetadata(getName(name), data); + comp->info.compCompHnd->reportMetadata(key, data, length); } //------------------------------------------------------------------------ @@ -54,7 +30,7 @@ void JitMetadata::report(Compiler* comp, JitMetadataName name, const void* data) template static void reportValue(Compiler* comp, const char* key, T value) { - comp->info.compCompHnd->reportMetadata(key, &value); + JitMetadata::report(comp, key, &value, sizeof(value)); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/jitmetadata.h b/src/coreclr/jit/jitmetadata.h index 42ce87d0966541..3b4b324497cc21 100644 --- a/src/coreclr/jit/jitmetadata.h +++ b/src/coreclr/jit/jitmetadata.h @@ -5,17 +5,13 @@ class Compiler; -enum class JitMetadataName -{ -#define JITMETADATA(name, type, flags) name, -#include "jitmetadatalist.h" -}; - class JitMetadata { public: - static const char* getName(JitMetadataName name); - static void report(Compiler* comp, JitMetadataName name, const void* data); +#define JITMETADATA(name, type, flags) static constexpr const char* name = #name; +#include "jitmetadatalist.h" + + static void report(Compiler* comp, const char* name, const void* data, size_t length); }; class JitMetrics diff --git a/src/coreclr/jit/jitmetadatalist.h b/src/coreclr/jit/jitmetadatalist.h index 8422d0ac1a81cf..8b69644d1a8fba 100644 --- a/src/coreclr/jit/jitmetadatalist.h +++ b/src/coreclr/jit/jitmetadatalist.h @@ -12,6 +12,18 @@ #error Define JITMETADATAINFO and JITMETADATAMETRIC before including this file. #endif +// List of metadata that the JIT can report. There are two categories: +// +// - JITMETADATAINFO: General info that can be of any type and that cannot be +// aggregated in straightforward ways. These properties are not handled +// automatically; the JIT must explicitly report them using +// JitMetadata::report, and the SPMI side needs to manually handle (or ignore) +// them in ICorJitInfo::reportMetadata. +// +// - JITMETADATAMETRIC: Metrics which are numeric types (currently int, double +// and int64_t types supported). Their reporting is handled automatically and +// they will be propagated all the way into SPMI replay/diff results. + // Name, type flags JITMETADATAINFO(MethodFullName, const char*, 0) JITMETADATAINFO(TieringName, const char*, 0) @@ -25,7 +37,7 @@ JITMETADATAMETRIC(VarsInSsa, int, 0) JITMETADATAMETRIC(HoistedExpressions, int, 0) JITMETADATAMETRIC(RedundantBranchesEliminated, int, JIT_METADATA_HIGHER_IS_BETTER) JITMETADATAMETRIC(JumpThreadingsPerformed, int, JIT_METADATA_HIGHER_IS_BETTER) -JITMETADATAMETRIC(Cses, int, 0) +JITMETADATAMETRIC(CseCount, int, 0) JITMETADATAMETRIC(BasicBlocksAtCodegen, int, 0) JITMETADATAMETRIC(PerfScore, double, JIT_METADATA_LOWER_IS_BETTER) JITMETADATAMETRIC(BytesAllocated, int64_t, JIT_METADATA_LOWER_IS_BETTER) diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index ffc9557e736a7a..8c888db5de7c6d 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -4370,7 +4370,7 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate) // Record that we created a new LclVar for use as a CSE temp m_addCSEcount++; m_pCompiler->optCSEcount++; - m_pCompiler->Metrics.Cses++; + m_pCompiler->Metrics.CseCount++; // Walk all references to this CSE, adding an assignment // to the CSE temp to all defs and changing all refs to diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index d1bd90f1688f4c..4d291954fe4272 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3157,7 +3157,7 @@ private void reportRichMappings(InlineTreeNode* inlineTree, uint numInlineTree, } #pragma warning disable CA1822 // Mark members as static - private void reportMetadata(byte* key, void* value) + private void reportMetadata(byte* key, void* value, nuint length) #pragma warning restore CA1822 // Mark members as static { } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 2e4e617b40b9b7..7789862f5074a1 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1548,12 +1548,12 @@ private static void _reportRichMappings(IntPtr thisHandle, IntPtr* ppException, } [UnmanagedCallersOnly] - private static void _reportMetadata(IntPtr thisHandle, IntPtr* ppException, byte* key, void* value) + private static void _reportMetadata(IntPtr thisHandle, IntPtr* ppException, byte* key, void* value, UIntPtr length) { var _this = GetThis(thisHandle); try { - _this.reportMetadata(key, value); + _this.reportMetadata(key, value, length); } catch (Exception ex) { @@ -2671,7 +2671,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[101] = (delegate* unmanaged)&_getVars; callbacks[102] = (delegate* unmanaged)&_setVars; callbacks[103] = (delegate* unmanaged)&_reportRichMappings; - callbacks[104] = (delegate* unmanaged)&_reportMetadata; + callbacks[104] = (delegate* unmanaged)&_reportMetadata; callbacks[105] = (delegate* unmanaged)&_allocateArray; callbacks[106] = (delegate* unmanaged)&_freeArray; callbacks[107] = (delegate* unmanaged)&_getArgNext; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 4b7a3589abdf72..fda65c03b9ab17 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -266,7 +266,7 @@ FUNCTIONS void getVars(CORINFO_METHOD_HANDLE ftn, uint32_t* cVars, ICorDebugInfo::ILVarInfo** vars, bool* extendOthers) void setVars(CORINFO_METHOD_HANDLE ftn, uint32_t cVars, ICorDebugInfo::NativeVarInfo* vars) void reportRichMappings(ICorDebugInfo::InlineTreeNode* inlineTreeNodes, uint32_t numInlineTreeNodes, ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings) - void reportMetadata(const char* key, const void* value) + void reportMetadata(const char* key, const void* value, size_t length) void*allocateArray(size_t cBytes); void freeArray(void*array); CORINFO_ARG_LIST_HANDLE getArgNext(CORINFO_ARG_LIST_HANDLE args); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 6b17b4a552ffde..3723b57aa4d8e2 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -115,7 +115,7 @@ struct JitInterfaceCallbacks void (* getVars)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, uint32_t* cVars, ICorDebugInfo::ILVarInfo** vars, bool* extendOthers); void (* setVars)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, uint32_t cVars, ICorDebugInfo::NativeVarInfo* vars); void (* reportRichMappings)(void * thisHandle, CorInfoExceptionClass** ppException, ICorDebugInfo::InlineTreeNode* inlineTreeNodes, uint32_t numInlineTreeNodes, ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings); - void (* reportMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, const char* key, const void* value); + void (* reportMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, const char* key, const void* value, size_t length); void* (* allocateArray)(void * thisHandle, CorInfoExceptionClass** ppException, size_t cBytes); void (* freeArray)(void * thisHandle, CorInfoExceptionClass** ppException, void* array); CORINFO_ARG_LIST_HANDLE (* getArgNext)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_ARG_LIST_HANDLE args); @@ -1217,10 +1217,11 @@ class JitInterfaceWrapper : public ICorJitInfo virtual void reportMetadata( const char* key, - const void* value) + const void* value, + size_t length) { CorInfoExceptionClass* pException = nullptr; - _callbacks->reportMetadata(_thisHandle, &pException, key, value); + _callbacks->reportMetadata(_thisHandle, &pException, key, value, length); if (pException != nullptr) throw pException; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 5d95ff65b6950a..0cbcfb2df1b0b1 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1193,10 +1193,10 @@ void interceptor_ICJI::reportRichMappings(ICorDebugInfo::InlineTreeNode* inli original_ICorJitInfo->reportRichMappings(inlineTreeNodes, numInlineTreeNodes, mappings, numMappings); } -void interceptor_ICJI::reportMetadata(const char* key, const void* value) +void interceptor_ICJI::reportMetadata(const char* key, const void* value, size_t length) { mc->cr->AddCall("reportMetadata"); - original_ICorJitInfo->reportMetadata(key, value); + original_ICorJitInfo->reportMetadata(key, value, length); } /*-------------------------- Misc ---------------------------------------*/ diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index ed2dd8c79c4194..d3fe993b94765b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -847,10 +847,11 @@ void interceptor_ICJI::reportRichMappings( void interceptor_ICJI::reportMetadata( const char* key, - const void* value) + const void* value, + size_t length) { mcs->AddCall("reportMetadata"); - original_ICorJitInfo->reportMetadata(key, value); + original_ICorJitInfo->reportMetadata(key, value, length); } void* interceptor_ICJI::allocateArray( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 6242fb8b055ed7..f3cdc4ff8ce636 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -743,9 +743,10 @@ void interceptor_ICJI::reportRichMappings( void interceptor_ICJI::reportMetadata( const char* key, - const void* value) + const void* value, + size_t length) { - original_ICorJitInfo->reportMetadata(key, value); + original_ICorJitInfo->reportMetadata(key, value, length); } void* interceptor_ICJI::allocateArray( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index c8ed4b67930d33..2c0b79bab4fcd9 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1027,36 +1027,32 @@ void MyICJI::reportRichMappings( freeArray(mappings); } -void MyICJI::reportMetadata(const char* key, const void* value) +void MyICJI::reportMetadata(const char* key, const void* value, size_t length) { jitInstance->mc->cr->AddCall("reportMetadata"); if (strcmp(key, "MethodFullName") == 0) { - const char* str = static_cast(value); - size_t len = strlen(str); - char* buf = static_cast(jitInstance->mc->cr->allocateMemory(len + 1)); - memcpy(buf, str, len + 1); + char* buf = static_cast(jitInstance->mc->cr->allocateMemory(length + 1)); + memcpy(buf, value, length + 1); jitInstance->mc->cr->MethodFullName = buf; return; } if (strcmp(key, "TieringName") == 0) { - const char* str = static_cast(value); - size_t len = strlen(str); - char* buf = static_cast(jitInstance->mc->cr->allocateMemory(len + 1)); - memcpy(buf, str, len + 1); + char* buf = static_cast(jitInstance->mc->cr->allocateMemory(length + 1)); + memcpy(buf, value, length + 1); jitInstance->mc->cr->TieringName = buf; return; } #define JITMETADATAINFO(name, type, flags) #define JITMETADATAMETRIC(name, type, flags) \ - if (strcmp(key, #name) == 0) \ - { \ + if ((strcmp(key, #name) == 0) && (length == sizeof(type))) \ + { \ memcpy(&jitInstance->mc->cr->name, value, sizeof(type)); \ - return; \ + return; \ } #include "jitmetadatalist.h" diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c6031ee224577f..a2146482a2fc02 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10958,7 +10958,8 @@ void CEEJitInfo::reportRichMappings( void CEEJitInfo::reportMetadata( const char* key, - const void* value) + const void* value, + size_t length) { CONTRACTL { NOTHROW; @@ -14436,7 +14437,7 @@ void CEEInfo::reportRichMappings( UNREACHABLE(); // only called on derived class. } -void CEEInfo::reportMetadata(const char* key, const void* value) +void CEEInfo::reportMetadata(const char* key, const void* value, size_t length) { LIMITED_METHOD_CONTRACT; UNREACHABLE(); // only called on derived class. diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 277f39e8a80eac..63666b46552cf9 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -897,7 +897,7 @@ class CEEJitInfo : public CEEInfo ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings) override final; - void reportMetadata(const char* key, const void* value) override final; + void reportMetadata(const char* key, const void* value, size_t length) override final; void* getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ void ** ppIndirection) override final; /* OUT */