Bug 1422057 - Deduplicate DisplayItemClipChain instances on creation. r?mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Sat, 06 Jan 2018 09:52:58 -0500
changeset 716818 667637f3cde67ad6a5f374d3347944c33c33e01f
parent 716817 2c7e515618faefdfcfa88f472960b99cb82e6aa1
child 716819 6e4c39178689687f0e9145cd3674e2d2cdd42b56
push id94505
push userkgupta@mozilla.com
push dateSat, 06 Jan 2018 16:27:17 +0000
reviewersmstange
bugs1422057
milestone59.0a1
Bug 1422057 - Deduplicate DisplayItemClipChain instances on creation. r?mstange MozReview-Commit-ID: Fdr0m0uKxKR
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1432,16 +1432,17 @@ nsDisplayListBuilder::FreeClipChains()
   // 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) {
+      mClipDeduplicator.erase(clip);
       it = mClipChainsToDestroy.erase(it);
       clip->DisplayItemClipChain::~DisplayItemClipChain();
       Destroy(DisplayItemType::TYPE_ZERO, clip);
     } else {
       ++it;
     }
   }
 }
@@ -1591,16 +1592,27 @@ 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);
+  auto result = mClipDeduplicator.insert(c);
+  if (!result.second) {
+    // An equivalent clip chain item was already created, so let's return that
+    // instead. Destroy the one we just created.
+    // Note that this can cause clip chains from different coordinate systems to
+    // collapse into the same clip chain object, because clip chains do not keep
+    // track of the reference frame that they were created in.
+    c->DisplayItemClipChain::~DisplayItemClipChain();
+    Destroy(DisplayItemType::TYPE_ZERO, c);
+    return *(result.first);
+  }
   mClipChainsToDestroy.emplace_front(c);
   return c;
 }
 
 struct ClipChainItem {
   DisplayItemClip clip;
   const ActiveScrolledRoot* asr;
 };
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -24,16 +24,17 @@
 #include "mozilla/Maybe.h"
 #include "mozilla/TemplateLib.h" // mozilla::tl::Max
 #include "nsCOMPtr.h"
 #include "nsContainerFrame.h"
 #include "nsPoint.h"
 #include "nsRect.h"
 #include "nsRegion.h"
 #include "nsDisplayListInvalidation.h"
+#include "DisplayItemClipChain.h"
 #include "DisplayListClipState.h"
 #include "LayerState.h"
 #include "FrameMetrics.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/gfx/UserData.h"
@@ -413,16 +414,18 @@ class nsDisplayListBuilder {
    *            to AGR_YES without restyling is possible.
    */
   enum AGRState { AGR_NO, AGR_YES, AGR_MAYBE };
 
 public:
   typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
   typedef mozilla::DisplayItemClip DisplayItemClip;
   typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
+  typedef mozilla::DisplayItemClipChainHasher DisplayItemClipChainHasher;
+  typedef mozilla::DisplayItemClipChainEqualer DisplayItemClipChainEqualer;
   typedef mozilla::DisplayListClipState DisplayListClipState;
   typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
   typedef nsIWidget::ThemeGeometry ThemeGeometry;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef mozilla::layers::FrameMetrics::ViewID ViewID;
   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
 
@@ -1843,16 +1846,20 @@ 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;
+  std::unordered_set<
+    const DisplayItemClipChain*,
+    DisplayItemClipChainHasher,
+    DisplayItemClipChainEqualer> mClipDeduplicator;
   std::list<DisplayItemClipChain*> mClipChainsToDestroy;
   nsTArray<nsDisplayItem*> mTemporaryItems;
   const ActiveScrolledRoot*      mActiveScrolledRootForRootScrollframe;
   nsDisplayListBuilderMode       mMode;
   ViewID                         mCurrentScrollParentId;
   ViewID                         mCurrentScrollbarTarget;
   nsDisplayOwnLayerFlags         mCurrentScrollbarFlags;
   Preserves3DContext             mPreserves3DCtx;