Bug 1340340 - Stop mutating nsRefreshDriver during parallel traversal. r=heycam
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Mon, 20 Feb 2017 14:37:13 +0900
changeset 372886 916e7ba3cd2b48f8a99f8093a20e455acd51d58f
parent 372885 0ba503d21240d295df9fc5a66b50af91fd1b9264
child 372887 48ea57cefa172ef8b67817eb1bd64b67ff4f0c66
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1340340
milestone54.0a1
Bug 1340340 - Stop mutating nsRefreshDriver during parallel traversal. r=heycam MozReview-Commit-ID: D5VYPWXm5jO
layout/base/ServoRestyleManager.cpp
layout/base/nsRefreshDriver.cpp
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/ServoRestyleManager.h"
 
 #include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsPrintfCString.h"
+#include "nsRefreshDriver.h"
 #include "nsStyleChangeList.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 ServoRestyleManager::ServoRestyleManager(nsPresContext* aPresContext)
   : RestyleManager(StyleBackendType::Servo, aPresContext)
@@ -361,16 +362,20 @@ ServoRestyleManager::ProcessPendingResty
   // Create a AnimationsWithDestroyedFrame during restyling process to
   // stop animations and transitions on elements that have no frame at the end
   // of the restyling process.
   AnimationsWithDestroyedFrame animationsWithDestroyedFrame(this);
 
   ServoStyleSet* styleSet = StyleSet();
   nsIDocument* doc = PresContext()->Document();
 
+  // Ensure the refresh driver is active during traversal to avoid mutating
+  // mActiveTimer and mMostRecentRefresh time.
+  PresContext()->RefreshDriver()->MostRecentRefresh();
+
   mInStyleRefresh = true;
 
   // Perform the Servo traversal, and the post-traversal if required.
   if (styleSet->StyleDocument()) {
 
     PresContext()->EffectCompositor()->ClearElementsToRestyle();
 
     // First do any queued-up frame creation. (see bugs 827239 and 997506).
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1233,17 +1233,21 @@ nsRefreshDriver::RestoreNormalRefresh()
   mTestControllingRefreshes = false;
   EnsureTimerStarted(eAllowTimeToGoBackwards);
   mCompletedTransaction = mPendingTransaction;
 }
 
 TimeStamp
 nsRefreshDriver::MostRecentRefresh() const
 {
-  const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted();
+  // In case of stylo traversal, we have already activated the refresh driver in
+  // ServoRestyleManager::ProcessPendingRestyles().
+  if (!ServoStyleSet::IsInServoTraversal()) {
+    const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted();
+  }
 
   return mMostRecentRefresh;
 }
 
 int64_t
 nsRefreshDriver::MostRecentRefreshEpochTime() const
 {
   const_cast<nsRefreshDriver*>(this)->EnsureTimerStarted();
@@ -1316,16 +1320,20 @@ nsRefreshDriver::RemoveImageRequest(imgI
       start->mEntries.RemoveEntry(aRequest);
     }
   }
 }
 
 void
 nsRefreshDriver::EnsureTimerStarted(EnsureTimerStartedFlags aFlags)
 {
+  MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal(),
+             "EnsureTimerStarted should be called only when we are not "
+             "in servo traversal");
+
   if (mTestControllingRefreshes)
     return;
 
   // will it already fire, and no other changes needed?
   if (mActiveTimer && !(aFlags & eForceAdjustTimer))
     return;
 
   if (IsFrozen() || !mPresContext) {