Commit 024b1ac4 authored by Steve Fink's avatar Steve Fink
Browse files

Bug 1672121 - Stop sGCRunner GC slice if the IdleTaskRunnerTask gets a...

Bug 1672121 - Stop sGCRunner GC slice if the IdleTaskRunnerTask gets a RequestInterrupt() call r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D109631
parent 0181c4d9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+11 −0
Original line number Diff line number Diff line
@@ -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;
+7 −1
Original line number Diff line number Diff line
@@ -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"
@@ -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()) {
@@ -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);
+4 −1
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include "nsThreadUtils.h"
#include "nsITimer.h"
#include "nsIThread.h"
#include "nsXPCOMPrivate.h"  // for gXPCOMThreadsShutDown

namespace mozilla::ipc {

@@ -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);
  }
+21 −6
Original line number Diff line number Diff line
@@ -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() {
Loading