From aae7a39751eb4b63c46991a56e3bf5c65ea21715 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Wed, 31 Jan 2018 18:01:22 -0800 Subject: Add ETL flags for ReadyToRun (#15801) Add flags to track the presence of ReadyToRun codegen in an assembly and module. Add jitting flags to indicate when a method is jitted because the precompiled code was rejected, either by a profiler or by ReadyToRun dependence tracking. Together these can be used to distingish between * methods jitted because their assemblies were not precompiled * methods jitted because they were not precompiled in an otherwise precompiled assembly --- src/inc/eventtracebase.h | 12 ++++++++---- src/vm/eventtrace.cpp | 18 ++++++++++++------ src/vm/method.hpp | 10 ++++++++-- src/vm/prestub.cpp | 43 ++++++++++++++++++++++++++++++++++++------- src/vm/readytoruninfo.cpp | 9 ++++++++- src/vm/readytoruninfo.h | 4 +++- 6 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/inc/eventtracebase.h b/src/inc/eventtracebase.h index c29308d385..c46cb8abab 100644 --- a/src/inc/eventtracebase.h +++ b/src/inc/eventtracebase.h @@ -518,6 +518,7 @@ namespace ETW DynamicAssembly=0x2, NativeAssembly=0x4, CollectibleAssembly=0x8, + ReadyToRunAssembly=0x10, }AssemblyFlags; typedef enum _ModuleFlags @@ -526,7 +527,8 @@ namespace ETW NativeModule=0x2, DynamicModule=0x4, ManifestModule=0x8, - IbcOptimized=0x10 + IbcOptimized=0x10, + ReadyToRunModule=0x20, }ModuleFlags; typedef enum _RangeFlags @@ -575,7 +577,7 @@ namespace ETW static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, SIZE_T pCode, ReJITID rejitID); - static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0); + static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); public: typedef union _MethodStructs @@ -586,7 +588,9 @@ namespace ETW GenericMethod=0x2, SharedGenericCode=0x4, JittedMethod=0x8, - JitHelperMethod=0x10 + JitHelperMethod=0x10, + ProfilerRejectedPrecompiledCode=0x20, + ReadyToRunRejectedPrecompiledCode=0x40, }MethodFlags; typedef enum _MethodExtent @@ -598,7 +602,7 @@ namespace ETW }MethodStructs; static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); - static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, SIZE_T pCode = 0, ReJITID rejitID = 0, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName); static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers); static VOID MethodRestored(MethodDesc * pMethodDesc); diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index 5fb63c90fe..7da80608d7 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -5277,7 +5277,7 @@ HRESULT ETW::CodeSymbolLog::ReadInMemorySymbols( /*******************************************************/ /* This is called by the runtime when a method is jitted completely */ /*******************************************************/ -VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID) +VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID, BOOL bProfilerRejectedPrecompiledCode, BOOL bReadyToRunRejectedPrecompiledCode) { CONTRACTL { NOTHROW; @@ -5290,7 +5290,7 @@ VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD)) { - ETW::MethodLog::SendMethodEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodLoad, TRUE, namespaceOrClassName, methodName, methodSignature, pCode, rejitID); + ETW::MethodLog::SendMethodEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodLoad, TRUE, namespaceOrClassName, methodName, methodSignature, pCode, rejitID, bProfilerRejectedPrecompiledCode, bReadyToRunRejectedPrecompiledCode); } if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, @@ -5803,6 +5803,7 @@ VOID ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions BOOL bIsCollectibleAssembly = pAssembly->IsCollectible(); BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral() ; BOOL bHasNativeImage = pAssembly->GetManifestFile()->HasNativeImage(); + BOOL bIsReadyToRun = pAssembly->GetManifestFile()->IsILImageReadyToRun(); ULONGLONG ullAssemblyId = (ULONGLONG)pAssembly; ULONGLONG ullDomainId = (ULONGLONG)pAssembly->GetDomain(); @@ -5810,7 +5811,8 @@ VOID ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions ULONG ulAssemblyFlags = ((bIsDomainNeutral ? ETW::LoaderLog::LoaderStructs::DomainNeutralAssembly : 0) | (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicAssembly : 0) | (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeAssembly : 0) | - (bIsCollectibleAssembly ? ETW::LoaderLog::LoaderStructs::CollectibleAssembly : 0)); + (bIsCollectibleAssembly ? ETW::LoaderLog::LoaderStructs::CollectibleAssembly : 0) | + (bIsReadyToRun ? ETW::LoaderLog::LoaderStructs::ReadyToRunAssembly : 0)); SString sAssemblyPath; pAssembly->GetDisplayName(sAssemblyPath); @@ -6127,12 +6129,14 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL { bIsIbcOptimized = pModule->IsIbcOptimized(); } + BOOL bIsReadyToRun = pModule->IsReadyToRun(); ULONG ulReservedFlags = 0; ULONG ulFlags = ((bIsDomainNeutral ? ETW::LoaderLog::LoaderStructs::DomainNeutralModule : 0) | (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeModule : 0) | (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicModule : 0) | (bIsManifestModule ? ETW::LoaderLog::LoaderStructs::ManifestModule : 0) | - (bIsIbcOptimized ? ETW::LoaderLog::LoaderStructs::IbcOptimized : 0)); + (bIsIbcOptimized ? ETW::LoaderLog::LoaderStructs::IbcOptimized : 0) | + (bIsReadyToRun ? ETW::LoaderLog::LoaderStructs::ReadyToRunModule : 0)); // Grab PDB path, guid, and age for managed PDB and native (NGEN) PDB when // available. Any failures are not fatal. The corresponding PDB info will remain @@ -6318,7 +6322,7 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n /****************************************************************************/ /* This routine is used to send a method load/unload or rundown event */ /****************************************************************************/ -VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID) +VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID, BOOL bProfilerRejectedPrecompiledCode, BOOL bReadyToRunRejectedPrecompiledCode) { CONTRACTL { THROWS; @@ -6392,7 +6396,9 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio (bHasSharedGenericCode ? ETW::MethodLog::MethodStructs::SharedGenericCode : 0) | (bIsGenericMethod ? ETW::MethodLog::MethodStructs::GenericMethod : 0) | (bIsDynamicMethod ? ETW::MethodLog::MethodStructs::DynamicMethod : 0) | - (bIsJit ? ETW::MethodLog::MethodStructs::JittedMethod : 0))); + (bIsJit ? ETW::MethodLog::MethodStructs::JittedMethod : 0) | + (bProfilerRejectedPrecompiledCode ? ETW::MethodLog::MethodStructs::ProfilerRejectedPrecompiledCode : 0) | + (bReadyToRunRejectedPrecompiledCode ? ETW::MethodLog::MethodStructs::ReadyToRunRejectedPrecompiledCode : 0))); // 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 9791ddd4ad..664716b8b1 100644 --- a/src/vm/method.hpp +++ b/src/vm/method.hpp @@ -1865,8 +1865,8 @@ public: private: PCODE PrepareILBasedCode(PrepareCodeConfig* pConfig); PCODE GetPrecompiledCode(PrepareCodeConfig* pConfig); - PCODE GetPrecompiledNgenCode(); - PCODE GetPrecompiledR2RCode(); + PCODE GetPrecompiledNgenCode(PrepareCodeConfig* pConfig); + PCODE GetPrecompiledR2RCode(PrepareCodeConfig* pConfig); PCODE GetMulticoreJitCode(); COR_ILMETHOD_DECODER* GetAndVerifyILHeader(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory); COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory); @@ -1891,12 +1891,18 @@ public: virtual BOOL SetNativeCode(PCODE pCode, PCODE * ppAlternateCodeToUse); virtual COR_ILMETHOD* GetILHeader(); virtual CORJIT_FLAGS GetJitCompilationFlags(); + BOOL ProfilerRejectedPrecompiledCode(); + BOOL ReadyToRunRejectedPrecompiledCode(); + void SetProfilerRejectedPrecompiledCode(); + void SetReadyToRunRejectedPrecompiledCode(); protected: MethodDesc* m_pMethodDesc; NativeCodeVersion m_nativeCodeVersion; BOOL m_needsMulticoreJitNotification; BOOL m_mayUsePrecompiledCode; + BOOL m_ProfilerRejectedPrecompiledCode; + BOOL m_ReadyToRunRejectedPrecompiledCode; }; #ifdef FEATURE_CODE_VERSIONING diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index cd857134ab..99f6ebb05a 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -319,13 +319,13 @@ PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig) PCODE pCode = NULL; #ifdef FEATURE_PREJIT - pCode = GetPrecompiledNgenCode(); + pCode = GetPrecompiledNgenCode(pConfig); #endif #ifdef FEATURE_READYTORUN if (pCode == NULL) { - pCode = GetPrecompiledR2RCode(); + pCode = GetPrecompiledR2RCode(pConfig); if (pCode != NULL) { pConfig->SetNativeCode(pCode, &pCode); @@ -336,7 +336,7 @@ PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig) return pCode; } -PCODE MethodDesc::GetPrecompiledNgenCode() +PCODE MethodDesc::GetPrecompiledNgenCode(PrepareCodeConfig* pConfig) { STANDARD_VM_CONTRACT; PCODE pCode = NULL; @@ -371,6 +371,7 @@ PCODE MethodDesc::GetPrecompiledNgenCode() { SetNativeCodeInterlocked(NULL, pCode); _ASSERTE(!IsPreImplemented()); + pConfig->SetProfilerRejectedPrecompiledCode(); pCode = NULL; } } @@ -423,7 +424,7 @@ PCODE MethodDesc::GetPrecompiledNgenCode() } -PCODE MethodDesc::GetPrecompiledR2RCode() +PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) { STANDARD_VM_CONTRACT; @@ -432,7 +433,7 @@ PCODE MethodDesc::GetPrecompiledR2RCode() Module * pModule = GetModule(); if (pModule->IsReadyToRun()) { - pCode = pModule->GetReadyToRunInfo()->GetEntryPoint(this); + pCode = pModule->GetReadyToRunInfo()->GetEntryPoint(this, pConfig); } #endif return pCode; @@ -725,7 +726,9 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J &methodName, &methodSignature, pCode, - pConfig->GetCodeVersion().GetVersionId()); + pConfig->GetCodeVersion().GetVersionId(), + pConfig->ProfilerRejectedPrecompiledCode(), + pConfig->ReadyToRunRejectedPrecompiledCode()); } } @@ -910,7 +913,9 @@ PrepareCodeConfig::PrepareCodeConfig(NativeCodeVersion codeVersion, BOOL needsMu m_pMethodDesc(codeVersion.GetMethodDesc()), m_nativeCodeVersion(codeVersion), m_needsMulticoreJitNotification(needsMulticoreJitNotification), - m_mayUsePrecompiledCode(mayUsePrecompiledCode) + m_mayUsePrecompiledCode(mayUsePrecompiledCode), + m_ProfilerRejectedPrecompiledCode(FALSE), + m_ReadyToRunRejectedPrecompiledCode(FALSE) {} MethodDesc* PrepareCodeConfig::GetMethodDesc() @@ -931,6 +936,30 @@ BOOL PrepareCodeConfig::NeedsMulticoreJitNotification() return m_needsMulticoreJitNotification; } +BOOL PrepareCodeConfig::ProfilerRejectedPrecompiledCode() +{ + LIMITED_METHOD_CONTRACT; + return m_ProfilerRejectedPrecompiledCode; +} + +void PrepareCodeConfig::SetProfilerRejectedPrecompiledCode() +{ + LIMITED_METHOD_CONTRACT; + m_ProfilerRejectedPrecompiledCode = TRUE; +} + +BOOL PrepareCodeConfig::ReadyToRunRejectedPrecompiledCode() +{ + LIMITED_METHOD_CONTRACT; + return m_ReadyToRunRejectedPrecompiledCode; +} + +void PrepareCodeConfig::SetReadyToRunRejectedPrecompiledCode() +{ + LIMITED_METHOD_CONTRACT; + m_ReadyToRunRejectedPrecompiledCode = TRUE; +} + NativeCodeVersion PrepareCodeConfig::GetCodeVersion() { LIMITED_METHOD_CONTRACT; diff --git a/src/vm/readytoruninfo.cpp b/src/vm/readytoruninfo.cpp index bcb8e8364d..5e29aede86 100644 --- a/src/vm/readytoruninfo.cpp +++ b/src/vm/readytoruninfo.cpp @@ -15,6 +15,7 @@ #include "compile.h" #include "versionresilienthashcode.h" #include "typehashingalgorithms.h" +#include "method.hpp" using namespace NativeFormat; @@ -673,7 +674,7 @@ static bool SigMatchesMethodDesc(MethodDesc* pMD, SigPointer &sig, Module * pMod return true; } -PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) +PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig, BOOL fFixups /*=TRUE*/) { STANDARD_VM_CONTRACT; @@ -727,6 +728,7 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) } if (!fShouldSearchCache) { + pConfig->SetProfilerRejectedPrecompiledCode(); return NULL; } #endif // PROFILING_SUPPORTED @@ -747,7 +749,12 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) if (fFixups) { if (!m_pModule->FixupDelayList(dac_cast(m_pLayout->GetBase()) + offset)) + { +#ifndef CROSSGEN_COMPILE + pConfig->SetReadyToRunRejectedPrecompiledCode(); +#endif // CROSSGEN_COMPILE return NULL; + } } id >>= 2; diff --git a/src/vm/readytoruninfo.h b/src/vm/readytoruninfo.h index 2266e9c119..c7eab9e8d7 100644 --- a/src/vm/readytoruninfo.h +++ b/src/vm/readytoruninfo.h @@ -17,6 +17,8 @@ typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; +class PrepareCodeConfig; + typedef DPTR(class ReadyToRunInfo) PTR_ReadyToRunInfo; class ReadyToRunInfo { @@ -50,7 +52,7 @@ public: static PTR_ReadyToRunInfo Initialize(Module * pModule, AllocMemTracker *pamTracker); - PCODE GetEntryPoint(MethodDesc * pMD, BOOL fFixups = TRUE); + PCODE GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig, BOOL fFixups = TRUE); MethodDesc * GetMethodDescForEntryPoint(PCODE entryPoint); -- cgit v1.2.3