diff --git a/src/coreclr/vm/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index b3f038321e3bfe..9d4eb754ac7d17 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -188,6 +188,9 @@ struct REGDISPLAY; #define NUM_CALLEE_SAVED_REGISTERS 6 +// No floating point callee saved registers on Unix AMD64 +#define ENUM_FP_CALLEE_SAVED_REGISTERS() + #else // UNIX_AMD64_ABI #define ENUM_ARGUMENT_REGISTERS() \ @@ -212,6 +215,18 @@ struct REGDISPLAY; #define NUM_CALLEE_SAVED_REGISTERS 8 +#define ENUM_FP_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(Xmm6) \ + CALLEE_SAVED_REGISTER(Xmm7) \ + CALLEE_SAVED_REGISTER(Xmm8) \ + CALLEE_SAVED_REGISTER(Xmm9) \ + CALLEE_SAVED_REGISTER(Xmm10) \ + CALLEE_SAVED_REGISTER(Xmm11) \ + CALLEE_SAVED_REGISTER(Xmm12) \ + CALLEE_SAVED_REGISTER(Xmm13) \ + CALLEE_SAVED_REGISTER(Xmm14) \ + CALLEE_SAVED_REGISTER(Xmm15) + #endif // UNIX_AMD64_ABI typedef DPTR(struct ArgumentRegisters) PTR_ArgumentRegisters; diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h index f60822ccaa87c2..499ce4db3e9a94 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -21,6 +21,27 @@ #define RESOLVE_STUB_THIRD_WORD 0xb460 #define LOOKUP_STUB_FIRST_WORD 0xf8df +#define ENUM_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(R4) \ + CALLEE_SAVED_REGISTER(R5) \ + CALLEE_SAVED_REGISTER(R6) \ + CALLEE_SAVED_REGISTER(R7) \ + CALLEE_SAVED_REGISTER(R8) \ + CALLEE_SAVED_REGISTER(R9) \ + CALLEE_SAVED_REGISTER(R10) \ + CALLEE_SAVED_REGISTER(R11) \ + CALLEE_SAVED_REGISTER(Lr) + +#define ENUM_FP_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(D[8]) \ + CALLEE_SAVED_REGISTER(D[9]) \ + CALLEE_SAVED_REGISTER(D[10]) \ + CALLEE_SAVED_REGISTER(D[11]) \ + CALLEE_SAVED_REGISTER(D[12]) \ + CALLEE_SAVED_REGISTER(D[13]) \ + CALLEE_SAVED_REGISTER(D[14]) \ + CALLEE_SAVED_REGISTER(D[15]) + class MethodDesc; class FramedMethodFrame; class Module; diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index 3ec3d6ea3b1a13..41147148c26f8f 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -17,6 +17,28 @@ #define USE_REDIRECT_FOR_GCSTRESS #endif // TARGET_UNIX +#define ENUM_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(Fp) \ + CALLEE_SAVED_REGISTER(Lr) \ + CALLEE_SAVED_REGISTER(X19) \ + CALLEE_SAVED_REGISTER(X20) \ + CALLEE_SAVED_REGISTER(X21) \ + CALLEE_SAVED_REGISTER(X22) \ + CALLEE_SAVED_REGISTER(X23) \ + CALLEE_SAVED_REGISTER(X24) \ + CALLEE_SAVED_REGISTER(X25) \ + CALLEE_SAVED_REGISTER(X26) + +#define ENUM_FP_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(V[8].Low) \ + CALLEE_SAVED_REGISTER(V[9].Low) \ + CALLEE_SAVED_REGISTER(V[10].Low) \ + CALLEE_SAVED_REGISTER(V[11].Low) \ + CALLEE_SAVED_REGISTER(V[12].Low) \ + CALLEE_SAVED_REGISTER(V[13].Low) \ + CALLEE_SAVED_REGISTER(V[14].Low) \ + CALLEE_SAVED_REGISTER(V[15].Low) + EXTERN_C void getFPReturn(int fpSize, INT64 *pRetVal); EXTERN_C void setFPReturn(int fpSize, INT64 retVal); diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 7a92fa7666f10e..c9ae699a517077 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -8491,14 +8491,9 @@ extern "C" bool QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollideCla isCollided = true; pExInfo->m_kind = (ExKind)((uint8_t)pExInfo->m_kind | (uint8_t)ExKind::SupersededFlag); - // Unwind until we hit the frame of the prevExInfo + // Unwind to the frame of the prevExInfo ExInfo* pPrevExInfo = pThis->GetNextExInfo(); - do - { - retVal = MoveToNextNonSkippedFrame(pThis); - } - while ((retVal == SWA_CONTINUE) && !(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD && pThis->m_crawl.GetRegisterSet()->SP == pPrevExInfo->m_regDisplay.SP)); - _ASSERTE(retVal != SWA_FAILED); + pThis->SkipTo(&pPrevExInfo->m_frameIter); pThis->ResetNextExInfoForSP(pThis->m_crawl.GetRegisterSet()->SP); } diff --git a/src/coreclr/vm/i386/cgencpu.h b/src/coreclr/vm/i386/cgencpu.h index 655ad8c7a2398b..358a2939f11004 100644 --- a/src/coreclr/vm/i386/cgencpu.h +++ b/src/coreclr/vm/i386/cgencpu.h @@ -103,6 +103,9 @@ inline unsigned StackElemSize(unsigned parmSize, bool isValueType = false /* unu CALLEE_SAVED_REGISTER(Ebx) \ CALLEE_SAVED_REGISTER(Ebp) +// There are no FP callee saved registers on x86 +#define ENUM_FP_CALLEE_SAVED_REGISTERS() + typedef DPTR(struct CalleeSavedRegisters) PTR_CalleeSavedRegisters; struct CalleeSavedRegisters { #define CALLEE_SAVED_REGISTER(regname) INT32 regname; diff --git a/src/coreclr/vm/loongarch64/cgencpu.h b/src/coreclr/vm/loongarch64/cgencpu.h index 0c3a7ca83a8d09..3bd6789906529a 100644 --- a/src/coreclr/vm/loongarch64/cgencpu.h +++ b/src/coreclr/vm/loongarch64/cgencpu.h @@ -15,6 +15,30 @@ #define USE_REDIRECT_FOR_GCSTRESS #endif // TARGET_UNIX +#define ENUM_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(Fp) \ + CALLEE_SAVED_REGISTER(Ra) \ + CALLEE_SAVED_REGISTER(S0) \ + CALLEE_SAVED_REGISTER(S1) \ + CALLEE_SAVED_REGISTER(S2) \ + CALLEE_SAVED_REGISTER(S3) \ + CALLEE_SAVED_REGISTER(S4) \ + CALLEE_SAVED_REGISTER(S5) \ + CALLEE_SAVED_REGISTER(S6) \ + CALLEE_SAVED_REGISTER(S7) \ + CALLEE_SAVED_REGISTER(S8) \ + CALLEE_SAVED_REGISTER(Tp) + +#define ENUM_FP_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(F[24]) \ + CALLEE_SAVED_REGISTER(F[25]) \ + CALLEE_SAVED_REGISTER(F[26]) \ + CALLEE_SAVED_REGISTER(F[27]) \ + CALLEE_SAVED_REGISTER(F[28]) \ + CALLEE_SAVED_REGISTER(F[29]) \ + CALLEE_SAVED_REGISTER(F[30]) \ + CALLEE_SAVED_REGISTER(F[31]) + EXTERN_C void getFPReturn(int fpSize, INT64 *pRetVal); EXTERN_C void setFPReturn(int fpSize, INT64 retVal); diff --git a/src/coreclr/vm/riscv64/cgencpu.h b/src/coreclr/vm/riscv64/cgencpu.h index 19fb205dffb0c8..d8fd06614f49bb 100644 --- a/src/coreclr/vm/riscv64/cgencpu.h +++ b/src/coreclr/vm/riscv64/cgencpu.h @@ -15,6 +15,37 @@ #define USE_REDIRECT_FOR_GCSTRESS #endif // TARGET_UNIX +#define ENUM_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(Fp) \ + CALLEE_SAVED_REGISTER(Ra) \ + CALLEE_SAVED_REGISTER(S1) \ + CALLEE_SAVED_REGISTER(S2) \ + CALLEE_SAVED_REGISTER(S3) \ + CALLEE_SAVED_REGISTER(S4) \ + CALLEE_SAVED_REGISTER(S5) \ + CALLEE_SAVED_REGISTER(S6) \ + CALLEE_SAVED_REGISTER(S7) \ + CALLEE_SAVED_REGISTER(S8) \ + CALLEE_SAVED_REGISTER(S9) \ + CALLEE_SAVED_REGISTER(S10) \ + CALLEE_SAVED_REGISTER(S11) \ + CALLEE_SAVED_REGISTER(Tp) \ + CALLEE_SAVED_REGISTER(Gp) + +#define ENUM_FP_CALLEE_SAVED_REGISTERS() \ + CALLEE_SAVED_REGISTER(F[8]) \ + CALLEE_SAVED_REGISTER(F[9]) \ + CALLEE_SAVED_REGISTER(F[18]) \ + CALLEE_SAVED_REGISTER(F[19]) \ + CALLEE_SAVED_REGISTER(F[20]) \ + CALLEE_SAVED_REGISTER(F[21]) \ + CALLEE_SAVED_REGISTER(F[22]) \ + CALLEE_SAVED_REGISTER(F[23]) \ + CALLEE_SAVED_REGISTER(F[24]) \ + CALLEE_SAVED_REGISTER(F[25]) \ + CALLEE_SAVED_REGISTER(F[26]) \ + CALLEE_SAVED_REGISTER(F[27]) + EXTERN_C void getFPReturn(int fpSize, INT64 *pRetVal); EXTERN_C void setFPReturn(int fpSize, INT64 retVal); diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index c1fd2841199d9e..56e76cdf4949d1 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -1546,6 +1546,66 @@ BOOL StackFrameIterator::IsValid(void) return TRUE; } // StackFrameIterator::IsValid() +#ifndef DACCESS_COMPILE +#ifdef FEATURE_EH_FUNCLETS +//--------------------------------------------------------------------------------------- +// +// Advance to the position that the other iterator is currently at. +// +void StackFrameIterator::SkipTo(StackFrameIterator *pOtherStackFrameIterator) +{ + // We copy the other stack frame iterator over the current one, but we need to + // keep a couple of members untouched. So we save them here and restore them + // after the copy. + ExInfo* pPrevExInfo = GetNextExInfo(); + REGDISPLAY *pRD = m_crawl.GetRegisterSet(); + Frame *pStartFrame = m_pStartFrame; +#ifdef _DEBUG + Frame *pRealStartFrame = m_pRealStartFrame; +#endif + + *this = *pOtherStackFrameIterator; + + m_pNextExInfo = pPrevExInfo; + m_crawl.pRD = pRD; + m_pStartFrame = pStartFrame; +#ifdef _DEBUG + m_pRealStartFrame = pRealStartFrame; +#endif + + REGDISPLAY *pOtherRD = pOtherStackFrameIterator->m_crawl.GetRegisterSet(); + *pRD->pCurrentContextPointers = *pOtherRD->pCurrentContextPointers; + SetIP(pRD->pCurrentContext, GetIP(pOtherRD->pCurrentContext)); + SetSP(pRD->pCurrentContext, GetSP(pOtherRD->pCurrentContext)); + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = (pRD->pCurrentContextPointers->regname == NULL) ? pOtherRD->pCurrentContext->regname : *pRD->pCurrentContextPointers->regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = pOtherRD->pCurrentContext->regname; + ENUM_FP_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + pRD->IsCallerContextValid = pOtherRD->IsCallerContextValid; + if (pRD->IsCallerContextValid) + { + *pRD->pCallerContextPointers = *pOtherRD->pCallerContextPointers; + SetIP(pRD->pCallerContext, GetIP(pOtherRD->pCallerContext)); + SetSP(pRD->pCallerContext, GetSP(pOtherRD->pCallerContext)); + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCallerContext->regname = (pRD->pCallerContextPointers->regname == NULL) ? pOtherRD->pCallerContext->regname : *pRD->pCallerContextPointers->regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCallerContext->regname = pOtherRD->pCallerContext->regname; + ENUM_FP_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + } + SyncRegDisplayToCurrentContext(pRD); +} +#endif // FEATURE_EH_FUNCLETS +#endif // DACCESS_COMPILE + //--------------------------------------------------------------------------------------- // // Advance to the next frame according to the stackwalk flags. If the iterator is stopped diff --git a/src/coreclr/vm/stackwalk.h b/src/coreclr/vm/stackwalk.h index 19fcebc2ec8188..ac37c6679e83c2 100644 --- a/src/coreclr/vm/stackwalk.h +++ b/src/coreclr/vm/stackwalk.h @@ -599,6 +599,13 @@ class StackFrameIterator // advance to the next frame according to the stackwalk flags StackWalkAction Next(void); +#ifndef DACCESS_COMPILE +#ifdef FEATURE_EH_FUNCLETS + // advance to the position that the other iterator is currently at + void SkipTo(StackFrameIterator *pOtherStackFrameIterator); +#endif // FEATURE_EH_FUNCLETS +#endif // DACCESS_COMPILE + #ifdef FEATURE_EH_FUNCLETS void ResetNextExInfoForSP(TADDR SP);