Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/8.0-rc1] [release/8.0] Events for IL methods without IL headers #92317

Merged
merged 6 commits into from
Sep 20, 2023
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
9 changes: 7 additions & 2 deletions src/coreclr/debug/daccess/stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1253,14 +1253,19 @@ ClrDataFrame::GetLocalSig(MetaSig** sig,
{
// It turns out we cannot really get rid of this check. Dynamic methods
// (including IL stubs) do not have their local sig's available after JIT time.
if (!m_methodDesc->IsIL())
// IL methods with dynamically generated IL (for example, UnsafeAccessors) may
// not have an IL header.
COR_ILMETHOD* ilHeader = m_methodDesc->IsIL()
? m_methodDesc->GetILHeader()
: NULL;
if (ilHeader == NULL)
{
*sig = NULL;
*count = 0;
return E_FAIL;
}

COR_ILMETHOD_DECODER methodDecoder(m_methodDesc->GetILHeader());
COR_ILMETHOD_DECODER methodDecoder(ilHeader);
mdSignature localSig = methodDecoder.GetLocalVarSigTok() ?
methodDecoder.GetLocalVarSigTok() : mdSignatureNil;
if (localSig == mdSignatureNil)
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/inc/eventtracebase.h
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ namespace ETW
BOOL fSendRichDebugInfoEvent,
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 SendMethodJitStartEvent(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL);
static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId);
static VOID SendMethodRichDebugInfo(MethodDesc * pMethodDesc, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId, MethodDescSet* sentMethodDetailsSet);
static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL, MethodDescSet* sentMethodDetailsSet = NULL);
Expand Down Expand Up @@ -938,7 +938,7 @@ namespace ETW

static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc);
static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint);
static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitting(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig);
static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc);
static VOID SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc, MethodDescSet* set);
Expand All @@ -952,7 +952,7 @@ namespace ETW
public:
static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc) {};
static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {};
static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitting(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName, SString *methodName, SString *methodSignature);
static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig);
static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {};
static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers) {};
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/utilcode/stresslog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
#include "switches.h"
#include "stresslog.h"
#include "clrhost.h"
#include "ex.h"
#define DONOT_DEFINE_ETW_CALLBACK
#include "eventtracebase.h"
#include "ex.h"

#if !defined(STRESS_LOG_READONLY)
#ifdef HOST_WINDOWS
Expand Down
21 changes: 12 additions & 9 deletions src/coreclr/vm/eventtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3555,7 +3555,7 @@ VOID ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC
/*************************************************/
/* This is called by the runtime when method jitting started */
/*************************************************/
VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature)
VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, COR_ILMETHOD_DECODER* methodDecoder, SString *namespaceOrClassName, SString *methodName, SString *methodSignature)
{
CONTRACTL {
NOTHROW;
Expand All @@ -3570,7 +3570,7 @@ VOID ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr
CLR_JIT_KEYWORD))
{
pMethodDesc->GetMethodInfo(*namespaceOrClassName, *methodName, *methodSignature);
ETW::MethodLog::SendMethodJitStartEvent(pMethodDesc, namespaceOrClassName, methodName, methodSignature);
ETW::MethodLog::SendMethodJitStartEvent(pMethodDesc, methodDecoder, namespaceOrClassName, methodName, methodSignature);
}
} EX_CATCH { } EX_END_CATCH(SwallowAllExceptions);
}
Expand Down Expand Up @@ -4528,7 +4528,12 @@ VOID ETW::MethodLog::SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc,
/*****************************************************************/
/* This routine is used to send an ETW event just before a method starts jitting*/
/*****************************************************************/
VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature)
VOID ETW::MethodLog::SendMethodJitStartEvent(
MethodDesc *pMethodDesc,
COR_ILMETHOD_DECODER* methodDecoder,
SString *namespaceOrClassName,
SString *methodName,
SString *methodSignature)
{
CONTRACTL {
THROWS;
Expand Down Expand Up @@ -4566,15 +4571,13 @@ VOID ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n
ulMethodToken = (ULONG)0;
}
else
ulMethodToken = (ULONG)pMethodDesc->GetMemberDef();

if(pMethodDesc->IsIL())
{
COR_ILMETHOD_DECODER::DecoderStatus decoderstatus = COR_ILMETHOD_DECODER::FORMAT_ERROR;
COR_ILMETHOD_DECODER ILHeader(pMethodDesc->GetILHeader(), pMethodDesc->GetMDImport(), &decoderstatus);
ulMethodILSize = (ULONG)ILHeader.GetCodeSize();
ulMethodToken = (ULONG)pMethodDesc->GetMemberDef();
}

if (methodDecoder != NULL)
ulMethodILSize = methodDecoder->GetCodeSize();

SString tNamespace, tMethodName, tMethodSignature;
if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty()))
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12286,7 +12286,7 @@ static CorJitResult CompileMethodWithEtwWrapper(EEJitManager *jitMgr,

SString namespaceOrClassName, methodName, methodSignature;
// Fire an ETW event to mark the beginning of JIT'ing
ETW::MethodLog::MethodJitting(reinterpret_cast<MethodDesc*>(info->ftn), &namespaceOrClassName, &methodName, &methodSignature);
ETW::MethodLog::MethodJitting(reinterpret_cast<MethodDesc*>(info->ftn), NULL, &namespaceOrClassName, &methodName, &methodSignature);

CorJitResult ret = jitMgr->m_jit->compileMethod(comp, info, flags, nativeEntry, nativeSizeOfCode);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1819,7 +1819,7 @@ class MethodDesc
PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0);
PCODE JitCompileCode(PrepareCodeConfig* pConfig);
PCODE JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry);
PCODE JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEntry* pLockEntry, ULONG* pSizeOfCode);
PCODE JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pilHeader, JitListLockEntry* pLockEntry, ULONG* pSizeOfCode);

public:
bool TryGenerateUnsafeAccessor(DynamicResolver** resolver, COR_ILMETHOD_DECODER** methodILDecoder);
Expand Down
116 changes: 58 additions & 58 deletions src/coreclr/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,53 @@ PCODE MethodDesc::JitCompileCode(PrepareCodeConfig* pConfig)
}
}

namespace
{
COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
_ASSERTE(!pMD->IsNoMetadata());
_ASSERTE(pConfig != NULL);
_ASSERTE(pDecoderMemory != NULL);

COR_ILMETHOD_DECODER* pHeader = NULL;
COR_ILMETHOD* ilHeader = pConfig->GetILHeader();
if (ilHeader == NULL)
return NULL;

COR_ILMETHOD_DECODER::DecoderStatus status = COR_ILMETHOD_DECODER::FORMAT_ERROR;
{
// Decoder ctor can AV on a malformed method header
AVInRuntimeImplOkayHolder AVOkay;
pHeader = new (pDecoderMemory) COR_ILMETHOD_DECODER(ilHeader, pMD->GetMDImport(), &status);
}

if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR)
COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);

return pHeader;
}

COR_ILMETHOD_DECODER* GetAndVerifyILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
if (pMD->IsIL())
{
return GetAndVerifyMetadataILHeader(pMD, pConfig, pIlDecoderMemory);
}
else if (pMD->IsILStub())
{
ILStubResolver* pResolver = pMD->AsDynamicMethodDesc()->GetILStubResolver();
return pResolver->GetILHeader();
}

_ASSERTE(pMD->IsNoMetadata());
return NULL;
}
}

PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry)
{
STANDARD_VM_CONTRACT;
Expand Down Expand Up @@ -759,11 +806,18 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
}
#endif // PROFILING_SUPPORTED

// The profiler may have changed the code on the callback. Need to
// pick up the new code.
//
// (don't want this for OSR, need to see how it works)
COR_ILMETHOD_DECODER ilDecoderTemp;
COR_ILMETHOD_DECODER* pilHeader = GetAndVerifyILHeader(this, pConfig, &ilDecoderTemp);

if (!ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context,
TRACE_LEVEL_VERBOSE,
CLR_JIT_KEYWORD))
{
pCode = JitCompileCodeLocked(pConfig, pEntry, &sizeOfCode);
pCode = JitCompileCodeLocked(pConfig, pilHeader, pEntry, &sizeOfCode);
}
else
{
Expand All @@ -778,12 +832,13 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
// a small stub of native code but no native-IL mapping.
#ifndef FEATURE_INTERPRETER
ETW::MethodLog::MethodJitting(this,
pilHeader,
&namespaceOrClassName,
&methodName,
&methodSignature);
#endif

pCode = JitCompileCodeLocked(pConfig, pEntry, &sizeOfCode);
pCode = JitCompileCodeLocked(pConfig, pilHeader, pEntry, &sizeOfCode);

// Interpretted methods skip this notification
#ifdef FEATURE_INTERPRETER
Expand Down Expand Up @@ -869,66 +924,11 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J
return pCode;
}

namespace
{
COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
_ASSERTE(!pMD->IsNoMetadata());
_ASSERTE(pConfig != NULL);
_ASSERTE(pDecoderMemory != NULL);

COR_ILMETHOD_DECODER* pHeader = NULL;
COR_ILMETHOD* ilHeader = pConfig->GetILHeader();
if (ilHeader == NULL)
return NULL;

COR_ILMETHOD_DECODER::DecoderStatus status = COR_ILMETHOD_DECODER::FORMAT_ERROR;
{
// Decoder ctor can AV on a malformed method header
AVInRuntimeImplOkayHolder AVOkay;
pHeader = new (pDecoderMemory) COR_ILMETHOD_DECODER(ilHeader, pMD->GetMDImport(), &status);
}

if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR)
COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);

return pHeader;
}

COR_ILMETHOD_DECODER* GetAndVerifyILHeader(MethodDesc* pMD, PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pMD != NULL);
if (pMD->IsIL())
{
return GetAndVerifyMetadataILHeader(pMD, pConfig, pIlDecoderMemory);
}
else if (pMD->IsILStub())
{
ILStubResolver* pResolver = pMD->AsDynamicMethodDesc()->GetILStubResolver();
return pResolver->GetILHeader();
}

_ASSERTE(pMD->IsNoMetadata());
return NULL;
}
}

PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEntry* pEntry, ULONG* pSizeOfCode)
PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pilHeader, JitListLockEntry* pEntry, ULONG* pSizeOfCode)
{
STANDARD_VM_CONTRACT;

PCODE pCode = NULL;

// The profiler may have changed the code on the callback. Need to
// pick up the new code.
//
// (don't want this for OSR, need to see how it works)
COR_ILMETHOD_DECODER ilDecoderTemp;
COR_ILMETHOD_DECODER* pilHeader = GetAndVerifyILHeader(this, pConfig, &ilDecoderTemp);

CORJIT_FLAGS jitFlags;
PCODE pOtherCode = NULL;

Expand Down
8 changes: 7 additions & 1 deletion src/coreclr/vm/versionresilienthashcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ bool AddVersionResilientHashCodeForInstruction(ILInstructionParser *parser, xxHa
hash->Add(varValue);
break;
}

case InlineVar: // 2 byte value which is token change resilient
{
uint16_t varValue;
Expand Down Expand Up @@ -388,6 +388,12 @@ bool GetVersionResilientILCodeHashCode(MethodDesc *pMD, int* hashCode, unsigned*

initLocals = (options & CORINFO_OPT_INIT_LOCALS) == CORINFO_OPT_INIT_LOCALS;
}
else if (!pMD->HasILHeader())
{
// Dynamically generated IL methods like UnsafeAccessors may not have
// an IL header.
return false;
}
else
{
COR_ILMETHOD_DECODER header(pMD->GetILHeader(TRUE), pMD->GetMDImport(), NULL);
Expand Down
Loading