Bug 935721, part 1 - Store the listener pointer on the nsCycleCollector data structure. r=smaug
authorAndrew McCreight <continuation@gmail.com>
Wed, 20 Nov 2013 14:35:15 -0800
changeset 156689 067924b4619249494ae181e15e029e0687752868
parent 156688 0a0081b34af7bb85fdb70501b0f00c66eb95a670
child 156690 5ceef597d36b5737e8e61741ac0d1f8db92258f5
push id25684
push usercbook@mozilla.com
push dateThu, 21 Nov 2013 13:21:05 +0000
treeherdermozilla-central@7427eede548f [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 1 - Store the listener pointer on the nsCycleCollector data structure. r=smaug With ICC, the listener must persist across invocations of the CC, so store it on the CC.
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;
+    nsCOMPtr<nsICycleCollectorListener> mListener;
 
     nsIThread* mThread;
 
     nsCycleCollectorParams mParams;
 
     nsTArray<PtrInfo*> *mWhiteNodes;
     uint32_t mWhiteNodeCount;
 
@@ -982,17 +983,17 @@ private:
 
     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 ScanRoots(nsICycleCollectorListener *aListener);
+    void ScanRoots();
     void ScanWeakMaps();
 
     // returns whether anything was collected
     bool CollectWhite();
 
     void CleanupAfterCollection();
 };
 
@@ -2283,58 +2284,59 @@ nsCycleCollector::ScanWeakMaps()
 
     if (failed) {
         MOZ_ASSERT(false, "Ran out of memory in ScanWeakMaps");
         CC_TELEMETRY(_OOM, true);
     }
 }
 
 void
-nsCycleCollector::ScanRoots(nsICycleCollectorListener *aListener)
+nsCycleCollector::ScanRoots()
 {
     mWhiteNodeCount = 0;
 
     // On the assumption that most nodes will be black, it's
     // probably faster to use a GraphWalker than a
     // NodePool::Enumerator.
     bool failed = false;
     GraphWalker<scanVisitor>(scanVisitor(mWhiteNodeCount, failed)).WalkFromRoots(mGraph);
 
     if (failed) {
         NS_ASSERTION(false, "Ran out of memory in ScanRoots");
         CC_TELEMETRY(_OOM, true);
     }
 
     ScanWeakMaps();
 
-    if (aListener) {
-        aListener->BeginResults();
+    if (mListener) {
+        mListener->BeginResults();
 
         NodePool::Enumerator etor(mGraph.mNodes);
         while (!etor.IsDone()) {
             PtrInfo *pi = etor.GetNext();
             switch (pi->mColor) {
             case black:
                 if (pi->mRefCount > 0 && pi->mRefCount < UINT32_MAX &&
                     pi->mInternalRefs != pi->mRefCount) {
-                    aListener->DescribeRoot((uint64_t)pi->mPointer,
+                    mListener->DescribeRoot((uint64_t)pi->mPointer,
                                             pi->mInternalRefs);
                 }
                 break;
             case white:
-                aListener->DescribeGarbage((uint64_t)pi->mPointer);
+                mListener->DescribeGarbage((uint64_t)pi->mPointer);
                 break;
             case grey:
                 // With incremental CC, we can end up with a grey object after
                 // scanning if it is only reachable from an object that gets freed.
                 break;
             }
         }
 
-        aListener->End();
+        mListener->End();
+        mListener = nullptr;
     }
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // Bacon & Rajan's |CollectWhite| routine, somewhat modified.
 ////////////////////////////////////////////////////////////////////////
 
@@ -2753,65 +2755,65 @@ void
 nsCycleCollector::BeginCollection(ccType aCCType,
                                   nsICycleCollectorListener *aManualListener)
 {
     TimeLog timeLog;
     bool isShutdown = (aCCType == ShutdownCC);
 
     // Set up the listener for this CC.
     MOZ_ASSERT_IF(isShutdown, !aManualListener);
-    nsCOMPtr<nsICycleCollectorListener> listener(aManualListener);
+    MOZ_ASSERT(!mListener, "Forgot to clear a previous listener?");
+    mListener = aManualListener;
     aManualListener = nullptr;
-    if (!listener) {
+    if (!mListener) {
         if (mParams.mLogAll || (isShutdown && mParams.mLogShutdown)) {
             nsRefPtr<nsCycleCollectorLogger> logger = new nsCycleCollectorLogger();
             if (isShutdown && mParams.mAllTracesAtShutdown) {
                 logger->SetAllTraces();
             }
-            listener = logger.forget();
+            mListener = logger.forget();
         }
     }
 
     bool forceGC = isShutdown;
-    if (!forceGC && listener) {
+    if (!forceGC && mListener) {
         // On a WantAllTraces CC, force a synchronous global GC to prevent
         // hijinks from ForgetSkippable and compartmental GCs.
-        listener->GetWantAllTraces(&forceGC);
+        mListener->GetWantAllTraces(&forceGC);
     }
     FixGrayBits(forceGC);
 
     FreeSnowWhite(true);
 
-    if (listener && NS_FAILED(listener->Begin())) {
-        listener = nullptr;
+    if (mListener && NS_FAILED(mListener->Begin())) {
+        mListener = nullptr;
     }
 
     // Set up the data structures for building the graph.
     bool mergeZones = ShouldMergeZones(aCCType);
     if (mResults) {
         mResults->mMergedZones = mergeZones;
     }
 
-    GCGraphBuilder builder(this, mGraph, mJSRuntime, listener,
-                           mergeZones);
+    GCGraphBuilder builder(this, mGraph, mJSRuntime, mListener, mergeZones);
 
     if (mJSRuntime) {
         mJSRuntime->BeginCycleCollection(builder);
         timeLog.Checkpoint("mJSRuntime->BeginCycleCollection()");
     }
 
     mScanInProgress = true;
     mPurpleBuf.SelectPointers(builder);
     timeLog.Checkpoint("SelectPointers()");
 
     // The main Bacon & Rajan collection algorithm.
     MarkRoots(builder);
     timeLog.Checkpoint("MarkRoots()");
 
-    ScanRoots(listener);
+    ScanRoots();
     timeLog.Checkpoint("ScanRoots()");
 
     mScanInProgress = false;
 }
 
 uint32_t
 nsCycleCollector::SuspectedCount()
 {