summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/inc/clrconfigvalues.h1
-rw-r--r--src/inc/eventtracebase.h11
-rw-r--r--src/vm/eventtrace.cpp52
-rw-r--r--src/vm/method.hpp17
-rw-r--r--src/vm/perfmap.cpp44
-rw-r--r--src/vm/perfmap.h9
-rw-r--r--src/vm/prestub.cpp63
7 files changed, 124 insertions, 73 deletions
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h
index 03c6569a7b..7713af5040 100644
--- a/src/inc/clrconfigvalues.h
+++ b/src/inc/clrconfigvalues.h
@@ -569,6 +569,7 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("Pro
#ifdef FEATURE_PERFMAP
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default", CLRConfig::REGUTIL_default)
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.")
#endif
RETAIL_CONFIG_STRING_INFO(EXTERNAL_StartupDelayMS, W("StartupDelayMS"), "")
diff --git a/src/inc/eventtracebase.h b/src/inc/eventtracebase.h
index b4be4dfbc6..43cc99a7ee 100644
--- a/src/inc/eventtracebase.h
+++ b/src/inc/eventtracebase.h
@@ -607,17 +607,6 @@ namespace ETW
}MethodStructs;
- enum class JitOptimizationTier
- {
- Unknown, // to identify older runtimes that would send this value
- MinOptJitted,
- Optimized,
- QuickJitted,
- OptimizedTier1,
-
- Count
- };
-
static const UINT8 MethodFlagsJitOptimizationTierShift = 7;
static const unsigned int MethodFlagsJitOptimizationTierLowMask = 0x7;
diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp
index 8489fff559..400fdf208f 100644
--- a/src/vm/eventtrace.cpp
+++ b/src/vm/eventtrace.cpp
@@ -6322,7 +6322,6 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio
if(pMethodDesc->GetMethodTable_NoLogging())
bIsGenericMethod = pMethodDesc->HasClassOrMethodInstantiation_NoLogging();
- int jitOptimizationTier = -1;
NativeCodeVersionId nativeCodeId = 0;
ulMethodFlags = ulMethodFlags |
(bHasSharedGenericCode ? ETW::MethodLog::MethodStructs::SharedGenericCode : 0) |
@@ -6340,59 +6339,16 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio
ulMethodFlags |= ETW::MethodLog::MethodStructs::ReadyToRunRejectedPrecompiledCode;
}
- if (pConfig->JitSwitchedToMinOpt())
- {
- jitOptimizationTier = (int)JitOptimizationTier::MinOptJitted;
- }
-#ifdef FEATURE_TIERED_COMPILATION
- else if (pConfig->JitSwitchedToOptimized())
- {
- _ASSERTE(pMethodDesc->IsEligibleForTieredCompilation());
- _ASSERTE(pConfig->GetCodeVersion().GetOptimizationTier() == NativeCodeVersion::OptimizationTierOptimized);
- jitOptimizationTier = (int)JitOptimizationTier::Optimized;
- }
- else if (pMethodDesc->IsEligibleForTieredCompilation())
- {
- switch (pConfig->GetCodeVersion().GetOptimizationTier())
- {
- case NativeCodeVersion::OptimizationTier0:
- jitOptimizationTier = (int)JitOptimizationTier::QuickJitted;
- break;
-
- case NativeCodeVersion::OptimizationTier1:
- jitOptimizationTier = (int)JitOptimizationTier::OptimizedTier1;
- break;
-
- case NativeCodeVersion::OptimizationTierOptimized:
- jitOptimizationTier = (int)JitOptimizationTier::Optimized;
- break;
-
- default:
- UNREACHABLE();
- }
- }
-#endif
-
#ifdef FEATURE_CODE_VERSIONING
nativeCodeId = pConfig->GetCodeVersion().GetVersionId();
#endif
}
- if (jitOptimizationTier < 0)
- {
- if (pMethodDesc->IsJitOptimizationDisabled())
- {
- jitOptimizationTier = (int)JitOptimizationTier::MinOptJitted;
- }
- else
- {
- jitOptimizationTier = (int)JitOptimizationTier::Optimized;
- }
- }
- static_assert_no_msg((unsigned int)JitOptimizationTier::Count - 1 <= MethodFlagsJitOptimizationTierLowMask);
- _ASSERTE((unsigned int)jitOptimizationTier <= MethodFlagsJitOptimizationTierLowMask);
+ unsigned int jitOptimizationTier = (unsigned int)PrepareCodeConfig::GetJitOptimizationTier(pConfig, pMethodDesc);
+ static_assert_no_msg((unsigned int)PrepareCodeConfig::JitOptimizationTier::Count - 1 <= MethodFlagsJitOptimizationTierLowMask);
+ _ASSERTE(jitOptimizationTier <= MethodFlagsJitOptimizationTierLowMask);
_ASSERTE(((ulMethodFlags >> MethodFlagsJitOptimizationTierShift) & MethodFlagsJitOptimizationTierLowMask) == 0);
- ulMethodFlags |= (unsigned int)jitOptimizationTier << MethodFlagsJitOptimizationTierShift;
+ ulMethodFlags |= jitOptimizationTier << MethodFlagsJitOptimizationTierShift;
// Intentionally set the extent flags (cold vs. hot) only after all the other common
// flags (above) have been set.
diff --git a/src/vm/method.hpp b/src/vm/method.hpp
index 3122e4e91a..e77ff9ce4c 100644
--- a/src/vm/method.hpp
+++ b/src/vm/method.hpp
@@ -2068,6 +2068,21 @@ public:
void SetReadyToRunRejectedPrecompiledCode();
#ifndef CROSSGEN_COMPILE
+public:
+ enum class JitOptimizationTier : UINT8
+ {
+ Unknown, // to identify older runtimes that would send this value
+ MinOptJitted,
+ Optimized,
+ QuickJitted,
+ OptimizedTier1,
+
+ Count
+ };
+
+ static JitOptimizationTier GetJitOptimizationTier(PrepareCodeConfig *config, MethodDesc *methodDesc);
+ static const char *GetJitOptimizationTierStr(PrepareCodeConfig *config, MethodDesc *methodDesc);
+
bool JitSwitchedToMinOpt() const
{
LIMITED_METHOD_CONTRACT;
@@ -2085,6 +2100,7 @@ public:
}
#ifdef FEATURE_TIERED_COMPILATION
+public:
bool JitSwitchedToOptimized() const
{
LIMITED_METHOD_CONTRACT;
@@ -2102,6 +2118,7 @@ public:
}
#endif
+public:
PrepareCodeConfig *GetNextInSameThread() const
{
LIMITED_METHOD_CONTRACT;
diff --git a/src/vm/perfmap.cpp b/src/vm/perfmap.cpp
index 593ab8d1c4..968e93789b 100644
--- a/src/vm/perfmap.cpp
+++ b/src/vm/perfmap.cpp
@@ -23,6 +23,7 @@
#endif
PerfMap * PerfMap::s_Current = nullptr;
+bool PerfMap::s_ShowOptimizationTiers = false;
// Initialize the map for the process - called from EEStartupHelper.
void PerfMap::Initialize()
@@ -44,6 +45,11 @@ void PerfMap::Initialize()
{
PAL_IgnoreProfileSignal(signalNum);
}
+
+ if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0)
+ {
+ s_ShowOptimizationTiers = true;
+ }
}
}
@@ -156,7 +162,7 @@ void PerfMap::WriteLine(SString& line)
}
// Log a method to the map.
-void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize)
+void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier)
{
CONTRACTL{
THROWS;
@@ -183,7 +189,15 @@ void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize)
// Build the map file line.
StackScratchBuffer scratch;
SString line;
- line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, fullMethodSignature.GetANSI(scratch));
+ line.Printf(FMT_CODE_ADDR " %x %s", pCode, codeSize, fullMethodSignature.GetANSI(scratch));
+ if (optimizationTier != nullptr && s_ShowOptimizationTiers)
+ {
+ line.AppendPrintf("[%s]\n", optimizationTier);
+ }
+ else
+ {
+ line.Append(W('\n'));
+ }
// Write the line.
WriteLine(line);
@@ -229,14 +243,24 @@ void PerfMap::LogImage(PEFile * pFile)
// Log a method to the map.
-void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize)
+void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig)
{
LIMITED_METHOD_CONTRACT;
- if (s_Current != nullptr)
+ if (s_Current == nullptr)
+ {
+ return;
+ }
+
+ const char *optimizationTier = nullptr;
+#ifndef CROSSGEN_COMPILE
+ if (s_ShowOptimizationTiers)
{
- s_Current->LogMethod(pMethod, pCode, codeSize);
+ optimizationTier = PrepareCodeConfig::GetJitOptimizationTierStr(pConfig, pMethod);
}
+#endif // CROSSGEN_COMPILE
+
+ s_Current->LogMethod(pMethod, pCode, codeSize, optimizationTier);
}
// Log a set of stub to the map.
@@ -333,7 +357,7 @@ void NativeImagePerfMap::LogDataForModule(Module * pModule)
MethodDesc *hotDesc = mi.GetMethodDesc();
hotDesc->CheckRestore();
- LogPreCompiledMethod(hotDesc, mi.GetMethodStartAddress(), baseAddr);
+ LogPreCompiledMethod(hotDesc, mi.GetMethodStartAddress(), baseAddr, nullptr);
}
return;
}
@@ -344,12 +368,12 @@ void NativeImagePerfMap::LogDataForModule(Module * pModule)
{
MethodDesc* hotDesc = mi.GetMethodDesc();
- LogPreCompiledMethod(hotDesc, mi.GetMethodStartAddress(), baseAddr);
+ LogPreCompiledMethod(hotDesc, mi.GetMethodStartAddress(), baseAddr, "ReadyToRun");
}
}
// Log a pre-compiled method to the perfmap.
-void NativeImagePerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, SIZE_T baseAddr)
+void NativeImagePerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, SIZE_T baseAddr, const char *optimizationTier)
{
STANDARD_VM_CONTRACT;
@@ -364,12 +388,12 @@ void NativeImagePerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode,
// Emit an entry for each section if it is used.
if (methodRegionInfo.hotSize > 0)
{
- LogMethod(pMethod, (PCODE)methodRegionInfo.hotStartAddress - baseAddr, methodRegionInfo.hotSize);
+ LogMethod(pMethod, (PCODE)methodRegionInfo.hotStartAddress - baseAddr, methodRegionInfo.hotSize, optimizationTier);
}
if (methodRegionInfo.coldSize > 0)
{
- LogMethod(pMethod, (PCODE)methodRegionInfo.coldStartAddress - baseAddr, methodRegionInfo.coldSize);
+ LogMethod(pMethod, (PCODE)methodRegionInfo.coldStartAddress - baseAddr, methodRegionInfo.coldSize, optimizationTier);
}
}
diff --git a/src/vm/perfmap.h b/src/vm/perfmap.h
index 1f06bd4091..23f1812b8e 100644
--- a/src/vm/perfmap.h
+++ b/src/vm/perfmap.h
@@ -19,6 +19,9 @@ private:
// The one and only PerfMap for the process.
static PerfMap * s_Current;
+ // Indicates whether optimization tiers should be shown for methods in perf maps
+ static bool s_ShowOptimizationTiers;
+
// The file stream to write the map to.
CFileStream * m_FileStream;
@@ -49,7 +52,7 @@ protected:
void OpenFile(SString& path);
// Does the actual work to log a method to the map.
- void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize);
+ void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier);
// Does the actual work to log an image
void LogImage(PEFile * pFile);
@@ -65,7 +68,7 @@ public:
static void LogImageLoad(PEFile * pFile);
// Log a JIT compiled method to the map.
- static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize);
+ static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig);
// Log a set of stub to the map.
static void LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, size_t codeSize);
@@ -79,7 +82,7 @@ class NativeImagePerfMap : PerfMap
{
private:
// Log a pre-compiled method to the map.
- void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, SIZE_T baseAddr);
+ void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, SIZE_T baseAddr, const char *optimizationTier);
public:
// Construct a new map for a native image.
diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp
index 056fdb7a01..d83c419e22 100644
--- a/src/vm/prestub.cpp
+++ b/src/vm/prestub.cpp
@@ -867,7 +867,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
{
#ifdef FEATURE_PERFMAP
// Save the JIT'd method information so that perf can resolve JIT'd call frames.
- PerfMap::LogJITCompiledMethod(this, pCode, sizeOfCode);
+ PerfMap::LogJITCompiledMethod(this, pCode, sizeOfCode, pConfig);
#endif
}
@@ -1143,6 +1143,67 @@ BOOL PrepareCodeConfig::MayUsePrecompiledCode()
return m_mayUsePrecompiledCode;
}
+PrepareCodeConfig::JitOptimizationTier PrepareCodeConfig::GetJitOptimizationTier(
+ PrepareCodeConfig *config,
+ MethodDesc *methodDesc)
+{
+ WRAPPER_NO_CONTRACT;
+ _ASSERTE(methodDesc != nullptr);
+ _ASSERTE(config == nullptr || methodDesc == config->GetMethodDesc());
+
+ if (config != nullptr)
+ {
+ if (config->JitSwitchedToMinOpt())
+ {
+ return JitOptimizationTier::MinOptJitted;
+ }
+ #ifdef FEATURE_TIERED_COMPILATION
+ else if (config->JitSwitchedToOptimized())
+ {
+ _ASSERTE(methodDesc->IsEligibleForTieredCompilation());
+ _ASSERTE(config->GetCodeVersion().GetOptimizationTier() == NativeCodeVersion::OptimizationTierOptimized);
+ return JitOptimizationTier::Optimized;
+ }
+ else if (methodDesc->IsEligibleForTieredCompilation())
+ {
+ switch (config->GetCodeVersion().GetOptimizationTier())
+ {
+ case NativeCodeVersion::OptimizationTier0:
+ return JitOptimizationTier::QuickJitted;
+
+ case NativeCodeVersion::OptimizationTier1:
+ return JitOptimizationTier::OptimizedTier1;
+
+ case NativeCodeVersion::OptimizationTierOptimized:
+ return JitOptimizationTier::Optimized;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+ #endif
+ }
+
+ return methodDesc->IsJitOptimizationDisabled() ? JitOptimizationTier::MinOptJitted : JitOptimizationTier::Optimized;
+}
+
+const char *PrepareCodeConfig::GetJitOptimizationTierStr(PrepareCodeConfig *config, MethodDesc *methodDesc)
+{
+ WRAPPER_NO_CONTRACT;
+
+ switch (GetJitOptimizationTier(config, methodDesc))
+ {
+ case JitOptimizationTier::Unknown: return "Unknown";
+ case JitOptimizationTier::MinOptJitted: return "MinOptJitted";
+ case JitOptimizationTier::Optimized: return "Optimized";
+ case JitOptimizationTier::QuickJitted: return "QuickJitted";
+ case JitOptimizationTier::OptimizedTier1: return "OptimizedTier1";
+
+ default:
+ UNREACHABLE();
+ }
+}
+
#ifdef FEATURE_CODE_VERSIONING
VersionedPrepareCodeConfig::VersionedPrepareCodeConfig() {}