Bug 1180118 - Part 11: Use ReparentStyleContext even if eRestyle_SomeDescendants is used. r=bzbarsky
authorCameron McCormack <cam@mcc.id.au>
Wed, 05 Aug 2015 22:42:21 +1000
changeset 287966 6f97ff142c890acb5f5c722d824315a7f475fa37
parent 287965 68bef2d8c8bfd412a5831896fa523ecbcc19266c
child 287967 685014edb54e3421439ef30630932ba9c3e2ab2d
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 11: Use ReparentStyleContext even if eRestyle_SomeDescendants is used. r=bzbarsky
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -3249,16 +3249,30 @@ bool
 ElementRestyler::MustRestyleSelf(nsRestyleHint aRestyleHint,
                                  Element* aElement)
 {
   return (aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) ||
          ((aRestyleHint & eRestyle_SomeDescendants) &&
           SelectorMatchesForRestyle(aElement));
 }
 
+bool
+ElementRestyler::CanReparentStyleContext(nsRestyleHint aRestyleHint)
+{
+  // If we had any restyle hints other than the ones listed below,
+  // which don't control whether the current frame/element needs
+  // a new style context by looking up a new rule node, or if
+  // we are reconstructing the entire rule tree, then we can't
+  // use ReparentStyleContext.
+  return !(aRestyleHint & ~(eRestyle_Force |
+                            eRestyle_ForceDescendants |
+                            eRestyle_SomeDescendants)) &&
+         !mPresContext->StyleSet()->IsInRuleTreeReconstruct();
+}
+
 ElementRestyler::RestyleResult
 ElementRestyler::RestyleSelf(nsIFrame* aSelf,
                              nsRestyleHint aRestyleHint,
                              uint32_t* aSwappedStructs)
 {
   MOZ_ASSERT(!(aRestyleHint & eRestyle_LaterSiblings),
              "eRestyle_LaterSiblings must not be part of aRestyleHint");
 
@@ -3360,18 +3374,17 @@ ElementRestyler::RestyleSelf(nsIFrame* a
   else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
     NS_ASSERTION(aSelf->GetContent(),
                  "non pseudo-element frame without content node");
     newContext = styleSet->ResolveStyleForNonElement(parentContext);
   }
   else {
     Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
     if (!MustRestyleSelf(aRestyleHint, element)) {
-      if (!(aRestyleHint & ~(eRestyle_Force | eRestyle_ForceDescendants)) &&
-          !styleSet->IsInRuleTreeReconstruct()) {
+      if (CanReparentStyleContext(aRestyleHint)) {
         LOG_RESTYLE("reparenting style context");
         newContext =
           styleSet->ReparentStyleContext(oldContext, parentContext, element);
       } else {
         // Use ResolveStyleWithReplacement either for actual replacements
         // or, with no replacements, as a substitute for
         // ReparentStyleContext that rebuilds the path in the rule tree
         // rather than reusing the rule node, as we need to do during a
@@ -3634,34 +3647,34 @@ ElementRestyler::RestyleSelf(nsIFrame* a
     const nsCSSPseudoElements::Type extraPseudoType =
       oldExtraContext->GetPseudoType();
     NS_ASSERTION(extraPseudoTag &&
                  extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
                  "extra style context is not pseudo element");
     Element* element = extraPseudoType != nsCSSPseudoElements::ePseudo_AnonBox
                          ? mContent->AsElement() : nullptr;
     if (!MustRestyleSelf(aRestyleHint, element)) {
-      if (styleSet->IsInRuleTreeReconstruct()) {
+      if (CanReparentStyleContext(aRestyleHint)) {
+        newExtraContext =
+          styleSet->ReparentStyleContext(oldExtraContext, newContext, element);
+      } else {
         // Use ResolveStyleWithReplacement as a substitute for
         // ReparentStyleContext that rebuilds the path in the rule tree
         // rather than reusing the rule node, as we need to do during a
         // rule tree reconstruct.
         Element* pseudoElement =
           PseudoElementForStyleContext(aSelf, extraPseudoType);
         MOZ_ASSERT(!element || element != pseudoElement,
                    "pseudo-element for selector matching should be "
                    "the anonymous content node that we create, "
                    "not the real element");
         newExtraContext =
           styleSet->ResolveStyleWithReplacement(element, pseudoElement,
                                                 newContext, oldExtraContext,
                                                 nsRestyleHint(0));
-      } else {
-        newExtraContext =
-          styleSet->ReparentStyleContext(oldExtraContext, newContext, element);
       }
     } else if (extraPseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
       newExtraContext = styleSet->ResolveAnonymousBoxStyle(extraPseudoTag,
                                                            newContext);
     } else {
       // Don't expect XUL tree stuff here, since it needs a comparator and
       // all.
       NS_ASSERTION(extraPseudoType <
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -655,16 +655,26 @@ private:
    * Specifically, this will return true when eRestyle_Self or
    * eRestyle_Subtree is present, or if eRestyle_SomeDescendants is
    * present and the specified element matches one of the selectors in
    * mSelectorsForDescendants.
    */
   bool MustRestyleSelf(nsRestyleHint aRestyleHint, Element* aElement);
 
   /**
+   * Returns true iff aRestyleHint indicates that we can call
+   * ReparentStyleContext rather than any other restyling method of
+   * nsStyleSet that looks up a new rule node, and if we are
+   * not in the process of reconstructing the whole rule tree.
+   * This is used to check whether it is appropriate to call
+   * ReparentStyleContext.
+   */
+  bool CanReparentStyleContext(nsRestyleHint aRestyleHint);
+
+  /**
    * Helpers for Restyle().
    */
   void AddLayerChangesForAnimation();
 
   /**
    * Helpers for RestyleSelf().
    */
   void CaptureChange(nsStyleContext* aOldContext,