зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1672121
- Stop sGCRunner GC slice if the IdleTaskRunnerTask gets a RequestInterrupt() call r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D109631
This commit is contained in:
Родитель
ec62429c88
Коммит
543df99e4e
|
@ -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
|
||||
|
|
|
@ -109,6 +109,8 @@ struct CCRunnerStep {
|
|||
|
||||
class CCGCScheduler {
|
||||
public:
|
||||
CCGCScheduler() : mInterruptRequested(false) {}
|
||||
|
||||
static bool CCRunnerFired(TimeStamp aDeadline);
|
||||
|
||||
// Parameter setting
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
@ -1924,6 +1923,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()) {
|
||||
|
@ -1940,6 +1944,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);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsXPCOMPrivate.h" // for gXPCOMThreadsShutDown
|
||||
|
||||
namespace mozilla::ipc {
|
||||
|
||||
|
@ -70,7 +71,9 @@ IdleSchedulerParent::IdleSchedulerParent() {
|
|||
CalculateNumIdleTasks();
|
||||
});
|
||||
|
||||
thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
if (MOZ_LIKELY(!gXPCOMThreadsShutDown)) {
|
||||
thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
});
|
||||
NS_DispatchBackgroundTask(runnable.forget(), NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -77,6 +91,7 @@ IdleTaskRunner::IdleTaskRunner(
|
|||
mRepeating(aRepeating),
|
||||
mTimerActive(false),
|
||||
mMayStopProcessing(aMayStopProcessing),
|
||||
mRequestInterrupt(aRequestInterrupt),
|
||||
mName(aRunnableName) {}
|
||||
|
||||
void IdleTaskRunner::Run() {
|
||||
|
|
|
@ -23,6 +23,7 @@ class IdleTaskRunnerTask;
|
|||
// true to completely remove the runner.
|
||||
class IdleTaskRunner {
|
||||
public:
|
||||
friend class IdleTaskRunnerTask;
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IdleTaskRunner)
|
||||
|
||||
// Return true if some meaningful work was done.
|
||||
|
@ -33,6 +34,12 @@ class IdleTaskRunner {
|
|||
// work together in different way.
|
||||
using MayStopProcessingCallbackType = std::function<bool()>;
|
||||
|
||||
// A callback to be invoked when an interrupt is requested
|
||||
// (eg during an idle activity when the user presses a key.)
|
||||
// The callback takes an "interrupt priority" value as its
|
||||
// sole parameter.
|
||||
using RequestInterruptCallbackType = std::function<void(uint32_t)>;
|
||||
|
||||
public:
|
||||
// An IdleTaskRunner has (up to) three phases:
|
||||
//
|
||||
|
@ -53,7 +60,8 @@ class IdleTaskRunner {
|
|||
const CallbackType& aCallback, const char* aRunnableName,
|
||||
TimeDuration aStartDelay, TimeDuration aMaxDelay,
|
||||
TimeDuration aMinimumUsefulBudget, bool aRepeating,
|
||||
const MayStopProcessingCallbackType& aMayStopProcessing);
|
||||
const MayStopProcessingCallbackType& aMayStopProcessing,
|
||||
const RequestInterruptCallbackType& aRequestInterrupt = nullptr);
|
||||
|
||||
void Run();
|
||||
|
||||
|
@ -77,7 +85,8 @@ class IdleTaskRunner {
|
|||
const CallbackType& aCallback, const char* aRunnableName,
|
||||
TimeDuration aStartDelay, TimeDuration aMaxDelay,
|
||||
TimeDuration aMinimumUsefulBudget, bool aRepeating,
|
||||
const MayStopProcessingCallbackType& aMayStopProcessing);
|
||||
const MayStopProcessingCallbackType& aMayStopProcessing,
|
||||
const RequestInterruptCallbackType& aRequestInterrupt);
|
||||
~IdleTaskRunner();
|
||||
void CancelTimer();
|
||||
void SetTimerInternal(TimeDuration aDelay);
|
||||
|
@ -103,6 +112,7 @@ class IdleTaskRunner {
|
|||
bool mRepeating;
|
||||
bool mTimerActive;
|
||||
MayStopProcessingCallbackType mMayStopProcessing;
|
||||
RequestInterruptCallbackType mRequestInterrupt;
|
||||
const char* mName;
|
||||
RefPtr<IdleTaskRunnerTask> mTask;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче