Bug 913080 - Make GCGraphBuilder's hash table initialization infallible. r=smaug
authorAndrew McCreight <continuation@gmail.com>
Fri, 06 Sep 2013 13:42:27 -0700
changeset 158932 f98b323128d97321cd1896a25aa5a12710c434fe
parent 158931 3705115c7dd9fe2b3fd739b10a9d89190549b504
child 158933 45c33630713688d19d83f52b600c3488b7123b9c
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs913080
milestone26.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 913080 - Make GCGraphBuilder's hash table initialization infallible. r=smaug
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -974,17 +974,17 @@ public:
     // Prepare for and cleanup after one or more collection(s).
     bool PrepareForCollection(nsCycleCollectorResults *aResults,
                               nsTArray<PtrInfo*> *aWhiteNodes);
     void FixGrayBits(bool aForceGC);
     bool ShouldMergeZones(ccType aCCType);
     void CleanupAfterCollection();
 
     // Start and finish an individual collection.
-    bool BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
+    void BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
     bool FinishCollection(nsICycleCollectorListener *aListener);
 
     bool FreeSnowWhite(bool aUntilNoSWInPurpleBuffer);
 
     uint32_t SuspectedCount();
     void Shutdown();
 
     void ClearGraph()
@@ -1559,17 +1559,16 @@ private:
 
 public:
     GCGraphBuilder(nsCycleCollector *aCollector,
                    GCGraph &aGraph,
                    CycleCollectedJSRuntime *aJSRuntime,
                    nsICycleCollectorListener *aListener,
                    bool aMergeZones);
     ~GCGraphBuilder();
-    bool Initialized();
 
     bool WantAllTraces() const
     {
         return nsCycleCollectionNoteRootCallback::WantAllTraces();
     }
 
     uint32_t Count() const { return mPtrToNodeMap.entryCount; }
 
@@ -1653,18 +1652,17 @@ GCGraphBuilder::GCGraphBuilder(nsCycleCo
       mJSParticipant(nullptr),
       mJSZoneParticipant(nullptr),
       mListener(aListener),
       mMergeZones(aMergeZones),
       mRanOutOfMemory(false)
 {
     if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nullptr,
                            sizeof(PtrToNodeEntry), 32768)) {
-        mPtrToNodeMap.ops = nullptr;
-        mRanOutOfMemory = true;
+        MOZ_CRASH();
     }
 
     if (aJSRuntime) {
         mJSParticipant = aJSRuntime->GCThingParticipant();
         mJSZoneParticipant = aJSRuntime->ZoneParticipant();
     }
 
     uint32_t flags = 0;
@@ -1687,22 +1685,16 @@ GCGraphBuilder::GCGraphBuilder(nsCycleCo
 }
 
 GCGraphBuilder::~GCGraphBuilder()
 {
     if (mPtrToNodeMap.ops)
         PL_DHashTableFinish(&mPtrToNodeMap);
 }
 
-bool
-GCGraphBuilder::Initialized()
-{
-    return !!mPtrToNodeMap.ops;
-}
-
 PtrInfo*
 GCGraphBuilder::AddNode(void *s, nsCycleCollectionParticipant *aParticipant)
 {
     PtrToNodeEntry *e = static_cast<PtrToNodeEntry*>(PL_DHashTableOperate(&mPtrToNodeMap, s, PL_DHASH_ADD));
     if (!e) {
         mRanOutOfMemory = true;
         return nullptr;
     }
@@ -2676,19 +2668,20 @@ nsCycleCollector::ShutdownCollect(nsICyc
     for (uint32_t i = 0; i < DEFAULT_SHUTDOWN_COLLECTIONS; ++i) {
         NS_ASSERTION(i < NORMAL_SHUTDOWN_COLLECTIONS, "Extra shutdown CC");
 
         // Synchronous cycle collection. Always force a JS GC beforehand.
         FixGrayBits(true);
         if (aListener && NS_FAILED(aListener->Begin()))
             aListener = nullptr;
         FreeSnowWhite(true);
-        if (!(BeginCollection(ShutdownCC, aListener) &&
-              FinishCollection(aListener)))
+        BeginCollection(ShutdownCC, aListener);
+        if (!FinishCollection(aListener)) {
             break;
+        }
     }
 
     CleanupAfterCollection();
 }
 
 void
 nsCycleCollector::Collect(ccType aCCType,
                           nsCycleCollectorResults *aResults,
@@ -2711,20 +2704,17 @@ nsCycleCollector::Collect(ccType aCCType
     }
 
     FreeSnowWhite(true);
 
     if (aListener && NS_FAILED(aListener->Begin())) {
         aListener = nullptr;
     }
 
-    if (!BeginCollection(aCCType, aListener)) {
-        return;
-    }
-
+    BeginCollection(aCCType, aListener);
     FinishCollection(aListener);
     CleanupAfterCollection();
 }
 
 // Don't merge too many times in a row, and do at least a minimum
 // number of unmerged CCs in a row.
 static const uint32_t kMinConsecutiveUnmerged = 3;
 static const uint32_t kMaxConsecutiveMerged = 3;
@@ -2754,35 +2744,30 @@ nsCycleCollector::ShouldMergeZones(ccTyp
         mMergedInARow++;
         return true;
     } else {
         mMergedInARow = 0;
         return false;
     }
 }
 
-bool
+void
 nsCycleCollector::BeginCollection(ccType aCCType,
                                   nsICycleCollectorListener *aListener)
 {
     // aListener should be Begin()'d before this
     TimeLog timeLog;
 
     bool mergeZones = ShouldMergeZones(aCCType);
     if (mResults) {
         mResults->mMergedZones = mergeZones;
     }
 
     GCGraphBuilder builder(this, mGraph, mJSRuntime, aListener,
                            mergeZones);
-    if (!builder.Initialized()) {
-        NS_ASSERTION(false, "Failed to initialize GCGraphBuilder, will probably leak.");
-        Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_OOM, true);
-        return false;
-    }
 
     if (mJSRuntime) {
         mJSRuntime->BeginCycleCollection(builder);
         timeLog.Checkpoint("mJSRuntime->BeginCycleCollection()");
     }
 
     mScanInProgress = true;
     mPurpleBuf.SelectPointers(builder);
@@ -2811,18 +2796,16 @@ nsCycleCollector::BeginCollection(ccType
                     aListener->DescribeRoot((uint64_t)pi->mPointer,
                                             pi->mInternalRefs);
                 }
             }
         }
     } else {
         mScanInProgress = false;
     }
-
-    return true;
 }
 
 bool
 nsCycleCollector::FinishCollection(nsICycleCollectorListener *aListener)
 {
     TimeLog timeLog;
     bool collected = CollectWhite(aListener);
     timeLog.Checkpoint("CollectWhite()");