diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index d14273a35f092..8569c45e476ca 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -177,6 +177,8 @@ private static CastResult ObjIsInstanceOfCached(object obj, void* toTypeHnd) // IsInstanceOf test used for unusual cases (naked type parameters, variant generic types) // Unlike the IsInstanceOfInterface, IsInstanceOfClass, and IsIsntanceofArray functions, // this test must deal with all kinds of type tests + [DebuggerStepThrough] + [DebuggerHidden] private static object? JIT_IsInstanceOfAny(void* toTypeHnd, object? obj) { CastResult result; @@ -199,6 +201,8 @@ private static CastResult ObjIsInstanceOfCached(object obj, void* toTypeHnd) // ChkCast test used for unusual cases (naked type parameters, variant generic types) // Unlike the ChkCastInterface, ChkCastClass, and ChkCastArray functions, // this test must deal with all kinds of type tests + [DebuggerStepThrough] + [DebuggerHidden] private static object? JIT_ChkCastAny(void* toTypeHnd, object? obj) { CastResult result; diff --git a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp index 1916c455e5181..dfe2fd4ddf2c1 100644 --- a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp @@ -5504,6 +5504,15 @@ IDacDbiInterface::DynamicMethodType DacDbiInterfaceImpl::IsILStubOrLCGMethod(VMP } } +bool DacDbiInterfaceImpl::IsJitHelper(VMPTR_MethodDesc vmMethodDesc) +{ + DD_ENTER_MAY_THROW; + + MethodDesc * pMD = vmMethodDesc.GetDacPtr(); + + return pMD->IsJitHelper(); +} + //--------------------------------------------------------------------------------------- // // Determine whether the specified thread is at a GC safe place. diff --git a/src/coreclr/src/debug/daccess/dacdbiimpl.h b/src/coreclr/src/debug/daccess/dacdbiimpl.h index 5ead4b027f5ac..f3d0d14be84ab 100644 --- a/src/coreclr/src/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/src/debug/daccess/dacdbiimpl.h @@ -901,6 +901,8 @@ class DacDbiInterfaceImpl : // Check if the given method is an IL stub or an LCD method. DynamicMethodType IsILStubOrLCGMethod(VMPTR_MethodDesc vmMethodDesc); + bool IsJitHelper(VMPTR_MethodDesc vmMethodDesc); + // Return a TargetBuffer for the raw vararg signature. TargetBuffer GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, CORDB_ADDRESS * pArgBase); diff --git a/src/coreclr/src/debug/di/rsstackwalk.cpp b/src/coreclr/src/debug/di/rsstackwalk.cpp index 83b3de28b8f38..d2a7ce2a04bdf 100644 --- a/src/coreclr/src/debug/di/rsstackwalk.cpp +++ b/src/coreclr/src/debug/di/rsstackwalk.cpp @@ -707,7 +707,8 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) // modified method, but at least the error won't leak out to interfere with inspection // of the callstack as a whole. if (!frameData.v.fNoMetadata && - pNativeCode->GetFunction()->IsNativeImpl() != CordbFunction::kNativeOnly) + pNativeCode->GetFunction()->IsNativeImpl() != CordbFunction::kNativeOnly && + !pDAC->IsJitHelper(pNativeCode->GetVMNativeCodeMethodDescToken())) { pNativeCode->LoadNativeInfo(); diff --git a/src/coreclr/src/debug/inc/dacdbiinterface.h b/src/coreclr/src/debug/inc/dacdbiinterface.h index 820f179f6590b..72929afef4b36 100644 --- a/src/coreclr/src/debug/inc/dacdbiinterface.h +++ b/src/coreclr/src/debug/inc/dacdbiinterface.h @@ -1630,6 +1630,9 @@ class IDacDbiInterface virtual DynamicMethodType IsILStubOrLCGMethod(VMPTR_MethodDesc vmMethodDesc) = 0; + virtual + bool IsJitHelper(VMPTR_MethodDesc vmMethodDesc) = 0; + // // Return a TargetBuffer for the raw vararg signature. // Also return the address of the first argument in the vararg signature. diff --git a/src/coreclr/src/vm/castcache.cpp b/src/coreclr/src/vm/castcache.cpp index b57b40f7da6f5..988d35e38b0a5 100644 --- a/src/coreclr/src/vm/castcache.cpp +++ b/src/coreclr/src/vm/castcache.cpp @@ -124,10 +124,12 @@ void CastCache::Initialize() CONTRACTL_END; MethodDesc* pMD = MscorlibBinder::GetMethod((BinderMethodID)(METHOD__CASTHELPERS__JIT_ISINSTANCEOFANY)); + pMD->SetIsJitHelper(); PCODE pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_ISINSTANCEOFANY, pDest); pMD = MscorlibBinder::GetMethod((BinderMethodID)(METHOD__CASTHELPERS__JIT_CHKCASTANY)); + pMD->SetIsJitHelper(); pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_CHKCASTANY, pDest); diff --git a/src/coreclr/src/vm/excep.cpp b/src/coreclr/src/vm/excep.cpp index ab1bde1c8c180..317e9d5029018 100644 --- a/src/coreclr/src/vm/excep.cpp +++ b/src/coreclr/src/vm/excep.cpp @@ -3518,7 +3518,9 @@ BOOL StackTraceInfo::AppendElement(BOOL bAllowAllocMem, UINT_PTR currentIP, UINT LOG((LF_EH, LL_INFO10000, "StackTraceInfo::AppendElement (%p), IP = %p, SP = %p, %s::%s\n", this, currentIP, currentSP, pFunc ? pFunc->m_pszDebugClassName : "", pFunc ? pFunc->m_pszDebugMethodName : "" )); BOOL bRetVal = FALSE; - if (pFunc != NULL && pFunc->IsILStub()) + // TODO: WIP is this actually the right place? + // are there more places that should skip JIT helpers. + if (pFunc != NULL && (pFunc->IsILStub() || pFunc->IsJitHelper())) return FALSE; // Save this function in the stack trace array, which we only build on the first pass. We'll try to expand the diff --git a/src/coreclr/src/vm/method.hpp b/src/coreclr/src/vm/method.hpp index d5561019594b0..a49493c7382ec 100644 --- a/src/coreclr/src/vm/method.hpp +++ b/src/coreclr/src/vm/method.hpp @@ -1845,7 +1845,9 @@ class MethodDesc enum_flag2_IsEligibleForTieredCompilation = 0x20, - // unused = 0x40, + // for most purposes these are regular managed methods. + // We do not want this to appear in stack traces though. + enum_flag2_IsJitHelper = 0x40, // unused = 0x80, }; BYTE m_bFlags2; @@ -1908,6 +1910,18 @@ class MethodDesc m_bFlags2 |= enum_flag2_IsJitIntrinsic; } + inline BOOL IsJitHelper() + { + LIMITED_METHOD_DAC_CONTRACT; + return (m_bFlags2 & enum_flag2_IsJitHelper) != 0; + } + + inline void SetIsJitHelper() + { + LIMITED_METHOD_CONTRACT; + m_bFlags2 |= enum_flag2_IsJitHelper; + } + static const SIZE_T s_ClassificationSizeTable[]; static SIZE_T GetBaseSize(DWORD classification)