Bug 1404181 - Part 8: Add refcounting for clip chains. r?mstange draft
authorMatt Woodrow <mwoodrow@mozilla.com>, Miko Mynttinen <mikokm@gmail.com>, Timothy Nikkel <tnikkel@gmail.com>
Wed, 27 Sep 2017 17:10:16 +1300
changeset 684519 d0752e7c27fed49affd863f47293b0d26de7cb77
parent 684518 a606e05994158caabea55f01b782de6ebe8cc52c
child 684520 1dcb9d77444cfde6ee47613bdd3eed627b1a2808
push id85633
push usermwoodrow@mozilla.com
push dateSun, 22 Oct 2017 23:03:02 +0000
reviewersmstange
bugs1404181
milestone58.0a1
Bug 1404181 - Part 8: Add refcounting for clip chains. r?mstange MozReview-Commit-ID: 9CIwJZ7ssqC
layout/painting/DisplayItemClipChain.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/painting/DisplayItemClipChain.h
+++ b/layout/painting/DisplayItemClipChain.h
@@ -43,16 +43,33 @@ struct DisplayItemClipChain {
                                            const ActiveScrolledRoot* aASR);
 
   static bool Equal(const DisplayItemClipChain* aClip1, const DisplayItemClipChain* aClip2);
 
   static nsCString ToString(const DisplayItemClipChain* aClipChain);
 
   bool HasRoundedCorners() const;
 
+  void AddRef() {
+    mRefCount++;
+  }
+  void Release() {
+    MOZ_ASSERT(mRefCount > 0);
+    mRefCount--;
+  }
+
+  DisplayItemClipChain(const DisplayItemClip& aClip, const ActiveScrolledRoot* aASR, const DisplayItemClipChain* aParent)
+    : mClip(aClip)
+    , mASR(aASR)
+    , mParent(aParent)
+  {}
+
+  DisplayItemClipChain() {}
+
   DisplayItemClip mClip;
   const ActiveScrolledRoot* mASR;
-  const DisplayItemClipChain* mParent;
+  RefPtr<const DisplayItemClipChain> mParent;
+  mutable uint32_t mRefCount = 0;
 };
 
 } // namespace mozilla
 
 #endif /* DISPLAYITEMCLIPCHAIN_H_ */
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -987,16 +987,17 @@ nsDisplayListBuilder::BeginFrame()
   mSyncDecodeImages = false;
 }
 
 void
 nsDisplayListBuilder::EndFrame()
 {
   mFrameToAnimatedGeometryRootMap.Clear();
   mActiveScrolledRoots.Clear();
+  FreeClipChains();
 
   nsCSSRendering::EndFrameTreesLocked();
 }
 
 void
 nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
 {
   mFramesMarkedForDisplay.AppendElement(aFrame);
@@ -1344,16 +1345,37 @@ nsDisplayListBuilder::LeavePresShell(nsI
     }
     mIsInChromePresContext = pc->IsChrome();
   } else {
     mCurrentAGR = mRootAGR;
   }
 }
 
 void
+nsDisplayListBuilder::FreeClipChains()
+{
+  // Iterate the clip chains from newest to oldest (forward
+  // iteration), so that we destroy descendants first which
+  // will drop the ref count on their ancestors.
+  auto it = mClipChainsToDestroy.begin();
+
+  while(it != mClipChainsToDestroy.end()) {
+    DisplayItemClipChain* clip = *it;
+
+    if (!clip->mRefCount) {
+      it = mClipChainsToDestroy.erase(it);
+      clip->DisplayItemClipChain::~DisplayItemClipChain();
+      Destroy(DisplayItemType::TYPE_ZERO, clip);
+    } else {
+      ++it;
+    }
+  }
+}
+
+void
 nsDisplayListBuilder::ResetMarkedFramesForDisplayList()
 {
   // Unmark and pop off the frames marked for display in this pres shell.
   uint32_t firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
   for (uint32_t i = firstFrameForShell;
        i < mFramesMarkedForDisplay.Length(); ++i) {
     UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
   }
@@ -1442,18 +1464,18 @@ nsDisplayListBuilder::AllocateActiveScro
 }
 
 const DisplayItemClipChain*
 nsDisplayListBuilder::AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
                                                    const ActiveScrolledRoot* aASR,
                                                    const DisplayItemClipChain* aParent)
 {
   void* p = Allocate(sizeof(DisplayItemClipChain), DisplayItemType::TYPE_ZERO);
-  DisplayItemClipChain* c = new (KnownNotNull, p) DisplayItemClipChain{ aClip, aASR, aParent };
-  mClipChainsToDestroy.AppendElement(c);
+  DisplayItemClipChain* c = new (KnownNotNull, p) DisplayItemClipChain(aClip, aASR, aParent);
+  mClipChainsToDestroy.emplace_front(c);
   return c;
 }
 
 struct ClipChainItem {
   DisplayItemClip clip;
   const ActiveScrolledRoot* asr;
 };
 
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -776,16 +776,18 @@ public:
    * Indicates whether we should synchronously decode images. If true, we decode
    * and draw whatever image data has been loaded. If false, we just draw
    * whatever has already been decoded.
    */
   void SetSyncDecodeImages(bool aSyncDecodeImages) {
     mSyncDecodeImages = aSyncDecodeImages;
   }
 
+  void FreeClipChains();
+
   /**
    * Helper method to generate background painting flags based on the
    * information available in the display list builder. Currently only
    * accounts for mSyncDecodeImages.
    */
   uint32_t GetBackgroundPaintFlags();
 
   /**
@@ -1663,17 +1665,17 @@ private:
   nsDisplayItem*                 mGlassDisplayItem;
   // A temporary list that we append scroll info items to while building
   // display items for the contents of frames with SVG effects.
   // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
   // This is a pointer and not a real nsDisplayList value because the
   // nsDisplayList class is defined below this class, so we can't use it here.
   nsDisplayList*                 mScrollInfoItemsForHoisting;
   nsTArray<RefPtr<ActiveScrolledRoot>>  mActiveScrolledRoots;
-  AutoTArray<DisplayItemClipChain*, 128> mClipChainsToDestroy;
+  std::list<DisplayItemClipChain*> mClipChainsToDestroy;
   nsTArray<nsDisplayItem*> mTemporaryItems;
   const ActiveScrolledRoot*      mActiveScrolledRootForRootScrollframe;
   nsDisplayListBuilderMode       mMode;
   ViewID                         mCurrentScrollParentId;
   ViewID                         mCurrentScrollbarTarget;
   uint32_t                       mCurrentScrollbarFlags;
   Preserves3DContext             mPreserves3DCtx;
   uint32_t                       mPerspectiveItemIndex;
@@ -2487,17 +2489,17 @@ public:
 protected:
   nsDisplayItem() = delete;
 
   typedef bool (*PrefFunc)(void);
   bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
   bool CanUseAdvancedLayer(LayerManager* aManager) const;
 
   nsIFrame* mFrame;
-  const DisplayItemClipChain* mClipChain;
+  RefPtr<const DisplayItemClipChain> mClipChain;
   const DisplayItemClip* mClip;
   RefPtr<const ActiveScrolledRoot> mActiveScrolledRoot;
   // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
   const nsIFrame* mReferenceFrame;
   RefPtr<struct AnimatedGeometryRoot> mAnimatedGeometryRoot;
   // Result of ToReferenceFrame(mFrame), if mFrame is non-null
   nsPoint   mToReferenceFrame;
   // This is the rectangle that needs to be painted.
@@ -2511,17 +2513,17 @@ protected:
   bool      mDisableSubpixelAA;
 #ifdef MOZ_DUMP_PAINTING
   // True if this frame has been painted.
   bool      mPainted;
 #endif
 
   struct {
     nsRect mVisibleRect;
-    const DisplayItemClipChain* mClipChain;
+    RefPtr<const DisplayItemClipChain> mClipChain;
     const DisplayItemClip* mClip;
   } mState;
 };
 
 /**
  * Manages a singly-linked list of display list items.
  *
  * mSentinel is the sentinel list value, the first value in the null-terminated