diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2015-03-30 18:53:09 +0200 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2015-03-30 18:53:09 +0200 |
commit | 00048d007ba7ecc9cbdefc5b91eb7322e0e6d400 (patch) | |
tree | 19d718673dd647acaa3bdcd2a20bc4a4af42f5dd | |
parent | 09456645352db6316d18a1f1243ba538aca4311b (diff) | |
parent | 73a8ac6fdbf12eff1102adcac62750c209789589 (diff) | |
download | coreclr-00048d007ba7ecc9cbdefc5b91eb7322e0e6d400.tar.gz coreclr-00048d007ba7ecc9cbdefc5b91eb7322e0e6d400.tar.bz2 coreclr-00048d007ba7ecc9cbdefc5b91eb7322e0e6d400.zip |
Merge pull request #595 from janvorli/fix-issue-566
Fix GC exception related issue
-rw-r--r-- | src/vm/exceptionhandling.cpp | 61 | ||||
-rw-r--r-- | src/vm/exceptionhandling.h | 33 |
2 files changed, 72 insertions, 22 deletions
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index 7e7dc57a5f..0d89fbb281 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -3518,6 +3518,36 @@ void ExceptionTracker::PopTrackers( } } +// Save the state of the source exception tracker +void ExceptionTracker::PartialTrackerState::Save(const ExceptionTracker* pSourceTracker) +{ + m_sfResumeStackFrame = pSourceTracker->m_sfResumeStackFrame; + m_ScannedStackRange = pSourceTracker->m_ScannedStackRange; + m_uCatchToCallPC = pSourceTracker->m_uCatchToCallPC; + m_pClauseForCatchToken = pSourceTracker->m_pClauseForCatchToken; + m_ClauseForCatch = pSourceTracker->m_ClauseForCatch; + m_ExceptionFlags = pSourceTracker->m_ExceptionFlags; + m_sfLastUnwoundEstablisherFrame = pSourceTracker->m_sfLastUnwoundEstablisherFrame; + m_EHClauseInfo = pSourceTracker->m_EHClauseInfo; + m_EnclosingClauseInfo = pSourceTracker->m_EnclosingClauseInfo; + m_EnclosingClauseInfoForGCReporting = pSourceTracker->m_EnclosingClauseInfoForGCReporting; +} + +// Restore the state into the target exception tracker +void ExceptionTracker::PartialTrackerState::Restore(ExceptionTracker* pTargetTracker) +{ + pTargetTracker->m_sfResumeStackFrame = m_sfResumeStackFrame; + pTargetTracker->m_ScannedStackRange = m_ScannedStackRange; + pTargetTracker->m_uCatchToCallPC = m_uCatchToCallPC; + pTargetTracker->m_pClauseForCatchToken = m_pClauseForCatchToken; + pTargetTracker->m_ClauseForCatch = m_ClauseForCatch; + pTargetTracker->m_ExceptionFlags = m_ExceptionFlags; + pTargetTracker->m_sfLastUnwoundEstablisherFrame = m_sfLastUnwoundEstablisherFrame; + pTargetTracker->m_EHClauseInfo = m_EHClauseInfo; + pTargetTracker->m_EnclosingClauseInfo = m_EnclosingClauseInfo; + pTargetTracker->m_EnclosingClauseInfoForGCReporting = m_EnclosingClauseInfoForGCReporting; +} + // // static ExceptionTracker* ExceptionTracker::GetOrCreateTracker( @@ -3550,12 +3580,7 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( bool fIsInterleavedHandling = false; bool fTransitionFromSecondToFirstPass = false; - StackFrame previousTrackerResumeStackFrame; - StackRange previousTrackerScannedStackRange; - UINT_PTR previousTrackerCatchToCallPC; - PTR_EXCEPTION_CLAUSE_TOKEN previousTrackerClauseForCatchToken; - EE_ILEXCEPTION_CLAUSE previousTrackerClauseForCatch; - ExceptionFlags previousTrackerExceptionFlags; + PartialTrackerState previousTrackerPartialState; // Initialize the out parameter. *pStackTraceState = STS_Append; @@ -3594,12 +3619,7 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( { // Remember part of the current state that needs to be transferred to // the newly created tracker. - previousTrackerResumeStackFrame = pTracker->m_sfResumeStackFrame; - previousTrackerScannedStackRange = pTracker->m_ScannedStackRange; - previousTrackerCatchToCallPC = pTracker->m_uCatchToCallPC; - previousTrackerClauseForCatchToken = pTracker->m_pClauseForCatchToken; - previousTrackerClauseForCatch = pTracker->m_ClauseForCatch; - previousTrackerExceptionFlags = pTracker->m_ExceptionFlags; + previousTrackerPartialState.Save(pTracker); // We just transitioned from 2nd pass to 1st pass when we handle the exception in an interleaved manner EH_LOG((LL_INFO100, ">>continued processing of PREVIOUS exception (interleaved handling)\n")); @@ -3695,12 +3715,12 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( // series of first and second passes. When we create a new tracker as a result // of switching from the 2nd pass back to the 1st pass, we need to carry over // several members that were set when processing one of the previous frames. - pNewTracker->m_sfResumeStackFrame = previousTrackerResumeStackFrame; - pNewTracker->m_uCatchToCallPC = previousTrackerCatchToCallPC; - pNewTracker->m_pClauseForCatchToken = previousTrackerClauseForCatchToken; - pNewTracker->m_ClauseForCatch = previousTrackerClauseForCatch; - pNewTracker->m_ExceptionFlags = previousTrackerExceptionFlags; - pNewTracker->m_ScannedStackRange = previousTrackerScannedStackRange; + previousTrackerPartialState.Restore(pNewTracker); + // Reset the 'unwind has started' flag to indicate we are in the first pass again + pNewTracker->m_ExceptionFlags.ResetUnwindHasStarted(); + // Remember the current scanned stack range so that we can restore it after + // switching to the 2nd pass. + pNewTracker->m_secondPassInitialScannedStackRange = pNewTracker->m_ScannedStackRange; } CONSISTENCY_CHECK(pNewTracker->IsValid()); @@ -3853,10 +3873,7 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( // We have to detect this transition because otherwise we break when unmanaged code // catches our exceptions. EH_LOG((LL_INFO100, ">>tracker transitioned to second pass\n")); - if (!fIsInterleavedHandling) - { - pTracker->m_ScannedStackRange.Reset(); - } + pTracker->m_ScannedStackRange = pTracker->m_secondPassInitialScannedStackRange; pTracker->m_ExceptionFlags.SetUnwindHasStarted(); if (pTracker->m_ExceptionFlags.UnwindingToFindResumeFrame()) diff --git a/src/vm/exceptionhandling.h b/src/vm/exceptionhandling.h index 5b2568aadc..9362fa4a65 100644 --- a/src/vm/exceptionhandling.h +++ b/src/vm/exceptionhandling.h @@ -660,11 +660,44 @@ private: ; bool m_fEnclosingClauseIsFunclet; }; + // This class saves partial state of an exception tracker that needs to + // be preserved when transitioning from the 2nd to 1st pass during the + // interleaved exception handling before processing next segment of + // managed stack frames. + // The exception tracker is recreated during such transition and + // only a subset of the exception tracker state defined by this class + // is propagated to the new tracker instance. + class PartialTrackerState + { + StackFrame m_sfResumeStackFrame; + StackRange m_ScannedStackRange; + UINT_PTR m_uCatchToCallPC; + PTR_EXCEPTION_CLAUSE_TOKEN m_pClauseForCatchToken; + EE_ILEXCEPTION_CLAUSE m_ClauseForCatch; + ExceptionFlags m_ExceptionFlags; + StackFrame m_sfLastUnwoundEstablisherFrame; + EHClauseInfo m_EHClauseInfo; + EnclosingClauseInfo m_EnclosingClauseInfo; + EnclosingClauseInfo m_EnclosingClauseInfoForGCReporting; + + public: + // Save the state of the source exception tracker + void Save(const ExceptionTracker* pSourceTracker); + // Restore the state into the target exception tracker + void Restore(ExceptionTracker* pTargetTracker); + }; + PTR_ExceptionTracker m_pPrevNestedInfo; 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 StackRange m_ScannedStackRange; + // Range used to initialize the m_ScannedStackRange at start of the 2nd pass. + // This is: + // 1) null range for non-interleaved exception handling and the very first + // 2nd pass of the interleaved handling and + // 2) non-null for the other 2nd passes of the interleaved handling. + StackRange m_secondPassInitialScannedStackRange; DAC_EXCEPTION_POINTERS m_ptrs; OBJECTHANDLE m_hThrowable; StackTraceInfo m_StackTraceInfo; |