diff --git a/dom/base/CCGCScheduler.cpp b/dom/base/CCGCScheduler.cpp index 2bc2bc5c245e..28e6468ff296 100644 --- a/dom/base/CCGCScheduler.cpp +++ b/dom/base/CCGCScheduler.cpp @@ -227,4 +227,30 @@ void CCGCScheduler::KillGCRunner() { } } +void CCGCScheduler::EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget) { + MOZ_ASSERT(!mDidShutdown); + + if (!mCCRunner) { + mCCRunner = IdleTaskRunner::Create( + CCRunnerFired, "EnsureCCRunner::CCRunnerFired", 0, + aDelay.ToMilliseconds(), aBudget.ToMilliseconds(), true, + [this] { return mDidShutdown; }); + } else { + mCCRunner->SetMinimumUsefulBudget(aBudget.ToMilliseconds()); + nsIEventTarget* target = mozilla::GetCurrentEventTarget(); + if (target) { + mCCRunner->SetTimer(aDelay.ToMilliseconds(), target); + } + } +} + +void CCGCScheduler::KillCCRunner() { + UnblockCC(); + DeactivateCCRunner(); + if (mCCRunner) { + mCCRunner->Cancel(); + mCCRunner = nullptr; + } +} + } // namespace mozilla diff --git a/dom/base/CCGCScheduler.h b/dom/base/CCGCScheduler.h index 4831fc430a33..abb3a1c2adea 100644 --- a/dom/base/CCGCScheduler.h +++ b/dom/base/CCGCScheduler.h @@ -121,6 +121,8 @@ class CCGCScheduler { // "suspected" of being members of cyclic garbage. static inline uint32_t SuspectedCCObjects(); + static bool CCRunnerFired(TimeStamp aDeadline); + // Parameter setting void SetActiveIntersliceGCBudget(TimeDuration aDuration) { @@ -151,6 +153,9 @@ class CCGCScheduler { void KillShrinkingGCTimer(); void KillFullGCTimer(); void KillGCRunner(); + void KillCCRunner(); + + void EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget); // State modification @@ -342,6 +347,10 @@ class CCGCScheduler { }; void InitCCRunnerStateMachine(CCRunnerState initialState) { + if (mCCRunner) { + return; + } + // The state machine should always have been deactivated after the previous // collection, however far that collection may have gone. MOZ_ASSERT(mCCRunnerState == CCRunnerState::Inactive, @@ -412,6 +421,7 @@ class CCGCScheduler { public: // XXX RefPtr mGCRunner; + RefPtr mCCRunner; private: nsITimer* mShrinkingGCTimer = nullptr; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 9cc52b22a9bd..c12d0df663f2 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -92,8 +92,6 @@ using namespace mozilla::dom; # undef CompareString #endif -static StaticRefPtr sCCRunner; - static JS::GCSliceCallback sPrevGCSliceCallback; static bool sIncrementalCC = false; @@ -275,7 +273,7 @@ static TimeDuration GetCollectionTimeDelta() { static void KillTimers() { sScheduler.KillShrinkingGCTimer(); - nsJSContext::KillCCRunner(); + sScheduler.KillCCRunner(); sScheduler.KillFullGCTimer(); sScheduler.KillGCRunner(); } @@ -1485,18 +1483,16 @@ void nsJSContext::BeginCycleCollectionCallback() { return; } - if (!sCCRunner) { - sScheduler.InitCCRunnerStateMachine( - mozilla::CCGCScheduler::CCRunnerState::CycleCollecting); - } - EnsureCCRunner(kICCIntersliceDelay, kIdleICCSliceBudget); + sScheduler.InitCCRunnerStateMachine( + mozilla::CCGCScheduler::CCRunnerState::CycleCollecting); + sScheduler.EnsureCCRunner(kICCIntersliceDelay, kIdleICCSliceBudget); } // static void nsJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults) { MOZ_ASSERT(NS_IsMainThread()); - nsJSContext::KillCCRunner(); + sScheduler.KillCCRunner(); // Update timing information for the current slice before we log it, if // we previously called PrepareForCycleCollectionSlice(). During shutdown @@ -1532,7 +1528,8 @@ void nsJSContext::EndCycleCollectionCallback(CycleCollectorResults& aResults) { sCCStats.Clear(); } -static bool CCRunnerFired(TimeStamp aDeadline) { +/* static */ +bool CCGCScheduler::CCRunnerFired(TimeStamp aDeadline) { bool didDoWork = false; // The CC/GC scheduler (sScheduler) decides what action(s) to take during @@ -1572,7 +1569,7 @@ static bool CCRunnerFired(TimeStamp aDeadline) { case CCRunnerAction::StopRunning: // End this CC, either because we have run a cycle collection slice, or // because a CC is no longer needed. - nsJSContext::KillCCRunner(); + sScheduler.KillCCRunner(); break; } @@ -1584,24 +1581,6 @@ static bool CCRunnerFired(TimeStamp aDeadline) { return didDoWork; } -// static -void nsJSContext::EnsureCCRunner(TimeDuration aDelay, TimeDuration aBudget) { - MOZ_ASSERT(!sShuttingDown); - - if (!sCCRunner) { - sCCRunner = IdleTaskRunner::Create( - CCRunnerFired, "EnsureCCRunner::CCRunnerFired", 0, - aDelay.ToMilliseconds(), aBudget.ToMilliseconds(), true, - [] { return sShuttingDown; }); - } else { - sCCRunner->SetMinimumUsefulBudget(aBudget.ToMilliseconds()); - nsIEventTarget* target = mozilla::GetCurrentEventTarget(); - if (target) { - sCCRunner->SetTimer(aDelay.ToMilliseconds(), target); - } - } -} - // static bool nsJSContext::HasHadCleanupSinceLastGC() { return sScheduler.IsEarlyForgetSkippable(1); @@ -1626,8 +1605,8 @@ void nsJSContext::RunNextCollectorTimer(JS::GCReason aReason, if (sScheduler.mGCRunner) { sScheduler.SetWantMajorGC(aReason); runner = sScheduler.mGCRunner; - } else if (sCCRunner) { - runner = sCCRunner; + } else if (sScheduler.mCCRunner) { + runner = sScheduler.mCCRunner; } if (runner) { @@ -1715,7 +1694,7 @@ void nsJSContext::PokeGC(JS::GCReason aReason, JSObject* aObj, sScheduler.SetWantMajorGC(aReason); - if (sCCRunner) { + if (sScheduler.mCCRunner) { // Make sure CC is called regardless of the size of the purple buffer, and // GC after it. sScheduler.EnsureCCThenGC(); @@ -1774,7 +1753,7 @@ void nsJSContext::LowMemoryGC() { // static void nsJSContext::MaybePokeCC() { - if (sCCRunner || sShuttingDown) { + if (sScheduler.mCCRunner || sShuttingDown) { return; } @@ -1782,21 +1761,11 @@ void nsJSContext::MaybePokeCC() { // We can kill some objects before running forgetSkippable. nsCycleCollector_dispatchDeferredDeletion(); - if (!sCCRunner) { + if (!sScheduler.mCCRunner) { sScheduler.InitCCRunnerStateMachine( mozilla::CCGCScheduler::CCRunnerState::ReducePurple); } - EnsureCCRunner(kCCSkippableDelay, kForgetSkippableSliceDuration); - } -} - -// static -void nsJSContext::KillCCRunner() { - sScheduler.UnblockCC(); - sScheduler.DeactivateCCRunner(); - if (sCCRunner) { - sCCRunner->Cancel(); - sCCRunner = nullptr; + sScheduler.EnsureCCRunner(kCCSkippableDelay, kForgetSkippableSliceDuration); } } diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 38eb6d40de48..33f6ad338ea1 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -111,9 +111,6 @@ class nsJSContext : public nsIScriptContext { static void LowMemoryGC(); static void MaybePokeCC(); - static void EnsureCCRunner(mozilla::TimeDuration aDelay, - mozilla::TimeDuration aBudget); - static void KillCCRunner(); // Calling LikelyShortLivingObjectCreated() makes a GC more likely. static void LikelyShortLivingObjectCreated();