Bug 1180118 - Part 8: Keep track of the closest restyle root in AddPendingRestylesForDescendantsMatchingSelectors. r=bzbarsky
☠☠ backed out by 01576b408ea7 ☠ ☠
authorCameron McCormack <cam@mcc.id.au>
Tue, 04 Aug 2015 17:27:53 +1000
changeset 287742 37493f6eef20c1dbf6d6c042a609474e93e1d996
parent 287741 b7ec8d4d2d7ec81147f6c37d536693a722c8f10b
child 287743 9b41cd9f2bc5822f27f287f515d8fd16a4d3af6e
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1180118
milestone42.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 1180118 - Part 8: Keep track of the closest restyle root in AddPendingRestylesForDescendantsMatchingSelectors. r=bzbarsky
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -2758,46 +2758,51 @@ private:
  * cases, when we come to restyling this element back up in
  * ProcessPendingRestyles, we will again find the eRestyle_SomeDescendants
  * hint and its selectors array.
  *
  * This ensures that we don't visit descendant elements and check them
  * against mSelectorsForDescendants more than once.
  */
 void
-ElementRestyler::AddPendingRestylesForDescendantsMatchingSelectors(Element* aElement)
+ElementRestyler::AddPendingRestylesForDescendantsMatchingSelectors(
+    Element* aElement,
+    Element* aRestyleRoot)
 {
+  if (aElement->HasFlag(mRestyleTracker.RootBit())) {
+    aRestyleRoot = aElement;
+  }
+
   if (mRestyleTracker.HasRestyleData(aElement)) {
     nsRestyleHint rshint = eRestyle_SomeDescendants;
     if (SelectorMatchesForRestyle(aElement)) {
       rshint |= eRestyle_Self;
     }
-    // XXX Traversing up the tree in AddPendingRestyle can be wasteful,
-    // as we can do this multiple times for descendants of the element
-    // we stopped restyling at, up in Restyle().  We should track the
-    // current restyle root as we traverse down here to avoid that.
     RestyleHintData data;
     data.mSelectorsForDescendants = mSelectorsForDescendants;
-    mRestyleTracker.AddPendingRestyle(aElement, rshint, nsChangeHint(0), &data);
+    mRestyleTracker.AddPendingRestyle(aElement, rshint, nsChangeHint(0), &data,
+                                      Some(aRestyleRoot));
     return;
   }
 
   if (SelectorMatchesForRestyle(aElement)) {
     RestyleHintData data;
     data.mSelectorsForDescendants = mSelectorsForDescendants;
     mRestyleTracker.AddPendingRestyle(aElement,
                                       eRestyle_Self | eRestyle_SomeDescendants,
-                                      nsChangeHint(0), &data);
+                                      nsChangeHint(0), &data,
+                                      Some(aRestyleRoot));
     return;
   }
 
   FlattenedChildIterator it(aElement);
   for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
     if (n->IsElement()) {
-      AddPendingRestylesForDescendantsMatchingSelectors(n->AsElement());
+      AddPendingRestylesForDescendantsMatchingSelectors(n->AsElement(),
+                                                        aRestyleRoot);
     }
   }
 }
 
 /**
  * Recompute style for mFrame (which should not have a prev continuation
  * with the same style), all of its next continuations with the same
  * style, and all ib-split siblings of the same type (either block or
@@ -2980,20 +2985,23 @@ ElementRestyler::Restyle(nsRestyleHint a
       SendAccessibilityNotifications();
     }
 
     mRestyleTracker.AddRestyleRootsIfAwaitingRestyle(descendants);
 
     if (mContent->IsElement()) {
       if ((aRestyleHint & eRestyle_SomeDescendants) &&
           !mSelectorsForDescendants.IsEmpty()) {
-        FlattenedChildIterator it(mContent->AsElement());
+        Element* element = mContent->AsElement();
+        Element* restyleRoot = mRestyleTracker.FindClosestRestyleRoot(element);
+        FlattenedChildIterator it(element);
         for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
           if (n->IsElement()) {
-            AddPendingRestylesForDescendantsMatchingSelectors(n->AsElement());
+            AddPendingRestylesForDescendantsMatchingSelectors(n->AsElement(),
+                                                              restyleRoot);
           }
         }
       }
     }
     return;
   }
 
   if (!swappedStructs) {
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -710,17 +710,18 @@ private:
   };
 
   enum A11yNotificationType {
     eDontNotify,
     eNotifyShown,
     eNotifyHidden
   };
 
-  void AddPendingRestylesForDescendantsMatchingSelectors(Element* aElement);
+  void AddPendingRestylesForDescendantsMatchingSelectors(Element* aElement,
+                                                         Element* aRestyleRoot);
 
 #ifdef RESTYLE_LOGGING
   int32_t& LoggingDepth() { return mLoggingDepth; }
 #endif
 
 #ifdef DEBUG
   static nsCString RestyleResultToString(RestyleResult aRestyleResult);
 #endif