Skip to content

Commit

Permalink
Profiler fixes dotnet#2
Browse files Browse the repository at this point in the history
  • Loading branch information
janvorli committed Dec 5, 2023
1 parent a6f73a1 commit c93c89d
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/coreclr/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ DEFINE_DACVAR(DWORD, dac__g_TlsIndex, g_TlsIndex)
#ifdef FEATURE_EH_FUNCLETS
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEHClass, ::g_pEHClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pExceptionServicesInternalCallsClass, ::g_pExceptionServicesInternalCallsClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pStackFrameIteratorClass, ::g_pStackFrameIteratorClass)
DEFINE_DACVAR(BOOL, dac__g_isNewExceptionHandlingEnabled, ::g_isNewExceptionHandlingEnabled)
#endif

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/appdomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,7 @@ void SystemDomain::LoadBaseSystemClasses()
#ifdef FEATURE_EH_FUNCLETS
g_pEHClass = CoreLibBinder::GetClass(CLASS__EH);
g_pExceptionServicesInternalCallsClass = CoreLibBinder::GetClass(CLASS__EXCEPTIONSERVICES_INTERNALCALLS);
g_pStackFrameIteratorClass = CoreLibBinder::GetClass(CLASS__STACKFRAMEITERATOR);
#endif

// Make sure that FCall mapping for Monitor.Enter is initialized. We need it in case Monitor.Enter is used only as JIT helper.
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,7 @@ DEFINE_METHOD(EH, RH_THROW_EX, RhThrowEx, SM_Obj_RefExInfo_RetVoid)
DEFINE_METHOD(EH, RH_THROWHW_EX, RhThrowHwEx, SM_UInt_RefExInfo_RetVoid)
DEFINE_METHOD(EH, RH_RETHROW, RhRethrow, SM_RefExInfo_RefExInfo_RetVoid)
DEFINE_CLASS(EXCEPTIONSERVICES_INTERNALCALLS, ExceptionServices, InternalCalls)
DEFINE_CLASS(STACKFRAMEITERATOR, Runtime, StackFrameIterator)
#endif // FEATURE_EH_FUNCLETS

#ifndef FOR_ILLINK
Expand Down
44 changes: 34 additions & 10 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8200,7 +8200,11 @@ extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalk
else
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchCatcherFound(pMD);
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionLeave(pMD);
if (pExInfo->m_pMDToReport != NULL)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionLeave(pExInfo->m_pMDToReport);
pExInfo->m_pMDToReport = NULL;
}

// We don't need to do anything special for continuable exceptions after calling
// this callback. We are going to start unwinding anyway.
Expand Down Expand Up @@ -8233,7 +8237,7 @@ extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalk
!(pExInfo->m_exception == CLRException::GetPreallocatedStackOverflowException());

pExInfo->m_stackTraceInfo.AppendElement(canAllocateMemory, NULL, GetRegdisplaySP(pExInfo->m_frameIter.m_crawl.GetRegisterSet()), pMD, &pExInfo->m_frameIter.m_crawl);
}
}
}
}
StackWalkAction retVal = pThis->Next();
Expand All @@ -8244,6 +8248,7 @@ extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalk
if (pExInfo->m_passNumber == 1)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionEnter(pMD);
pExInfo->m_pMDToReport = pMD;

// Notify the debugger that we are on the first pass for a managed exception.
// Note that this callback is made for every managed frame.
Expand All @@ -8252,6 +8257,7 @@ extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalk
else
{
EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionEnter(pMD);
pExInfo->m_pMDToReport = pMD;
}

pExInfo->m_sfLowBound = GetRegdisplaySP(pThis->m_crawl.GetRegisterSet());
Expand Down Expand Up @@ -8296,15 +8302,24 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla

ExInfo* pExInfo = pThis->GetNextExInfo();
ExInfo* pTopExInfo = pThread->GetExceptionState()->GetCurrentExInfo();
bool isCollided = false;

MethodDesc *pMD = pThis->m_crawl.GetFunction();
if (pTopExInfo->m_passNumber == 1)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionLeave(pMD);
if (pTopExInfo->m_pMDToReport != NULL)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionLeave(pTopExInfo->m_pMDToReport);
pTopExInfo->m_pMDToReport = NULL;
}
}
else
{
EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionLeave(pMD);
if (pTopExInfo->m_pMDToReport != NULL)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionLeave(pTopExInfo->m_pMDToReport);
pTopExInfo->m_pMDToReport = NULL;
}
}

// Check for reverse pinvoke (but eliminate the case when the caller is managed) or CallDescrWorkerInternal.
Expand Down Expand Up @@ -8434,6 +8449,7 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla
else
{
*uExCollideClauseIdx = pExInfo->m_idxCurClause;
isCollided = true;
pExInfo->m_kind = (ExKind)((uint8_t)pExInfo->m_kind | (uint8_t)ExKind::SupersededFlag);

// Unwind until we hit the frame of the prevExInfo
Expand Down Expand Up @@ -8471,15 +8487,23 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla
pMD = pThis->m_crawl.GetFunction();
if (pTopExInfo->m_passNumber == 1)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionEnter(pMD);

// Notify the debugger that we are on the first pass for a managed exception.
// Note that this callback is made for every managed frame.
EEToDebuggerExceptionInterfaceWrapper::FirstChanceManagedException(pThread, GetControlPC(pThis->m_crawl.GetRegisterSet()), GetRegdisplaySP(pThis->m_crawl.GetRegisterSet()));
// TODO: skip this and the related ...Leave for collided Unwind - maybe move this to the AppendElement above?
if (!isCollided)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFunctionEnter(pMD);
pTopExInfo->m_pMDToReport = pMD;
// Notify the debugger that we are on the first pass for a managed exception.
// Note that this callback is made for every managed frame.
EEToDebuggerExceptionInterfaceWrapper::FirstChanceManagedException(pThread, GetControlPC(pThis->m_crawl.GetRegisterSet()), GetRegdisplaySP(pThis->m_crawl.GetRegisterSet()));
}
}
else
{
EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionEnter(pMD);
if (!isCollided)
{
EEToProfilerExceptionInterfaceWrapper::ExceptionUnwindFunctionEnter(pMD);
pTopExInfo->m_pMDToReport = pMD;
}
}

Exit:;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/exinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ void ExInfo::Init()
m_StackAddress = this;
DestroyExceptionHandle();
m_hThrowable = NULL;
m_ExceptionCode = 0;
m_pMDToReport = NULL;

// By default, mark the tracker as not having delivered the first
// chance exception notification
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/exinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ struct ExInfo
EHClauseInfo m_EHClauseInfo;
ExceptionFlags m_ExceptionFlags;
DWORD m_ExceptionCode;
MethodDesc *m_pMDToReport;

#ifndef TARGET_UNIX
EHWatsonBucketTracker m_WatsonBucketTracker;
Expand Down
25 changes: 25 additions & 0 deletions src/coreclr/vm/proftoeeinterfaceimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8073,6 +8073,17 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D
CONTEXT builtContext;
#endif

//
// Skip all managed exception handling functions
//
if (pFunc != NULL && (
(pFunc->GetMethodTable() == g_pEHClass) ||
(pFunc->GetMethodTable() == g_pExceptionServicesInternalCallsClass) ||
(pFunc->GetMethodTable() == g_pStackFrameIteratorClass)))
{
return SWA_CONTINUE;
}

//
// For Unmanaged-to-managed transitions we get a NativeMarker back, which we want
// to return to the profiler as the context seed if it wants to walk the unmanaged
Expand All @@ -8091,6 +8102,18 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D
return SWA_CONTINUE;
}

if (g_isNewExceptionHandlingEnabled && !pCf->IsFrameless() && InlinedCallFrame::FrameHasActiveCall(pCf->GetFrame()))
{
// Skip new exception handling helpers
InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pCf->GetFrame();
PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum;
TADDR datum = dac_cast<TADDR>(pMD);
if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper)
{
return SWA_CONTINUE;
}
}

//
// If this is not a transition of any sort and not a managed
// method, ignore it.
Expand All @@ -8114,6 +8137,8 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D
{
frameInfo.funcID = NULL;
frameInfo.extraArg = NULL;
// TODO: fixme - intermediate native frames should likely be reported
//return SWA_CONTINUE;
}

frameInfo.IP = currentIP;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/vars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ MethodTable* g_pCastHelpers;
#ifdef FEATURE_EH_FUNCLETS
GPTR_IMPL(MethodTable, g_pEHClass);
GPTR_IMPL(MethodTable, g_pExceptionServicesInternalCallsClass);
GPTR_IMPL(MethodTable, g_pStackFrameIteratorClass);
GVAL_IMPL(bool, g_isNewExceptionHandlingEnabled);
#endif

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/vars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ GVAL_DECL(DWORD, g_TlsIndex);
#ifdef FEATURE_EH_FUNCLETS
GPTR_DECL(MethodTable, g_pEHClass);
GPTR_DECL(MethodTable, g_pExceptionServicesInternalCallsClass);
GPTR_DECL(MethodTable, g_pStackFrameIteratorClass);
GVAL_DECL(bool, g_isNewExceptionHandlingEnabled);
#endif

Expand Down

0 comments on commit c93c89d

Please sign in to comment.