From ea3497e1701d4acb719338aebd6eb6d582c160f8 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 3 Dec 2013 10:47:47 -0800 Subject: [PATCH] Bug 937751, part 7 - Incrementalize nsCycleCollector::MarkRoots. r=smaug Now that all of MarkRoots's state is stored on the heap, it can be run incrementally. Like with Collect, it takes a budget to determine how long it can run. Any residual budget will be available to the caller. One difference is that Collect calls checkOverBudget() which always checks the time, but MarkRoots uses isOverBudget() to determine if there is any time remaining. This only checks the current time every kNumNodesBetweenTimeChecks nodes, to reduce the overhead of checking. --- xpcom/base/nsCycleCollector.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 2730f50706aa..547abad25aec 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -1085,7 +1085,7 @@ private: bool ShouldMergeZones(ccType aCCType); void BeginCollection(ccType aCCType, nsICycleCollectorListener *aManualListener); - void MarkRoots(); + void MarkRoots(SliceBudget &aBudget); void ScanRoots(); void ScanWeakMaps(); @@ -2211,8 +2211,11 @@ nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes, } MOZ_NEVER_INLINE void -nsCycleCollector::MarkRoots() +nsCycleCollector::MarkRoots(SliceBudget &aBudget) { + const intptr_t kNumNodesBetweenTimeChecks = 1000; + const intptr_t kStep = SliceBudget::CounterReset / kNumNodesBetweenTimeChecks; + TimeLog timeLog; AutoRestore ar(mScanInProgress); MOZ_ASSERT(!mScanInProgress); @@ -2220,14 +2223,20 @@ nsCycleCollector::MarkRoots() MOZ_ASSERT(mIncrementalPhase == GraphBuildingPhase); MOZ_ASSERT(mCurrNode); - while (!mCurrNode->IsDone()) { + while (!aBudget.isOverBudget() && !mCurrNode->IsDone()) { PtrInfo *pi = mCurrNode->GetNext(); CC_AbortIfNull(pi); mBuilder->Traverse(pi); if (mCurrNode->AtBlockEnd()) { mBuilder->SetLastChild(); } + aBudget.step(kStep); } + + if (!mCurrNode->IsDone()) { + return; + } + if (mGraph.mRootCount > 0) { mBuilder->SetLastChild(); } @@ -2763,7 +2772,7 @@ nsCycleCollector::Collect(ccType aCCType, break; case GraphBuildingPhase: PrintPhase("MarkRoots"); - MarkRoots(); + MarkRoots(aBudget); break; case ScanAndCollectWhitePhase: // We do ScanRoots and CollectWhite in a single slice to ensure