Bug 1515216, ensure IdleTaskRunners are added only once to RefreshDriver's idle runnable list, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 15 Apr 2019 15:41:15 +0000
changeset 469509 debaeed47505
parent 469508 1ed5db9c200a
child 469510 45358a231fb3
push id35873
push userccoroiu@mozilla.com
push dateMon, 15 Apr 2019 21:36:26 +0000
treeherdermozilla-central@b8f49a14c458 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1515216
milestone68.0a1
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
Bug 1515216, ensure IdleTaskRunners are added only once to RefreshDriver's idle runnable list, r=mccr8 Differential Revision: https://phabricator.services.mozilla.com/D27424
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
xpcom/threads/IdleTaskRunner.cpp
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1708,20 +1708,26 @@ void nsRefreshDriver::RunFrameRequestCal
 
 struct RunnableWithDelay {
   nsCOMPtr<nsIRunnable> mRunnable;
   uint32_t mDelay;
 };
 
 static AutoTArray<RunnableWithDelay, 8>* sPendingIdleRunnables = nullptr;
 
-void nsRefreshDriver::DispatchIdleRunnableAfterTick(nsIRunnable* aRunnable,
-                                                    uint32_t aDelay) {
+void nsRefreshDriver::DispatchIdleRunnableAfterTickUnlessExists(
+    nsIRunnable* aRunnable, uint32_t aDelay) {
   if (!sPendingIdleRunnables) {
     sPendingIdleRunnables = new AutoTArray<RunnableWithDelay, 8>();
+  } else {
+    for (uint32_t i = 0; i < sPendingIdleRunnables->Length(); ++i) {
+      if ((*sPendingIdleRunnables)[i].mRunnable == aRunnable) {
+        return;
+      }
+    }
   }
 
   RunnableWithDelay rwd = {aRunnable, aDelay};
   sPendingIdleRunnables->AppendElement(rwd);
 }
 
 void nsRefreshDriver::CancelIdleRunnable(nsIRunnable* aRunnable) {
   if (!sPendingIdleRunnables) {
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -410,18 +410,18 @@ class nsRefreshDriver final : public moz
   static mozilla::TimeStamp GetIdleDeadlineHint(mozilla::TimeStamp aDefault);
 
   /**
    * It returns the expected timestamp of the next tick or nothing if the next
    * tick is missed.
    */
   static mozilla::Maybe<mozilla::TimeStamp> GetNextTickHint();
 
-  static void DispatchIdleRunnableAfterTick(nsIRunnable* aRunnable,
-                                            uint32_t aDelay);
+  static void DispatchIdleRunnableAfterTickUnlessExists(nsIRunnable* aRunnable,
+                                                        uint32_t aDelay);
   static void CancelIdleRunnable(nsIRunnable* aRunnable);
 
   void NotifyDOMContentLoaded();
 
   // Schedule a refresh so that any delayed events will run soon.
   void RunDelayedEventsSoon();
 
   void InitializeTimer() {
--- a/xpcom/threads/IdleTaskRunner.cpp
+++ b/xpcom/threads/IdleTaskRunner.cpp
@@ -114,17 +114,17 @@ void IdleTaskRunner::Schedule(bool aAllo
     return;
   }
 
   mDeadline = TimeStamp();
   TimeStamp now = TimeStamp::Now();
   TimeStamp hint = nsRefreshDriver::GetIdleDeadlineHint(now);
   if (hint != now) {
     // RefreshDriver is ticking, let it schedule the idle dispatch.
-    nsRefreshDriver::DispatchIdleRunnableAfterTick(this, mDelay);
+    nsRefreshDriver::DispatchIdleRunnableAfterTickUnlessExists(this, mDelay);
     // Ensure we get called at some point, even if RefreshDriver is stopped.
     SetTimerInternal(mDelay);
   } else {
     // RefreshDriver doesn't seem to be running.
     if (aAllowIdleDispatch) {
       nsCOMPtr<nsIRunnable> runnable = this;
       SetTimerInternal(mDelay);
       NS_DispatchToCurrentThreadQueue(runnable.forget(),