Bug 832611 - Use NotifyDestroyingFrame to remove frames from the OverflowChangedTracker. r=roc a=akeybl
authorMatt Woodrow <mwoodrow@mozilla.com>
Sat, 26 Jan 2013 14:34:58 +1300
changeset 127359 34e17e7cafd557cae15b80b69d889386cfb90984
parent 127358 8c1ae6ca956a638a064327f9ee967841f91ff423
child 127360 2869cb7fdf8eb12ff9dca620d519b3794f69011c
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, akeybl
bugs832611
milestone20.0a2
Bug 832611 - Use NotifyDestroyingFrame to remove frames from the OverflowChangedTracker. r=roc a=akeybl
layout/base/RestyleTracker.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -44,39 +44,22 @@ public:
    */
   void AddFrame(nsIFrame* aFrame) {
     if (!mEntryList.contains(Entry(aFrame, true))) {
       mEntryList.insert(new Entry(aFrame, true));
     }
   }
 
   /**
-   * Remove a frame and all descendants of that frame.
+   * Remove a frame.
    */
-  void RemoveFrameAndDescendants(nsIFrame* aFrame) {
+  void RemoveFrame(nsIFrame* aFrame) {
     if (mEntryList.contains(Entry(aFrame, 0, false))) {
       delete mEntryList.remove(Entry(aFrame, 0, false));
     }
-    if (mEntryList.empty()) {
-      return;
-    }
-
-    nsAutoTArray<nsIFrame::ChildList,4> childListArray;
-    aFrame->GetCrossDocChildLists(&childListArray);
-
-    nsIFrame::ChildListArrayIterator lists(childListArray);
-    for (; !lists.IsDone(); lists.Next()) {
-      nsFrameList::Enumerator childFrames(lists.CurrentList());
-      for (; !childFrames.AtEnd(); childFrames.Next()) {
-        RemoveFrameAndDescendants(childFrames.get());
-        if (mEntryList.empty()) {
-          return;
-        }
-      }
-    }
   }
 
   /**
    * Update the overflow of all added frames, and clear the entry list.
    *
    * Start from those deepest in the frame tree and works upwards. This stops 
    * us from processing the same frame twice.
    */
@@ -133,36 +116,29 @@ private:
     {}
 
     bool operator==(const Entry& aOther) const
     {
       return mFrame == aOther.mFrame;
     }
  
     /**
-     * Sort by the depth in the frame tree, and then
-     * the frame pointer.
+     * Sort by the frame pointer.
      */
     bool operator<(const Entry& aOther) const
     {
-      if (mDepth != aOther.mDepth) {
-        // nsTPriorityQueue implements a min-heap and we
-        // want the highest depth first, so reverse this check.
-        return mDepth > aOther.mDepth;
-      }
-
       return mFrame < aOther.mFrame;
     }
 
     static int compare(const Entry& aOne, const Entry& aTwo)
     {
-      if (aOne < aTwo) {
+      if (aOne == aTwo) {
+        return 0;
+      } else if (aOne < aTwo) {
         return -1;
-      } else if (aOne == aTwo) {
-        return 0;
       } else {
         return 1;
       }
     }
 
     nsIFrame* mFrame;
     /* Depth in the frame tree */
     uint32_t mDepth;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1396,16 +1396,17 @@ 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();
@@ -1475,16 +1476,20 @@ 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);
+  }
+
   nsFrameManager::NotifyDestroyingFrame(aFrame);
 }
 
 struct nsGenConInitializer {
   nsAutoPtr<nsGenConNode> mNode;
   nsGenConList*           mList;
   void (nsCSSFrameConstructor::*mDirtyAll)();
   
@@ -8075,16 +8080,20 @@ nsCSSFrameConstructor::ProcessRestyledFr
   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.
@@ -8159,19 +8168,16 @@ nsCSSFrameConstructor::ProcessRestyledFr
     }
     if (hint & nsChangeHint_ReconstructFrame) {
       // If we ever start passing true here, be careful of restyles
       // that involve a reframe and animations.  In particular, if the
       // restyle we're processing here is an animation restyle, but
       // the style resolution we will do for the frame construction
       // happens async when we're not in an animation restyle already,
       // problems could arise.
-      if (content->GetPrimaryFrame()) {
-        aTracker.RemoveFrameAndDescendants(content->GetPrimaryFrame());
-      }
       RecreateFramesForContent(content, false);
     } else {
       NS_ASSERTION(frame, "This shouldn't happen");
 
       if ((frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
           (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
         // frame does not maintain overflow rects, so avoid calling
         // FinishAndStoreOverflow on it:
@@ -8263,16 +8269,17 @@ 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,
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -302,16 +302,25 @@ 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)
+  {
+    mOverflowChangedTracker = aTracker;    
+  }
+
 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
    *                      on them.
    * @param aMinChangeHint: A minimum change hint for aContent and its
@@ -1886,16 +1895,18 @@ 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;
+
   // 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;
 };