Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 102 additions & 52 deletions src/coreclr/vm/perfmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "perfinfo.h"
#include "pal.h"


// The code addresses are actually native image offsets during crossgen. Print
// them as 32-bit numbers for consistent output when cross-targeting and to
// make the output more compact.
Expand All @@ -21,14 +22,23 @@
Volatile<bool> PerfMap::s_enabled = false;
PerfMap * PerfMap::s_Current = nullptr;
bool PerfMap::s_ShowOptimizationTiers = false;
unsigned PerfMap::s_StubsMapped = 0;

enum
{
DISABLED,
ALL,
JITDUMP,
PERFMAP
};

// Initialize the map for the process - called from EEStartupHelper.
void PerfMap::Initialize()
{
LIMITED_METHOD_CONTRACT;

// Only enable the map if requested.
if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled))
if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == ALL || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == PERFMAP)
{
// Get the current process id.
int currentPid = GetCurrentProcessId();
Expand All @@ -49,7 +59,10 @@ void PerfMap::Initialize()
}

s_enabled = true;
}

if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == ALL || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapEnabled) == JITDUMP)
{
const char* jitdumpPath;
char jitdumpPathBuffer[4096];

Expand All @@ -65,6 +78,13 @@ void PerfMap::Initialize()
}

PAL_PerfJitDump_Start(jitdumpPath);

if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerfMapShowOptimizationTiers) != 0)
{
s_ShowOptimizationTiers = true;
}

s_enabled = true;
}
}

Expand All @@ -89,8 +109,6 @@ PerfMap::PerfMap(int pid)
// Initialize with no failures.
m_ErrorEncountered = false;

m_StubsMapped = 0;

// Build the path to the map file on disk.
WCHAR tempPath[MAX_LONGPATH+1];
if(!GetTempPathW(MAX_LONGPATH, tempPath))
Expand All @@ -117,8 +135,6 @@ PerfMap::PerfMap()

// Initialize with no failures.
m_ErrorEncountered = false;

m_StubsMapped = 0;
}

// Clean-up resources.
Expand Down Expand Up @@ -156,6 +172,11 @@ void PerfMap::WriteLine(SString& line)
{
STANDARD_VM_CONTRACT;

if (m_FileStream == nullptr || m_ErrorEncountered)
{
return;
}

EX_TRY
{
// Write the line.
Expand All @@ -176,50 +197,9 @@ void PerfMap::WriteLine(SString& line)
EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
}

// Log a method to the map.
void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier)
{
CONTRACTL{
THROWS;
GC_NOTRIGGER;
MODE_PREEMPTIVE;
PRECONDITION(pMethod != nullptr);
PRECONDITION(pCode != nullptr);
PRECONDITION(codeSize > 0);
} CONTRACTL_END;

if (m_FileStream == nullptr || m_ErrorEncountered)
{
// A failure occurred, do not log.
return;
}

// Logging failures should not cause any exceptions to flow upstream.
EX_TRY
{
// Get the full method signature.
SString name;
pMethod->GetFullMethodInfo(name);

// Build the map file line.
if (optimizationTier != nullptr && s_ShowOptimizationTiers)
{
name.AppendPrintf("[%s]", optimizationTier);
}
SString line;
line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8());

// Write the line.
WriteLine(line);
PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr);
}
EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
}


void PerfMap::LogImageLoad(PEAssembly * pPEAssembly)
{
if (s_enabled)
if (s_enabled && s_Current != nullptr)
{
s_Current->LogImage(pPEAssembly);
}
Expand Down Expand Up @@ -258,6 +238,15 @@ void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t cod
{
LIMITED_METHOD_CONTRACT;

CONTRACTL{
THROWS;
GC_NOTRIGGER;
MODE_PREEMPTIVE;
PRECONDITION(pMethod != nullptr);
PRECONDITION(pCode != nullptr);
PRECONDITION(codeSize > 0);
} CONTRACTL_END;

if (!s_enabled)
{
return;
Expand All @@ -269,7 +258,31 @@ void PerfMap::LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t cod
optimizationTier = PrepareCodeConfig::GetJitOptimizationTierStr(pConfig, pMethod);
}

s_Current->LogMethod(pMethod, pCode, codeSize, optimizationTier);
// Logging failures should not cause any exceptions to flow upstream.
EX_TRY
{
// Get the full method signature.
SString name;
pMethod->GetFullMethodInfo(name);

// Build the map file line.
if (optimizationTier != nullptr && s_ShowOptimizationTiers)
{
name.AppendPrintf("[%s]", optimizationTier);
}

SString line;
line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8());

// Write the line.
if(s_Current != nullptr)
{
s_Current->WriteLine(line);
}
PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr);
}
EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);

}

// Log a pre-compiled method to the perfmap.
Expand Down Expand Up @@ -326,7 +339,7 @@ void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode,
{
LIMITED_METHOD_CONTRACT;

if (!s_enabled || s_Current->m_FileStream == nullptr)
if (!s_enabled)
{
return;
}
Expand All @@ -344,13 +357,15 @@ void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode,
}

SString name;
// Build the map file line.
name.Printf("stub<%d> %s<%s>", ++(s_Current->m_StubsMapped), stubType, stubOwner);
name.Printf("stub<%d> %s<%s>", ++(s_StubsMapped), stubType, stubOwner);
SString line;
line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8());

// Write the line.
s_Current->WriteLine(line);
if(s_Current != nullptr)
{
s_Current->WriteLine(line);
}
PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr);
}
EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
Expand Down Expand Up @@ -407,6 +422,41 @@ NativeImagePerfMap::NativeImagePerfMap(Assembly * pAssembly, BSTR pDestPath)
}
}

void NativeImagePerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier)
{
CONTRACTL{
THROWS;
GC_NOTRIGGER;
MODE_PREEMPTIVE;
PRECONDITION(pMethod != nullptr);
PRECONDITION(pCode != nullptr);
PRECONDITION(codeSize > 0);
} CONTRACTL_END;

// Logging failures should not cause any exceptions to flow upstream.
EX_TRY
{
// Get the full method signature.
SString name;
pMethod->GetFullMethodInfo(name);

// Build the map file line.
if (optimizationTier != nullptr && s_ShowOptimizationTiers)
{
name.AppendPrintf("[%s]", optimizationTier);
}
SString line;
line.Printf(FMT_CODE_ADDR " %x %s\n", pCode, codeSize, name.GetUTF8());

if (s_Current != nullptr)
{
s_Current->WriteLine(line);
}
PAL_PerfJitDump_LogMethod((void*)pCode, codeSize, name.GetUTF8(), nullptr, nullptr);
}
EX_CATCH{} EX_END_CATCH(SwallowAllExceptions);
}

// Log data to the perfmap for the specified module.
void NativeImagePerfMap::LogDataForModule(Module * pModule)
{
Expand Down
28 changes: 14 additions & 14 deletions src/coreclr/vm/perfmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ class PerfMap
private:
static Volatile<bool> s_enabled;

// 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;
// Set to true if an error is encountered when writing to the file.
static unsigned s_StubsMapped;

// The file stream to write the map to.
CFileStream * m_FileStream;
Expand All @@ -33,16 +30,16 @@ class PerfMap
// Set to true if an error is encountered when writing to the file.
bool m_ErrorEncountered;

// Set to true if an error is encountered when writing to the file.
unsigned m_StubsMapped;

// Construct a new map for the specified pid.
PerfMap(int pid);

// Write a line to the map file.
void WriteLine(SString & line);

protected:
// Indicates whether optimization tiers should be shown for methods in perf maps
static bool s_ShowOptimizationTiers;

// The one and only PerfMap for the process.
static PerfMap * s_Current;

// Construct a new map without a specified file name.
// Used for offline creation of NGEN map files.
PerfMap();
Expand All @@ -53,16 +50,16 @@ class PerfMap
// Open the perf map file for write.
void OpenFile(SString& path);

// Does the actual work to log a method to the map.
void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier);

// Does the actual work to log an image
void LogImage(PEAssembly * pPEAssembly);

// Get the image signature and store it as a string.
static void GetNativeImageSignature(PEAssembly * pPEAssembly, WCHAR * pwszSig, unsigned int nSigSize);

public:
// Write a line to the map file.
void WriteLine(SString & line);

// Initialize the map for the current process.
static void Initialize();

Expand Down Expand Up @@ -91,6 +88,9 @@ class NativeImagePerfMap : PerfMap
// Specify the address format since it's now possible for 'perf script' to output file offsets or RVAs.
bool m_EmitRVAs;

// Does the actual work to log a method to the map.
void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier);

// Log a pre-compiled method to the map.
void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, PEImageLayout *pLoadedLayout, const char *optimizationTier);

Expand Down