Bug 840480. r=roc, a=lsblakk
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 20 Feb 2013 13:13:01 +1300
changeset 132205 d492919c068b61b1608d46db3fc380ed7220bb4f
parent 132204 8f571fa8ec14d315c1a9ff0aca71330fd303b2c8
child 132206 3429bb5e8954cd44b047e541604227c8e0f6c22e
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, lsblakk
bugs840480
milestone21.0a2
Bug 840480. r=roc, a=lsblakk
layout/base/RestyleTracker.cpp
layout/base/RestyleTracker.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsPresShell.cpp
layout/style/nsTransitionManager.cpp
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -104,53 +104,49 @@ CollectRestyles(nsISupports* aElement,
   *restyleArrayPtr = currentRestyle + 1;
 
   return PL_DHASH_NEXT;
 }
 
 inline void
 RestyleTracker::ProcessOneRestyle(Element* aElement,
                                   nsRestyleHint aRestyleHint,
-                                  nsChangeHint aChangeHint,
-                                  OverflowChangedTracker& aTracker)
+                                  nsChangeHint aChangeHint)
 {
   NS_PRECONDITION((aRestyleHint & eRestyle_LaterSiblings) == 0,
                   "Someone should have handled this before calling us");
   NS_PRECONDITION(Document(), "Must have a document");
   NS_PRECONDITION(aElement->GetCurrentDoc() == Document(),
                   "Element has unexpected document");
 
   nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
   if (aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) {
     mFrameConstructor->RestyleElement(aElement, primaryFrame, aChangeHint,
                                       *this,
-                                      (aRestyleHint & eRestyle_Subtree) != 0, 
-                                      aTracker);
+                                      (aRestyleHint & eRestyle_Subtree) != 0);
   } else if (aChangeHint &&
              (primaryFrame ||
               (aChangeHint & nsChangeHint_ReconstructFrame))) {
     // Don't need to recompute style; just apply the hint
     nsStyleChangeList changeList;
     changeList.AppendChange(primaryFrame, aElement, aChangeHint);
-    mFrameConstructor->ProcessRestyledFrames(changeList, aTracker);
+    mFrameConstructor->ProcessRestyledFrames(changeList);
   }
 }
 
 void
 RestyleTracker::DoProcessRestyles()
 {
   SAMPLE_LABEL("CSS", "ProcessRestyles");
   // Make sure to not rebuild quote or counter lists while we're
   // processing restyles
   mFrameConstructor->BeginUpdate();
 
   mFrameConstructor->mInStyleRefresh = true;
 
-  OverflowChangedTracker tracker;
-
   // loop so that we process any restyle events generated by processing
   while (mPendingRestyles.Count()) {
     if (mHaveLaterSiblingRestyles) {
       // Convert them to individual restyles on all the later siblings
       nsAutoTArray<nsRefPtr<Element>, RESTYLE_ARRAY_STACKSIZE> laterSiblingArr;
       LaterSiblingCollector siblingCollector = { this, &laterSiblingArr };
       mPendingRestyles.Enumerate(CollectLaterSiblings, &siblingCollector);
       for (uint32_t i = 0; i < laterSiblingArr.Length(); ++i) {
@@ -205,17 +201,17 @@ RestyleTracker::DoProcessRestyles()
         continue;
       }
 
       RestyleData data;
       if (!GetRestyleData(element, &data)) {
         continue;
       }
 
-      ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint, tracker);
+      ProcessOneRestyle(element, data.mRestyleHint, data.mChangeHint);
     }
 
     if (mHaveLaterSiblingRestyles) {
       // Keep processing restyles for now
       continue;
     }
 
     // Now we only have entries with change hints left.  To be safe in
@@ -234,23 +230,22 @@ RestyleTracker::DoProcessRestyles()
       // Clear the hashtable now that we don't need it anymore
       mPendingRestyles.Clear();
 
       for (RestyleEnumerateData* currentRestyle = restylesToProcess;
            currentRestyle != lastRestyle;
            ++currentRestyle) {
         ProcessOneRestyle(currentRestyle->mElement,
                           currentRestyle->mRestyleHint,
-                          currentRestyle->mChangeHint,
-                          tracker);
+                          currentRestyle->mChangeHint);
       }
     }
   }
 
-  tracker.Flush();
+  mFrameConstructor->FlushOverflowChangedTracker();
 
   // Set mInStyleRefresh to false now, since the EndUpdate call might
   // add more restyles.
   mFrameConstructor->mInStyleRefresh = false;
 
   mFrameConstructor->EndUpdate();
 
 #ifdef DEBUG
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -26,16 +26,21 @@ namespace css {
  * Helper class that collects a list of frames that need
  * UpdateOverflow() called on them, and coalesces them
  * to avoid walking up the same ancestor tree multiple times.
  */
 class OverflowChangedTracker
 {
 public:
 
+  ~OverflowChangedTracker()
+  {
+    NS_ASSERTION(mEntryList.empty(), "Need to flush before destroying!");
+  }
+
   /**
    * Add a frame that has had a style change, and needs its
    * overflow updated.
    *
    * If there are pre-transform overflow areas stored for this
    * frame, then we will call FinishAndStoreOverflow with those
    * areas instead of UpdateOverflow().
    *
@@ -242,18 +247,17 @@ public:
 private:
   /**
    * Handle a single mPendingRestyles entry.  aRestyleHint must not
    * include eRestyle_LaterSiblings; that needs to be dealt with
    * before calling this function.
    */
   inline void ProcessOneRestyle(Element* aElement,
                                 nsRestyleHint aRestyleHint,
-                                nsChangeHint aChangeHint,
-                                OverflowChangedTracker& aTracker);
+                                nsChangeHint aChangeHint);
 
   /**
    * The guts of our restyle processing.
    */
   void DoProcessRestyles();
 
   typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
   typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1432,17 +1432,16 @@ nsCSSFrameConstructor::nsCSSFrameConstru
   , mCountersDirty(false)
   , mIsDestroyingFrameTree(false)
   , mRebuildAllStyleData(false)
   , mHasRootAbsPosContainingBlock(false)
   , mObservingRefreshDriver(false)
   , mInStyleRefresh(false)
   , mHoverGeneration(0)
   , mRebuildAllExtraHint(nsChangeHint(0))
-  , mOverflowChangedTracker(nullptr)
   , mAnimationGeneration(0)
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT, this)
   , mPendingAnimationRestyles(ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
                               ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT, this)
 {
   // XXXbz this should be in Init() or something!
   mPendingRestyles.Init();
@@ -1512,19 +1511,17 @@ nsCSSFrameConstructor::NotifyDestroyingF
 
   if (mCounterManager.DestroyNodesFor(aFrame)) {
     // Technically we don't need to update anything if we destroyed only
     // USE nodes.  However, this is unlikely to happen in the real world
     // since USE nodes generally go along with INCREMENT nodes.
     CountersDirty();
   }
 
-  if (mOverflowChangedTracker) {
-    mOverflowChangedTracker->RemoveFrame(aFrame);
-  }
+  mOverflowChangedTracker.RemoveFrame(aFrame);
 
   nsFrameManager::NotifyDestroyingFrame(aFrame);
 }
 
 struct nsGenConInitializer {
   nsAutoPtr<nsGenConNode> mNode;
   nsGenConList*           mList;
   void (nsCSSFrameConstructor::*mDirtyAll)();
@@ -8196,31 +8193,26 @@ NeedToReframeForAddingOrRemovingTransfor
     if (FrameHasPositionedPlaceholderDescendants(f, positionMask)) {
       return true;
     }
   }
   return false;
 }
 
 nsresult
-nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList,
-                                             OverflowChangedTracker& aTracker)
+nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
   int32_t count = aChangeList.Count();
   if (!count)
     return NS_OK;
 
   SAMPLE_LABEL("CSS", "ProcessRestyledFrames");
 
-  MOZ_ASSERT(!GetOverflowChangedTracker(), 
-             "Can't have multiple overflow changed trackers!");
-  SetOverflowChangedTracker(&aTracker);
-
   // Make sure to not rebuild quote or counter lists while we're
   // processing restyles
   BeginUpdate();
 
   nsPresContext* presContext = mPresShell->GetPresContext();
   FramePropertyTable* propTable = presContext->PropertyTable();
 
   // Mark frames so that we skip frames that die along the way, bug 123049.
@@ -8341,30 +8333,30 @@ nsCSSFrameConstructor::ProcessRestyledFr
           nsIFrame* childFrame = hintFrame->GetFirstPrincipalChild();
           for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
             NS_ABORT_IF_FALSE(childFrame->IsFrameOfType(nsIFrame::eSVG),
                               "Not expecting non-SVG children");
             // If |childFrame| is dirty or has dirty children, we don't bother
             // updating overflows since that will happen when it's reflowed.
             if (!(childFrame->GetStateBits() &
                   (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
-              aTracker.AddFrame(childFrame);
+              mOverflowChangedTracker.AddFrame(childFrame);
             }
             NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrSpecialSibling(childFrame),
                          "SVG frames should not have continuations or special siblings");
             NS_ASSERTION(childFrame->GetParent() == hintFrame,
                          "SVG child frame not expected to have different parent");
           }
         }
         // If |frame| is dirty or has dirty children, we don't bother updating
         // overflows since that will happen when it's reflowed.
         if (!(frame->GetStateBits() &
               (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
           while (frame) {
-            aTracker.AddFrame(frame);
+            mOverflowChangedTracker.AddFrame(frame);
 
             frame =
               nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
           }
         }
       }
       if (hint & nsChangeHint_UpdateCursor) {
         mPresShell->SynthesizeMouseMove(false);
@@ -8396,28 +8388,26 @@ nsCSSFrameConstructor::ProcessRestyledFr
         }
       }
     } else {
       NS_WARNING("Unable to test style tree integrity -- no content node");
     }
 #endif
   }
 
-  SetOverflowChangedTracker(nullptr);
   aChangeList.Clear();
   return NS_OK;
 }
 
 void
 nsCSSFrameConstructor::RestyleElement(Element        *aElement,
                                       nsIFrame       *aPrimaryFrame,
                                       nsChangeHint   aMinHint,
                                       RestyleTracker& aRestyleTracker,
-                                      bool            aRestyleDescendants,
-                                      OverflowChangedTracker& aTracker)
+                                      bool            aRestyleDescendants)
 {
   NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
                "frame/content mismatch");
   if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
     // XXXbz this is due to image maps messing with the primary frame pointer
     // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
     aPrimaryFrame = nullptr;
   }
@@ -8445,17 +8435,17 @@ nsCSSFrameConstructor::RestyleElement(El
   }
 
   if (aMinHint & nsChangeHint_ReconstructFrame) {
     RecreateFramesForContent(aElement, false);
   } else if (aPrimaryFrame) {
     nsStyleChangeList changeList;
     ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
                           aRestyleTracker, aRestyleDescendants);
-    ProcessRestyledFrames(changeList, aTracker);
+    ProcessRestyledFrames(changeList);
   } else {
     // no frames, reconstruct for content
     MaybeRecreateFramesForElement(aElement);
   }
 }
 
 nsresult
 nsCSSFrameConstructor::ContentStateChanged(nsIContent* aContent,
@@ -12229,19 +12219,18 @@ nsCSSFrameConstructor::DoRebuildAllStyle
   nsStyleChangeList changeList;
   // XXX Does it matter that we're passing aExtraHint to the real root
   // frame and not the root node's primary frame?
   // Note: The restyle tracker we pass in here doesn't matter.
   ComputeStyleChangeFor(mPresShell->GetRootFrame(),
                         &changeList, aExtraHint,
                         aRestyleTracker, true);
   // Process the required changes
-  OverflowChangedTracker tracker;
-  ProcessRestyledFrames(changeList, tracker);
-  tracker.Flush();
+  ProcessRestyledFrames(changeList);
+  FlushOverflowChangedTracker();
 
   // Tell the style set it's safe to destroy the old rule tree.  We
   // must do this after the ProcessRestyledFrames call in case the
   // change list has frame reconstructs in it (since frames to be
   // reconstructed will still have their old style context pointers
   // until they are destroyed).
   mPresShell->StyleSet()->EndReconstruct();
 }
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -236,18 +236,17 @@ public:
   // track whether off-main-thread animations are up-to-date.
   uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
 
   // Note: It's the caller's responsibility to make sure to wrap a
   // ProcessRestyledFrames call in a view update batch and a script blocker.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
   // itself.
-  nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray,
-                                 OverflowChangedTracker& aTracker);
+  nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
 
 private:
 
   friend class mozilla::css::RestyleTracker;
 
   void RestyleForEmptyChange(Element* aContainer);
 
 public:
@@ -302,23 +301,19 @@ public:
   // See PostRestyleEventCommon below.
   void PostAnimationRestyleEvent(Element* aElement,
                                  nsRestyleHint aRestyleHint,
                                  nsChangeHint aMinChangeHint)
   {
     PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint, true);
   }
 
-  OverflowChangedTracker *GetOverflowChangedTracker() const 
-  { 
-    return mOverflowChangedTracker; 
-  }
-  void SetOverflowChangedTracker(OverflowChangedTracker *aTracker)
+  void FlushOverflowChangedTracker() 
   {
-    mOverflowChangedTracker = aTracker;    
+    mOverflowChangedTracker.Flush();
   }
 
 private:
   /**
    * Notify the frame constructor that an element needs to have its
    * style recomputed.
    * @param aElement: The element to be restyled.
    * @param aRestyleHint: Which nodes need to have selector matching run
@@ -401,18 +396,17 @@ private:
                               nsIFrame*&     aCanvasFrame);
 
   /* aMinHint is the minimal change that should be made to the element */
   // XXXbz do we really need the aPrimaryFrame argument here?
   void RestyleElement(Element* aElement,
                       nsIFrame*       aPrimaryFrame,
                       nsChangeHint    aMinHint,
                       RestyleTracker& aRestyleTracker,
-                      bool            aRestyleDescendants,
-                      OverflowChangedTracker& aTracker);
+                      bool            aRestyleDescendants);
 
   nsresult InitAndRestoreFrame (const nsFrameConstructorState& aState,
                                 nsIContent*                    aContent,
                                 nsIFrame*                      aParentFrame,
                                 nsIFrame*                      aPrevInFlow,
                                 nsIFrame*                      aNewFrame,
                                 bool                           aAllowCounters = true);
 
@@ -1909,17 +1903,17 @@ private:
   bool                mObservingRefreshDriver : 1;
   // True if we're in the middle of a nsRefreshDriver refresh
   bool                mInStyleRefresh : 1;
   uint32_t            mHoverGeneration;
   nsChangeHint        mRebuildAllExtraHint;
 
   nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
 
-  OverflowChangedTracker *mOverflowChangedTracker;
+  OverflowChangedTracker mOverflowChangedTracker;
 
   // The total number of animation flushes by this frame constructor.
   // Used to keep the layer and animation manager in sync.
   uint64_t mAnimationGeneration;
 
   RestyleTracker mPendingRestyles;
   RestyleTracker mPendingAnimationRestyles;
 };
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2729,19 +2729,18 @@ PresShell::RecreateFramesFor(nsIContent*
 
   nsAutoScriptBlocker scriptBlocker;
 
   nsStyleChangeList changeList;
   changeList.AppendChange(nullptr, aContent, nsChangeHint_ReconstructFrame);
 
   // Mark ourselves as not safe to flush while we're doing frame construction.
   ++mChangeNestCount;
-  css::OverflowChangedTracker tracker;
-  nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList, tracker);
-  tracker.Flush();
+  nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
+  mFrameConstructor->FlushOverflowChangedTracker();
   --mChangeNestCount;
   
   return rv;
 }
 
 void
 nsIPresShell::PostRecreateFramesFor(Element* aElement)
 {
@@ -7894,19 +7893,18 @@ PresShell::Observe(nsISupports* aSubject
         nsStyleChangeList changeList;
         WalkFramesThroughPlaceholders(mPresContext, rootFrame,
                                       ReframeImageBoxes, &changeList);
         // Mark ourselves as not safe to flush while we're doing frame
         // construction.
         {
           nsAutoScriptBlocker scriptBlocker;
           ++mChangeNestCount;
-          css::OverflowChangedTracker tracker;
-          mFrameConstructor->ProcessRestyledFrames(changeList, tracker);
-          tracker.Flush();
+          mFrameConstructor->ProcessRestyledFrames(changeList);
+          mFrameConstructor->FlushOverflowChangedTracker();
           --mChangeNestCount;
         }
       }
     }
     return NS_OK;
   }
 #endif
 
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -424,20 +424,20 @@ nsTransitionManager::UpdateAllThrottledS
     nsIFrame* primaryFrame;
     if (element &&
         (primaryFrame = element->GetPrimaryFrame())) {
       UpdateThrottledStylesForSubtree(element,
         primaryFrame->StyleContext()->GetParent(), changeList);
     }
   }
 
-  OverflowChangedTracker tracker;
   mPresContext->PresShell()->FrameConstructor()->
-    ProcessRestyledFrames(changeList, tracker);
-  tracker.Flush();
+    ProcessRestyledFrames(changeList);
+  mPresContext->PresShell()->FrameConstructor()->
+    FlushOverflowChangedTracker();
 }
 
 already_AddRefed<nsIStyleRule>
 nsTransitionManager::StyleContextChanged(dom::Element *aElement,
                                          nsStyleContext *aOldStyleContext,
                                          nsStyleContext *aNewStyleContext)
 {
   NS_PRECONDITION(aOldStyleContext->GetPseudo() ==