Skip to content

Commit

Permalink
Remove uses of DECODE_RETURN_KIND part of GCInfo (#110799)
Browse files Browse the repository at this point in the history
* make hijack frames leaf frames

* not using DECODE_RETURN_KIND in NativeAOT

* delete DECODE_RETURN_KIND

* Fix for unix (x64)

* fixes for AOT

* arm64 fixes

* fix for RISC platforms

* fix arm32 build

* remove unnecessary now PTFF_RAX_IS_GCREF and similar.

* fix fir arm32

* revert to the former value of DECODE_HAS_TAILCALLS - in case there are dependencies in diagnostics.
  • Loading branch information
VSadov authored Dec 19, 2024
1 parent 54527ea commit ddc7867
Show file tree
Hide file tree
Showing 42 changed files with 224 additions and 376 deletions.
4 changes: 0 additions & 4 deletions src/coreclr/gcdump/gcdumpnonx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock,
| DECODE_GENERICS_INST_CONTEXT
| DECODE_GC_LIFETIMES
| DECODE_PROLOG_LENGTH
| DECODE_RETURN_KIND
#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
| DECODE_HAS_TAILCALLS
#endif
Expand Down Expand Up @@ -502,9 +501,6 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock,
gcPrintf("Size of parameter area: %x\n", hdrdecoder.GetSizeOfStackParameterArea());
#endif

ReturnKind returnKind = hdrdecoder.GetReturnKind();
gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind));

UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength();
gcPrintf("Code size: %x\n", cbEncodedMethodSize);

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/inc/eetwain.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ virtual size_t GetFunctionSize(GCInfoToken gcInfoToken) = 0;
* returns true.
* If hijacking is not possible for some reason, it return false.
*/
virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind) = 0;
virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken X86_ARG(ReturnKind * returnKind)) = 0;

#ifndef USE_GC_INFO_DECODER
/*
Expand Down Expand Up @@ -575,7 +575,7 @@ size_t GetFunctionSize(GCInfoToken gcInfoToken);
* returns true.
* If hijacking is not possible for some reason, it return false.
*/
virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind);
virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken X86_ARG(ReturnKind * returnKind));

#ifndef USE_GC_INFO_DECODER
/*
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/inc/gcinfodecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ enum GcInfoDecoderFlags
DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context)
DECODE_EDIT_AND_CONTINUE = 0x800,
DECODE_REVERSE_PINVOKE_VAR = 0x1000,
DECODE_RETURN_KIND = 0x2000,
#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
DECODE_HAS_TAILCALLS = 0x4000,
#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64
Expand Down Expand Up @@ -582,7 +581,6 @@ class GcInfoDecoder
#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
bool HasTailCalls();
#endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || defined(TARGET_RISCV64)
ReturnKind GetReturnKind();
UINT32 GetCodeLength();
UINT32 GetStackBaseRegister();
UINT32 GetSizeOfEditAndContinuePreservedArea();
Expand Down Expand Up @@ -615,7 +613,6 @@ class GcInfoDecoder
#ifdef TARGET_ARM64
UINT32 m_SizeOfEditAndContinueFixedStackFrame;
#endif
ReturnKind m_ReturnKind;
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
UINT32 m_NumSafePoints;
UINT32 m_SafePointIndex;
Expand Down
8 changes: 5 additions & 3 deletions src/coreclr/nativeaot/Runtime/AsmOffsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ ASM_OFFSET( 30, 48, Thread, m_pTransitionFrame)
ASM_OFFSET( 34, 50, Thread, m_pDeferredTransitionFrame)
ASM_OFFSET( 44, 70, Thread, m_ppvHijackedReturnAddressLocation)
ASM_OFFSET( 48, 78, Thread, m_pvHijackedReturnAddress)
ASM_OFFSET( 4c, 80, Thread, m_uHijackedReturnValueFlags)
ASM_OFFSET( 50, 88, Thread, m_pExInfoStackHead)
ASM_OFFSET( 54, 90, Thread, m_threadAbortException)
ASM_OFFSET( 4c, 80, Thread, m_pExInfoStackHead)
ASM_OFFSET( 50, 88, Thread, m_threadAbortException)
#ifdef TARGET_X86
ASM_OFFSET( 54, FF, Thread, m_uHijackedReturnValueFlags)
#endif

ASM_SIZEOF( 14, 20, EHEnum)

Expand Down
125 changes: 11 additions & 114 deletions src/coreclr/nativeaot/Runtime/ICodeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,92 +28,11 @@ enum GCRefKind : unsigned char
GCRK_Scalar = 0x00,
GCRK_Object = 0x01,
GCRK_Byref = 0x02,
#ifdef TARGET_64BIT
// Composite return kinds for value types returned in two registers (encoded with two bits per register)
GCRK_Scalar_Obj = (GCRK_Object << 2) | GCRK_Scalar,
GCRK_Obj_Obj = (GCRK_Object << 2) | GCRK_Object,
GCRK_Byref_Obj = (GCRK_Object << 2) | GCRK_Byref,
GCRK_Scalar_Byref = (GCRK_Byref << 2) | GCRK_Scalar,
GCRK_Obj_Byref = (GCRK_Byref << 2) | GCRK_Object,
GCRK_Byref_Byref = (GCRK_Byref << 2) | GCRK_Byref,

GCRK_LastValid = GCRK_Byref_Byref,
#else // TARGET_ARM64
GCRK_LastValid = GCRK_Byref,
#endif // TARGET_ARM64
GCRK_Unknown = 0xFF,
};

#ifdef TARGET_ARM64
// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back
C_ASSERT(PTFF_X0_IS_GCREF == ((uint64_t)GCRK_Object << 32));
C_ASSERT(PTFF_X0_IS_BYREF == ((uint64_t)GCRK_Byref << 32));
C_ASSERT(PTFF_X1_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 32));
C_ASSERT(PTFF_X1_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 32));

inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind)
{
// just need to report gc ref bits here.
// appropriate PTFF_SAVE_ bits will be added by the frame building routine.
return ((uint64_t)returnKind << 32);
}

inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags)
{
GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_X0_IS_GCREF | PTFF_X0_IS_BYREF | PTFF_X1_IS_GCREF | PTFF_X1_IS_BYREF)) >> 32);
ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_X0) && (transFrameFlags & PTFF_SAVE_X1)));
return returnKind;
}

#elif defined(TARGET_LOONGARCH64)
// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back
C_ASSERT(PTFF_R4_IS_GCREF == ((uint64_t)GCRK_Object << 31));
C_ASSERT(PTFF_R4_IS_BYREF == ((uint64_t)GCRK_Byref << 31));
C_ASSERT(PTFF_R5_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 31));
C_ASSERT(PTFF_R5_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 31));

inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind)
{
// just need to report gc ref bits here.
// appropriate PTFF_SAVE_ bits will be added by the frame building routine.
return ((uint64_t)returnKind << 31);
}

inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags)
{
GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_R4_IS_GCREF | PTFF_R4_IS_BYREF | PTFF_R5_IS_GCREF | PTFF_R5_IS_BYREF)) >> 31);
ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_R4) && (transFrameFlags & PTFF_SAVE_R5)));
return returnKind;
}

#elif defined(TARGET_AMD64)

// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back
C_ASSERT(PTFF_RAX_IS_GCREF == ((uint64_t)GCRK_Object << 16));
C_ASSERT(PTFF_RAX_IS_BYREF == ((uint64_t)GCRK_Byref << 16));
C_ASSERT(PTFF_RDX_IS_GCREF == ((uint64_t)GCRK_Scalar_Obj << 16));
C_ASSERT(PTFF_RDX_IS_BYREF == ((uint64_t)GCRK_Scalar_Byref << 16));

inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind)
{
// just need to report gc ref bits here.
// appropriate PTFF_SAVE_ bits will be added by the frame building routine.
return ((uint64_t)returnKind << 16);
}

inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags)
{
GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_RAX_IS_GCREF | PTFF_RAX_IS_BYREF | PTFF_RDX_IS_GCREF | PTFF_RDX_IS_BYREF)) >> 16);
#if defined(TARGET_UNIX)
ASSERT((returnKind == GCRK_Scalar) || ((transFrameFlags & PTFF_SAVE_RAX) && (transFrameFlags & PTFF_SAVE_RDX)));
#else
ASSERT((returnKind == GCRK_Scalar) || (transFrameFlags & PTFF_SAVE_RAX));
#endif
return returnKind;
}

#elif defined(TARGET_X86)

#if defined(TARGET_X86)
// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back
C_ASSERT(PTFF_RAX_IS_GCREF == ((uint64_t)GCRK_Object << 16));
C_ASSERT(PTFF_RAX_IS_BYREF == ((uint64_t)GCRK_Byref << 16));
Expand All @@ -132,40 +51,13 @@ inline GCRefKind TransitionFrameFlagsToReturnKind(uintptr_t transFrameFlags)
return returnKind;
}

#elif defined(TARGET_ARM)

// Verify that we can use bitwise shifts to convert from GCRefKind to PInvokeTransitionFrameFlags and back
C_ASSERT(PTFF_R0_IS_GCREF == ((uint64_t)GCRK_Object << 14));
C_ASSERT(PTFF_R0_IS_BYREF == ((uint64_t)GCRK_Byref << 14));

inline uint64_t ReturnKindToTransitionFrameFlags(GCRefKind returnKind)
{
// just need to report gc ref bits here.
// appropriate PTFF_SAVE_ bits will be added by the frame building routine.
return ((uint64_t)returnKind << 14);
}

inline GCRefKind TransitionFrameFlagsToReturnKind(uint64_t transFrameFlags)
{
GCRefKind returnKind = (GCRefKind)((transFrameFlags & (PTFF_R0_IS_GCREF | PTFF_R0_IS_BYREF)) >> 14);
ASSERT((returnKind == GCRK_Scalar) || (transFrameFlags & PTFF_SAVE_R0));
return returnKind;
}

#endif

// Extract individual GCRefKind components from a composite return kind
inline GCRefKind ExtractReg0ReturnKind(GCRefKind returnKind)
inline GCRefKind ExtractReturnKind(GCRefKind returnKind)
{
ASSERT(returnKind <= GCRK_LastValid);
return (GCRefKind)(returnKind & (GCRK_Object | GCRK_Byref));
}

inline GCRefKind ExtractReg1ReturnKind(GCRefKind returnKind)
{
ASSERT(returnKind <= GCRK_LastValid);
return (GCRefKind)(returnKind >> 2);
}
#endif

//
// MethodInfo is placeholder type used to allocate space for MethodInfo. Maximum size
Expand Down Expand Up @@ -272,9 +164,14 @@ class ICodeManager
virtual bool IsUnwindable(PTR_VOID pvAddress) PURE_VIRTUAL

virtual bool GetReturnAddressHijackInfo(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet, // in
PTR_PTR_VOID * ppvRetAddrLocation, // out
GCRefKind * pRetValueKind) PURE_VIRTUAL // out
REGDISPLAY * pRegisterSet, // in
PTR_PTR_VOID * ppvRetAddrLocation // out
) PURE_VIRTUAL

#ifdef TARGET_X86
virtual GCRefKind GetReturnValueKind(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet) PURE_VIRTUAL
#endif

virtual PTR_VOID RemapHardwareFaultToGCSafePoint(MethodInfo * pMethodInfo, PTR_VOID controlPC) PURE_VIRTUAL

Expand Down
43 changes: 17 additions & 26 deletions src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,18 @@ StackFrameIterator::StackFrameIterator(Thread * pThreadToWalk, PInvokeTransition
{
InternalInit(pThreadToWalk, pThreadToWalk->GetInterruptedContext(), GcStackWalkFlags | ActiveStackFrame);
}
else
else if (pInitialTransitionFrame == TOP_OF_STACK_MARKER)
{
InternalInit(pThreadToWalk, pInitialTransitionFrame, GcStackWalkFlags);
}
else
{
uint32_t flags = (pInitialTransitionFrame->m_Flags & PTFF_THREAD_HIJACK) == 0 ?
GcStackWalkFlags :
GcStackWalkFlags | ActiveStackFrame;

InternalInit(pThreadToWalk, pInitialTransitionFrame, flags);
}

PrepareToYieldFrame();
}
Expand Down Expand Up @@ -110,8 +118,10 @@ void StackFrameIterator::EnterInitialInvalidState(Thread * pThreadToWalk)
m_pThread = pThreadToWalk;
m_pInstance = GetRuntimeInstance();
m_pCodeManager = NULL;
#ifdef TARGET_X86
m_pHijackedReturnValue = NULL;
m_HijackedReturnValueKind = GCRK_Unknown;
#endif
m_pConservativeStackRangeLowerBound = NULL;
m_pConservativeStackRangeUpperBound = NULL;
m_pendingFuncletFramePointer = NULL;
Expand Down Expand Up @@ -180,17 +190,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF
if (pFrame->m_Flags & PTFF_SAVE_R3) { m_RegDisplay.pR3 = pPreservedRegsCursor++; }
if (pFrame->m_Flags & PTFF_SAVE_LR) { m_RegDisplay.pLR = pPreservedRegsCursor++; }

if (pFrame->m_Flags & PTFF_R0_IS_GCREF)
{
m_pHijackedReturnValue = (PTR_OBJECTREF) m_RegDisplay.pR0;
m_HijackedReturnValueKind = GCRK_Object;
}
if (pFrame->m_Flags & PTFF_R0_IS_BYREF)
{
m_pHijackedReturnValue = (PTR_OBJECTREF) m_RegDisplay.pR0;
m_HijackedReturnValueKind = GCRK_Byref;
}

#elif defined(TARGET_ARM64)
m_RegDisplay.pFP = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_FramePointer);
m_RegDisplay.pLR = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_RIP);
Expand Down Expand Up @@ -232,13 +231,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF

if (pFrame->m_Flags & PTFF_SAVE_LR) { m_RegDisplay.pLR = pPreservedRegsCursor++; }

GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags);
if (retValueKind != GCRK_Scalar)
{
m_pHijackedReturnValue = (PTR_OBJECTREF)m_RegDisplay.pX0;
m_HijackedReturnValueKind = retValueKind;
}

#elif defined(TARGET_LOONGARCH64)
m_RegDisplay.pFP = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_FramePointer);
m_RegDisplay.pRA = (PTR_uintptr_t)PTR_HOST_MEMBER_TADDR(PInvokeTransitionFrame, pFrame, m_RIP);
Expand Down Expand Up @@ -280,13 +272,6 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF

if (pFrame->m_Flags & PTFF_SAVE_RA) { m_RegDisplay.pRA = pPreservedRegsCursor++; }

GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags);
if (retValueKind != GCRK_Scalar)
{
m_pHijackedReturnValue = (PTR_OBJECTREF)m_RegDisplay.pR4;
m_HijackedReturnValueKind = retValueKind;
}

#else // TARGET_ARM
if (pFrame->m_Flags & PTFF_SAVE_RBX) { m_RegDisplay.pRbx = pPreservedRegsCursor++; }
if (pFrame->m_Flags & PTFF_SAVE_RSI) { m_RegDisplay.pRsi = pPreservedRegsCursor++; }
Expand Down Expand Up @@ -314,12 +299,14 @@ void StackFrameIterator::InternalInit(Thread * pThreadToWalk, PInvokeTransitionF
if (pFrame->m_Flags & PTFF_SAVE_R11) { m_RegDisplay.pR11 = pPreservedRegsCursor++; }
#endif // TARGET_AMD64

#ifdef TARGET_X86
GCRefKind retValueKind = TransitionFrameFlagsToReturnKind(pFrame->m_Flags);
if (retValueKind != GCRK_Scalar)
{
m_pHijackedReturnValue = (PTR_OBJECTREF)m_RegDisplay.pRax;
m_HijackedReturnValueKind = retValueKind;
}
#endif

#endif // TARGET_ARM

Expand Down Expand Up @@ -1529,8 +1516,10 @@ void StackFrameIterator::NextInternal()
m_dwFlags &= ~(ExCollide|MethodStateCalculated|UnwoundReversePInvoke|ActiveStackFrame);
ASSERT(IsValid());

#ifdef TARGET_X86
m_pHijackedReturnValue = NULL;
m_HijackedReturnValueKind = GCRK_Unknown;
#endif

#ifdef _DEBUG
SetControlPC(dac_cast<PTR_VOID>((void*)666));
Expand Down Expand Up @@ -1944,6 +1933,7 @@ void StackFrameIterator::CalculateCurrentMethodState()
m_dwFlags |= MethodStateCalculated;
}

#ifdef TARGET_X86
bool StackFrameIterator::GetHijackedReturnValueLocation(PTR_OBJECTREF * pLocation, GCRefKind * pKind)
{
if (GCRK_Unknown == m_HijackedReturnValueKind)
Expand All @@ -1955,6 +1945,7 @@ bool StackFrameIterator::GetHijackedReturnValueLocation(PTR_OBJECTREF * pLocatio
*pKind = m_HijackedReturnValueKind;
return true;
}
#endif

void StackFrameIterator::SetControlPC(PTR_VOID controlPC)
{
Expand Down
8 changes: 6 additions & 2 deletions src/coreclr/nativeaot/Runtime/StackFrameIterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class StackFrameIterator
PTR_ICodeManager GetCodeManager();
MethodInfo * GetMethodInfo();
bool IsActiveStackFrame();
#ifdef TARGET_X86
bool GetHijackedReturnValueLocation(PTR_OBJECTREF * pLocation, GCRefKind * pKind);
#endif
void SetControlPC(PTR_VOID controlPC);

static bool IsValidReturnAddress(PTR_VOID pvAddress);
Expand Down Expand Up @@ -221,10 +223,12 @@ class StackFrameIterator
PTR_ICodeManager m_pCodeManager;
MethodInfo m_methodInfo;
PTR_VOID m_effectiveSafePointAddress;
#ifdef TARGET_X86
PTR_OBJECTREF m_pHijackedReturnValue;
GCRefKind m_HijackedReturnValueKind;
PTR_uintptr_t m_pConservativeStackRangeLowerBound;
PTR_uintptr_t m_pConservativeStackRangeUpperBound;
#endif
PTR_uintptr_t m_pConservativeStackRangeLowerBound;
PTR_uintptr_t m_pConservativeStackRangeUpperBound;
uint32_t m_dwFlags;
PTR_ExInfo m_pNextExInfo;
PTR_VOID m_pendingFuncletFramePointer;
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/nativeaot/Runtime/amd64/AsmMacros.inc
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,8 @@ PTFF_SAVE_ALL_PRESERVED equ 000000F7h ;; NOTE: RBP is not included in this set
PTFF_SAVE_RSP equ 00008000h
PTFF_SAVE_RAX equ 00000100h ;; RAX is saved in hijack handler - in case it contains a GC ref
PTFF_SAVE_ALL_SCRATCH equ 00007F00h
PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Object, clear -> eax is scalar
PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar
PTFF_THREAD_ABORT equ 00100000h ;; indicates that ThreadAbortException should be thrown when returning from the transition
PTFF_THREAD_HIJACK equ 00200000h ;; indicates that this is a frame for a hijacked call

;; These must match the TrapThreadsFlags enum
TrapThreadsFlags_None equ 0
Expand Down
Loading

0 comments on commit ddc7867

Please sign in to comment.