Bug 1399160 - Make CCGraphBuilder::BuildGraph to check the budget more often, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 12 Sep 2017 18:59:57 +0300
changeset 663358 644d9742cf75fecc073c6f13553c7806cfe48ffb
parent 663357 294b732822db474cbce1624a517282956e174669
child 663359 c439271f94d7a8cb1e314f2134d97150b5d0dac6
push id79424
push userbmo:tchiovoloni@mozilla.com
push dateTue, 12 Sep 2017 23:17:54 +0000
reviewersmccr8
bugs1399160
milestone57.0a1
Bug 1399160 - Make CCGraphBuilder::BuildGraph to check the budget more often, r=mccr8
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -2095,16 +2095,17 @@ private:
   EdgePool::Builder mEdgeBuilder;
   MOZ_INIT_OUTSIDE_CTOR PtrInfo* mCurrPi;
   nsCycleCollectionParticipant* mJSParticipant;
   nsCycleCollectionParticipant* mJSZoneParticipant;
   nsCString mNextEdgeName;
   RefPtr<nsCycleCollectorLogger> mLogger;
   bool mMergeZones;
   nsAutoPtr<NodePool::Enumerator> mCurrNode;
+  uint32_t mNoteChildCount;
 
 public:
   CCGraphBuilder(CCGraph& aGraph,
                  CycleCollectorResults& aResults,
                  CycleCollectedJSRuntime* aCCRuntime,
                  nsCycleCollectorLogger* aLogger,
                  bool aMergeZones);
   virtual ~CCGraphBuilder();
@@ -2208,16 +2209,17 @@ CCGraphBuilder::CCGraphBuilder(CCGraph& 
   : mGraph(aGraph)
   , mResults(aResults)
   , mNodeBuilder(aGraph.mNodes)
   , mEdgeBuilder(aGraph.mEdges)
   , mJSParticipant(nullptr)
   , mJSZoneParticipant(nullptr)
   , mLogger(aLogger)
   , mMergeZones(aMergeZones)
+  , mNoteChildCount(0)
 {
   if (aCCRuntime) {
     mJSParticipant = aCCRuntime->GCThingParticipant();
     mJSZoneParticipant = aCCRuntime->ZoneParticipant();
   }
 
   if (mLogger) {
     mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO;
@@ -2285,22 +2287,24 @@ CCGraphBuilder::DoneAddingRoots()
   mGraph.mRootCount = mGraph.MapCount();
 
   mCurrNode = new NodePool::Enumerator(mGraph.mNodes);
 }
 
 MOZ_NEVER_INLINE bool
 CCGraphBuilder::BuildGraph(SliceBudget& aBudget)
 {
-  const intptr_t kNumNodesBetweenTimeChecks = 500;
+  const intptr_t kNumNodesBetweenTimeChecks = 1000;
   const intptr_t kStep = SliceBudget::CounterReset / kNumNodesBetweenTimeChecks;
 
   MOZ_ASSERT(mCurrNode);
 
   while (!aBudget.isOverBudget() && !mCurrNode->IsDone()) {
+    mNoteChildCount = 0;
+
     PtrInfo* pi = mCurrNode->GetNext();
     if (!pi) {
       MOZ_CRASH();
     }
 
     mCurrPi = pi;
 
     // We need to call SetFirstChild() even on deleted nodes, to set their
@@ -2311,17 +2315,17 @@ CCGraphBuilder::BuildGraph(SliceBudget& 
       nsresult rv = pi->mParticipant->TraverseNativeAndJS(pi->mPointer, *this);
       MOZ_RELEASE_ASSERT(!NS_FAILED(rv), "Cycle collector Traverse method failed");
     }
 
     if (mCurrNode->AtBlockEnd()) {
       SetLastChild();
     }
 
-    aBudget.step(kStep);
+    aBudget.step(kStep * (mNoteChildCount + 1));
   }
 
   if (!mCurrNode->IsDone()) {
     return false;
   }
 
   if (mGraph.mRootCount > 0) {
     SetLastChild();
@@ -2402,16 +2406,18 @@ CCGraphBuilder::NoteXPCOMChild(nsISuppor
   if (WantDebugInfo()) {
     edgeName.Assign(mNextEdgeName);
     mNextEdgeName.Truncate();
   }
   if (!aChild || !(aChild = CanonicalizeXPCOMParticipant(aChild))) {
     return;
   }
 
+  ++mNoteChildCount;
+
   nsXPCOMCycleCollectionParticipant* cp;
   ToParticipant(aChild, &cp);
   if (cp && (!cp->CanSkipThis(aChild) || WantAllTraces())) {
     NoteChild(aChild, cp, edgeName);
   }
 }
 
 NS_IMETHODIMP_(void)
@@ -2422,29 +2428,33 @@ CCGraphBuilder::NoteNativeChild(void* aC
   if (WantDebugInfo()) {
     edgeName.Assign(mNextEdgeName);
     mNextEdgeName.Truncate();
   }
   if (!aChild) {
     return;
   }
 
+  ++mNoteChildCount;
+
   MOZ_ASSERT(aParticipant, "Need a nsCycleCollectionParticipant!");
   if (!aParticipant->CanSkipThis(aChild) || WantAllTraces()) {
     NoteChild(aChild, aParticipant, edgeName);
   }
 }
 
 NS_IMETHODIMP_(void)
 CCGraphBuilder::NoteJSChild(const JS::GCCellPtr& aChild)
 {
   if (!aChild) {
     return;
   }
 
+  ++mNoteChildCount;
+
   nsCString edgeName;
   if (MOZ_UNLIKELY(WantDebugInfo())) {
     edgeName.Assign(mNextEdgeName);
     mNextEdgeName.Truncate();
   }
 
   if (GCThingIsGrayCCThing(aChild) || MOZ_UNLIKELY(WantAllTraces())) {
     if (JS::Zone* zone = MergeZone(aChild)) {