diff options
author | Koundinya Veluri <kouvel@users.noreply.github.com> | 2019-05-08 19:16:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-08 19:16:16 -0700 |
commit | 93ec324ee831cd4db087ae985c5b3a814ba8abb3 (patch) | |
tree | 350a6362ac2548c390d1294c3388150f7626fa28 | |
parent | 54affc4d950184a11f7815eaa418cba5fe0a9a36 (diff) | |
download | coreclr-93ec324ee831cd4db087ae985c5b3a814ba8abb3.tar.gz coreclr-93ec324ee831cd4db087ae985c5b3a814ba8abb3.tar.bz2 coreclr-93ec324ee831cd4db087ae985c5b3a814ba8abb3.zip |
Fix ETL event rejit IDs and sending of the IL to native map event when code versioning is in use (#24422)
Fix ETL event rejit IDs and sending of the IL to native map event when code versioning is in use
Fixes https://github.com/dotnet/coreclr/issues/22904
Fixes https://github.com/dotnet/coreclr/issues/22908
- Method events now always send the native code ID for the rejit ID, and the IL to native map event continues to send the IL code ID
- Took code versioning into account when sending rundown events for a method including the IL to native map
-rw-r--r-- | src/debug/ee/debugger.cpp | 16 | ||||
-rw-r--r-- | src/debug/ee/debugger.h | 2 | ||||
-rw-r--r-- | src/debug/ee/functioninfo.cpp | 1 | ||||
-rw-r--r-- | src/inc/eventtracebase.h | 14 | ||||
-rw-r--r-- | src/vm/dbginterface.h | 2 | ||||
-rw-r--r-- | src/vm/eventtrace.cpp | 200 | ||||
-rw-r--r-- | src/vm/prestub.cpp | 1 |
7 files changed, 126 insertions, 110 deletions
diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp index 235a937cd6..c6ce925ec5 100644 --- a/src/debug/ee/debugger.cpp +++ b/src/debug/ee/debugger.cpp @@ -3079,7 +3079,7 @@ HRESULT Debugger::GetILToNativeMapping(PCODE pNativeCodeStartAddress, ULONG32 cM HRESULT Debugger::GetILToNativeMappingIntoArrays( MethodDesc * pMethodDesc, - PCODE pCode, + PCODE pNativeCodeStartAddress, USHORT cMapMax, USHORT * pcMap, UINT ** prguiILOffset, @@ -3092,6 +3092,7 @@ HRESULT Debugger::GetILToNativeMappingIntoArrays( } CONTRACTL_END; + _ASSERTE(pMethodDesc != NULL); _ASSERTE(pcMap != NULL); _ASSERTE(prguiILOffset != NULL); _ASSERTE(prguiNativeOffset != NULL); @@ -3102,7 +3103,18 @@ HRESULT Debugger::GetILToNativeMappingIntoArrays( // Get the JIT info by functionId. - DebuggerJitInfo * pDJI = GetJitInfo(pMethodDesc, (const BYTE *)pCode); + if (pMethodDesc->IsWrapperStub() || pMethodDesc->IsDynamicMethod()) + { + return E_FAIL; + } + + DebuggerMethodInfo *pDMI = GetOrCreateMethodInfo(pMethodDesc->GetModule(), pMethodDesc->GetMemberDef()); + if (pDMI == NULL) + { + return E_FAIL; + } + + DebuggerJitInfo *pDJI = pDMI->FindOrCreateInitAndAddJitInfo(pMethodDesc, pNativeCodeStartAddress); // Dunno what went wrong if (pDJI == NULL) diff --git a/src/debug/ee/debugger.h b/src/debug/ee/debugger.h index 8386a227eb..67180c0a27 100644 --- a/src/debug/ee/debugger.h +++ b/src/debug/ee/debugger.h @@ -2031,7 +2031,7 @@ public: HRESULT GetILToNativeMappingIntoArrays( MethodDesc * pMethodDesc, - PCODE pCode, + PCODE pNativeCodeStartAddress, USHORT cMapMax, USHORT * pcMap, UINT ** prguiILOffset, diff --git a/src/debug/ee/functioninfo.cpp b/src/debug/ee/functioninfo.cpp index 1bbcde2c54..7638180530 100644 --- a/src/debug/ee/functioninfo.cpp +++ b/src/debug/ee/functioninfo.cpp @@ -1584,6 +1584,7 @@ DebuggerJitInfo *DebuggerMethodInfo::FindOrCreateInitAndAddJitInfo(MethodDesc* f else { _ASSERTE(g_pEEInterface->GetNativeCodeMethodDesc(startAddr) == fd); + _ASSERTE(g_pEEInterface->GetNativeCodeStartAddress(startAddr) == startAddr); } // Check the lsit to see if we've already populated an entry for this JitInfo. diff --git a/src/inc/eventtracebase.h b/src/inc/eventtracebase.h index 12a4201a32..5a92d98fd9 100644 --- a/src/inc/eventtracebase.h +++ b/src/inc/eventtracebase.h @@ -31,6 +31,8 @@ struct EventStructTypeData; void InitializeEventTracing(); +typedef DWORD NativeCodeVersionId; // keep in sync with codeversion.h + // !!!!!!! NOTE !!!!!!!! // The flags must match those in the ETW manifest exactly // !!!!!!! NOTE !!!!!!!! @@ -569,18 +571,18 @@ namespace ETW friend class ETW::EnumerationLog; #ifdef FEATURE_EVENT_TRACE static VOID SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); - static VOID SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, + static VOID SendEventsForJitMethodsHelper( LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions, BOOL fLoadOrDCStart, BOOL fUnloadOrDCEnd, BOOL fSendMethodEvent, BOOL fSendILToNativeMapEvent, - BOOL fGetReJitIDs); + BOOL fGetCodeIds); 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, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); + static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, ReJITID ilCodeId); + static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, NativeCodeVersionId nativeCodeId = 0, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); public: typedef union _MethodStructs @@ -606,7 +608,7 @@ namespace ETW static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint); 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, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, ReJITID ilCodeId = 0, NativeCodeVersionId nativeCodeId = 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); @@ -616,7 +618,7 @@ namespace ETW public: static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {}; 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, BOOL bProfilerRejectedPrecompiledCode = FALSE, BOOL bReadyToRunRejectedPrecompiledCode = FALSE) {}; + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, ReJITID ilCodeId = 0, NativeCodeVersionId nativeCodeId = 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/dbginterface.h b/src/vm/dbginterface.h index 13231c0f5f..ebf85e397a 100644 --- a/src/vm/dbginterface.h +++ b/src/vm/dbginterface.h @@ -286,7 +286,7 @@ public: virtual HRESULT GetILToNativeMappingIntoArrays( MethodDesc * pMethodDesc, - PCODE pCode, + PCODE pNativeCodeStartAddress, USHORT cMapMax, USHORT * pcMap, UINT ** prguiILOffset, diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp index c145584551..a4e7d6ffe4 100644 --- a/src/vm/eventtrace.cpp +++ b/src/vm/eventtrace.cpp @@ -61,83 +61,83 @@ Volatile<LONGLONG> ETW::GCLog::s_l64LastClientSequenceNumber = 0; //--------------------------------------------------------------------------------------- // Helper macros to determine which version of the Method events to use // -// The V2 versions of these events include the ReJITID, the V1 versions do not. +// The V2 versions of these events include the NativeCodeId, the V1 versions do not. // Historically, when we version events, we'd just stop sending the old version and only // send the new one. However, now that we have xperf in heavy use internally and soon to be // used externally, we need to be a bit careful. In particular, we'd like to allow -// current xperf to continue working without knowledge of ReJITIDs, and allow future +// current xperf to continue working without knowledge of NativeCodeIds, and allow future // xperf to decode symbols in ReJITted functions. Thus, // * During a first-JIT, only issue the existing V1 MethodLoad, etc. events (NOT v0, -// NOT v2). This event does not include a ReJITID, and can thus continue to be +// NOT v2). This event does not include a NativeCodeId, and can thus continue to be // parsed by older decoders. // * During a rejit, only issue the new V2 events (NOT v0 or v1), which will include a -// nonzero ReJITID. Thus, your unique key for a method extent would be MethodID + -// ReJITID + extent (hot/cold). These events will be ignored by older decoders +// nonzero NativeCodeId. Thus, your unique key for a method extent would be MethodID + +// NativeCodeId + extent (hot/cold). These events will be ignored by older decoders // (including current xperf) because of the version number, but xperf will be // updated to decode these in the future. -#define FireEtwMethodLoadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID) \ +#define FireEtwMethodLoadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodLoadVerbose_V1(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID); } \ else \ - { FireEtwMethodLoadVerbose_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID); } \ + { FireEtwMethodLoadVerbose_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodLoad_V1_or_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, clrInstanceID, rejitID) \ +#define FireEtwMethodLoad_V1_or_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodLoad_V1(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, clrInstanceID); } \ else \ - { FireEtwMethodLoad_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, clrInstanceID, rejitID); } \ + { FireEtwMethodLoad_V2(ullMethodIdentifier, ullModuleID, ullMethodStartAddress, ulMethodSize, ulMethodToken, ulMethodFlags, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodUnloadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID) \ +#define FireEtwMethodUnloadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodUnloadVerbose_V1(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID); } \ else \ - { FireEtwMethodUnloadVerbose_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID); } \ + { FireEtwMethodUnloadVerbose_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodUnload_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, rejitID) \ +#define FireEtwMethodUnload_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodUnload_V1(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID); } \ else \ - { FireEtwMethodUnload_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, rejitID); } \ + { FireEtwMethodUnload_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodDCStartVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID) \ +#define FireEtwMethodDCStartVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodDCStartVerbose_V1(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID); } \ else \ - { FireEtwMethodDCStartVerbose_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID); } \ + { FireEtwMethodDCStartVerbose_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodDCStart_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, rejitID) \ +#define FireEtwMethodDCStart_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodDCStart_V1(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID); } \ else \ - { FireEtwMethodDCStart_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, rejitID); } \ + { FireEtwMethodDCStart_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodDCEndVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID) \ +#define FireEtwMethodDCEndVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodDCEndVerbose_V1(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID); } \ else \ - { FireEtwMethodDCEndVerbose_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, rejitID); } \ + { FireEtwMethodDCEndVerbose_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, szDtraceOutput1, szDtraceOutput2, szDtraceOutput3, clrInstanceID, nativeCodeId); } \ } -#define FireEtwMethodDCEnd_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, rejitID) \ +#define FireEtwMethodDCEnd_V1_or_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, nativeCodeId) \ { \ - if (rejitID == 0) \ + if (nativeCodeId == 0) \ { FireEtwMethodDCEnd_V1(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID); } \ else \ - { FireEtwMethodDCEnd_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, rejitID); } \ + { FireEtwMethodDCEnd_V2(ullMethodIdentifier, ullModuleID, ullColdMethodStartAddress, ulColdMethodSize, ulMethodToken, ulColdMethodFlags, clrInstanceID, nativeCodeId); } \ } // Module load / unload events: @@ -5227,7 +5227,7 @@ VOID ETW::MethodLog::GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPo /*******************************************************/ /* 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, BOOL bProfilerRejectedPrecompiledCode, BOOL bReadyToRunRejectedPrecompiledCode) +VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, ReJITID ilCodeId, NativeCodeVersionId nativeCodeId, BOOL bProfilerRejectedPrecompiledCode, BOOL bReadyToRunRejectedPrecompiledCode) { CONTRACTL { NOTHROW; @@ -5240,7 +5240,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, bProfilerRejectedPrecompiledCode, bReadyToRunRejectedPrecompiledCode); + ETW::MethodLog::SendMethodEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodLoad, TRUE, namespaceOrClassName, methodName, methodSignature, pNativeCodeStartAddress, nativeCodeId, bProfilerRejectedPrecompiledCode, bReadyToRunRejectedPrecompiledCode); } if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, @@ -5255,7 +5255,7 @@ VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC _ASSERTE(g_pDebugInterface != NULL); g_pDebugInterface->InitializeLazyDataIfNecessary(); - ETW::MethodLog::SendMethodILToNativeMapEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodILToNativeMap, pCode, rejitID); + ETW::MethodLog::SendMethodILToNativeMapEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodILToNativeMap, pNativeCodeStartAddress, ilCodeId); } } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); @@ -6263,7 +6263,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, BOOL bProfilerRejectedPrecompiledCode, BOOL bReadyToRunRejectedPrecompiledCode) +VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, NativeCodeVersionId nativeCodeId, BOOL bProfilerRejectedPrecompiledCode, BOOL bReadyToRunRejectedPrecompiledCode) { CONTRACTL { THROWS; @@ -6346,7 +6346,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodFlags = ulMethodFlags | ETW::MethodLog::MethodStructs::HotSection; // Method Extent (bits 28, 29, 30, 31) // MethodDesc ==> Code Address ==>JitMananger - TADDR start = pCode ? pCode : PCODEToPINSTR(pMethodDesc->GetNativeCode()); + TADDR start = PCODEToPINSTR(pNativeCodeStartAddress ? pNativeCodeStartAddress : pMethodDesc->GetNativeCode()); if(start == 0) { // this method hasn't been jitted return; @@ -6424,7 +6424,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6435,7 +6435,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } if(bFireEventForColdSection) { @@ -6451,7 +6451,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6462,7 +6462,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulColdMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } } } @@ -6481,7 +6481,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6492,7 +6492,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } if(bFireEventForColdSection) { @@ -6508,7 +6508,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6519,7 +6519,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulColdMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } } } @@ -6538,7 +6538,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6549,7 +6549,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } if(bFireEventForColdSection) { @@ -6565,7 +6565,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6576,7 +6576,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulColdMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } } } @@ -6595,7 +6595,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6606,7 +6606,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } if(bFireEventForColdSection) { @@ -6622,7 +6622,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio szDtraceOutput2, szDtraceOutput3, GetClrInstanceId(), - rejitID); + nativeCodeId); } else { @@ -6633,7 +6633,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ulMethodToken, ulColdMethodFlags, GetClrInstanceId(), - rejitID); + nativeCodeId); } } } @@ -6662,7 +6662,7 @@ VOID ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // // static -VOID ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, SIZE_T pCode, ReJITID rejitID) +VOID ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, ReJITID ilCodeId) { CONTRACTL { @@ -6695,7 +6695,7 @@ VOID ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWOR HRESULT hr = g_pDebugInterface->GetILToNativeMappingIntoArrays( pMethodDesc, - pCode, + pNativeCodeStartAddress, kMapEntriesMax, &cMap, &rguiILOffset, @@ -6711,7 +6711,7 @@ VOID ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWOR { FireEtwMethodILToNativeMap( ullMethodIdentifier, - rejitID, + ilCodeId, 0, // Extent: This event is only sent for JITted (not NGENd) methods, and // currently there is only one extent (hot) for JITted methods. cMap, @@ -6803,20 +6803,22 @@ VOID ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOpti // Called be ETW::MethodLog::SendEventsForJitMethods // Sends the ETW events once our caller determines whether or not rejit locks can be acquired -VOID ETW::MethodLog::SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, - LoaderAllocator *pLoaderAllocatorFilter, +VOID ETW::MethodLog::SendEventsForJitMethodsHelper(LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions, BOOL fLoadOrDCStart, BOOL fUnloadOrDCEnd, BOOL fSendMethodEvent, BOOL fSendILToNativeMapEvent, - BOOL fGetReJitIDs) + BOOL fGetCodeIds) { CONTRACTL{ THROWS; GC_NOTRIGGER; } CONTRACTL_END; + _ASSERTE(pLoaderAllocatorFilter == nullptr || pLoaderAllocatorFilter->IsCollectible()); + _ASSERTE(pLoaderAllocatorFilter == nullptr || !fGetCodeIds); + EEJitManager::CodeHeapIterator heapIterator(pLoaderAllocatorFilter); while (heapIterator.Next()) { @@ -6824,16 +6826,40 @@ VOID ETW::MethodLog::SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, if (pMD == NULL) continue; - TADDR codeStart = heapIterator.GetMethodCode(); + PCODE codeStart = PINSTRToPCODE(heapIterator.GetMethodCode()); - // Grab rejitID from the rejit manager. In some cases, such as collectible loader - // allocators, we don't support rejit so we need to short circuit the call. - // This also allows our caller to avoid having to pre-enter the rejit - // manager locks. + // Get the IL and native code IDs. In some cases, such as collectible loader + // allocators, we don't support code versioning so we need to short circuit the call. + // This also allows our caller to avoid having to pre-enter the relevant locks. // see code:#TableLockHolder - ReJITID rejitID = - fGetReJitIDs ? ReJitManager::GetReJitIdNoLock(pMD, codeStart) : 0; - + ReJITID ilCodeId = 0; + NativeCodeVersionId nativeCodeId = 0; +#ifdef FEATURE_CODE_VERSIONING + if (fGetCodeIds) + { + CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager(); + _ASSERTE(pCodeVersionManager->LockOwnedByCurrentThread()); + NativeCodeVersion nativeCodeVersion = pCodeVersionManager->GetNativeCodeVersion(pMD, codeStart); + if (nativeCodeVersion.IsNull()) + { + // The code version manager hasn't been updated with the jitted code + if (codeStart != pMD->GetNativeCode()) + { + continue; + } + } + else + { + nativeCodeId = nativeCodeVersion.GetVersionId(); + ilCodeId = nativeCodeVersion.GetILCodeVersionId(); + } + } + else +#endif + if (codeStart != pMD->GetNativeCode()) + { + continue; + } // When we're called to announce loads, then the methodload event itself must // precede any supplemental events, so that the method load or method jitting @@ -6851,41 +6877,13 @@ VOID ETW::MethodLog::SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, NULL, // methodName NULL, // methodSignature codeStart, - rejitID); + nativeCodeId); } } - // The filtering line below excludes all methods that don't go directly to the - // native body (And that includes all Tiered JIT methods). In V3.0 Tiered JIT - // is only by default which means important methods are filtered out. - // - // This filter used to exclude all events for a particular method, but has been - // moved here so it only applies to the IL->Native map. - // This filter needs to be removed in its entirety, because right now all Tiered - // methods don't have a IL->Native map (and thus can't support source line profiling) - // moving it here at least minimizes the damage. - // - // We did not remove the filter right now because currently - // SendMethodILToNativeMapEvent relies on a fragile invariant where all lazy data is - // known to be populated (see g_pDebugInterface->InitializeLazyDataIfNecessary(); above) - // and this may not be true for tiered methods. - // - // There was also concern that there are races where the heap-iterator might see - // data between the time that the code was created and the debug information was set - // (there is a lock that protects the code manager data, however the JIT does not - // let all the data in one go (in particular the debug data is set latter). - // - // Note that currently the rejitID variable is likely always 0 because it seems that - // fGetReJitIDs=false except in the case that an appdomain is being unloaded (which I - // think never happens in .NET core) - // - // Issue #22904 tracks the work to fix the IL->Native mapping. - if ((rejitID != 0) || (codeStart == PCODEToPINSTR(pMD->GetNativeCode()))) - { - // Send any supplemental events requested for this MethodID - if (fSendILToNativeMapEvent) - ETW::MethodLog::SendMethodILToNativeMapEvent(pMD, dwEventOptions, codeStart, rejitID); - } + // Send any supplemental events requested for this MethodID + if (fSendILToNativeMapEvent) + ETW::MethodLog::SendMethodILToNativeMapEvent(pMD, dwEventOptions, codeStart, ilCodeId); // When we're called to announce unloads, then the methodunload event itself must // come after any supplemental events, so that the method unload event is the @@ -6902,7 +6900,7 @@ VOID ETW::MethodLog::SendEventsForJitMethodsHelper(BaseDomain *pDomainFilter, NULL, // methodName NULL, // methodSignature codeStart, - rejitID); + nativeCodeId); } } } @@ -6958,7 +6956,7 @@ VOID ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // #TableLockHolder: // // A word about ReJitManager::TableLockHolder... As we enumerate through the functions, - // we may need to grab their ReJITIDs. The ReJitManager grabs its table Crst in order to + // we may need to grab their code IDs. The ReJitManager grabs its table Crst in order to // fetch these. However, several other kinds of locks are being taken during this // enumeration, such as the SystemDomain lock and the EEJitManager::CodeHeapIterator's // lock. In order to avoid lock-leveling issues, we grab the appropriate ReJitManager @@ -6974,10 +6972,11 @@ VOID ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // // We only support getting rejit IDs when filtering by domain. +#ifdef FEATURE_CODE_VERSIONING if (pDomainFilter) { CodeVersionManager::TableLockHolder lkRejitMgrModule(pDomainFilter->GetCodeVersionManager()); - SendEventsForJitMethodsHelper(pDomainFilter, + SendEventsForJitMethodsHelper( pLoaderAllocatorFilter, dwEventOptions, fLoadOrDCStart, @@ -6987,8 +6986,9 @@ VOID ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl TRUE); } else +#endif { - SendEventsForJitMethodsHelper(pDomainFilter, + SendEventsForJitMethodsHelper( pLoaderAllocatorFilter, dwEventOptions, fLoadOrDCStart, diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 1d99f43b30..0e45b96cad 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -811,6 +811,7 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J &methodName, &methodSignature, pCode, + pConfig->GetCodeVersion().GetILCodeVersionId(), pConfig->GetCodeVersion().GetVersionId(), pConfig->ProfilerRejectedPrecompiledCode(), pConfig->ReadyToRunRejectedPrecompiledCode()); |