Bug 898209 patch 6: Create and use ElementRestyler::mParentContent and mContent. r=heycam
authorL. David Baron <dbaron@dbaron.org>
Tue, 30 Jul 2013 17:36:09 -0700
changeset 152935 5cfd498adf3366c52effc117844ace55c14e8348
parent 152934 38528a20bcf49ab54734ee0cda2fb6bb02ecab52
child 152936 a6ee9b412a8b0c41c36dad59285e15ee76a808a0
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs898209
milestone25.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 898209 patch 6: Create and use ElementRestyler::mParentContent and mContent. r=heycam
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1909,103 +1909,113 @@ RestyleManager::ReparentStyleContext(nsI
   return NS_OK;
 }
 
 ElementRestyler::ElementRestyler(nsPresContext* aPresContext,
                                  nsIFrame* aFrame,
                                  nsChangeHint aHintsHandledByAncestors)
   : mPresContext(aPresContext)
   , mFrame(aFrame)
+  , mParentContent(nullptr)
+    // XXXldb Why does it make sense to use aParentContent?  (See
+    // comment above assertion at start of ElementRestyler::Restyle.)
+  , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
   , mHintsHandled(NS_SubtractHint(aHintsHandledByAncestors,
                   NS_HintsNotHandledForDescendantsIn(aHintsHandledByAncestors)))
 {
 }
 
 ElementRestyler::ElementRestyler(const ElementRestyler& aParentRestyler,
                                  nsIFrame* aFrame)
   : mPresContext(aParentRestyler.mPresContext)
   , mFrame(aFrame)
+  , mParentContent(aParentRestyler.mContent)
+    // XXXldb Why does it make sense to use aParentContent?  (See
+    // comment above assertion at start of ElementRestyler::Restyle.)
+  , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
   , mHintsHandled(NS_SubtractHint(aParentRestyler.mHintsHandled,
                   NS_HintsNotHandledForDescendantsIn(aParentRestyler.mHintsHandled)))
 {
 }
 
 ElementRestyler::ElementRestyler(ParentContextFromChildFrame,
                                  const ElementRestyler& aParentRestyler,
                                  nsIFrame* aFrame)
   : mPresContext(aParentRestyler.mPresContext)
   , mFrame(aFrame)
+  , mParentContent(aParentRestyler.mParentContent)
+    // XXXldb Why does it make sense to use aParentContent?  (See
+    // comment above assertion at start of ElementRestyler::Restyle.)
+  , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
   , mHintsHandled(NS_SubtractHint(aParentRestyler.mHintsHandled,
                   NS_HintsNotHandledForDescendantsIn(aParentRestyler.mHintsHandled)))
 {
 }
 
 void
 ElementRestyler::CaptureChange(nsStyleContext* aOldContext,
                                nsStyleContext* aNewContext,
-                               nsIContent* aContent,
                                nsStyleChangeList* aChangeList,
                                /*in*/nsChangeHint aParentHintsNotHandledForDescendants,
                                /*out*/nsChangeHint &aHintsNotHandledForDescendants,
                                nsChangeHint aChangeToAssume)
 {
   nsChangeHint ourChange = aOldContext->CalcStyleDifference(aNewContext,
                              aParentHintsNotHandledForDescendants);
   NS_ASSERTION(!(ourChange & nsChangeHint_AllReflowHints) ||
                (ourChange & nsChangeHint_NeedReflow),
                "Reflow hint bits set without actually asking for a reflow");
 
   // nsChangeHint_UpdateEffects is inherited, but it can be set due to changes
   // in inherited properties (fill and stroke).  Avoid propagating it into
   // text nodes.
   if ((ourChange & nsChangeHint_UpdateEffects) &&
-      aContent && !aContent->IsElement()) {
+      mContent && !mContent->IsElement()) {
     ourChange = NS_SubtractHint(ourChange, nsChangeHint_UpdateEffects);
   }
 
   NS_UpdateHint(ourChange, aChangeToAssume);
   if (NS_UpdateHint(mHintsHandled, ourChange)) {
-    if (!(ourChange & nsChangeHint_ReconstructFrame) || aContent) {
-      aChangeList->AppendChange(mFrame, aContent, ourChange);
+    if (!(ourChange & nsChangeHint_ReconstructFrame) || mContent) {
+      aChangeList->AppendChange(mFrame, mContent, ourChange);
     }
   }
   aHintsNotHandledForDescendants = NS_HintsNotHandledForDescendantsIn(ourChange);
 }
 
 /**
  * Recompute style for mFrame and accumulate changes into aChangeList
  * given that mHintsHandled is already accumulated for an ancestor.
- * aParentContent is the content node used to resolve the parent style
+ * mParentContent is the content node used to resolve the parent style
  * context.  This means that, for pseudo-elements, it is the content
  * that should be used for selector matching (rather than the fake
  * content node attached to the frame).
  *
  * For aParentFrameHintsNotHandledForDescendants, see
  * nsStyleContext::CalcStyleDifference.
  */
 void
-ElementRestyler::Restyle(nsIContent        *aParentContent,
-                         nsStyleChangeList *aChangeList,
+ElementRestyler::Restyle(nsStyleChangeList *aChangeList,
                          nsChangeHint       aParentFrameHintsNotHandledForDescendants,
                          nsRestyleHint      aRestyleHint,
                          RestyleTracker&    aRestyleTracker,
                          DesiredA11yNotifications aDesiredA11yNotifications,
                          nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
                          TreeMatchContext &aTreeMatchContext)
 {
   // It would be nice if we could make stronger assertions here; they
   // would let us simplify the ?: expressions below setting |content|
   // and |pseudoContent| in sensible ways as well as making what
   // |content| and |pseudoContent| mean, and their relationship to
   // |mFrame->GetContent()|, make more sense.  However, we can't,
   // because of frame trees like the one in
   // https://bugzilla.mozilla.org/show_bug.cgi?id=472353#c14 .  Once we
   // fix bug 242277 we should be able to make this make more sense.
-  NS_ASSERTION(mFrame->GetContent() || !aParentContent ||
-               !aParentContent->GetParent(),
+  NS_ASSERTION(mFrame->GetContent() || !mParentContent ||
+               !mParentContent->GetParent(),
                "frame must have content (unless at the top of the tree)");
   // XXXldb get new context from prev-in-flow if possible, to avoid
   // duplication.  (Or should we just let |GetContext| handle that?)
   // Getting the hint would be nice too, but that's harder.
 
   // XXXbryner we may be able to avoid some of the refcounting goop here.
   // We do need a reference to oldContext for the lifetime of this function, and it's possible
   // that the frame has the last reference to it, so AddRef it here.
@@ -2022,30 +2032,23 @@ ElementRestyler::Restyle(nsIContent     
 
 #ifdef ACCESSIBILITY
     bool wasFrameVisible = nsIPresShell::IsAccessibilityActive() ?
       oldContext->StyleVisibility()->IsVisible() : false;
 #endif
 
     nsIAtom* const pseudoTag = oldContext->GetPseudo();
     const nsCSSPseudoElements::Type pseudoType = oldContext->GetPseudoType();
-    // |content| is the node that we used for rule matching of
-    // normal elements (not pseudo-elements) and for which we generate
-    // framechange hints if we need them.
-    // XXXldb Why does it make sense to use aParentContent?  (See
-    // comment above assertion at start of function.)
-    nsIContent* content = mFrame->GetContent() ? mFrame->GetContent()
-                                               : aParentContent;
 
-    if (content && content->IsElement()) {
-      content->OwnerDoc()->FlushPendingLinkUpdates();
+    if (mContent && mContent->IsElement()) {
+      mContent->OwnerDoc()->FlushPendingLinkUpdates();
       RestyleTracker::RestyleData restyleData;
-      if (aRestyleTracker.GetRestyleData(content->AsElement(), &restyleData)) {
+      if (aRestyleTracker.GetRestyleData(mContent->AsElement(), &restyleData)) {
         if (NS_UpdateHint(mHintsHandled, restyleData.mChangeHint)) {
-          aChangeList->AppendChange(mFrame, content, restyleData.mChangeHint);
+          aChangeList->AppendChange(mFrame, mContent, restyleData.mChangeHint);
         }
         aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
       }
     }
 
     nsRestyleHint childRestyleHint = aRestyleHint;
 
     if (childRestyleHint == eRestyle_Self) {
@@ -2076,17 +2079,17 @@ ElementRestyler::Restyle(nsIContent     
       // applied to this frame, no matter what
       // nsStyleContext::CalcStyleDifference says. CalcStyleDifference
       // can't be trusted because it assumes any changes to the parent
       // style context provider will be automatically propagated to
       // the frame(s) with child style contexts.
 
       ElementRestyler providerRestyler(PARENT_CONTEXT_FROM_CHILD_FRAME,
                                        *this, providerFrame);
-      providerRestyler.Restyle(aParentContent, aChangeList,
+      providerRestyler.Restyle(aChangeList,
                                                    nsChangeHint_Hints_NotHandledForDescendants,
                                                    aRestyleHint,
                                                    aRestyleTracker,
                                                    aDesiredA11yNotifications,
                                                    aVisibleKidsOfHiddenElement,
                                                    aTreeMatchContext);
       assumeDifferenceHint = providerRestyler.HintsHandledForFrame();
 
@@ -2180,25 +2183,25 @@ ElementRestyler::Restyle(nsIContent     
       // processing prevContinuation.  So we don't know whether aRestyleHint
       // should really be 0 here or whether it should be eRestyle_Self.  Be
       // pessimistic and force an actual reresolve in that situation.  The good
       // news is that in the common case when prevContinuation is non-null we
       // just used prevContinuationContext anyway and aren't reaching this code
       // to start with.
       newContext =
         styleSet->ReparentStyleContext(oldContext, parentContext,
-                                       ElementForStyleContext(aParentContent,
+                                       ElementForStyleContext(mParentContent,
                                                               mFrame,
                                                               pseudoType));
     } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
       newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
                                                       parentContext);
     }
     else {
-      Element* element = ElementForStyleContext(aParentContent,
+      Element* element = ElementForStyleContext(mParentContent,
                                                 mFrame,
                                                 pseudoType);
       if (pseudoTag) {
         if (pseudoTag == nsCSSPseudoElements::before ||
             pseudoTag == nsCSSPseudoElements::after) {
           // XXX what other pseudos do we need to treat like this?
           newContext = styleSet->ProbePseudoElementStyle(element,
                                                          pseudoType,
@@ -2252,17 +2255,17 @@ ElementRestyler::Restyle(nsIContent     
       }
 
       if (newContext != oldContext) {
         if (!copyFromContinuation) {
           TryStartingTransition(mPresContext, mFrame->GetContent(),
                                 oldContext, &newContext);
         }
 
-        CaptureChange(oldContext, newContext, content, aChangeList,
+        CaptureChange(oldContext, newContext, aChangeList,
                       aParentFrameHintsNotHandledForDescendants,
                       nonInheritedHints, assumeDifferenceHint);
         if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
           // if frame gets regenerated, let it keep old context
           mFrame->SetStyleContext(newContext);
         }
       }
       oldContext->Release();
@@ -2292,24 +2295,24 @@ ElementRestyler::Restyle(nsIContent     
                                                                newContext);
         }
         else {
           // Don't expect XUL tree stuff here, since it needs a comparator and
           // all.
           NS_ASSERTION(extraPseudoType <
                          nsCSSPseudoElements::ePseudo_PseudoElementCount,
                        "Unexpected type");
-          newExtraContext = styleSet->ResolvePseudoElementStyle(content->AsElement(),
+          newExtraContext = styleSet->ResolvePseudoElementStyle(mContent->AsElement(),
                                                                 extraPseudoType,
                                                                 newContext);
         }
         if (newExtraContext) {
           if (oldExtraContext != newExtraContext) {
             nsChangeHint extraHintsNotHandledForDescendants = nsChangeHint(0);
-            CaptureChange(oldExtraContext, newExtraContext, content,
+            CaptureChange(oldExtraContext, newExtraContext,
                           aChangeList,
                           aParentFrameHintsNotHandledForDescendants,
                           extraHintsNotHandledForDescendants,
                           assumeDifferenceHint);
             NS_UpdateHint(nonInheritedHints, extraHintsNotHandledForDescendants);
             if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
               mFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
             }
@@ -2417,17 +2420,17 @@ ElementRestyler::Restyle(nsIContent     
           // Checking for a :before frame is cheaper than getting the
           // :before style context.
           if (!nsLayoutUtils::GetBeforeFrame(mFrame) &&
               nsLayoutUtils::HasPseudoStyle(mFrame->GetContent(), newContext,
                                             nsCSSPseudoElements::ePseudo_before,
                                             mPresContext)) {
             // Have to create the new :before frame
             NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-            aChangeList->AppendChange(mFrame, content,
+            aChangeList->AppendChange(mFrame, mContent,
                                       nsChangeHint_ReconstructFrame);
           }
         }
       }
     }
 
     // Check whether we might need to create a new ::after frame.
     // There's no need to do this if we're planning to reframe already
@@ -2449,17 +2452,17 @@ ElementRestyler::Restyle(nsIContent     
           // Getting the :after frame is more expensive than getting the pseudo
           // context, so get the pseudo context first.
           if (nsLayoutUtils::HasPseudoStyle(mFrame->GetContent(), newContext,
                                             nsCSSPseudoElements::ePseudo_after,
                                             mPresContext) &&
               !nsLayoutUtils::GetAfterFrame(mFrame)) {
             // have to create the new :after frame
             NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-            aChangeList->AppendChange(mFrame, content,
+            aChangeList->AppendChange(mFrame, mContent,
                                       nsChangeHint_ReconstructFrame);
           }
         }
       }
     }
 
     // There is no need to waste time crawling into a frame's children
     // on a frame change.  The act of reconstructing frames will force
@@ -2507,18 +2510,18 @@ ElementRestyler::Restyle(nsIContent     
       }
 #endif
 
       // now do children
       nsIFrame::ChildListIterator lists(mFrame);
       for (TreeMatchContext::AutoAncestorPusher
              pushAncestor(!lists.IsDone(),
                           aTreeMatchContext,
-                          content && content->IsElement() ? content->AsElement()
-                                                          : nullptr);
+                          mContent && mContent->IsElement()
+                            ? mContent->AsElement() : nullptr);
            !lists.IsDone(); lists.Next()) {
         nsFrameList::Enumerator childFrames(lists.CurrentList());
         for (; !childFrames.AtEnd(); childFrames.Next()) {
           nsIFrame* child = childFrames.get();
           if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
             // Get the parent of the child frame's content and check if it is a XBL
             // children element. Push the children element as an ancestor here because it does
             // not have a frame and would not otherwise be pushed as an ancestor.
@@ -2553,42 +2556,40 @@ ElementRestyler::Restyle(nsIContent     
 
               // |nsFrame::GetParentStyleContextFrame| checks being out
               // of flow so that this works correctly.
               do {
                 ElementRestyler oofRestyler(*this, outOfFlowFrame);
                 oofRestyler.mHintsHandled =
                   NS_SubtractHint(oofRestyler.mHintsHandled,
                                   nsChangeHint_AllReflowHints);
-                oofRestyler.Restyle(content, aChangeList,
+                oofRestyler.Restyle(aChangeList,
                                       nonInheritedHints,
                                       childRestyleHint,
                                       aRestyleTracker,
                                       kidsDesiredA11yNotification,
                                       aVisibleKidsOfHiddenElement,
                                       aTreeMatchContext);
               } while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
 
               // reresolve placeholder's context under the same parent
               // as the out-of-flow frame
               ElementRestyler phRestyler(*this, child);
-              phRestyler.Restyle(content,
-                                    aChangeList,
+              phRestyler.Restyle(aChangeList,
                                     nonInheritedHints,
                                     childRestyleHint,
                                     aRestyleTracker,
                                     kidsDesiredA11yNotification,
                                     aVisibleKidsOfHiddenElement,
                                     aTreeMatchContext);
             }
             else {  // regular child frame
               if (child != resolvedChild) {
                 ElementRestyler childRestyler(*this, child);
-                childRestyler.Restyle(content,
-                                      aChangeList,
+                childRestyler.Restyle(aChangeList,
                                       nonInheritedHints,
                                       childRestyleHint,
                                       aRestyleTracker,
                                       kidsDesiredA11yNotification,
                                       aVisibleKidsOfHiddenElement,
                                       aTreeMatchContext);
               }
             }
@@ -2666,18 +2667,17 @@ RestyleManager::ComputeStyleChangeFor(ns
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
   do {
     // Outer loop over special siblings
     do {
       // Inner loop over next-in-flows of the current frame
       ElementRestyler restyler(mPresContext, frame,
                                aMinChange);
 
-      restyler.Restyle(nullptr,
-                              aChangeList, nsChangeHint(0),
+      restyler.Restyle(aChangeList, nsChangeHint(0),
                               aRestyleDescendants ?
                                 eRestyle_Subtree : eRestyle_Self,
                               aRestyleTracker,
                               ElementRestyler::eSendAllNotifications,
                               visibleKidsOfHiddenElement,
                               treeMatchContext);
 
       if (restyler.HintsHandledForFrame() & nsChangeHint_ReconstructFrame) {
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -308,18 +308,17 @@ public:
    * Restyle our frame's element and its subtree.
    *
    * Use eRestyle_Self for the aRestyleHint argument to mean
    * "reresolve our style context but not kids", use eRestyle_Subtree
    * to mean "reresolve our style context and kids", and use
    * nsRestyleHint(0) to mean recompute a new style context for our
    * current parent and existing rulenode, and the same for kids.
    */
-  void Restyle(nsIContent        *aParentContent,
-               nsStyleChangeList *aChangeList,
+  void Restyle(nsStyleChangeList *aChangeList,
                nsChangeHint       aParentFrameHintsNotHandledForDescendants,
                nsRestyleHint      aRestyleHint,
                RestyleTracker&    aRestyleTracker,
                DesiredA11yNotifications aDesiredA11yNotifications,
                nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
                TreeMatchContext &aTreeMatchContext);
 
   /**
@@ -329,25 +328,29 @@ public:
    * method is intended to be called after Restyle, to find out what
    * hints have been handled for this frame.
    */
   nsChangeHint HintsHandledForFrame() { return mHintsHandled; }
 
 private:
   void CaptureChange(nsStyleContext* aOldContext,
                      nsStyleContext* aNewContext,
-                     nsIContent* aContent,
                      nsStyleChangeList* aChangeList,
                      /*in*/nsChangeHint aParentHintsNotHandledForDescendants,
                      /*out*/nsChangeHint &aHintsNotHandledForDescendants,
                      nsChangeHint aChangeToAssume);
 
 private:
   nsPresContext* const mPresContext;
   nsIFrame* const mFrame;
+  nsIContent* const mParentContent;
+  // |mContent| is the node that we used for rule matching of
+  // normal elements (not pseudo-elements) and for which we generate
+  // framechange hints if we need them.
+  nsIContent* const mContent;
   // We have already generated change list entries for hints listed in
   // mHintsHandled (initially it's those handled by ancestors, but by
   // the end of Restyle it is those handled for this frame as well).  We
   // need to generate a new change list entry for the frame when its
   // style comparision returns a hint other than one of these hints.
   nsChangeHint mHintsHandled;
 };