Bug 1453028 - Add new zeal modes to test the different parts of incremental sweeping r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 17 Apr 2018 08:44:56 +0200
changeset 467606 c0f28a370935a094926f22d3d49ac68ee2d87256
parent 467605 de5cfd97ac491f80740ccd4822d5bf5119573e46
child 467607 25682f0fb6488aded7f3aec579b48297ccba7395
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [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 - Add new zeal modes to test the different parts of incremental sweeping r=sfink
js/src/gc/GC.cpp
js/src/gc/GCEnum.h
js/src/gc/GCRuntime.h
js/src/jit-test/tests/gc/incremental-state.js
js/src/jsapi-tests/testGCFinalizeCallback.cpp
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -1034,25 +1034,40 @@ const char* gc::ZealModeHelpText =
     "    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";
+    "    18: (CheckGrayMarking) Check gray marking invariants after every GC\n"
+    "    19: (YieldBeforeSweepingCaches) Incremental GC in two slices that yields\n"
+    "        before sweeping weak caches\n"
+    "    20: (YieldBeforeSweepingTypes) Incremental GC in two slices that yields\n"
+    "        before sweeping type information\n"
+    "    21: (YieldBeforeSweepingObjects) Incremental GC in two slices that yields\n"
+    "        before sweeping foreground finalized objects\n"
+    "    22: (YieldBeforeSweepingNonObjects) Incremental GC in two slices that yields\n"
+    "        before sweeping non-object GC things\n"
+    "    23: (YieldBeforeSweepingShapeTrees) Incremental GC in two slices that yields\n"
+    "        before sweeping shape trees\n";
 
 // The set of zeal modes that control incremental slices. These modes are
 // mutually exclusive.
 static const mozilla::EnumSet<ZealMode> IncrementalSliceZealModes = {
     ZealMode::YieldBeforeMarking,
     ZealMode::YieldBeforeSweeping,
     ZealMode::IncrementalMultipleSlices,
-    ZealMode::YieldBeforeSweepingAtoms
+    ZealMode::YieldBeforeSweepingAtoms,
+    ZealMode::YieldBeforeSweepingCaches,
+    ZealMode::YieldBeforeSweepingTypes,
+    ZealMode::YieldBeforeSweepingObjects,
+    ZealMode::YieldBeforeSweepingNonObjects,
+    ZealMode::YieldBeforeSweepingShapeTrees
 };
 
 void
 GCRuntime::setZeal(uint8_t zeal, uint32_t frequency)
 {
     MOZ_ASSERT(zeal <= unsigned(ZealMode::Limit));
 
     if (verifyPreData)
@@ -4986,22 +5001,20 @@ 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 YieldBeforeSweepingAtoms zeal mode.
-    if (isIncremental && reason == JS::gcreason::DEBUG_GC &&
-        hasZealMode(ZealMode::YieldBeforeSweepingAtoms))
-    {
+    // Use one component for two-slice zeal modes.
+    MOZ_ASSERT_IF(useZeal, isIncremental);
+    if (useZeal && hasIncrementalTwoSliceZealMode())
         finder.useOneComponent();
-    }
 #endif
 
     for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
         MOZ_ASSERT(zone->isGCMarking());
         finder.addNode(zone);
     }
     sweepGroups = finder.getResultsList();
     currentSweepGroup = sweepGroups;
@@ -6528,25 +6541,30 @@ GCRuntime::initSweepActions()
             Sequence(
                 Call(&GCRuntime::endMarkingSweepGroup),
                 Call(&GCRuntime::beginSweepingSweepGroup),
 #ifdef JS_GC_ZEAL
                 Call(&GCRuntime::maybeYieldForSweepingZeal),
 #endif
                 MaybeYield(ZealMode::YieldBeforeSweepingAtoms,
                            Call(&GCRuntime::sweepAtomsTable)),
-                Call(&GCRuntime::sweepWeakCaches),
+                MaybeYield(ZealMode::YieldBeforeSweepingCaches,
+                           Call(&GCRuntime::sweepWeakCaches)),
                 ForEachZoneInSweepGroup(rt,
                     Sequence(
-                        Call(&GCRuntime::sweepTypeInformation),
-                        ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
-                                         Call(&GCRuntime::finalizeAllocKind)),
-                        ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
-                                         Call(&GCRuntime::finalizeAllocKind)),
-                        Call(&GCRuntime::sweepShapeTree),
+                        MaybeYield(ZealMode::YieldBeforeSweepingTypes,
+                                   Call(&GCRuntime::sweepTypeInformation)),
+                        MaybeYield(ZealMode::YieldBeforeSweepingObjects,
+                                   ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
+                                                    Call(&GCRuntime::finalizeAllocKind))),
+                        MaybeYield(ZealMode::YieldBeforeSweepingNonObjects,
+                                   ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
+                                                    Call(&GCRuntime::finalizeAllocKind))),
+                        MaybeYield(ZealMode::YieldBeforeSweepingShapeTrees,
+                                   Call(&GCRuntime::sweepShapeTree)),
                         Call(&GCRuntime::releaseSweptEmptyArenas))),
                 Call(&GCRuntime::endSweepingSweepGroup)));
 
     return sweepActions != nullptr;
 }
 
 IncrementalProgress
 GCRuntime::performSweepActions(SliceBudget& budget)
--- a/js/src/gc/GCEnum.h
+++ b/js/src/gc/GCEnum.h
@@ -52,32 +52,37 @@ enum class State {
     D(CompartmentRevived) \
     D(GrayRootBufferingFailed)
 enum class AbortReason {
 #define MAKE_REASON(name) name,
     GC_ABORT_REASONS(MAKE_REASON)
 #undef MAKE_REASON
 };
 
-#define JS_FOR_EACH_ZEAL_MODE(D)       \
-    D(RootsChange, 1)                  \
-    D(Alloc, 2)                        \
-    D(VerifierPre, 4)                  \
-    D(GenerationalGC, 7)               \
-    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(YieldBeforeSweepingAtoms, 17)    \
-    D(CheckGrayMarking, 18)
+#define JS_FOR_EACH_ZEAL_MODE(D)         \
+    D(RootsChange, 1)                    \
+    D(Alloc, 2)                          \
+    D(VerifierPre, 4)                    \
+    D(GenerationalGC, 7)                 \
+    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(YieldBeforeSweepingAtoms, 17)      \
+    D(CheckGrayMarking, 18)              \
+    D(YieldBeforeSweepingCaches, 19)     \
+    D(YieldBeforeSweepingTypes, 20)      \
+    D(YieldBeforeSweepingObjects, 21)    \
+    D(YieldBeforeSweepingNonObjects, 22) \
+    D(YieldBeforeSweepingShapeTrees, 23)
 
 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
@@ -1023,34 +1023,37 @@ GCRuntime::upcomingZealousGC() {
     return nextScheduled == 1;
 }
 
 inline bool
 GCRuntime::needZealousGC() {
     if (nextScheduled > 0 && --nextScheduled == 0) {
         if (hasZealMode(ZealMode::Alloc) ||
             hasZealMode(ZealMode::GenerationalGC) ||
-            hasZealMode(ZealMode::YieldBeforeMarking) ||
-            hasZealMode(ZealMode::YieldBeforeSweeping) ||
             hasZealMode(ZealMode::IncrementalMultipleSlices) ||
             hasZealMode(ZealMode::Compact) ||
-            hasZealMode(ZealMode::YieldBeforeSweepingAtoms))
+            hasIncrementalTwoSliceZealMode())
         {
             nextScheduled = zealFrequency;
         }
         return true;
     }
     return false;
 }
 
 inline bool
 GCRuntime::hasIncrementalTwoSliceZealMode() {
     return hasZealMode(ZealMode::YieldBeforeMarking) ||
            hasZealMode(ZealMode::YieldBeforeSweeping) ||
-           hasZealMode(ZealMode::YieldBeforeSweepingAtoms);
+           hasZealMode(ZealMode::YieldBeforeSweepingAtoms) ||
+           hasZealMode(ZealMode::YieldBeforeSweepingCaches) ||
+           hasZealMode(ZealMode::YieldBeforeSweepingTypes) ||
+           hasZealMode(ZealMode::YieldBeforeSweepingObjects) ||
+           hasZealMode(ZealMode::YieldBeforeSweepingNonObjects) ||
+           hasZealMode(ZealMode::YieldBeforeSweepingShapeTrees);
 }
 
 #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; }
--- a/js/src/jit-test/tests/gc/incremental-state.js
+++ b/js/src/jit-test/tests/gc/incremental-state.js
@@ -51,16 +51,28 @@ assertEq(gcstate(), "NotActive");
 gczeal(10, 0);
 gcslice(1000000);
 assertEq(gcstate(), "Sweep");
 gcslice(1000000);
 while (gcstate() == "Finalize") { gcslice(1); }
 while (gcstate() == "Decommit") { gcslice(1); }
 assertEq(gcstate(), "NotActive");
 
-// Zeal mode 17: Incremental GC in two slices:
-//   1) mark everything and start sweeping
-//   2) finish sweeping
-gczeal(17, 0);
-gcslice(1);
-assertEq(gcstate(), "Sweep");
-gcslice(1);
-assertEq(gcstate(), "NotActive");
+// Two-slice zeal modes that yield once during sweeping.
+for (let mode of [ 17, 19 ]) {
+    print(mode);
+    gczeal(mode, 0);
+    gcslice(1);
+    assertEq(gcstate(), "Sweep");
+    gcslice(1);
+    assertEq(gcstate(), "NotActive");
+}
+
+// Two-slice zeal modes that yield per-zone during sweeping.
+const sweepingZealModes = [ 20, 21, 22, 23 ];
+for (let mode of sweepingZealModes) {
+    print(mode);
+    gczeal(mode, 0);
+    gcslice(1);
+    while (gcstate() === "Sweep")
+        gcslice(1);
+    assertEq(gcstate(), "NotActive");
+}
--- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp
+++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
@@ -106,17 +106,17 @@ BEGIN_TEST(testGCFinalizeCallback)
     CHECK(cx->runtime()->gc.isFullGc());
 
     JS::RootedObject global4(cx, createTestGlobal());
     budget = js::SliceBudget(js::WorkBudget(1));
     cx->runtime()->gc.debugGCSlice(budget);
     while (cx->runtime()->gc.isIncrementalGCInProgress())
         cx->runtime()->gc.debugGCSlice(budget);
     CHECK(!cx->runtime()->gc.isIncrementalGCInProgress());
-    CHECK(checkMultipleGroups());
+    CHECK(checkSingleGroup());
     CHECK(checkFinalizeStatus());
 
     JS_SetGCZeal(cx, 0, 0);
 
 #endif
 
     /*
      * Make some use of the globals here to ensure the compiler doesn't optimize