diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 3043a9728deae2..33a92db177420f 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -10571,9 +10571,6 @@ StackWalkAction TAResetStateCallback(CrawlFrame* pCf, void* data) // Note: This function should be invoked ONLY during unwind. #ifndef FEATURE_EH_FUNCLETS void ResetThreadAbortState(PTR_Thread pThread, void *pEstablisherFrame) -#else -void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCurrentStackFrame) -#endif { CONTRACTL { @@ -10581,77 +10578,19 @@ void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCur GC_NOTRIGGER; MODE_ANY; PRECONDITION(pThread != NULL); -#ifndef FEATURE_EH_FUNCLETS PRECONDITION(pEstablisherFrame != NULL); -#else - PRECONDITION(pCf != NULL); - PRECONDITION(!sfCurrentStackFrame.IsNull()); -#endif } CONTRACTL_END; if (pThread->IsAbortRequested()) { -#ifndef FEATURE_EH_FUNCLETS if (GetNextCOMPlusSEHRecord(static_cast(pEstablisherFrame)) == EXCEPTION_CHAIN_END) { _ASSERTE(!"Topmost handler and abort requested."); } -#else // !FEATURE_EH_FUNCLETS - // Get the active exception tracker - PTR_ExceptionTracker pCurEHTracker = (PTR_ExceptionTracker)pThread->GetExceptionState()->GetCurrentExceptionTracker(); - _ASSERTE(pCurEHTracker != NULL); - - // We will check if thread abort state needs to be reset only for the case of exception caught in - // native code. This will happen when: - // - // 1) an unwind is triggered and - // 2) current frame is the topmost frame we saw in the first pass and - // 3) a thread abort is requested and - // 4) we dont have address of the exception handler to be invoked. - // - // (1), (2) and (4) above are checked for in ExceptionTracker::ProcessOSExceptionNotification from where we call this - // function. - - // Current frame should be the topmost frame we saw in the first pass - _ASSERTE(pCurEHTracker->GetTopmostStackFrameFromFirstPass() == sfCurrentStackFrame); - - // If the exception has been caught in native code, then alongwith not having address of the handler to be - // invoked, we also wont have the IL clause for the catch block and resume stack frame will be NULL as well. - _ASSERTE((pCurEHTracker->GetCatchToCallPC() == 0) && - (pCurEHTracker->GetCatchHandlerExceptionClauseToken() == NULL) && - (pCurEHTracker->GetResumeStackFrame().IsNull())); - - // Walk the frame chain to see if there is any more managed code on the stack. If not, then this is the last managed frame - // on the stack and we can reset the thread abort state. - // - // Get the frame from which to start the stack walk from - Frame* pFrame = pCurEHTracker->GetLimitFrame(); - - // At this point, we are at the topmost frame we saw during the first pass - // before the unwind began. Walk the stack using the specified crawlframe and the topmost - // explicit frame to determine if we have more managed code up the stack. If none is found, - // we can reset the thread abort state. - - // Setup the data structure to be passed to the callback - TAResetStateCallbackData dataCallback; - dataCallback.fDoWeHaveMoreManagedCodeOnStack = FALSE; - - // At this point, the StackFrame in CrawlFrame should represent the current frame we have been called for. - // _ASSERTE(sfCurrentStackFrame == StackFrame::FromRegDisplay(pCf->GetRegisterSet())); - - // Reference to the StackFrame beyond which we are looking for managed code. - dataCallback.sfSeedCrawlFrame = sfCurrentStackFrame; - - pThread->StackWalkFramesEx(pCf->GetRegisterSet(), TAResetStateCallback, &dataCallback, QUICKUNWIND, pFrame); - - if (!dataCallback.fDoWeHaveMoreManagedCodeOnStack) - { - _ASSERTE(!"There is no more managed code on the stack, and thread abort is requested."); - } -#endif // !FEATURE_EH_FUNCLETS } } +#endif // !FEATURE_EH_FUNCLETS #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h index b31d34f431f038..f346638b4ca410 100644 --- a/src/coreclr/vm/excep.h +++ b/src/coreclr/vm/excep.h @@ -833,8 +833,6 @@ class ExceptionNotifications #ifndef FEATURE_EH_FUNCLETS void ResetThreadAbortState(PTR_Thread pThread, void *pEstablisherFrame); -#else -void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCurrentStackFrame); #endif X86_ONLY(EXCEPTION_REGISTRATION_RECORD* GetNextCOMPlusSEHRecord(EXCEPTION_REGISTRATION_RECORD* pRec);) diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 046f8fea6d14a0..dba6730f4c90ff 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -127,7 +127,6 @@ static void DoEHLog(DWORD lvl, _In_z_ const char *fmt, ...); #define EH_LOG(expr) #endif -TrackerAllocator g_theTrackerAllocator; uint32_t g_exceptionCount; void FixContext(PCONTEXT pContextRecord) @@ -155,40 +154,6 @@ BOOL HandleHardwareException(PAL_SEHException* ex); BOOL IsSafeToHandleHardwareException(PCONTEXT contextRecord, PEXCEPTION_RECORD exceptionRecord); #endif // TARGET_UNIX -static ExceptionTracker* GetTrackerMemory() -{ - CONTRACTL - { - GC_TRIGGERS; - NOTHROW; - MODE_ANY; - } - CONTRACTL_END; - - return g_theTrackerAllocator.GetTrackerMemory(); -} - -void FreeTrackerMemory(ExceptionTracker* pTracker, TrackerMemoryType mem) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; - MODE_ANY; - } - CONTRACTL_END; - - if (mem & memManaged) - { - pTracker->ReleaseResources(); - } - - if (mem & memUnmanaged) - { - g_theTrackerAllocator.FreeTrackerMemory(pTracker); - } -} - static inline void UpdatePerformanceMetrics(CrawlFrame *pcfThisFrame, BOOL bIsRethrownException, BOOL bIsNewException) { WRAPPER_NO_CONTRACT; @@ -222,8 +187,6 @@ void InitializeExceptionHandling() CLRAddVectoredHandlers(); - g_theTrackerAllocator.Init(); - #ifdef TARGET_UNIX // Register handler of hardware exceptions like null reference in PAL PAL_SetHardwareExceptionHandler(HandleHardwareException, IsSafeToHandleHardwareException); @@ -907,31 +870,6 @@ EXCEPTION_DISPOSITION ClrDebuggerDoUnwindAndIntercept(X86_FIRST_ARG(EXCEPTION_RE #endif // DEBUGGING_SUPPORTED #ifdef _DEBUG -inline bool ExceptionTracker::IsValid() -{ - bool fRetVal = false; - - EX_TRY - { - Thread* pThisThread = GetThreadNULLOk(); - if (m_pThread == pThisThread) - { - fRetVal = true; - } - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); - - if (!fRetVal) - { - EH_LOG((LL_ERROR, "ExceptionTracker::IsValid() failed! this = 0x%p\n", this)); - } - - return fRetVal; -} - // // static UINT_PTR ExceptionTracker::DebugComputeNestingLevel() @@ -1785,136 +1723,6 @@ void ClrUnwindEx(EXCEPTION_RECORD* pExceptionRecord, UINT_PTR ReturnValue, UINT_ } #endif // !TARGET_UNIX -void TrackerAllocator::Init() -{ - void* pvFirstPage = (void*)new BYTE[TRACKER_ALLOCATOR_PAGE_SIZE]; - - ZeroMemory(pvFirstPage, TRACKER_ALLOCATOR_PAGE_SIZE); - - m_pFirstPage = (Page*)pvFirstPage; - - _ASSERTE(NULL == m_pFirstPage->m_header.m_pNext); - _ASSERTE(0 == m_pFirstPage->m_header.m_idxFirstFree); - - m_pCrst = new Crst(CrstException, CRST_UNSAFE_ANYMODE); - - EH_LOG((LL_INFO100, "TrackerAllocator::Init() succeeded..\n")); -} - -void TrackerAllocator::Terminate() -{ - Page* pPage = m_pFirstPage; - - while (pPage) - { - Page* pDeleteMe = pPage; - pPage = pPage->m_header.m_pNext; - delete [] pDeleteMe; - } - delete m_pCrst; -} - -ExceptionTracker* TrackerAllocator::GetTrackerMemory() -{ - CONTRACT(ExceptionTracker*) - { - GC_TRIGGERS; - NOTHROW; - MODE_ANY; - POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); - } - CONTRACT_END; - - _ASSERTE(NULL != m_pFirstPage); - - Page* pPage = m_pFirstPage; - - ExceptionTracker* pTracker = NULL; - - for (int i = 0; i < TRACKER_ALLOCATOR_MAX_OOM_SPINS; i++) - { - { // open lock scope - CrstHolder ch(m_pCrst); - - while (pPage) - { - int idx; - for (idx = 0; idx < NUM_TRACKERS_PER_PAGE; idx++) - { - pTracker = &(pPage->m_rgTrackers[idx]); - if (pTracker->m_pThread == NULL) - { - break; - } - } - - if (idx < NUM_TRACKERS_PER_PAGE) - { - break; - } - else - { - if (NULL == pPage->m_header.m_pNext) - { - Page* pNewPage = (Page*) new (nothrow) BYTE[TRACKER_ALLOCATOR_PAGE_SIZE]; - - if (pNewPage) - { - STRESS_LOG0(LF_EH, LL_INFO10, "TrackerAllocator: allocated page\n"); - pPage->m_header.m_pNext = pNewPage; - ZeroMemory(pPage->m_header.m_pNext, TRACKER_ALLOCATOR_PAGE_SIZE); - } - else - { - STRESS_LOG0(LF_EH, LL_WARNING, "TrackerAllocator: failed to allocate a page\n"); - pTracker = NULL; - } - } - - pPage = pPage->m_header.m_pNext; - } - } - - if (pTracker) - { - Thread* pThread = GetThread(); - _ASSERTE(NULL != pPage); - ZeroMemory(pTracker, sizeof(*pTracker)); - pTracker->m_pThread = pThread; - EH_LOG((LL_INFO100, "TrackerAllocator: allocating tracker 0x%p, thread = 0x%p\n", pTracker, pTracker->m_pThread)); - break; - } - } // end lock scope - - // - // We could not allocate a new page of memory. This is a fatal error if it happens twice (nested) - // on the same thread because we have only one m_OOMTracker. We will spin hoping for another thread - // to give back to the pool or for the allocation to succeed. - // - - ClrSleepEx(TRACKER_ALLOCATOR_OOM_SPIN_DELAY, FALSE); - STRESS_LOG1(LF_EH, LL_WARNING, "TrackerAllocator: retry #%d\n", i); - } - - RETURN pTracker; -} - -void TrackerAllocator::FreeTrackerMemory(ExceptionTracker* pTracker) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; - MODE_ANY; - } - CONTRACTL_END; - - // mark this entry as free - EH_LOG((LL_INFO100, "TrackerAllocator: freeing tracker 0x%p, thread = 0x%p\n", pTracker, pTracker->m_pThread)); - CONSISTENCY_CHECK(pTracker->IsValid()); - InterlockedExchangeT(&(pTracker->m_pThread), NULL); -} - #ifdef TARGET_WINDOWS // This is Windows specific implementation as it is based upon the notion of collided unwind that is specific // to Windows 64bit. @@ -3157,86 +2965,6 @@ ExceptionTrackerBase::StackRange::StackRange() #endif // DACCESS_COMPILE } -ExceptionTracker::EnclosingClauseInfo::EnclosingClauseInfo() -{ - LIMITED_METHOD_CONTRACT; - - m_fEnclosingClauseIsFunclet = false; - m_dwEnclosingClauseOffset = 0; - m_uEnclosingClauseCallerSP = 0; -} - -ExceptionTracker::EnclosingClauseInfo::EnclosingClauseInfo(bool fEnclosingClauseIsFunclet, - DWORD dwEnclosingClauseOffset, - UINT_PTR uEnclosingClauseCallerSP) -{ - LIMITED_METHOD_CONTRACT; - - m_fEnclosingClauseIsFunclet = fEnclosingClauseIsFunclet; - m_dwEnclosingClauseOffset = dwEnclosingClauseOffset; - m_uEnclosingClauseCallerSP = uEnclosingClauseCallerSP; -} - -bool ExceptionTracker::EnclosingClauseInfo::EnclosingClauseIsFunclet() -{ - LIMITED_METHOD_CONTRACT; - return m_fEnclosingClauseIsFunclet; -} - -DWORD ExceptionTracker::EnclosingClauseInfo::GetEnclosingClauseOffset() -{ - LIMITED_METHOD_CONTRACT; - return m_dwEnclosingClauseOffset; -} - -UINT_PTR ExceptionTracker::EnclosingClauseInfo::GetEnclosingClauseCallerSP() -{ - LIMITED_METHOD_CONTRACT; - return m_uEnclosingClauseCallerSP; -} - -void ExceptionTracker::EnclosingClauseInfo::SetEnclosingClauseCallerSP(UINT_PTR callerSP) -{ - LIMITED_METHOD_CONTRACT; - m_uEnclosingClauseCallerSP = callerSP; -} - -bool ExceptionTracker::EnclosingClauseInfo::operator==(const EnclosingClauseInfo & rhs) -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return ((this->m_fEnclosingClauseIsFunclet == rhs.m_fEnclosingClauseIsFunclet) && - (this->m_dwEnclosingClauseOffset == rhs.m_dwEnclosingClauseOffset) && - (this->m_uEnclosingClauseCallerSP == rhs.m_uEnclosingClauseCallerSP)); -} - -void ExceptionTracker::ReleaseResources() -{ -#ifndef DACCESS_COMPILE - if (m_hThrowable) - { - if (!CLRException::IsPreallocatedExceptionHandle(m_hThrowable)) - { - DestroyHandle(m_hThrowable); - } - m_hThrowable = NULL; - } - -#ifndef TARGET_UNIX - // Clear any held Watson Bucketing details - GetWatsonBucketTracker()->ClearWatsonBucketDetails(); -#else // !TARGET_UNIX - if (m_fOwnsExceptionPointers) - { - PAL_FreeExceptionRecords(m_ptrs.ExceptionRecord, m_ptrs.ContextRecord); - m_fOwnsExceptionPointers = FALSE; - } -#endif // !TARGET_UNIX -#endif // DACCESS_COMPILE -} - - #ifdef DACCESS_COMPILE void ExceptionTrackerBase::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { diff --git a/src/coreclr/vm/exceptionhandling.h b/src/coreclr/vm/exceptionhandling.h index 15f59d50d515c5..881a1d4ebb3249 100644 --- a/src/coreclr/vm/exceptionhandling.h +++ b/src/coreclr/vm/exceptionhandling.h @@ -219,98 +219,25 @@ struct ExceptionTrackerBase typedef DPTR(class ExceptionTracker) PTR_ExceptionTracker; class ExceptionTracker : public ExceptionTrackerBase { - friend class TrackerAllocator; friend class ThreadExceptionState; friend class ClrDataExceptionState; #ifdef DACCESS_COMPILE friend class ClrDataAccess; #endif // DACCESS_COMPILE - friend void FreeTrackerMemory(ExceptionTracker* pTracker, TrackerMemoryType mem); - -public: - - ExceptionTracker() : - ExceptionTrackerBase(PTR_NULL, PTR_NULL, PTR_NULL), - m_pThread(NULL) - { - m_sfFirstPassTopmostFrame.Clear(); - - m_dwIndexClauseForCatch = 0; - m_sfEstablisherOfActualHandlerFrame.Clear(); - m_sfCallerOfActualHandlerFrame.Clear(); - - m_fFixupCallerSPForGCReporting = false; - - m_fResetEnclosingClauseSPForCatchFunclet = FALSE; - - m_sfCurrentEstablisherFrame.Clear(); - m_sfLastUnwoundEstablisherFrame.Clear(); - m_pInitialExplicitFrame = NULL; - m_pLimitFrame = NULL; - m_csfEHClauseOfCollapsedTracker.Clear(); - -#ifdef TARGET_UNIX - m_fOwnsExceptionPointers = FALSE; -#endif - } - - ExceptionTracker(DWORD_PTR dwExceptionPc, - PTR_EXCEPTION_RECORD pExceptionRecord, - PTR_CONTEXT pContextRecord) : - ExceptionTrackerBase(pExceptionRecord, pContextRecord, PTR_NULL), - m_pThread(GetThread()), - m_uCatchToCallPC{}, - m_pSkipToParentFunctionMD(NULL), -// these members were added for resume frame processing - m_pClauseForCatchToken(NULL) -// end resume frame members + ExceptionTracker() : + ExceptionTrackerBase(PTR_NULL, PTR_NULL, PTR_NULL) { - m_pLimitFrame = NULL; - - if (IsInstanceTaggedSEHCode(pExceptionRecord->ExceptionCode) && ::WasThrownByUs(pExceptionRecord, pExceptionRecord->ExceptionCode)) - { - m_ExceptionFlags.SetWasThrownByUs(); - } - - m_dwIndexClauseForCatch = 0; - m_sfEstablisherOfActualHandlerFrame.Clear(); - m_sfCallerOfActualHandlerFrame.Clear(); + UNREACHABLE(); + } - m_sfFirstPassTopmostFrame.Clear(); - - m_fFixupCallerSPForGCReporting = false; - - m_fResetEnclosingClauseSPForCatchFunclet = FALSE; - - m_sfCurrentEstablisherFrame.Clear(); - m_sfLastUnwoundEstablisherFrame.Clear(); - m_pInitialExplicitFrame = NULL; - m_csfEHClauseOfCollapsedTracker.Clear(); - -#ifdef TARGET_UNIX - m_fOwnsExceptionPointers = FALSE; -#endif - } - - ~ExceptionTracker() - { - ReleaseResources(); - } - - enum StackTraceState - { - STS_Append, - STS_FirstRethrowFrame, - STS_NewException, - }; +public: static OBJECTREF CreateThrowable( PEXCEPTION_RECORD pExceptionRecord, BOOL bAsynchronousThreadStop ); - INDEBUG(inline bool IsValid()); INDEBUG(static UINT_PTR DebugComputeNestingLevel()); // Return a StackFrame of the current frame for parent frame checking purposes. @@ -323,39 +250,6 @@ class ExceptionTracker : public ExceptionTrackerBase static bool HasFrameBeenUnwoundByAnyActiveException(CrawlFrame * pCF); - void SetLastUnwoundEstablisherFrame(StackFrame sfEstablisher) - { - LIMITED_METHOD_CONTRACT; - - m_sfLastUnwoundEstablisherFrame = sfEstablisher; - } - - StackFrame GetLastUnwoundEstablisherFrame() - { - LIMITED_METHOD_CONTRACT; - - return m_sfLastUnwoundEstablisherFrame; - } - - PTR_Frame GetInitialExplicitFrame() - { - LIMITED_METHOD_CONTRACT; - - return m_pInitialExplicitFrame; - } - -#ifdef TARGET_UNIX - // Reset the range of explicit frames, the limit frame and the scanned - // stack range before unwinding a sequence of native frames. These frames - // will be in the unwound part of the stack. - void CleanupBeforeNativeFramesUnwind() - { - m_pInitialExplicitFrame = NULL; - m_pLimitFrame = NULL; - m_ScannedStackRange.Reset(); - } -#endif // TARGET_UNIX - // Determines if we have unwound to the specified parent method frame. // Currently this is only used for funclet skipping. static bool IsUnwoundToTargetParentFrame(CrawlFrame * pCF, StackFrame sfParent); @@ -400,15 +294,7 @@ class ExceptionTracker : public ExceptionTrackerBase static void PopTrackers(void* pvStackPointer); -#if defined(TARGET_UNIX) && !defined(CROSS_COMPILE) - void TakeExceptionPointersOwnership(PAL_SEHException* ex) - { - _ASSERTE(ex->GetExceptionRecord() == m_ptrs.ExceptionRecord); - _ASSERTE(ex->GetContextRecord() == m_ptrs.ContextRecord); - ex->Clear(); - m_fOwnsExceptionPointers = TRUE; - } -#endif // TARGET_UNIX && !CROSS_COMPILE + static void UpdateNonvolatileRegisters(T_CONTEXT* pContextRecord, REGDISPLAY *pRegDisplay, bool fAborting); private: // private helpers @@ -423,224 +309,9 @@ class ExceptionTracker : public ExceptionTrackerBase DWORD* pParentOffset); static StackWalkAction RareFindParentStackFrameCallback(CrawlFrame* pCF, LPVOID pData); - - struct DAC_EXCEPTION_POINTERS - { - PTR_EXCEPTION_RECORD ExceptionRecord; - PTR_CONTEXT ContextRecord; - }; - -public: - - static void UpdateNonvolatileRegisters(T_CONTEXT* pContextRecord, REGDISPLAY *pRegDisplay, bool fAborting); - - PTR_Frame GetLimitFrame() - { - LIMITED_METHOD_CONTRACT; - return m_pLimitFrame; - } - - UINT_PTR GetCatchToCallPC() - { - LIMITED_METHOD_CONTRACT; - - return m_uCatchToCallPC; - } - - EE_ILEXCEPTION_CLAUSE GetEHClauseForCatch() - { - return m_ClauseForCatch; - } - - // Returns the topmost frame seen during the first pass. - StackFrame GetTopmostStackFrameFromFirstPass() - { - LIMITED_METHOD_CONTRACT; - - return m_sfFirstPassTopmostFrame; - } - -#ifdef _DEBUG - StackFrame GetResumeStackFrame() - { - LIMITED_METHOD_CONTRACT; - - return m_sfResumeStackFrame; - } - - PTR_EXCEPTION_CLAUSE_TOKEN GetCatchHandlerExceptionClauseToken() - { - LIMITED_METHOD_CONTRACT; - - return m_pClauseForCatchToken; - } -#endif // _DEBUG - - DWORD GetCatchHandlerExceptionClauseIndex() - { - LIMITED_METHOD_CONTRACT; - - return m_dwIndexClauseForCatch; - } - - StackFrame GetEstablisherOfActualHandlingFrame() - { - LIMITED_METHOD_CONTRACT; - - return m_sfEstablisherOfActualHandlerFrame; - } - - StackFrame GetCallerOfActualHandlingFrame() - { - LIMITED_METHOD_CONTRACT; - - return m_sfCallerOfActualHandlerFrame; - } - - StackFrame GetCallerOfEnclosingClause() - { - LIMITED_METHOD_CONTRACT; - - return m_EnclosingClauseInfoForGCReporting.GetEnclosingClauseCallerSP(); - } - - StackFrame GetCallerOfCollapsedEnclosingClause() - { - LIMITED_METHOD_CONTRACT; - - return m_EnclosingClauseInfoOfCollapsedTracker.GetEnclosingClauseCallerSP(); - } - -public: - - // Returns the throwble associated with the tracker as handle - inline OBJECTHANDLE GetThrowableAsHandle() - { - LIMITED_METHOD_CONTRACT; - - return m_hThrowable; - } - - EHClauseInfo* GetEHClauseInfo() - { - return &m_EHClauseInfo; - } - -private: ; - - void ReleaseResources(); - - struct EnclosingClauseInfo - { - public: - EnclosingClauseInfo(); - EnclosingClauseInfo(bool fEnclosingClauseIsFunclet, DWORD dwEnclosingClauseOffset, UINT_PTR uEnclosingClauseCallerSP); - - bool EnclosingClauseIsFunclet(); - DWORD GetEnclosingClauseOffset(); - UINT_PTR GetEnclosingClauseCallerSP(); - void SetEnclosingClauseCallerSP(UINT_PTR callerSP); - - bool operator==(const EnclosingClauseInfo & rhs); - - private: - UINT_PTR m_uEnclosingClauseCallerSP; - DWORD m_dwEnclosingClauseOffset; - bool m_fEnclosingClauseIsFunclet; - }; - - Thread* m_pThread; // this is used as an IsValid/IsFree field -- if it's NULL, the allocator can - // reuse its memory, if it's non-NULL, it better be a valid thread pointer - -#ifdef TARGET_UNIX - BOOL m_fOwnsExceptionPointers; -#endif - UINT_PTR m_uCatchToCallPC; - BOOL m_fResetEnclosingClauseSPForCatchFunclet; - - union - { - MethodDesc* m_pSkipToParentFunctionMD; // SKIPTOPARENT - MethodDesc* m_pMethodDescOfCatcher; - }; - - StackFrame m_sfResumeStackFrame; // RESUMEFRAME - StackFrame m_sfFirstPassTopmostFrame; // Topmost frame seen during first pass - PTR_EXCEPTION_CLAUSE_TOKEN m_pClauseForCatchToken; // RESUMEFRAME - EE_ILEXCEPTION_CLAUSE m_ClauseForCatch; - // Index of EH clause that will catch the exception - DWORD m_dwIndexClauseForCatch; - - // Establisher frame of the managed frame that contains - // the handler for the exception (corresponding - // to the EH index we save off in m_dwIndexClauseForCatch) - StackFrame m_sfEstablisherOfActualHandlerFrame; - StackFrame m_sfCallerOfActualHandlerFrame; - - PTR_Frame m_pLimitFrame; - - // This flag indicates whether the SP we pass to a funclet is for an enclosing funclet. - EnclosingClauseInfo m_EnclosingClauseInfo; - - // This stores the actual callerSP of the frame that is about to execute the funclet. - // It differs from "m_EnclosingClauseInfo" where upon detecting a nested exception, - // the latter can contain the callerSP of the original funclet instead of that of the - // current frame. - EnclosingClauseInfo m_EnclosingClauseInfoForGCReporting; - bool m_fFixupCallerSPForGCReporting; - - StackFrame m_sfCurrentEstablisherFrame; - StackFrame m_sfLastUnwoundEstablisherFrame; - PTR_Frame m_pInitialExplicitFrame; - CallerStackFrame m_csfEHClauseOfCollapsedTracker; - EnclosingClauseInfo m_EnclosingClauseInfoOfCollapsedTracker; }; -PTR_ExceptionTracker GetEHTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable, PTR_ExceptionTracker pStartingEHTracker); - -class TrackerAllocator -{ -public: - void Init(); - void Terminate(); - ExceptionTracker* GetTrackerMemory(); - void FreeTrackerMemory(ExceptionTracker* pTracker); - -private: - - struct Page; - - struct PageHeader - { - Page* m_pNext; - LONG m_idxFirstFree; - }; - - enum - { - // - // Due to the unexpected growth of the ExceptionTracker struct, - // GetOsPageSize() does not seem appropriate anymore on x64, and - // we should behave the same on x64 as on ia64 regardless of - // the difference between the page sizes on the platforms. - // - TRACKER_ALLOCATOR_PAGE_SIZE = 8*1024, - TRACKER_ALLOCATOR_MAX_OOM_SPINS = 20, - TRACKER_ALLOCATOR_OOM_SPIN_DELAY = 100, - NUM_TRACKERS_PER_PAGE = ((TRACKER_ALLOCATOR_PAGE_SIZE - sizeof(PageHeader)) / sizeof(ExceptionTracker)), - }; - - struct Page - { - PageHeader m_header; - ExceptionTracker m_rgTrackers[NUM_TRACKERS_PER_PAGE]; - }; - - static_assert_no_msg(sizeof(Page) <= TRACKER_ALLOCATOR_PAGE_SIZE); - - Page* m_pFirstPage; - Crst* m_pCrst; -}; +PTR_ExceptionTrackerBase GetEHTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable, PTR_ExceptionTrackerBase pStartingEHTracker); #endif // FEATURE_EH_FUNCLETS diff --git a/src/coreclr/vm/exstate.h b/src/coreclr/vm/exstate.h index 07432c32c1e61f..4c0b37681ff782 100644 --- a/src/coreclr/vm/exstate.h +++ b/src/coreclr/vm/exstate.h @@ -143,7 +143,6 @@ class ThreadExceptionState #ifdef FEATURE_EH_FUNCLETS PTR_ExceptionTrackerBase m_pCurrentTracker; - ExceptionTracker m_OOMTracker; public: PTR_ExceptionTrackerBase GetCurrentExceptionTracker() { diff --git a/src/coreclr/vm/stackwalk.cpp b/src/coreclr/vm/stackwalk.cpp index 859e87c2d3e551..2b857d8cf4b569 100644 --- a/src/coreclr/vm/stackwalk.cpp +++ b/src/coreclr/vm/stackwalk.cpp @@ -1628,7 +1628,6 @@ StackWalkAction StackFrameIterator::Filter(void) fSkippingFunclet = false; #if defined(FEATURE_EH_FUNCLETS) - ExceptionTracker* pTracker = NULL; ExInfo* pExInfo = NULL; pExInfo = (PTR_ExInfo)m_crawl.pThread->GetExceptionState()->GetCurrentExceptionTracker(); @@ -1746,70 +1745,6 @@ StackWalkAction StackFrameIterator::Filter(void) // Check if we are in the mode of enumerating GC references (or not) if (m_flags & GC_FUNCLET_REFERENCE_REPORTING) { -#ifdef TARGET_UNIX - // For interleaved exception handling on non-windows systems, we need to find out if the current frame - // was a caller of an already executed exception handler based on the previous exception trackers. - // The handler funclet frames are already gone from the stack, so the exception trackers are the - // only source of evidence about it. - // This is different from Windows where the full stack is preserved until an exception is fully handled - // and so we can detect it just from walking the stack. - // The filter funclet frames are different, they behave the same way on Windows and Unix. They can be present - // on the stack when we reach their parent frame if the filter hasn't finished running yet or they can be - // gone if the filter completed running, either successfully or with unhandled exception. - // So the special handling below ignores trackers belonging to filter clauses. - bool fProcessingFilterFunclet = !m_sfFuncletParent.IsNull() && !(m_fProcessNonFilterFunclet || m_fProcessIntermediaryNonFilterFunclet); - if (!fRecheckCurrentFrame && !fSkippingFunclet && (pTracker != NULL) && !fProcessingFilterFunclet) - { - // The stack walker is not skipping frames now, which means it didn't find a funclet frame that - // would require skipping the current frame. If we find a tracker with caller of actual handling - // frame matching the current frame, it means that the funclet stack frame was reclaimed. - StackFrame sfFuncletParent; - ExceptionTracker* pCurrTracker = pTracker; - - bool hasFuncletStarted = pTracker->GetEHClauseInfo()->IsManagedCodeEntered(); - - while (pCurrTracker != NULL) - { - // Ignore exception trackers for filter clauses, since their frames are handled the same way as on Windows - if (pCurrTracker->GetEHClauseInfo()->GetClauseType() != COR_PRF_CLAUSE_FILTER) - { - if (hasFuncletStarted) - { - sfFuncletParent = pCurrTracker->GetCallerOfEnclosingClause(); - if (!sfFuncletParent.IsNull() && ExceptionTracker::IsUnwoundToTargetParentFrame(&m_crawl, sfFuncletParent)) - { - break; - } - } - - sfFuncletParent = pCurrTracker->GetCallerOfCollapsedEnclosingClause(); - if (!sfFuncletParent.IsNull() && ExceptionTracker::IsUnwoundToTargetParentFrame(&m_crawl, sfFuncletParent)) - { - break; - } - } - - // Funclets handling exception for trackers older than the current one were always started, - // since the current tracker was created due to an exception in the funclet belonging to - // the previous tracker. - hasFuncletStarted = true; - pCurrTracker = (PTR_ExceptionTracker)pCurrTracker->GetPreviousExceptionTracker(); - } - - if (pCurrTracker != NULL) - { - // The current frame is a parent of a funclet that was already unwound and removed from the stack - // Set the members the same way we would set them on Windows when we - // would detect this just from stack walking. - m_sfParent = sfFuncletParent; - m_sfFuncletParent = sfFuncletParent; - m_fProcessNonFilterFunclet = true; - m_fDidFuncletReportGCReferences = false; - fSkippingFunclet = true; - } - } -#endif // TARGET_UNIX - fRecheckCurrentFrame = false; // Do we already have a reference to a funclet parent? if (!m_sfFuncletParent.IsNull()) @@ -2095,9 +2030,8 @@ StackWalkAction StackFrameIterator::Filter(void) STRESS_LOG2(LF_GCROOTS, LL_INFO100, "STACKWALK: Reached parent of funclet which didn't report GC roots, since funclet is already unwound, pExInfo->m_sfCallerOfActualHandlerFrame=%p, m_sfFuncletParent=%p\n", (void*)pExInfo->m_sfCallerOfActualHandlerFrame.SP, (void*)m_sfFuncletParent.SP); - _ASSERT(pExInfo != NULL || pTracker != NULL); - if ((pExInfo && pExInfo->m_sfCallerOfActualHandlerFrame == m_sfFuncletParent) || - (pTracker && pTracker->GetCallerOfActualHandlingFrame() == m_sfFuncletParent)) + _ASSERT(pExInfo != NULL); + if (pExInfo && pExInfo->m_sfCallerOfActualHandlerFrame == m_sfFuncletParent) { // we should not skip reporting for this parent frame shouldSkipReporting = false;