Backed out changeset 15a5f1ecca37 (bug 1216175) for m(oth)/m(c2) failures in test_WorkerDebugger.xul a=backout
authorWes Kocher <wkocher@mozilla.com>
Fri, 27 Jan 2017 13:50:12 -0800
changeset 378176 4ae1f35907f85eb93c607c17560524c2bf070891
parent 378175 db68cec8a4167601dffa2527ef88413e6eea8191
child 378177 12896715acd1dbd50f20df2a5601084d5a919c20
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1216175
milestone54.0a1
backs out15a5f1ecca37bbd67eef5bb87652c6e220e427e3
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
Backed out changeset 15a5f1ecca37 (bug 1216175) for m(oth)/m(c2) failures in test_WorkerDebugger.xul a=backout MozReview-Commit-ID: LOu50H5NS2L
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1262,18 +1262,16 @@ void
 IdleGCTimerCallback(nsITimer* aTimer, void* aClosure)
 {
   auto workerPrivate = static_cast<WorkerPrivate*>(aClosure);
   MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
   workerPrivate->AssertIsOnWorkerThread();
   workerPrivate->GarbageCollectInternal(workerPrivate->GetJSContext(),
                                         true /* shrinking */,
                                         false /* collect children */);
-  // After running idle GC we can cancel the current timers.
-  workerPrivate->CancelGCTimers();
 }
 
 class UpdateContextOptionsRunnable final : public WorkerControlRunnable
 {
   JS::ContextOptions mContextOptions;
 
 public:
   UpdateContextOptionsRunnable(WorkerPrivate* aWorkerPrivate,
@@ -1406,21 +1404,16 @@ private:
     // Silence bad assertions, this can be dispatched from either the main
     // thread or the timer thread..
   }
 
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     aWorkerPrivate->GarbageCollectInternal(aCx, mShrinking, mCollectChildren);
-    if (mShrinking) {
-      // Either we've run the idle GC or explicit GC call from the parent,
-      // we can cancel the current timers.
-      aWorkerPrivate->CancelGCTimers();
-    }
     return true;
   }
 };
 
 class CycleCollectRunnable : public WorkerControlRunnable
 {
   bool mCollectChildren;
 
@@ -4720,19 +4713,17 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
         // Unroot the globals
         mScope = nullptr;
         mDebuggerScope = nullptr;
 
         return;
       }
     }
 
-    bool hadDebuggerOrNormalRunnables = false;
     if (debuggerRunnablesPending || normalRunnablesPending) {
-      hadDebuggerOrNormalRunnables = true;
       // Start the periodic GC timer if it is not already running.
       SetGCTimerMode(PeriodicTimer);
     }
 
     if (debuggerRunnablesPending) {
       WorkerRunnable* runnable;
 
       {
@@ -4764,18 +4755,17 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
       normalRunnablesPending = NS_HasPendingEvents(mThread);
       if (normalRunnablesPending && GlobalScope()) {
         // Now *might* be a good time to GC. Let the JS engine make the decision.
         JSAutoCompartment ac(aCx, GlobalScope()->GetGlobalJSObject());
         JS_MaybeGC(aCx);
       }
     }
 
-    if (hadDebuggerOrNormalRunnables &&
-        (!debuggerRunnablesPending && !normalRunnablesPending)) {
+    if (!debuggerRunnablesPending && !normalRunnablesPending) {
       // Both the debugger event queue and the normal event queue has been
       // exhausted, cancel the periodic GC timer and schedule the idle GC timer.
       SetGCTimerMode(IdleTimer);
     }
 
     // If the worker thread is spamming the main thread faster than it can
     // process the work, then pause the worker thread until the MT catches
     // up.
@@ -4858,100 +4848,100 @@ WorkerPrivate::ControlEventTarget()
   return mWorkerControlEventTarget;
 }
 
 void
 WorkerPrivate::InitializeGCTimers()
 {
   AssertIsOnWorkerThread();
 
-  // We need timers for GC. The basic plan is to run a non-shrinking GC
+  // We need a timer for GC. The basic plan is to run a non-shrinking GC
   // periodically (PERIODIC_GC_TIMER_DELAY_SEC) while the worker is running.
   // Once the worker goes idle we set a short (IDLE_GC_TIMER_DELAY_SEC) timer to
-  // run a shrinking GC.
-  mPeriodicGCTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  mIdleGCTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  // run a shrinking GC. If the worker receives more messages then the short
+  // timer is canceled and the periodic timer resumes.
+  mGCTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  MOZ_ASSERT(mGCTimer);
 
   mPeriodicGCTimerRunning = false;
   mIdleGCTimerRunning = false;
 }
 
 void
 WorkerPrivate::SetGCTimerMode(GCTimerMode aMode)
 {
   AssertIsOnWorkerThread();
-  MOZ_ASSERT(mPeriodicGCTimer);
-  MOZ_ASSERT(mIdleGCTimer);
-
-  // If we schedule the idle timer, cancel the periodic timer.
-  // But if the idle timer is running, don't cancel it when the periodic timer
-  // is scheduled since we do want shrinking GC to be called occasionally.
-  if (aMode == PeriodicTimer && mPeriodicGCTimerRunning) {
+  MOZ_ASSERT(mGCTimer);
+
+  if ((aMode == PeriodicTimer && mPeriodicGCTimerRunning) ||
+      (aMode == IdleTimer && mIdleGCTimerRunning)) {
     return;
   }
 
-  if (aMode == IdleTimer || aMode == NoTimer) {
-    MOZ_ALWAYS_SUCCEEDS(mPeriodicGCTimer->Cancel());
-    mPeriodicGCTimerRunning = false;
-  }
-
-  if (aMode == IdleTimer && mIdleGCTimerRunning) {
-    return;
-  }
+  MOZ_ALWAYS_SUCCEEDS(mGCTimer->Cancel());
+
+  mPeriodicGCTimerRunning = false;
+  mIdleGCTimerRunning = false;
+  LOG(WorkerLog(),
+      ("Worker %p canceled GC timer because %s\n", this,
+       aMode == PeriodicTimer ?
+       "periodic" :
+       aMode == IdleTimer ? "idle" : "none"));
 
   if (aMode == NoTimer) {
-    MOZ_ALWAYS_SUCCEEDS(mIdleGCTimer->Cancel());
-    mIdleGCTimerRunning = false;
     return;
   }
 
   MOZ_ASSERT(aMode == PeriodicTimer || aMode == IdleTimer);
 
   uint32_t delay = 0;
   int16_t type = nsITimer::TYPE_ONE_SHOT;
   nsTimerCallbackFunc callback = nullptr;
   const char* name = nullptr;
-  nsITimer* timer = nullptr;
 
   if (aMode == PeriodicTimer) {
     delay = PERIODIC_GC_TIMER_DELAY_SEC * 1000;
     type = nsITimer::TYPE_REPEATING_SLACK;
     callback = PeriodicGCTimerCallback;
     name = "dom::workers::PeriodicGCTimerCallback";
-    timer = mPeriodicGCTimer;
-    mPeriodicGCTimerRunning = true;
-    LOG(WorkerLog(), ("Worker %p scheduled periodic GC timer\n", this));
-  } else {
+  }
+  else {
     delay = IDLE_GC_TIMER_DELAY_SEC * 1000;
     type = nsITimer::TYPE_ONE_SHOT;
     callback = IdleGCTimerCallback;
     name = "dom::workers::IdleGCTimerCallback";
-    timer = mIdleGCTimer;
-    mIdleGCTimerRunning = true;
+  }
+
+  MOZ_ALWAYS_SUCCEEDS(mGCTimer->SetTarget(mWorkerControlEventTarget));
+  MOZ_ALWAYS_SUCCEEDS(
+    mGCTimer->InitWithNamedFuncCallback(callback, this, delay, type, name));
+
+  if (aMode == PeriodicTimer) {
+    LOG(WorkerLog(), ("Worker %p scheduled periodic GC timer\n", this));
+    mPeriodicGCTimerRunning = true;
+  }
+  else {
     LOG(WorkerLog(), ("Worker %p scheduled idle GC timer\n", this));
-  }
-
-  MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(mWorkerControlEventTarget));
-  MOZ_ALWAYS_SUCCEEDS(
-    timer->InitWithNamedFuncCallback(callback, this, delay, type, name));
+    mIdleGCTimerRunning = true;
+  }
 }
 
 void
 WorkerPrivate::ShutdownGCTimers()
 {
   AssertIsOnWorkerThread();
 
-  // Always make sure the timers are canceled.
-  MOZ_ALWAYS_SUCCEEDS(mPeriodicGCTimer->Cancel());
-  MOZ_ALWAYS_SUCCEEDS(mIdleGCTimer->Cancel());
-
-  LOG(WorkerLog(), ("Worker %p killed the GC timers\n", this));
-
-  mPeriodicGCTimer = nullptr;
-  mIdleGCTimer = nullptr;
+  MOZ_ASSERT(mGCTimer);
+
+  // Always make sure the timer is canceled.
+  MOZ_ALWAYS_SUCCEEDS(mGCTimer->Cancel());
+
+  LOG(WorkerLog(), ("Worker %p killed the GC timer\n", this));
+
+  mGCTimer = nullptr;
   mPeriodicGCTimerRunning = false;
   mIdleGCTimerRunning = false;
 }
 
 bool
 WorkerPrivate::InterruptCallback(JSContext* aCx)
 {
   AssertIsOnWorkerThread();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -954,18 +954,17 @@ class WorkerPrivate : public WorkerPriva
   // This is only modified on the worker thread, but in DEBUG builds
   // AssertValidSyncLoop function iterates it on other threads. Therefore
   // modifications are done with mMutex held *only* in DEBUG builds.
   nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack;
 
   nsCOMPtr<nsITimer> mTimer;
   nsCOMPtr<nsITimerCallback> mTimerRunnable;
 
-  nsCOMPtr<nsITimer> mPeriodicGCTimer;
-  nsCOMPtr<nsITimer> mIdleGCTimer;
+  nsCOMPtr<nsITimer> mGCTimer;
 
   RefPtr<MemoryReporter> mMemoryReporter;
 
   // fired on the main thread if the worker script fails to load
   nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
 
   JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
   TimeStamp mKillTime;
@@ -1392,22 +1391,16 @@ public:
                        uint32_t aFlags = NS_DISPATCH_NORMAL);
 
   // Get an event target that will dispatch runnables as control runnables on
   // the worker thread.  Implement nsICancelableRunnable if you wish to take
   // action on cancelation.
   nsIEventTarget*
   ControlEventTarget();
 
-  void
-  CancelGCTimers()
-  {
-    SetGCTimerMode(NoTimer);
-  }
-
 private:
   WorkerPrivate(WorkerPrivate* aParent,
                 const nsAString& aScriptURL, bool aIsChromeWorker,
                 WorkerType aWorkerType, const nsACString& aSharedWorkerName,
                 WorkerLoadInfo& aLoadInfo);
 
   bool
   MayContinueRunning()