Loading dom/base/CCGCScheduler.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -486,7 +486,8 @@ void CCGCScheduler::EnsureGCRunner(TimeDuration aDelay) { "CCGCScheduler::EnsureGCRunner", aDelay, TimeDuration::FromMilliseconds( StaticPrefs::javascript_options_gc_delay_interslice()), mActiveIntersliceGCBudget, true, [this] { return mDidShutdown; }); mActiveIntersliceGCBudget, true, [this] { return mDidShutdown; }, [this](uint32_t) { mInterruptRequested = true; }); } // nsJSEnvironmentObserver observes the user-interaction-inactive notifications Loading dom/base/CCGCScheduler.h +11 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,8 @@ struct CCRunnerStep { class CCGCScheduler { public: CCGCScheduler() : mInterruptRequested(false) {} static bool CCRunnerFired(TimeStamp aDeadline); // Parameter setting Loading Loading @@ -151,6 +153,11 @@ class CCGCScheduler { void KillCCRunner(); void KillAllTimersAndRunners(); js::SliceBudget CreateGCSliceBudget(JS::GCReason aReason, int64_t aMillis) { return js::SliceBudget(mozilla::TimeDuration::FromMilliseconds(aMillis), &mInterruptRequested); } /* * aDelay is the delay before the first time the idle task runner runs. * Then it runs every Loading Loading @@ -435,6 +442,10 @@ class CCGCScheduler { // The parent process is ready for us to do a major GC. bool mReadyForMajorGC = false; // Set when the IdleTaskRunner requests the current task be interrupted. // Cleared when the GC slice budget has detected the interrupt request. mozilla::Atomic<bool> mInterruptRequested; // When a shrinking GC has been requested but we back-out, if this is true // we run a non-shrinking GC. bool mWantAtLeastRegularGC = false; Loading dom/base/nsJSEnvironment.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ #include "mozilla/ContentEvents.h" #include "mozilla/CycleCollectedJSContext.h" #include "nsCycleCollectionNoteRootCallback.h" #include "mozilla/IdleTaskRunner.h" #include "nsViewManager.h" #include "mozilla/EventStateManager.h" #include "mozilla/ProfilerLabels.h" Loading Loading @@ -1923,6 +1922,11 @@ static bool ConsumeStream(JSContext* aCx, JS::HandleObject aObj, nullptr); } static js::SliceBudget CreateGCSliceBudget(JS::GCReason aReason, int64_t aMillis) { return sScheduler.CreateGCSliceBudget(aReason, aMillis); } void nsJSContext::EnsureStatics() { if (sIsInitialized) { if (!nsContentUtils::XPConnect()) { Loading @@ -1939,6 +1943,8 @@ void nsJSContext::EnsureStatics() { sPrevGCSliceCallback = JS::SetGCSliceCallback(jsapi.cx(), DOMGCSliceCallback); JS::SetCreateGCSliceBudgetCallback(jsapi.cx(), CreateGCSliceBudget); JS::InitDispatchToEventLoop(jsapi.cx(), DispatchToEventLoop, nullptr); JS::InitConsumeStreamCallback(jsapi.cx(), ConsumeStream, FetchUtil::ReportJSStreamError); Loading ipc/glue/IdleSchedulerParent.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include "nsThreadUtils.h" #include "nsITimer.h" #include "nsIThread.h" #include "nsXPCOMPrivate.h" // for gXPCOMThreadsShutDown namespace mozilla::ipc { Loading Loading @@ -72,8 +73,10 @@ IdleSchedulerParent::IdleSchedulerParent() { CalculateNumIdleTasks(); }); if (MOZ_LIKELY(!gXPCOMThreadsShutDown)) { thread->Dispatch(runnable, NS_DISPATCH_NORMAL); } } }); NS_DispatchBackgroundTask(runnable.forget(), NS_DISPATCH_EVENT_MAY_BLOCK); } Loading xpcom/threads/IdleTaskRunner.cpp +21 −6 Original line number Diff line number Diff line Loading @@ -14,14 +14,15 @@ already_AddRefed<IdleTaskRunner> IdleTaskRunner::Create( const CallbackType& aCallback, const char* aRunnableName, TimeDuration aStartDelay, TimeDuration aMaxDelay, TimeDuration aMinimumUsefulBudget, bool aRepeating, const MayStopProcessingCallbackType& aMayStopProcessing) { const MayStopProcessingCallbackType& aMayStopProcessing, const RequestInterruptCallbackType& aRequestInterrupt) { if (aMayStopProcessing && aMayStopProcessing()) { return nullptr; } RefPtr<IdleTaskRunner> runner = new IdleTaskRunner(aCallback, aRunnableName, aStartDelay, aMaxDelay, aMinimumUsefulBudget, aRepeating, aMayStopProcessing); RefPtr<IdleTaskRunner> runner = new IdleTaskRunner( aCallback, aRunnableName, aStartDelay, aMaxDelay, aMinimumUsefulBudget, aRepeating, aMayStopProcessing, aRequestInterrupt); runner->Schedule(false); // Initial scheduling shouldn't use idle dispatch. return runner.forget(); } Loading @@ -29,7 +30,9 @@ already_AddRefed<IdleTaskRunner> IdleTaskRunner::Create( class IdleTaskRunnerTask : public Task { public: explicit IdleTaskRunnerTask(IdleTaskRunner* aRunner) : Task(true, EventQueuePriority::Idle), mRunner(aRunner) { : Task(true, EventQueuePriority::Idle), mRunner(aRunner), mRequestInterrupt(aRunner->mRequestInterrupt) { SetManager(TaskController::Get()->GetIdleTaskManager()); } Loading Loading @@ -61,15 +64,26 @@ class IdleTaskRunnerTask : public Task { return true; } void RequestInterrupt(uint32_t aInterruptPriority) override { if (mRequestInterrupt) { mRequestInterrupt(aInterruptPriority); } } private: IdleTaskRunner* mRunner; // Copied here and invoked even if there is no mRunner currently, to avoid // race conditions checking mRunner when an interrupt is requested. IdleTaskRunner::RequestInterruptCallbackType mRequestInterrupt; }; IdleTaskRunner::IdleTaskRunner( const CallbackType& aCallback, const char* aRunnableName, TimeDuration aStartDelay, TimeDuration aMaxDelay, TimeDuration aMinimumUsefulBudget, bool aRepeating, const MayStopProcessingCallbackType& aMayStopProcessing) const MayStopProcessingCallbackType& aMayStopProcessing, const RequestInterruptCallbackType& aRequestInterrupt) : mCallback(aCallback), mStartTime(TimeStamp::Now() + aStartDelay), mMaxDelay(aMaxDelay), Loading @@ -77,6 +91,7 @@ IdleTaskRunner::IdleTaskRunner( mRepeating(aRepeating), mTimerActive(false), mMayStopProcessing(aMayStopProcessing), mRequestInterrupt(aRequestInterrupt), mName(aRunnableName) {} void IdleTaskRunner::Run() { Loading Loading
dom/base/CCGCScheduler.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -486,7 +486,8 @@ void CCGCScheduler::EnsureGCRunner(TimeDuration aDelay) { "CCGCScheduler::EnsureGCRunner", aDelay, TimeDuration::FromMilliseconds( StaticPrefs::javascript_options_gc_delay_interslice()), mActiveIntersliceGCBudget, true, [this] { return mDidShutdown; }); mActiveIntersliceGCBudget, true, [this] { return mDidShutdown; }, [this](uint32_t) { mInterruptRequested = true; }); } // nsJSEnvironmentObserver observes the user-interaction-inactive notifications Loading
dom/base/CCGCScheduler.h +11 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,8 @@ struct CCRunnerStep { class CCGCScheduler { public: CCGCScheduler() : mInterruptRequested(false) {} static bool CCRunnerFired(TimeStamp aDeadline); // Parameter setting Loading Loading @@ -151,6 +153,11 @@ class CCGCScheduler { void KillCCRunner(); void KillAllTimersAndRunners(); js::SliceBudget CreateGCSliceBudget(JS::GCReason aReason, int64_t aMillis) { return js::SliceBudget(mozilla::TimeDuration::FromMilliseconds(aMillis), &mInterruptRequested); } /* * aDelay is the delay before the first time the idle task runner runs. * Then it runs every Loading Loading @@ -435,6 +442,10 @@ class CCGCScheduler { // The parent process is ready for us to do a major GC. bool mReadyForMajorGC = false; // Set when the IdleTaskRunner requests the current task be interrupted. // Cleared when the GC slice budget has detected the interrupt request. mozilla::Atomic<bool> mInterruptRequested; // When a shrinking GC has been requested but we back-out, if this is true // we run a non-shrinking GC. bool mWantAtLeastRegularGC = false; Loading
dom/base/nsJSEnvironment.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ #include "mozilla/ContentEvents.h" #include "mozilla/CycleCollectedJSContext.h" #include "nsCycleCollectionNoteRootCallback.h" #include "mozilla/IdleTaskRunner.h" #include "nsViewManager.h" #include "mozilla/EventStateManager.h" #include "mozilla/ProfilerLabels.h" Loading Loading @@ -1923,6 +1922,11 @@ static bool ConsumeStream(JSContext* aCx, JS::HandleObject aObj, nullptr); } static js::SliceBudget CreateGCSliceBudget(JS::GCReason aReason, int64_t aMillis) { return sScheduler.CreateGCSliceBudget(aReason, aMillis); } void nsJSContext::EnsureStatics() { if (sIsInitialized) { if (!nsContentUtils::XPConnect()) { Loading @@ -1939,6 +1943,8 @@ void nsJSContext::EnsureStatics() { sPrevGCSliceCallback = JS::SetGCSliceCallback(jsapi.cx(), DOMGCSliceCallback); JS::SetCreateGCSliceBudgetCallback(jsapi.cx(), CreateGCSliceBudget); JS::InitDispatchToEventLoop(jsapi.cx(), DispatchToEventLoop, nullptr); JS::InitConsumeStreamCallback(jsapi.cx(), ConsumeStream, FetchUtil::ReportJSStreamError); Loading
ipc/glue/IdleSchedulerParent.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include "nsThreadUtils.h" #include "nsITimer.h" #include "nsIThread.h" #include "nsXPCOMPrivate.h" // for gXPCOMThreadsShutDown namespace mozilla::ipc { Loading Loading @@ -72,8 +73,10 @@ IdleSchedulerParent::IdleSchedulerParent() { CalculateNumIdleTasks(); }); if (MOZ_LIKELY(!gXPCOMThreadsShutDown)) { thread->Dispatch(runnable, NS_DISPATCH_NORMAL); } } }); NS_DispatchBackgroundTask(runnable.forget(), NS_DISPATCH_EVENT_MAY_BLOCK); } Loading
xpcom/threads/IdleTaskRunner.cpp +21 −6 Original line number Diff line number Diff line Loading @@ -14,14 +14,15 @@ already_AddRefed<IdleTaskRunner> IdleTaskRunner::Create( const CallbackType& aCallback, const char* aRunnableName, TimeDuration aStartDelay, TimeDuration aMaxDelay, TimeDuration aMinimumUsefulBudget, bool aRepeating, const MayStopProcessingCallbackType& aMayStopProcessing) { const MayStopProcessingCallbackType& aMayStopProcessing, const RequestInterruptCallbackType& aRequestInterrupt) { if (aMayStopProcessing && aMayStopProcessing()) { return nullptr; } RefPtr<IdleTaskRunner> runner = new IdleTaskRunner(aCallback, aRunnableName, aStartDelay, aMaxDelay, aMinimumUsefulBudget, aRepeating, aMayStopProcessing); RefPtr<IdleTaskRunner> runner = new IdleTaskRunner( aCallback, aRunnableName, aStartDelay, aMaxDelay, aMinimumUsefulBudget, aRepeating, aMayStopProcessing, aRequestInterrupt); runner->Schedule(false); // Initial scheduling shouldn't use idle dispatch. return runner.forget(); } Loading @@ -29,7 +30,9 @@ already_AddRefed<IdleTaskRunner> IdleTaskRunner::Create( class IdleTaskRunnerTask : public Task { public: explicit IdleTaskRunnerTask(IdleTaskRunner* aRunner) : Task(true, EventQueuePriority::Idle), mRunner(aRunner) { : Task(true, EventQueuePriority::Idle), mRunner(aRunner), mRequestInterrupt(aRunner->mRequestInterrupt) { SetManager(TaskController::Get()->GetIdleTaskManager()); } Loading Loading @@ -61,15 +64,26 @@ class IdleTaskRunnerTask : public Task { return true; } void RequestInterrupt(uint32_t aInterruptPriority) override { if (mRequestInterrupt) { mRequestInterrupt(aInterruptPriority); } } private: IdleTaskRunner* mRunner; // Copied here and invoked even if there is no mRunner currently, to avoid // race conditions checking mRunner when an interrupt is requested. IdleTaskRunner::RequestInterruptCallbackType mRequestInterrupt; }; IdleTaskRunner::IdleTaskRunner( const CallbackType& aCallback, const char* aRunnableName, TimeDuration aStartDelay, TimeDuration aMaxDelay, TimeDuration aMinimumUsefulBudget, bool aRepeating, const MayStopProcessingCallbackType& aMayStopProcessing) const MayStopProcessingCallbackType& aMayStopProcessing, const RequestInterruptCallbackType& aRequestInterrupt) : mCallback(aCallback), mStartTime(TimeStamp::Now() + aStartDelay), mMaxDelay(aMaxDelay), Loading @@ -77,6 +91,7 @@ IdleTaskRunner::IdleTaskRunner( mRepeating(aRepeating), mTimerActive(false), mMayStopProcessing(aMayStopProcessing), mRequestInterrupt(aRequestInterrupt), mName(aRunnableName) {} void IdleTaskRunner::Run() { Loading