Bug 935721, part 2 - Allocate GCGraphBuilder on the heap. r=smaug
authorAndrew McCreight <continuation@gmail.com>
Wed, 20 Nov 2013 14:35:15 -0800
changeset 156635 5ceef597d36b5737e8e61741ac0d1f8db92258f5
parent 156634 067924b4619249494ae181e15e029e0687752868
child 156636 50329b4cf0bea45ec718b4de4d2bed210b6afd3c
push id36488
push useramccreight@mozilla.com
push dateWed, 20 Nov 2013 22:36:15 +0000
treeherdermozilla-inbound@e597cdb674ea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs935721
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 935721, part 2 - Allocate GCGraphBuilder on the heap. r=smaug With ICC, the graph builder must persist across invocations of the CC, so store it on the heap.
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -910,16 +910,17 @@ class nsCycleCollector
     // mScanInProgress should be false when we're collecting white objects.
     bool mScanInProgress;
     nsCycleCollectorResults *mResults;
     TimeStamp mCollectionStart;
 
     CycleCollectedJSRuntime *mJSRuntime;
 
     GCGraph mGraph;
+    nsAutoPtr<GCGraphBuilder> mBuilder;
     nsCOMPtr<nsICycleCollectorListener> mListener;
 
     nsIThread* mThread;
 
     nsCycleCollectorParams mParams;
 
     nsTArray<PtrInfo*> *mWhiteNodes;
     uint32_t mWhiteNodeCount;
@@ -982,17 +983,17 @@ private:
     void ShutdownCollect();
 
     void PrepareForCollection(nsCycleCollectorResults *aResults,
                               nsTArray<PtrInfo*> *aWhiteNodes);
     void FixGrayBits(bool aForceGC);
     bool ShouldMergeZones(ccType aCCType);
 
     void BeginCollection(ccType aCCType, nsICycleCollectorListener *aManualListener);
-    void MarkRoots(GCGraphBuilder &aBuilder);
+    void MarkRoots();
     void ScanRoots();
     void ScanWeakMaps();
 
     // returns whether anything was collected
     bool CollectWhite();
 
     void CleanupAfterCollection();
 };
@@ -1581,17 +1582,17 @@ private:
     bool mRanOutOfMemory;
 
 public:
     GCGraphBuilder(nsCycleCollector *aCollector,
                    GCGraph &aGraph,
                    CycleCollectedJSRuntime *aJSRuntime,
                    nsICycleCollectorListener *aListener,
                    bool aMergeZones);
-    ~GCGraphBuilder();
+    virtual ~GCGraphBuilder();
 
     bool WantAllTraces() const
     {
         return nsCycleCollectionNoteRootCallback::WantAllTraces();
     }
 
     uint32_t Count() const { return mPtrToNodeMap.entryCount; }
 
@@ -2142,38 +2143,40 @@ nsCycleCollector::ForgetSkippable(bool a
         mJSRuntime->PrepareForForgetSkippable();
     }
     MOZ_ASSERT(!mScanInProgress, "Don't forget skippable or free snow-white while scan is in progress.");
     mPurpleBuf.RemoveSkippable(this, aRemoveChildlessNodes,
                                aAsyncSnowWhiteFreeing, mForgetSkippableCB);
 }
 
 MOZ_NEVER_INLINE void
-nsCycleCollector::MarkRoots(GCGraphBuilder &aBuilder)
+nsCycleCollector::MarkRoots()
 {
-    mGraph.mRootCount = aBuilder.Count();
+    mGraph.mRootCount = mBuilder->Count();
 
     // read the PtrInfo out of the graph that we are building
     NodePool::Enumerator queue(mGraph.mNodes);
     while (!queue.IsDone()) {
         PtrInfo *pi = queue.GetNext();
         CC_AbortIfNull(pi);
-        aBuilder.Traverse(pi);
+        mBuilder->Traverse(pi);
         if (queue.AtBlockEnd()) {
-            aBuilder.SetLastChild();
+            mBuilder->SetLastChild();
         }
     }
     if (mGraph.mRootCount > 0) {
-        aBuilder.SetLastChild();
+        mBuilder->SetLastChild();
     }
 
-    if (aBuilder.RanOutOfMemory()) {
+    if (mBuilder->RanOutOfMemory()) {
         MOZ_ASSERT(false, "Ran out of memory while building cycle collector graph");
         CC_TELEMETRY(_OOM, true);
     }
+
+    mBuilder = nullptr;
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // Bacon & Rajan's |ScanRoots| routine.
 ////////////////////////////////////////////////////////////////////////
 
 
@@ -2788,29 +2791,30 @@ nsCycleCollector::BeginCollection(ccType
     }
 
     // Set up the data structures for building the graph.
     bool mergeZones = ShouldMergeZones(aCCType);
     if (mResults) {
         mResults->mMergedZones = mergeZones;
     }
 
-    GCGraphBuilder builder(this, mGraph, mJSRuntime, mListener, mergeZones);
+    MOZ_ASSERT(!mBuilder, "Forgot to clear mBuilder");
+    mBuilder = new GCGraphBuilder(this, mGraph, mJSRuntime, mListener, mergeZones);
 
     if (mJSRuntime) {
-        mJSRuntime->BeginCycleCollection(builder);
+        mJSRuntime->BeginCycleCollection(*mBuilder);
         timeLog.Checkpoint("mJSRuntime->BeginCycleCollection()");
     }
 
     mScanInProgress = true;
-    mPurpleBuf.SelectPointers(builder);
+    mPurpleBuf.SelectPointers(*mBuilder);
     timeLog.Checkpoint("SelectPointers()");
 
     // The main Bacon & Rajan collection algorithm.
-    MarkRoots(builder);
+    MarkRoots();
     timeLog.Checkpoint("MarkRoots()");
 
     ScanRoots();
     timeLog.Checkpoint("ScanRoots()");
 
     mScanInProgress = false;
 }