Bug 1404181 - Part 3: Track the current set of alive display items on nsIFrame. r?mstange draft
authorMatt Woodrow <mwoodrow@mozilla.com>, Miko Mynttinen <mikokm@gmail.com>, Timothy Nikkel <tnikkel@gmail.com>
Wed, 27 Sep 2017 15:35:29 +1300
changeset 684514 97dd15672281963c7b118418ab4ae9d2b915aa8b
parent 684513 3ab692cb96bb4f8638f3693fb3897ab0da462586
child 684515 825ee9dffd483d3439d613a199b3fe0de45c8ed8
push id85633
push usermwoodrow@mozilla.com
push dateSun, 22 Oct 2017 23:03:02 +0000
reviewersmstange
bugs1404181
milestone58.0a1
Bug 1404181 - Part 3: Track the current set of alive display items on nsIFrame. r?mstange MozReview-Commit-ID: BgB1XBMpJ8t
layout/base/PresShell.cpp
layout/base/nsLayoutUtils.cpp
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -2042,18 +2042,17 @@ PresShell::SetIgnoreFrameDestruction(boo
 }
 
 void
 PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
 {
   // We must remove these from FrameLayerBuilder::DisplayItemData::mFrameList here,
   // otherwise the DisplayItemData destructor will use the destroyed frame when it
   // tries to remove it from the (array) value of this property.
-  FrameLayerBuilder::RemoveFrameFromLayerManager(aFrame, aFrame->DisplayItemData());
-  aFrame->DisplayItemData().Clear();
+  aFrame->RemoveDisplayItemDataForDeletion();
 
   if (!mIgnoreFrameDestruction) {
     if (aFrame->HasImageRequest()) {
       mDocument->StyleImageLoader()->DropRequestsForFrame(aFrame);
     }
 
     mFrameConstructor->NotifyDestroyingFrame(aFrame);
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2972,17 +2972,17 @@ nsLayoutUtils::GetLayerTransformForFrame
                                nsDisplayListBuilderMode::TRANSFORM_COMPUTATION,
                                false/*don't build caret*/);
   builder.BeginFrame();
   nsDisplayList list(&builder);
   nsDisplayTransform* item =
     new (&builder) nsDisplayTransform(&builder, aFrame, &list, nsRect());
 
   *aTransform = item->GetTransform();
-  item->~nsDisplayTransform();
+  item->Destroy(&builder);
 
   builder.EndFrame();
 
   return true;
 }
 
 static bool
 TransformGfxPointFromAncestor(nsIFrame *aFrame,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -881,16 +881,74 @@ AddAndRemoveImageAssociations(nsFrame* a
   }
 
   CompareLayers(aNewLayers, aOldLayers,
     [&imageLoader, aFrame](imgRequestProxy* aReq)
     { imageLoader->AssociateRequestToFrame(aReq, aFrame); }
   );
 }
 
+void
+nsIFrame::AddDisplayItem(nsDisplayItem* aItem)
+{
+  DisplayItemArray* items = GetProperty(DisplayItems());
+  if (!items) {
+    items = new DisplayItemArray();
+    AddProperty(DisplayItems(), items);
+  }
+  MOZ_ASSERT(!items->Contains(aItem));
+  items->AppendElement(aItem);
+}
+
+bool
+nsIFrame::RemoveDisplayItem(nsDisplayItem* aItem)
+{
+  DisplayItemArray* items = GetProperty(DisplayItems());
+  if (!items) {
+    return false;
+  }
+  bool result = items->RemoveElement(aItem);
+  if (items->IsEmpty()) {
+    DeleteProperty(DisplayItems());
+  }
+  return result;
+}
+
+bool
+nsIFrame::HasDisplayItems()
+{
+  DisplayItemArray* items = GetProperty(DisplayItems());
+  return items != nullptr;
+}
+
+bool
+nsIFrame::HasDisplayItem(nsDisplayItem* aItem)
+{
+  DisplayItemArray* items = GetProperty(DisplayItems());
+  if (!items) {
+    return false;
+  }
+  return items->Contains(aItem);
+}
+
+void
+nsIFrame::RemoveDisplayItemDataForDeletion()
+{
+  FrameLayerBuilder::RemoveFrameFromLayerManager(this, DisplayItemData());
+  DisplayItemData().Clear();
+
+  DisplayItemArray* items = RemoveProperty(DisplayItems());
+  if (items) {
+    for (nsDisplayItem* item : *items) {
+      item->RemoveFrame(this);
+    }
+    delete items;
+  }
+}
+
 // Subclass hook for style post processing
 /* virtual */ void
 nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (nsSVGUtils::IsInSVGTextSubtree(this)) {
     SVGTextFrame* svgTextFrame = static_cast<SVGTextFrame*>(
       nsLayoutUtils::GetClosestFrameOfType(this, LayoutFrameType::SVGText));
     nsIFrame* anonBlock = svgTextFrame->PrincipalChildList().FirstChild();
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -71,16 +71,17 @@ class nsAtom;
 class nsPresContext;
 class nsIPresShell;
 class nsView;
 class nsIWidget;
 class nsISelectionController;
 class nsBoxLayoutState;
 class nsBoxLayout;
 class nsILineIterator;
+class nsDisplayItem;
 class nsDisplayListBuilder;
 class nsDisplayListSet;
 class nsDisplayList;
 class gfxSkipChars;
 class gfxSkipCharsIterator;
 class gfxContext;
 class nsLineList_iterator;
 class nsAbsoluteContainingBlock;
@@ -598,17 +599,17 @@ public:
   typedef mozilla::layout::FrameChildListIDs ChildListIDs;
   typedef mozilla::layout::FrameChildListIterator ChildListIterator;
   typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Matrix Matrix;
   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
   typedef mozilla::Sides Sides;
   typedef mozilla::LogicalSides LogicalSides;
-  typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> DisplayItemArray;
+  typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> DisplayItemDataArray;
   typedef nsQueryFrame::ClassID ClassID;
 
   NS_DECL_QUERYFRAME_TARGET(nsIFrame)
 
   explicit nsIFrame(ClassID aID)
     : mRect()
     , mContent(nullptr)
     , mStyleContext(nullptr)
@@ -1129,16 +1130,18 @@ public:
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
   { return aChild->GetPosition(); }
 
   nsPoint GetPositionIgnoringScrolling();
 
   typedef AutoTArray<nsIContent*, 2> ContentArray;
   static void DestroyContentArray(ContentArray* aArray);
 
+  typedef AutoTArray<nsDisplayItem*, 4> DisplayItemArray;
+
   typedef mozilla::layers::WebRenderUserData WebRenderUserData;
   typedef nsRefPtrHashtable<nsUint32HashKey, WebRenderUserData> WebRenderUserDataTable;
 
 #define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor)             \
   static const mozilla::FramePropertyDescriptor<type>* prop() {           \
     /* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */    \
     static const auto descriptor =                                        \
       mozilla::FramePropertyDescriptor<type>::NewWithDestructor<dtor>();  \
@@ -1226,16 +1229,18 @@ public:
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BClampMarginBoxMinSizeProperty, nscoord)
 
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(IBaselinePadProperty, nscoord)
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BBaselinePadProperty, nscoord)
 
   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(GenConProperty, ContentArray,
                                       DestroyContentArray)
 
+  NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayItems, DisplayItemArray)
+
   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData)
 
   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty, nsPlaceholderFrame)
   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(WebRenderUserDataProperty, WebRenderUserDataTable, DestroyWebRenderUserDataTable)
 
   static void DestroyWebRenderUserDataTable(WebRenderUserDataTable* aTable);
 
   mozilla::FrameBidiData GetBidiData() const
@@ -4068,17 +4073,23 @@ public:
    */
   nscoord ComputeISizeValue(gfxContext*         aRenderingContext,
                             nscoord             aContainingBlockISize,
                             nscoord             aContentEdgeToBoxSizing,
                             nscoord             aBoxSizingToMarginEdge,
                             const nsStyleCoord& aCoord,
                             ComputeSizeFlags    aFlags = eDefault);
 
-  DisplayItemArray& DisplayItemData() { return mDisplayItemData; }
+  DisplayItemDataArray& DisplayItemData() { return mDisplayItemData; }
+
+  void AddDisplayItem(nsDisplayItem* aItem);
+  bool RemoveDisplayItem(nsDisplayItem* aItem);
+  void RemoveDisplayItemDataForDeletion();
+  bool HasDisplayItems();
+  bool HasDisplayItem(nsDisplayItem* aItem);
 
   void DestroyAnonymousContent(already_AddRefed<nsIContent> aContent);
 
   bool ForceDescendIntoIfVisible() { return mForceDescendIntoIfVisible; }
   void SetForceDescendIntoIfVisible(bool aForce) { mForceDescendIntoIfVisible = aForce; }
 
 protected:
 
@@ -4099,17 +4110,18 @@ protected:
   // Members
   nsRect                 mRect;
   nsCOMPtr<nsIContent>   mContent;
   RefPtr<nsStyleContext> mStyleContext;
 private:
   nsContainerFrame* mParent;
   nsIFrame*        mNextSibling;  // doubly-linked list of frames
   nsIFrame*        mPrevSibling;  // Do not touch outside SetNextSibling!
-  DisplayItemArray mDisplayItemData;
+
+  DisplayItemDataArray mDisplayItemData;
 
   void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder);
 
   static void DestroyPaintedPresShellList(nsTArray<nsWeakPtr>* list) {
     list->Clear();
     delete list;
   }
 
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2711,16 +2711,20 @@ nsDisplayItem::nsDisplayItem(nsDisplayLi
   , mActiveScrolledRoot(aActiveScrolledRoot)
   , mAnimatedGeometryRoot(nullptr)
   , mForceNotVisible(aBuilder->IsBuildingInvisibleItems())
   , mDisableSubpixelAA(false)
 #ifdef MOZ_DUMP_PAINTING
   , mPainted(false)
 #endif
 {
+  MOZ_COUNT_CTOR(nsDisplayItem);
+  if (aBuilder->IsRetainingDisplayList()) {
+    mFrame->AddDisplayItem(this);
+  }
   mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame, &mToReferenceFrame);
   // This can return the wrong result if the item override ShouldFixToViewport(),
   // the item needs to set it again in its constructor.
   mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(aFrame);
   MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(),
                                                     *mAnimatedGeometryRoot), "Bad");
   NS_ASSERTION(aBuilder->GetVisibleRect().width >= 0 ||
                !aBuilder->IsForPainting(), "visible rect not set");
@@ -5764,17 +5768,17 @@ void
 nsDisplayWrapList::MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
                                             const nsDisplayItem* aItem)
 {
   const nsDisplayWrapList* wrappedItem = aItem->AsDisplayWrapList();
   MOZ_ASSERT(wrappedItem);
 
   // Create a new nsDisplayWrapList using a copy-constructor. This is done
   // to preserve the information about bounds.
-  nsDisplayWrapList* wrapper = new (aBuilder) nsDisplayWrapList(*wrappedItem);
+  nsDisplayWrapList* wrapper = new (aBuilder) nsDisplayWrapList(aBuilder, *wrappedItem);
 
   // Set the display list pointer of the new wrapper item to the display list
   // of the wrapped item.
   wrapper->mListPtr = wrappedItem->mListPtr;
 
   mListPtr->AppendToBottom(wrapper);
 }
 
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1783,63 +1783,83 @@ public:
     , mReferenceFrame(nullptr)
     , mAnimatedGeometryRoot(nullptr)
     , mForceNotVisible(false)
     , mDisableSubpixelAA(false)
 #ifdef MOZ_DUMP_PAINTING
     , mPainted(false)
 #endif
   {
-  }
+    MOZ_COUNT_CTOR(nsDisplayItem);
+  }
+
 protected:
   virtual ~nsDisplayItem() {
+    MOZ_COUNT_DTOR(nsDisplayItem);
+    if (mFrame) {
+      mFrame->RemoveDisplayItem(this);
+    }
   }
 public:
 
   virtual void Destroy(nsDisplayListBuilder* aBuilder)
   {
     DisplayItemType type = GetType();
     this->~nsDisplayItem();
     aBuilder->Destroy(type, this);
   }
 
+  virtual void RemoveFrame(nsIFrame* aFrame)
+  {
+    if (aFrame == mFrame) {
+      MOZ_ASSERT(!mFrame->HasDisplayItem(this));
+      mFrame = nullptr;
+    }
+  }
+
   /**
    * Downcasts this item to nsDisplayWrapList, if possible.
    */
   virtual const nsDisplayWrapList* AsDisplayWrapList() const { return nullptr; }
 
   /**
    * Create a clone of this item.
    */
   virtual nsDisplayItem* Clone(nsDisplayListBuilder* aBuilder) const
   {
     return nullptr;
   }
 
+  nsDisplayItem(const nsDisplayItem&) = delete;
   /**
    * The custom copy-constructor is implemented to prevent copying the saved
    * state of the item.
    * This is currently only used when creating temporary items for merging.
    */
-  nsDisplayItem(const nsDisplayItem& aOther)
+  nsDisplayItem(nsDisplayListBuilder* aBuilder, const nsDisplayItem& aOther)
     : mFrame(aOther.mFrame)
     , mClipChain(aOther.mClipChain)
     , mClip(aOther.mClip)
     , mActiveScrolledRoot(aOther.mActiveScrolledRoot)
     , mReferenceFrame(aOther.mReferenceFrame)
     , mAnimatedGeometryRoot(aOther.mAnimatedGeometryRoot)
     , mToReferenceFrame(aOther.mToReferenceFrame)
     , mVisibleRect(aOther.mVisibleRect)
     , mForceNotVisible(aOther.mForceNotVisible)
     , mDisableSubpixelAA(aOther.mDisableSubpixelAA)
 #ifdef MOZ_DUMP_PAINTING
     , mPainted(false)
 #endif
   {
-  }
+    MOZ_COUNT_CTOR(nsDisplayItem);
+    if (aBuilder->IsRetainingDisplayList()) {
+      mFrame->AddDisplayItem(this);
+    }
+  }
+
 
   struct HitTestState {
     explicit HitTestState() : mInPreserves3D(false) {}
 
     ~HitTestState() {
       NS_ASSERTION(mItemBuffer.Length() == 0,
                    "mItemBuffer should have been cleared");
     }
@@ -4127,18 +4147,19 @@ public:
     mBaseVisibleRect = mVisibleRect;
     mListPtr = &mList;
   }
 
   /**
    * A custom copy-constructor that does not copy mList, as this would mutate
    * the other item.
    */
-  nsDisplayWrapList(const nsDisplayWrapList& aOther)
-    : nsDisplayItem(aOther)
+  nsDisplayWrapList(const nsDisplayWrapList& aOther) = delete;
+  nsDisplayWrapList(nsDisplayListBuilder* aBuilder, const nsDisplayWrapList& aOther)
+    : nsDisplayItem(aBuilder, aOther)
     , mList(aOther.mList.mBuilder)
     , mListPtr(&mList)
     , mMergedFrames(aOther.mMergedFrames)
     , mBounds(aOther.mBounds)
     , mBaseVisibleRect(aOther.mBaseVisibleRect)
     , mOverrideZIndex(aOther.mOverrideZIndex)
     , mHasZIndexOverride(aOther.mHasZIndexOverride)
   {
@@ -4333,24 +4354,30 @@ protected:
  * set by the stacking context root frame's 'opacity' style.
  */
 class nsDisplayOpacity : public nsDisplayWrapList {
 public:
   nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                    nsDisplayList* aList,
                    const ActiveScrolledRoot* aActiveScrolledRoot,
                    bool aForEventsAndPluginsOnly);
+  nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
+                   const nsDisplayOpacity& aOther)
+    : nsDisplayWrapList(aBuilder, aOther)
+    , mOpacity(aOther.mOpacity)
+    , mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly)
+  {}
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayOpacity();
 #endif
 
   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
   {
     MOZ_COUNT_CTOR(nsDisplayOpacity);
-    return new (aBuilder) nsDisplayOpacity(*this);
+    return new (aBuilder) nsDisplayOpacity(aBuilder, *this);
   }
 
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
@@ -4403,24 +4430,30 @@ private:
 };
 
 class nsDisplayBlendMode : public nsDisplayWrapList {
 public:
   nsDisplayBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                         nsDisplayList* aList, uint8_t aBlendMode,
                         const ActiveScrolledRoot* aActiveScrolledRoot,
                         uint32_t aIndex = 0);
+  nsDisplayBlendMode(nsDisplayListBuilder* aBuilder,
+                     const nsDisplayBlendMode& aOther)
+    : nsDisplayWrapList(aBuilder, aOther)
+    , mBlendMode(aOther.mBlendMode)
+    , mIndex(aOther.mIndex)
+  {}
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayBlendMode();
 #endif
 
   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
   {
     MOZ_COUNT_CTOR(nsDisplayBlendMode);
-    return new (aBuilder) nsDisplayBlendMode(*this);
+    return new (aBuilder) nsDisplayBlendMode(aBuilder, *this);
   }
 
   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
@@ -4472,17 +4505,17 @@ public:
 
 #ifdef NS_BUILD_REFCNT_LOGGING
     virtual ~nsDisplayBlendContainer();
 #endif
 
     virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
     {
       MOZ_COUNT_CTOR(nsDisplayBlendContainer);
-      return new (aBuilder) nsDisplayBlendContainer(*this);
+      return new (aBuilder) nsDisplayBlendContainer(aBuilder, *this);
     }
 
     virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                                LayerManager* aManager,
                                                const ContainerLayerParameters& aContainerParameters) override;
     virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      const ContainerLayerParameters& aParameters) override;
@@ -4509,16 +4542,21 @@ public:
     }
     NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
 
 private:
     nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                             nsDisplayList* aList,
                             const ActiveScrolledRoot* aActiveScrolledRoot,
                             bool aIsForBackground);
+    nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
+                            const nsDisplayBlendContainer& aOther)
+      : nsDisplayWrapList(aBuilder, aOther)
+      , mIsForBackground(aOther.mIsForBackground)
+    {}
 
     // Used to distinguish containers created at building stacking
     // context or appending background.
     bool mIsForBackground;
 };
 
 /**
  * A display item that has no purpose but to ensure its contents get
@@ -4555,18 +4593,18 @@ public:
                     const ActiveScrolledRoot* aActiveScrolledRoot,
                     uint32_t aFlags = 0,
                     ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID,
                     const ScrollThumbData& aThumbData = ScrollThumbData{},
                     bool aForceActive = true);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayOwnLayer();
 #endif
-  nsDisplayOwnLayer(const nsDisplayOwnLayer& aOther)
-    : nsDisplayWrapList(aOther)
+  nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, const nsDisplayOwnLayer& aOther)
+    : nsDisplayWrapList(aBuilder, aOther)
     , mFlags(aOther.mFlags)
     , mScrollTarget(aOther.mFlags)
     , mThumbData(aOther.mThumbData)
     , mForceActive(aOther.mForceActive)
     , mWrAnimationId(aOther.mWrAnimationId)
   {
     MOZ_COUNT_CTOR(nsDisplayOwnLayer);
   }
@@ -4677,25 +4715,30 @@ public:
  * gets its own layer and creates a stacking context, and the layer will have
  * position-related metadata set on it.
  */
 class nsDisplayStickyPosition : public nsDisplayOwnLayer {
 public:
   nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                           nsDisplayList* aList,
                           const ActiveScrolledRoot* aActiveScrolledRoot);
+  nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
+                          const nsDisplayStickyPosition& aOther)
+    : nsDisplayOwnLayer(aBuilder, aOther)
+  {}
+
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayStickyPosition();
 #endif
 
   void SetClipChain(const DisplayItemClipChain* aClipChain) override;
   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
   {
     MOZ_COUNT_CTOR(nsDisplayStickyPosition);
-    return new (aBuilder) nsDisplayStickyPosition(*this);
+    return new (aBuilder) nsDisplayStickyPosition(aBuilder, *this);
   }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
@@ -4717,31 +4760,38 @@ public:
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 };
 
 class nsDisplayFixedPosition : public nsDisplayOwnLayer {
 public:
   nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                          nsDisplayList* aList,
                          const ActiveScrolledRoot* aActiveScrolledRoot);
+  nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
+                         const nsDisplayFixedPosition& aOther)
+    : nsDisplayOwnLayer(aBuilder, aOther)
+    , mAnimatedGeometryRootForScrollMetadata(aOther.mAnimatedGeometryRootForScrollMetadata)
+    , mIndex(aOther.mIndex)
+    , mIsFixedBackground(aOther.mIsFixedBackground)
+  {}
 
   static nsDisplayFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
                                                           nsIFrame* aFrame,
                                                           nsDisplayBackgroundImage* aImage,
                                                           uint32_t aIndex);
 
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFixedPosition();
 #endif
 
   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
   {
     MOZ_COUNT_CTOR(nsDisplayFixedPosition);
-    return new (aBuilder) nsDisplayFixedPosition(*this);
+    return new (aBuilder) nsDisplayFixedPosition(aBuilder, *this);
   }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
@@ -4913,18 +4963,19 @@ public:
                       nsDisplayList* aList, bool aHandleOpacity,
                       const ActiveScrolledRoot* aActiveScrolledRoot);
   nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                       nsDisplayList* aList, bool aHandleOpacity);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplaySVGEffects();
 #endif
 
-  nsDisplaySVGEffects(const nsDisplaySVGEffects& aOther)
-    : nsDisplayWrapList(aOther)
+  nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
+                      const nsDisplaySVGEffects& aOther)
+    : nsDisplayWrapList(aBuilder, aOther)
     , mEffectsBounds(aOther.mEffectsBounds)
     , mHandleOpacity(aOther.mHandleOpacity)
   {
     MOZ_COUNT_CTOR(nsDisplaySVGEffects);
   }
 
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const override;
@@ -4957,24 +5008,29 @@ protected:
  */
 class nsDisplayMask : public nsDisplaySVGEffects {
 public:
   typedef mozilla::layers::ImageLayer ImageLayer;
 
   nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 nsDisplayList* aList, bool aHandleOpacity,
                 const ActiveScrolledRoot* aActiveScrolledRoot);
+  nsDisplayMask(nsDisplayListBuilder* aBuilder,
+                const nsDisplayMask& aOther)
+    : nsDisplaySVGEffects(aBuilder, aOther)
+    , mDestRects(aOther.mDestRects)
+  {}
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMask();
 #endif
 
   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
   {
     MOZ_COUNT_CTOR(nsDisplayMask);
-    return new (aBuilder) nsDisplayMask(*this);
+    return new (aBuilder) nsDisplayMask(aBuilder, *this);
   }
 
   NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
 
   virtual bool CanMerge(const nsDisplayItem* aItem) const override;
 
   virtual void Merge(const nsDisplayItem* aItem) override
   {
@@ -5037,24 +5093,29 @@ private:
 /**
  * A display item to paint a stacking context with filter effects set by the
  * stacking context root frame's style.
  */
 class nsDisplayFilter : public nsDisplaySVGEffects {
 public:
   nsDisplayFilter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                   nsDisplayList* aList, bool aHandleOpacity);
+  nsDisplayFilter(nsDisplayListBuilder* aBuilder,
+                  const nsDisplayFilter& aOther)
+    : nsDisplaySVGEffects(aBuilder, aOther)
+    , mEffectsBounds(aOther.mEffectsBounds)
+  {}
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFilter();
 #endif
 
   virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
   {
     MOZ_COUNT_CTOR(nsDisplayFilter);
-    return new (aBuilder) nsDisplayFilter(*this);
+    return new (aBuilder) nsDisplayFilter(aBuilder, *this);
   }
 
   NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
 
   virtual bool CanMerge(const nsDisplayItem* aItem) const override
   {
     // Items for the same content element should be merged into a single
     // compositing group.
@@ -5136,22 +5197,16 @@ class nsDisplayTransform: public nsDispl
     StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
               nsDisplayList* aList) :
       nsDisplayWrapList(aBuilder, aFrame, aList) {}
     StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
               nsDisplayItem* aItem) :
       nsDisplayWrapList(aBuilder, aFrame, aItem) {}
     virtual ~StoreList() {}
 
-    // This override is needed since StoreList is only allocated from the stack.
-    virtual void Destroy(nsDisplayListBuilder* aBuilder) override
-    {
-      mList.DeleteAll(aBuilder);
-    }
-
     virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {
       // For extending 3d rendering context, the bounds would be
       // updated by DoUpdateBoundsPreserves3D(), not here.
       if (!mFrame->Extend3DContext()) {
         nsDisplayWrapList::UpdateBounds(aBuilder);
       }
     }
     virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
@@ -5198,17 +5253,17 @@ public:
   virtual ~nsDisplayTransform()
   {
     MOZ_COUNT_DTOR(nsDisplayTransform);
   }
 #endif
 
   virtual void Destroy(nsDisplayListBuilder* aBuilder) override
   {
-    mStoredList.Destroy(aBuilder);
+    mStoredList.GetChildren()->DeleteAll(aBuilder);
     nsDisplayItem::Destroy(aBuilder);
   }
 
   NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
 
   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override
   {
     if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())