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/9.0-preview2] Fix the new EH with hot-cold split code #99015

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal static unsafe partial bool RhpCallFilterFunclet(

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EHEnumInitFromStackFrameIterator")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool RhpEHEnumInitFromStackFrameIterator(ref StackFrameIterator pFrameIter, byte** pMethodStartAddress, void* pEHEnum);
internal static unsafe partial bool RhpEHEnumInitFromStackFrameIterator(ref StackFrameIterator pFrameIter, out EH.MethodRegionInfo pMethodRegionInfo, void* pEHEnum);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EHEnumNext")]
[return: MarshalAs(UnmanagedType.Bool)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ private struct EHEnum
private IntPtr _dummy; // For alignment
}

internal struct MethodRegionInfo
{
internal byte* _hotStartAddress;
internal nuint _hotSize;
internal byte* _coldStartAddress;
internal nuint _coldSize;
}

#pragma warning disable IDE0060
// This is a fail-fast function used by the runtime as a last resort that will terminate the process with
// as little effort as possible. No guarantee is made about the semantics of this fail-fast.
Expand Down Expand Up @@ -932,6 +940,20 @@ private static void DebugVerifyHandlingFrame(UIntPtr handlingFrameSP)
"Handling frame must have a valid stack frame pointer");
}

// Caclulate the code offset from the start of the method as if the hot and cold regions were
// stored sequentially in memory.
private static uint CalculateCodeOffset(byte* pbControlPC, in MethodRegionInfo methodRegionInfo)
{
uint codeOffset = (uint)(pbControlPC - methodRegionInfo._hotStartAddress);
// If the PC is in the cold region, adjust the offset to be relative to the start of the method.
if ((methodRegionInfo._coldSize != 0) && (codeOffset >= methodRegionInfo._hotSize))
{
codeOffset = (uint)(methodRegionInfo._hotSize + (nuint)(pbControlPC - methodRegionInfo._coldStartAddress));
}

return codeOffset;
}

private static void UpdateStackTrace(object exceptionObj, UIntPtr curFramePtr, IntPtr ip, UIntPtr sp,
ref bool isFirstRethrowFrame, ref UIntPtr prevFramePtr, ref bool isFirstFrame, ref ExInfo exInfo)
{
Expand All @@ -958,13 +980,13 @@ private static bool FindFirstPassHandler(object exception, uint idxStart,
tryRegionIdx = MaxTryRegionIdx;

EHEnum ehEnum;
byte* pbMethodStartAddress;
if (!InternalCalls.RhpEHEnumInitFromStackFrameIterator(ref frameIter, &pbMethodStartAddress, &ehEnum))
MethodRegionInfo methodRegionInfo;
if (!InternalCalls.RhpEHEnumInitFromStackFrameIterator(ref frameIter, out methodRegionInfo, &ehEnum))
return false;

byte* pbControlPC = frameIter.ControlPC;

uint codeOffset = (uint)(pbControlPC - pbMethodStartAddress);
uint codeOffset = CalculateCodeOffset(pbControlPC, in methodRegionInfo);

uint lastTryStart = 0, lastTryEnd = 0;

Expand Down Expand Up @@ -1111,13 +1133,14 @@ private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart)
private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart, uint idxLimit)
{
EHEnum ehEnum;
byte* pbMethodStartAddress;
if (!InternalCalls.RhpEHEnumInitFromStackFrameIterator(ref exInfo._frameIter, &pbMethodStartAddress, &ehEnum))
MethodRegionInfo methodRegionInfo;

if (!InternalCalls.RhpEHEnumInitFromStackFrameIterator(ref exInfo._frameIter, out methodRegionInfo, &ehEnum))
return;

byte* pbControlPC = exInfo._frameIter.ControlPC;

uint codeOffset = (uint)(pbControlPC - pbMethodStartAddress);
uint codeOffset = CalculateCodeOffset(pbControlPC, in methodRegionInfo);

uint lastTryStart = 0, lastTryEnd = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ internal static int RhEndNoGCRegion()

[RuntimeImport(Redhawk.BaseName, "RhpEHEnumInitFromStackFrameIterator")]
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern unsafe bool RhpEHEnumInitFromStackFrameIterator(ref StackFrameIterator pFrameIter, byte** pMethodStartAddress, void* pEHEnum);
internal static extern unsafe bool RhpEHEnumInitFromStackFrameIterator(ref StackFrameIterator pFrameIter, out EH.MethodRegionInfo pMethodRegionInfo, void* pEHEnum);

[RuntimeImport(Redhawk.BaseName, "RhpEHEnumNext")]
[MethodImpl(MethodImplOptions.InternalCall)]
Expand Down
16 changes: 14 additions & 2 deletions src/coreclr/nativeaot/Runtime/EHHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,25 @@
#include "MethodTable.inl"
#include "CommonMacros.inl"

struct MethodRegionInfo
{
void* hotStartAddress;
size_t hotSize;
void* coldStartAddress;
size_t coldSize;
};

COOP_PINVOKE_HELPER(FC_BOOL_RET, RhpEHEnumInitFromStackFrameIterator, (
StackFrameIterator* pFrameIter, void ** pMethodStartAddressOut, EHEnum* pEHEnum))
StackFrameIterator* pFrameIter, MethodRegionInfo* pMethodRegionInfoOut, EHEnum* pEHEnum))
{
ICodeManager * pCodeManager = pFrameIter->GetCodeManager();
pEHEnum->m_pCodeManager = pCodeManager;

FC_RETURN_BOOL(pCodeManager->EHEnumInit(pFrameIter->GetMethodInfo(), pMethodStartAddressOut, &pEHEnum->m_state));
pMethodRegionInfoOut->hotSize = 0; // unknown
pMethodRegionInfoOut->coldStartAddress = nullptr;
pMethodRegionInfoOut->coldSize = 0;

FC_RETURN_BOOL(pCodeManager->EHEnumInit(pFrameIter->GetMethodInfo(), &pMethodRegionInfoOut->hotStartAddress, &pEHEnum->m_state));
}

COOP_PINVOKE_HELPER(FC_BOOL_RET, RhpEHEnumNext, (EHEnum* pEHEnum, EHClause* pEHClause))
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7970,7 +7970,7 @@ struct ExtendedEHClauseEnumerator : EH_CLAUSE_ENUMERATOR
unsigned EHCount;
};

extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, BYTE** pMethodStartAddress, EH_CLAUSE_ENUMERATOR * pEHEnum)
extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo* pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum)
{
QCALL_CONTRACT;

Expand All @@ -7984,7 +7984,7 @@ extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *p

IJitManager* pJitMan = pFrameIter->m_crawl.GetJitManager();
const METHODTOKEN& MethToken = pFrameIter->m_crawl.GetMethodToken();
*pMethodStartAddress = (BYTE*)pJitMan->JitTokenToStartAddress(MethToken);
pJitMan->JitTokenToMethodRegionInfo(MethToken, pMethodRegionInfo);
pExtendedEHEnum->EHCount = pJitMan->InitializeEHEnumeration(MethToken, pEHEnum);

END_QCALL;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/exceptionhandlingqcalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extern "C" void QCALLTYPE CallFinallyFunclet(BYTE* pHandlerIP, REGDISPLAY* pvReg
extern "C" BOOL QCALLTYPE CallFilterFunclet(QCall::ObjectHandleOnStack exceptionObj, BYTE* pFilterP, REGDISPLAY* pvRegDisplay);
extern "C" void QCALLTYPE ResumeAtInterceptionLocation(REGDISPLAY* pvRegDisplay);
extern "C" void QCALLTYPE AppendExceptionStackFrame(QCall::ObjectHandleOnStack exceptionObj, SIZE_T ip, SIZE_T sp, int flags, ExInfo *pExInfo);
extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, BYTE** pMethodStartAddress, EH_CLAUSE_ENUMERATOR * pEHEnum);
extern "C" BOOL QCALLTYPE EHEnumInitFromStackFrameIterator(StackFrameIterator *pFrameIter, IJitManager::MethodRegionInfo *pMethodRegionInfo, EH_CLAUSE_ENUMERATOR * pEHEnum);
extern "C" BOOL QCALLTYPE EHEnumNext(EH_CLAUSE_ENUMERATOR* pEHEnum, RhEHClause* pEHClause);
extern "C" bool QCALLTYPE SfiInit(StackFrameIterator* pThis, CONTEXT* pStackwalkCtx, bool instructionFault, bool* pIsExceptionIntercepted);
extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, unsigned int* uExCollideClauseIdx, bool* fUnwoundReversePInvoke, bool* pIsExceptionIntercepted);
Expand Down
Loading