Bug 1453028 - Rename GC zeal modes that run in two slices and refactor r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 17 Apr 2018 08:44:56 +0200
changeset 414071 12337456bdd9cefdc8663d0c1fc1c1040247c616
parent 414070 0f26c7b0aa7d9a4ef77bb4819e53c46d663e88b8
child 414072 de5cfd97ac491f80740ccd4822d5bf5119573e46
push id33858
push userncsoregi@mozilla.com
push dateTue, 17 Apr 2018 21:55:44 +0000
treeherdermozilla-central@d6eb5597d744 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1453028
milestone61.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 1453028 - Rename GC zeal modes that run in two slices and refactor r=sfink
js/src/gc/GC.cpp
js/src/gc/GCEnum.h
js/src/gc/GCRuntime.h
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -1015,40 +1015,44 @@ GCRuntime::getZealBits(uint32_t* zealBit
 }
 
 const char* gc::ZealModeHelpText =
     "  Specifies how zealous the garbage collector should be. Some of these modes can\n"
     "  be set simultaneously, by passing multiple level options, e.g. \"2;4\" will activate\n"
     "  both modes 2 and 4. Modes can be specified by name or number.\n"
     "  \n"
     "  Values:\n"
-    "    0: (None) Normal amount of collection (resets all modes)\n"
-    "    1: (RootsChange) Collect when roots are added or removed\n"
-    "    2: (Alloc) Collect when every N allocations (default: 100)\n"
-    "    4: (VerifierPre) Verify pre write barriers between instructions\n"
-    "    7: (GenerationalGC) Collect the nursery every N nursery allocations\n"
-    "    8: (IncrementalRootsThenFinish) Incremental GC in two slices: 1) mark roots 2) finish collection\n"
-    "    9: (IncrementalMarkAllThenFinish) Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
-    "   10: (IncrementalMultipleSlices) Incremental GC in multiple slices\n"
-    "   11: (IncrementalMarkingValidator) Verify incremental marking\n"
-    "   12: (ElementsBarrier) Always use the individual element post-write barrier, regardless of elements size\n"
-    "   13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n"
-    "   14: (Compact) Perform a shrinking collection every N allocations\n"
-    "   15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n"
-    "   16: (CheckNursery) Check nursery integrity on minor GC\n"
-    "   17: (IncrementalSweepThenFinish) Incremental GC in two slices: 1) start sweeping 2) finish collection\n"
-    "   18: (CheckGrayMarking) Check gray marking invariants after every GC\n";
+    "    0:  (None) Normal amount of collection (resets all modes)\n"
+    "    1:  (RootsChange) Collect when roots are added or removed\n"
+    "    2:  (Alloc) Collect when every N allocations (default: 100)\n"
+    "    4:  (VerifierPre) Verify pre write barriers between instructions\n"
+    "    7:  (GenerationalGC) Collect the nursery every N nursery allocations\n"
+    "    8:  (YieldBeforeMarking) Incremental GC in two slices that yields between\n"
+    "        the root marking and marking phases\n"
+    "    9:  (YieldBeforeSweeping) Incremental GC in two slices that yields between\n"
+    "        the marking and sweeping phases\n"
+    "    10: (IncrementalMultipleSlices) Incremental GC in many slices\n"
+    "    11: (IncrementalMarkingValidator) Verify incremental marking\n"
+    "    12: (ElementsBarrier) Use the individual element post-write barrier\n"
+    "        regardless of elements size\n"
+    "    13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n"
+    "    14: (Compact) Perform a shrinking collection every N allocations\n"
+    "    15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n"
+    "    16: (CheckNursery) Check nursery integrity on minor GC\n"
+    "    17: (YieldBeforeSweepingAtoms) Incremental GC in two slices that yields\n"
+    "        before sweeping the atoms table\n"
+    "    18: (CheckGrayMarking) Check gray marking invariants after every GC\n";
 
 // The set of zeal modes that control incremental slices. These modes are
 // mutually exclusive.
 static const mozilla::EnumSet<ZealMode> IncrementalSliceZealModes = {
-    ZealMode::IncrementalRootsThenFinish,
-    ZealMode::IncrementalMarkAllThenFinish,
+    ZealMode::YieldBeforeMarking,
+    ZealMode::YieldBeforeSweeping,
     ZealMode::IncrementalMultipleSlices,
-    ZealMode::IncrementalSweepThenFinish
+    ZealMode::YieldBeforeSweepingAtoms
 };
 
 void
 GCRuntime::setZeal(uint8_t zeal, uint32_t frequency)
 {
     MOZ_ASSERT(zeal <= unsigned(ZealMode::Limit));
 
     if (verifyPreData)
@@ -4982,19 +4986,19 @@ GCRuntime::groupZonesForSweeping(JS::gcr
 
     JSContext* cx = rt->mainContextFromOwnThread();
     Zone* maybeAtomsZone = atomsZone->wasGCStarted() ? atomsZone.ref() : nullptr;
     ZoneComponentFinder finder(cx->nativeStackLimit[JS::StackForSystemCode], maybeAtomsZone);
     if (!isIncremental || !findInterZoneEdges())
         finder.useOneComponent();
 
 #ifdef JS_GC_ZEAL
-    // Use one component for IncrementalSweepThenFinish zeal mode.
+    // Use one component for YieldBeforeSweepingAtoms zeal mode.
     if (isIncremental && reason == JS::gcreason::DEBUG_GC &&
-        hasZealMode(ZealMode::IncrementalSweepThenFinish))
+        hasZealMode(ZealMode::YieldBeforeSweepingAtoms))
     {
         finder.useOneComponent();
     }
 #endif
 
     for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
         MOZ_ASSERT(zone->isGCMarking());
         finder.addNode(zone);
@@ -5736,17 +5740,17 @@ GCRuntime::maybeYieldForSweepingZeal(Fre
 {
     /*
      * Check whether we need to yield for GC zeal. We always yield when running
      * in incremental multi-slice zeal mode so RunDebugGC can reset the slice
      * budget.
      */
     if (isIncremental && useZeal && initialState != State::Sweep &&
         (hasZealMode(ZealMode::IncrementalMultipleSlices) ||
-         hasZealMode(ZealMode::IncrementalSweepThenFinish)))
+         hasZealMode(ZealMode::YieldBeforeSweepingAtoms)))
     {
         return NotFinished;
     }
 
     return Finished;
 }
 #endif
 
@@ -6982,20 +6986,17 @@ GCRuntime::incrementalCollectSlice(Slice
 #endif
 
     MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental);
     if (isIncrementalGCInProgress() && budget.isUnlimited())
         changeToNonIncrementalGC();
 
     isIncremental = !budget.isUnlimited();
 
-    if (useZeal && (hasZealMode(ZealMode::IncrementalRootsThenFinish) ||
-                    hasZealMode(ZealMode::IncrementalMarkAllThenFinish) ||
-                    hasZealMode(ZealMode::IncrementalSweepThenFinish)))
-    {
+    if (useZeal && hasIncrementalTwoSliceZealMode()) {
         /*
          * Yields between slices occurs at predetermined points in these modes;
          * the budget is not used.
          */
         budget.makeUnlimited();
     }
 
     switch (incrementalState) {
@@ -7016,17 +7017,17 @@ GCRuntime::incrementalCollectSlice(Slice
             return;
         }
 
         if (!destroyingRuntime)
             pushZealSelectedObjects();
 
         incrementalState = State::Mark;
 
-        if (isIncremental && useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))
+        if (isIncremental && useZeal && hasZealMode(ZealMode::YieldBeforeMarking))
             break;
 
         MOZ_FALLTHROUGH;
 
       case State::Mark:
         AutoGCRooter::traceAllWrappers(rt->mainContextFromOwnThread(), &marker);
 
         /* If we needed delayed marking for gray roots, then collect until done. */
@@ -7042,26 +7043,26 @@ GCRuntime::incrementalCollectSlice(Slice
         MOZ_ASSERT(marker.isDrained());
 
         /*
          * In incremental GCs where we have already performed more than once
          * slice we yield after marking with the aim of starting the sweep in
          * the next slice, since the first slice of sweeping can be expensive.
          *
          * This is modified by the various zeal modes.  We don't yield in
-         * IncrementalRootsThenFinish mode and we always yield in
-         * IncrementalMarkAllThenFinish mode.
+         * YieldBeforeMarking mode and we always yield in YieldBeforeSweeping
+         * mode.
          *
          * We will need to mark anything new on the stack when we resume, so
          * we stay in Mark state.
          */
         if (!lastMarkSlice && isIncremental &&
             ((initialState == State::Mark &&
-              !(useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))) ||
-             (useZeal && hasZealMode(ZealMode::IncrementalMarkAllThenFinish))))
+              !(useZeal && hasZealMode(ZealMode::YieldBeforeMarking))) ||
+             (useZeal && hasZealMode(ZealMode::YieldBeforeSweeping))))
         {
             lastMarkSlice = true;
             break;
         }
 
         incrementalState = State::Sweep;
 
         beginSweepPhase(reason, session);
@@ -8062,53 +8063,47 @@ GCRuntime::runDebugGC()
         return;
 
     if (hasZealMode(ZealMode::GenerationalGC))
         return minorGC(JS::gcreason::DEBUG_GC);
 
     PrepareForDebugGC(rt);
 
     auto budget = SliceBudget::unlimited();
-    if (hasZealMode(ZealMode::IncrementalRootsThenFinish) ||
-        hasZealMode(ZealMode::IncrementalMarkAllThenFinish) ||
-        hasZealMode(ZealMode::IncrementalMultipleSlices) ||
-        hasZealMode(ZealMode::IncrementalSweepThenFinish))
-    {
+    if (hasZealMode(ZealMode::IncrementalMultipleSlices)) {
+        /*
+         * Start with a small slice limit and double it every slice. This
+         * ensure that we get multiple slices, and collection runs to
+         * completion.
+         */
+        if (!isIncrementalGCInProgress())
+            incrementalLimit = zealFrequency / 2;
+        else
+            incrementalLimit *= 2;
+        budget = SliceBudget(WorkBudget(incrementalLimit));
+
         js::gc::State initialState = incrementalState;
-        if (hasZealMode(ZealMode::IncrementalMultipleSlices)) {
-            /*
-             * Start with a small slice limit and double it every slice. This
-             * ensure that we get multiple slices, and collection runs to
-             * completion.
-             */
-            if (!isIncrementalGCInProgress())
-                incrementalLimit = zealFrequency / 2;
-            else
-                incrementalLimit *= 2;
-            budget = SliceBudget(WorkBudget(incrementalLimit));
-        } else {
-            // This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
-            budget = SliceBudget(WorkBudget(1));
-        }
-
         if (!isIncrementalGCInProgress())
             invocationKind = GC_SHRINK;
         collect(false, budget, JS::gcreason::DEBUG_GC);
 
-        /*
-         * For multi-slice zeal, reset the slice size when we get to the sweep
-         * or compact phases.
-         */
-        if (hasZealMode(ZealMode::IncrementalMultipleSlices)) {
-            if ((initialState == State::Mark && incrementalState == State::Sweep) ||
-                (initialState == State::Sweep && incrementalState == State::Compact))
-            {
-                incrementalLimit = zealFrequency / 2;
-            }
+        /* Reset the slice size when we get to the sweep or compact phases. */
+        if ((initialState == State::Mark && incrementalState == State::Sweep) ||
+            (initialState == State::Sweep && incrementalState == State::Compact))
+        {
+            incrementalLimit = zealFrequency / 2;
         }
+    } else if (hasIncrementalTwoSliceZealMode()) {
+        // These modes trigger incremental GC that happens in two slices and the
+        // supplied budget is ignored by incrementalCollectSlice.
+        budget = SliceBudget(WorkBudget(1));
+
+        if (!isIncrementalGCInProgress())
+            invocationKind = GC_NORMAL;
+        collect(false, budget, JS::gcreason::DEBUG_GC);
     } else if (hasZealMode(ZealMode::Compact)) {
         gc(GC_SHRINK, JS::gcreason::DEBUG_GC);
     } else {
         gc(GC_NORMAL, JS::gcreason::DEBUG_GC);
     }
 
 #endif
 }
--- a/js/src/gc/GCEnum.h
+++ b/js/src/gc/GCEnum.h
@@ -57,26 +57,26 @@ enum class AbortReason {
 #undef MAKE_REASON
 };
 
 #define JS_FOR_EACH_ZEAL_MODE(D)       \
     D(RootsChange, 1)                  \
     D(Alloc, 2)                        \
     D(VerifierPre, 4)                  \
     D(GenerationalGC, 7)               \
-    D(IncrementalRootsThenFinish, 8)   \
-    D(IncrementalMarkAllThenFinish, 9) \
+    D(YieldBeforeMarking, 8)           \
+    D(YieldBeforeSweeping, 9)          \
     D(IncrementalMultipleSlices, 10)   \
     D(IncrementalMarkingValidator, 11) \
     D(ElementsBarrier, 12)             \
     D(CheckHashTablesOnMinorGC, 13)    \
     D(Compact, 14)                     \
     D(CheckHeapAfterGC, 15)            \
     D(CheckNursery, 16)                \
-    D(IncrementalSweepThenFinish, 17)  \
+    D(YieldBeforeSweepingAtoms, 17)    \
     D(CheckGrayMarking, 18)
 
 enum class ZealMode {
 #define ZEAL_MODE(name, value) name = value,
     JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
 #undef ZEAL_MODE
     Count,
     Limit = Count - 1
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -225,16 +225,17 @@ class GCRuntime
     MOZ_MUST_USE bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
     void finishRoots();
     void finish();
 
     inline bool hasZealMode(ZealMode mode);
     inline void clearZealMode(ZealMode mode);
     inline bool upcomingZealousGC();
     inline bool needZealousGC();
+    inline bool hasIncrementalTwoSliceZealMode();
 
     MOZ_MUST_USE bool addRoot(Value* vp, const char* name);
     void removeRoot(Value* vp);
     void setMarkStackLimit(size_t limit, AutoLockGC& lock);
 
     MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock);
     void resetParameter(JSGCParamKey key, AutoLockGC& lock);
     uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock);
@@ -1021,31 +1022,40 @@ GCRuntime::upcomingZealousGC() {
     return nextScheduled == 1;
 }
 
 inline bool
 GCRuntime::needZealousGC() {
     if (nextScheduled > 0 && --nextScheduled == 0) {
         if (hasZealMode(ZealMode::Alloc) ||
             hasZealMode(ZealMode::GenerationalGC) ||
-            hasZealMode(ZealMode::IncrementalRootsThenFinish) ||
-            hasZealMode(ZealMode::IncrementalMarkAllThenFinish) ||
+            hasZealMode(ZealMode::YieldBeforeMarking) ||
+            hasZealMode(ZealMode::YieldBeforeSweeping) ||
             hasZealMode(ZealMode::IncrementalMultipleSlices) ||
             hasZealMode(ZealMode::Compact) ||
-            hasZealMode(ZealMode::IncrementalSweepThenFinish))
+            hasZealMode(ZealMode::YieldBeforeSweepingAtoms))
         {
             nextScheduled = zealFrequency;
         }
         return true;
     }
     return false;
 }
+
+inline bool
+GCRuntime::hasIncrementalTwoSliceZealMode() {
+    return hasZealMode(ZealMode::YieldBeforeMarking) ||
+           hasZealMode(ZealMode::YieldBeforeSweeping) ||
+           hasZealMode(ZealMode::YieldBeforeSweepingAtoms);
+}
+
 #else
 inline bool GCRuntime::hasZealMode(ZealMode mode) { return false; }
 inline void GCRuntime::clearZealMode(ZealMode mode) { }
 inline bool GCRuntime::upcomingZealousGC() { return false; }
 inline bool GCRuntime::needZealousGC() { return false; }
+inline bool GCRuntime::hasIncrementalTwoSliceZealMode() { return false; }
 #endif
 
 } /* namespace gc */
 } /* namespace js */
 
 #endif