@@ -1098,6 +1098,7 @@ void StackFrameIterator::CommonCtor(Thread * pThread, PTR_Frame pFrame, ULONG32
10981098 m_forceReportingWhileSkipping = ForceGCReportingStage::Off;
10991099 m_movedPastFirstExInfo = false ;
11001100 m_fFuncletNotSeen = false ;
1101+ m_fFoundFirstFunclet = false ;
11011102#if defined(RECORD_RESUMABLE_FRAME_SP)
11021103 m_pvResumableFrameTargetSP = NULL ;
11031104#endif
@@ -1460,6 +1461,8 @@ void StackFrameIterator::ResetCrawlFrame()
14601461 m_crawl.isFilterFuncletCached = false ;
14611462 m_crawl.fShouldParentToFuncletSkipReportingGCReferences = false ;
14621463 m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = false ;
1464+ m_crawl.fShouldSaveFuncletInfo = false ;
1465+ m_crawl.fShouldParentToFuncletReportSavedFuncletSlots = false ;
14631466#endif // FEATURE_EH_FUNCLETS
14641467
14651468 m_crawl.pThread = this ->m_pThread ;
@@ -1631,10 +1634,11 @@ StackWalkAction StackFrameIterator::Filter(void)
16311634 {
16321635 if (!m_movedPastFirstExInfo)
16331636 {
1634- if ((pExInfo->m_passNumber == 2 ) && !pExInfo->m_csfEnclosingClause .IsNull () && m_sfFuncletParent.IsNull ())
1637+ if ((pExInfo->m_passNumber == 2 ) && !pExInfo->m_csfEnclosingClause .IsNull () && m_sfFuncletParent.IsNull () && pExInfo-> m_lastReportedFunclet . IP != 0 )
16351638 {
16361639 // We are in the 2nd pass and we have already called an exceptionally called
1637- // a finally funclet, but we have not seen any funclet on the call stack yet.
1640+ // finally funclet and reported that to GC in a previous GC run. But we have
1641+ // not seen any funclet on the call stack yet.
16381642 // Simulate that we have actualy seen a finally funclet during this pass and
16391643 // that it didn't report GC references to ensure that the references will be
16401644 // reported by the parent correctly.
@@ -1651,6 +1655,8 @@ StackWalkAction StackFrameIterator::Filter(void)
16511655 }
16521656 }
16531657
1658+ m_crawl.fShouldParentToFuncletReportSavedFuncletSlots = false ;
1659+
16541660 // by default, there is no funclet for the current frame
16551661 // that reported GC references
16561662 m_crawl.fShouldParentToFuncletSkipReportingGCReferences = false ;
@@ -1659,6 +1665,8 @@ StackWalkAction StackFrameIterator::Filter(void)
16591665 // CrawlFrame
16601666 m_crawl.fShouldCrawlframeReportGCReferences = true ;
16611667
1668+ m_crawl.fShouldSaveFuncletInfo = false ;
1669+
16621670 // By default, assume that parent frame is going to report GC references from
16631671 // the actual location reported by the stack walk.
16641672 m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = false ;
@@ -1855,7 +1863,7 @@ StackWalkAction StackFrameIterator::Filter(void)
18551863 // Initiate force reporting of references in the new managed exception handling code frames.
18561864 // These frames are still alive when we are in a finally funclet.
18571865 m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame;
1858- STRESS_LOG0 (LF_GCROOTS, LL_INFO100, " STACKWALK: Setting m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame\n " );
1866+ STRESS_LOG0 (LF_GCROOTS, LL_INFO100, " STACKWALK: Setting m_forceReportingWhileSkipping = ForceGCReportingStage::LookForManagedFrame while processing filter funclet \n " );
18591867 }
18601868 }
18611869 }
@@ -1873,10 +1881,11 @@ StackWalkAction StackFrameIterator::Filter(void)
18731881 m_sfFuncletParent = ExceptionTracker::FindParentStackFrameForStackWalk (&m_crawl, true );
18741882 _ASSERTE (!m_fFuncletNotSeen);
18751883
1884+ bool fFrameWasUnwound = ExceptionTracker::HasFrameBeenUnwoundByAnyActiveException (&m_crawl);
18761885 if (m_sfFuncletParent.IsNull ())
18771886 {
18781887 // This can only happen if the funclet (and its parent) have been unwound.
1879- _ASSERTE (ExceptionTracker::HasFrameBeenUnwoundByAnyActiveException (&m_crawl) );
1888+ _ASSERTE (fFrameWasUnwound );
18801889 }
18811890 else
18821891 {
@@ -1899,7 +1908,17 @@ StackWalkAction StackFrameIterator::Filter(void)
18991908
19001909 if (g_isNewExceptionHandlingEnabled)
19011910 {
1902- if (!ExecutionManager::IsManagedCode (GetIP (m_crawl.GetRegisterSet ()->pCallerContext )))
1911+ if (!m_fFoundFirstFunclet && pExInfo > (void *)GetRegdisplaySP (m_crawl.GetRegisterSet ()))
1912+ {
1913+ // For the first funclet we encounter below the topmost ExInfo, we instruct the GC scanning of the frame
1914+ // to save information on the funclet so that we can use it to report references in the parent frame if
1915+ // no such funclet is found in future GC scans for the same exception.
1916+ _ASSERTE (pExInfo != NULL );
1917+ m_crawl.fShouldSaveFuncletInfo = true ;
1918+ m_fFoundFirstFunclet = true ;
1919+ }
1920+
1921+ if (!fFrameWasUnwound && !ExecutionManager::IsManagedCode (GetIP (m_crawl.GetRegisterSet ()->pCallerContext )))
19031922 {
19041923 // Initiate force reporting of references in the new managed exception handling code frames.
19051924 // These frames are still alive when we are in a finally funclet.
@@ -2119,6 +2138,14 @@ StackWalkAction StackFrameIterator::Filter(void)
21192138 }
21202139 else if (!m_crawl.IsFunclet ())
21212140 {
2141+ if (m_fFuncletNotSeen)
2142+ {
2143+ // We have reached a real parent of a funclet that would be on the stack if GC didn't
2144+ // kick in between the calls to funclets in the second pass. We instruct GC to report
2145+ // roots using the info of the saved funclet we've seen during a previous GC.
2146+ m_crawl.fShouldParentToFuncletReportSavedFuncletSlots = true ;
2147+ m_fFuncletNotSeen = false ;
2148+ }
21222149 // we've reached the parent and it's not handling an exception, it's also not
21232150 // a funclet so reset our state. note that we cannot reset the state when the
21242151 // parent is a funclet since the leaf funclet didn't report any references and
@@ -2131,15 +2158,6 @@ StackWalkAction StackFrameIterator::Filter(void)
21312158 if (g_isNewExceptionHandlingEnabled)
21322159 {
21332160 _ASSERTE (!ExceptionTracker::HasFrameBeenUnwoundByAnyActiveException (&m_crawl));
2134- if (m_fFuncletNotSeen && m_crawl.IsFunclet ())
2135- {
2136- _ASSERTE (!m_fProcessIntermediaryNonFilterFunclet);
2137- _ASSERTE (m_crawl.fShouldCrawlframeReportGCReferences );
2138- m_fDidFuncletReportGCReferences = true ;
2139- shouldSkipReporting = false ;
2140- m_crawl.fShouldParentFrameUseUnwindTargetPCforGCReporting = true ;
2141- m_crawl.ehClauseForCatch = pExInfo->m_ClauseForCatch ;
2142- }
21432161 }
21442162 else
21452163 {
0 commit comments