Bug 1343128 - Don't leave stale change hints and other restyle data hanging around in reconstructed subtrees. r=emilio
authorBobby Holley <bobbyholley@gmail.com>
Mon, 27 Feb 2017 18:29:28 -0800
changeset 374223 086f36cc278fe6f6cd4fa023dcda4b31950f1d5b
parent 374222 3e1458b66c24f63f4ae813b1602748e0953b47ab
child 374224 a9871ce99a2a9bb02864bd9d695543fae69b2f24
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)
reviewersemilio
bugs1343128
milestone54.0a1
Bug 1343128 - Don't leave stale change hints and other restyle data hanging around in reconstructed subtrees. r=emilio MozReview-Commit-ID: 4BIvC6lPUmF
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoRestyleManager.h"
 
 #include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoStyleSet.h"
+#include "mozilla/Unused.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsPrintfCString.h"
 #include "nsRefreshDriver.h"
 #include "nsStyleChangeList.h"
 
 using namespace mozilla::dom;
@@ -112,26 +113,32 @@ ServoRestyleManager::ClearServoDataFromS
     if (n->IsElement()) {
       ClearServoDataFromSubtree(n->AsElement());
     }
   }
 
   aElement->UnsetHasDirtyDescendantsForServo();
 }
 
-/* static */ void
-ServoRestyleManager::ClearDirtyDescendantsFromSubtree(Element* aElement)
+
+// Clears HasDirtyDescendants and RestyleData from all elements in the
+// subtree rooted at aElement.
+static void
+ClearRestyleStateFromSubtree(Element* aElement)
 {
-  StyleChildrenIterator it(aElement);
-  for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
-    if (n->IsElement()) {
-      ClearDirtyDescendantsFromSubtree(n->AsElement());
+  if (aElement->HasDirtyDescendantsForServo()) {
+    StyleChildrenIterator it(aElement);
+    for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
+      if (n->IsElement()) {
+        ClearRestyleStateFromSubtree(n->AsElement());
+      }
     }
   }
 
+  Unused << Servo_TakeChangeHint(aElement);
   aElement->UnsetHasDirtyDescendantsForServo();
 }
 
 static void
 UpdateStyleContextForTableWrapper(nsIFrame* aTableWrapper,
                                   nsStyleContext* aTableStyleContext,
                                   ServoStyleSet* aStyleSet)
 {
@@ -178,17 +185,17 @@ ServoRestyleManager::RecreateStyleContex
   }
 
   // If our change hint is reconstruct, we delegate to the frame constructor,
   // which consumes the new style and expects the old style to be on the frame.
   //
   // XXXbholley: We should teach the frame constructor how to clear the dirty
   // descendants bit to avoid the traversal here.
   if (changeHint & nsChangeHint_ReconstructFrame) {
-    ClearDirtyDescendantsFromSubtree(aElement);
+    ClearRestyleStateFromSubtree(aElement);
     return;
   }
 
   // TODO(emilio): We could avoid some refcount traffic here, specially in the
   // ServoComputedValues case, which uses atomic refcounting.
   //
   // Hold the old style context alive, because it could become a dangling
   // pointer during the replacement. In practice it's not a huge deal (on
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -87,22 +87,16 @@ public:
                                          nsIAtom* aPseudoTagOrNull);
 
   /**
    * Clears the ServoElementData and HasDirtyDescendants from all elements
    * in the subtree rooted at aElement.
    */
   static void ClearServoDataFromSubtree(Element* aElement);
 
-  /**
-   * Clears HasDirtyDescendants from all elements in the subtree rooted at
-   * aElement.
-   */
-  static void ClearDirtyDescendantsFromSubtree(Element* aElement);
-
 protected:
   ~ServoRestyleManager() override
   {
     MOZ_ASSERT(!mReentrantChanges);
   }
 
 private:
   /**