Bug 1453028 - Add a new sweep action to yield in a specified zeal mode r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 17 Apr 2018 08:44:56 +0200
changeset 414072 de5cfd97ac491f80740ccd4822d5bf5119573e46
parent 414071 12337456bdd9cefdc8663d0c1fc1c1040247c616
child 414073 c0f28a370935a094926f22d3d49ac68ee2d87256
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 - Add a new sweep action to yield in a specified zeal mode r=sfink
js/src/gc/GC.cpp
js/src/gc/GCRuntime.h
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -5730,33 +5730,38 @@ GCRuntime::beginSweepingSweepGroup(FreeO
 
     sweepCache = nullptr;
     safeToYield = true;
 
     return Finished;
 }
 
 #ifdef JS_GC_ZEAL
+
+bool
+GCRuntime::shouldYieldForZeal(ZealMode mode)
+{
+    MOZ_ASSERT_IF(useZeal, isIncremental);
+    return useZeal && hasZealMode(mode);
+}
+
 IncrementalProgress
 GCRuntime::maybeYieldForSweepingZeal(FreeOp* fop, SliceBudget& budget)
 {
     /*
      * 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::YieldBeforeSweepingAtoms)))
-    {
+    if (initialState != State::Sweep && shouldYieldForZeal(ZealMode::IncrementalMultipleSlices))
         return NotFinished;
-    }
 
     return Finished;
 }
+
 #endif
 
 IncrementalProgress
 GCRuntime::endSweepingSweepGroup(FreeOp* fop, SliceBudget& budget)
 {
     {
         gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::FINALIZE_END);
         FreeOp fop(rt);
@@ -6277,16 +6282,48 @@ class SweepActionCall final : public Swe
   public:
     explicit SweepActionCall(Method m) : method(m) {}
     IncrementalProgress run(GCRuntime* gc, Args... args) override {
         return (gc->*method)(args...);
     }
     void assertFinished() const override { }
 };
 
+#ifdef JS_GC_ZEAL
+// Implementation of the SweepAction interface that yields in a specified zeal
+// mode and then calls another action.
+template <typename... Args>
+class SweepActionMaybeYield final : public SweepAction<GCRuntime*, Args...>
+{
+    using Action = SweepAction<GCRuntime*, Args...>;
+
+    ZealMode mode;
+    UniquePtr<Action> action;
+    bool triggered;
+
+  public:
+    SweepActionMaybeYield(UniquePtr<Action> action, ZealMode mode)
+      : mode(mode), action(Move(action)), triggered(false) {}
+
+    IncrementalProgress run(GCRuntime* gc, Args... args) override {
+        if (!triggered && gc->shouldYieldForZeal(mode)) {
+            triggered = true;
+            return NotFinished;
+        }
+
+        triggered = false;
+        return action->run(gc, args...);
+    }
+
+    void assertFinished() const override {
+        MOZ_ASSERT(!triggered);
+    }
+};
+#endif
+
 // Implementation of the SweepAction interface that calls a list of actions in
 // sequence.
 template <typename... Args>
 class SweepActionSequence final : public SweepAction<Args...>
 {
     using Action = SweepAction<Args...>;
     using ActionVector = Vector<UniquePtr<Action>, 0, SystemAllocPolicy>;
     using Iter = IncrementalIter<ContainerIter<ActionVector>>;
@@ -6413,17 +6450,27 @@ class RemoveLastTemplateParameter<Target
 
   public:
     using Type = typename Impl<List<>, Args...>::Type;
 };
 
 template <typename... Args>
 static UniquePtr<SweepAction<GCRuntime*, Args...>>
 Call(IncrementalProgress (GCRuntime::*method)(Args...)) {
-    return MakeUnique<SweepActionCall<Args...>>(method);
+   return MakeUnique<SweepActionCall<Args...>>(method);
+}
+
+template <typename... Args>
+static UniquePtr<SweepAction<GCRuntime*, Args...>>
+MaybeYield(ZealMode zealMode, UniquePtr<SweepAction<GCRuntime*, Args...>> action) {
+#ifdef JS_GC_ZEAL
+    return js::MakeUnique<SweepActionMaybeYield<Args...>>(Move(action), zealMode);
+#else
+    return action;
+#endif
 }
 
 template <typename... Args, typename... Rest>
 static UniquePtr<SweepAction<Args...>>
 Sequence(UniquePtr<SweepAction<Args...>> first, Rest... rest)
 {
     UniquePtr<SweepAction<Args...>> actions[] = { Move(first), Move(rest)... };
     auto seq = MakeUnique<SweepActionSequence<Args...>>();
@@ -6479,17 +6526,18 @@ GCRuntime::initSweepActions()
     sweepActions.ref() =
         RepeatForSweepGroup(rt,
             Sequence(
                 Call(&GCRuntime::endMarkingSweepGroup),
                 Call(&GCRuntime::beginSweepingSweepGroup),
 #ifdef JS_GC_ZEAL
                 Call(&GCRuntime::maybeYieldForSweepingZeal),
 #endif
-                Call(&GCRuntime::sweepAtomsTable),
+                MaybeYield(ZealMode::YieldBeforeSweepingAtoms,
+                           Call(&GCRuntime::sweepAtomsTable)),
                 Call(&GCRuntime::sweepWeakCaches),
                 ForEachZoneInSweepGroup(rt,
                     Sequence(
                         Call(&GCRuntime::sweepTypeInformation),
                         ForEachAllocKind(ForegroundObjectFinalizePhase.kinds,
                                          Call(&GCRuntime::finalizeAllocKind)),
                         ForEachAllocKind(ForegroundNonObjectFinalizePhase.kinds,
                                          Call(&GCRuntime::finalizeAllocKind)),
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -442,16 +442,17 @@ class GCRuntime
     Chunk* getOrAllocChunk(AutoLockGCBgAlloc& lock);
     void recycleChunk(Chunk* chunk, const AutoLockGC& lock);
 
 #ifdef JS_GC_ZEAL
     void startVerifyPreBarriers();
     void endVerifyPreBarriers();
     void finishVerifier();
     bool isVerifyPreBarriersEnabled() const { return !!verifyPreData; }
+    bool shouldYieldForZeal(ZealMode mode);
 #else
     bool isVerifyPreBarriersEnabled() const { return false; }
 #endif
 
     // Free certain LifoAlloc blocks when it is safe to do so.
     void freeUnusedLifoBlocksAfterSweeping(LifoAlloc* lifo);
     void freeAllLifoBlocksAfterSweeping(LifoAlloc* lifo);