Backed out changeset 9483bb6d8ce6 (bug 1330570) for test failures in test_selection_move_commands.html | cmd_scrollBottom - -300 should equal -300
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 10 May 2017 12:11:11 +0200
changeset 357484 df9358a0469ad540a31aedbd4307ed9f5c3cd532
parent 357483 59688757b4ba961b7ad42843efe256ff062a5977
child 357485 dc3008e45ba6cf5130eec89598fd51d1e6bbbc27
push id31792
push usercbook@mozilla.com
push dateWed, 10 May 2017 13:07:59 +0000
treeherdermozilla-central@ebbcdaa5b580 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1330570
milestone55.0a1
backs out9483bb6d8ce6f860c60bebcc1d57b8d9a1c0aa41
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 9483bb6d8ce6 (bug 1330570) for test failures in test_selection_move_commands.html | cmd_scrollBottom - -300 should equal -300
layout/base/nsPresArena.cpp
layout/base/nsPresArenaObjectList.h
layout/painting/FrameLayerBuilder.cpp
layout/painting/FrameLayerBuilder.h
layout/style/ImageLoader.cpp
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -9,17 +9,16 @@
 
 #include "nsPresArena.h"
 
 #include "mozilla/Poison.h"
 #include "nsDebug.h"
 #include "nsArenaMemoryStats.h"
 #include "nsPrintfCString.h"
 #include "nsStyleContext.h"
-#include "FrameLayerBuilder.h"
 
 #include <inttypes.h>
 
 using namespace mozilla;
 
 nsPresArena::nsPresArena()
 {
 }
--- a/layout/base/nsPresArenaObjectList.h
+++ b/layout/base/nsPresArenaObjectList.h
@@ -43,17 +43,16 @@
 // Files including nsPresArenaObjectList.h can either define one or both
 // of PRES_ARENA_OBJECT_{WITH,WITHOUT}_ARENAREFPTR_SUPPORT to capture those
 // classes separately, or PRES_ARENA_OBJECT to capture all nsPresArena-
 // allocated classes.
 
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsLineBox)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsRuleNode)
 PRES_ARENA_OBJECT_WITH_ARENAREFPTR_SUPPORT(nsStyleContext)
-PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(DisplayItemData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsInheritedStyleData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsResetStyleData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsConditionalResetStyleData)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsConditionalResetStyleDataEntry)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(nsFrameList)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(CustomCounterStyle)
 PRES_ARENA_OBJECT_WITHOUT_ARENAREFPTR_SUPPORT(DependentBuiltinCounterStyle)
 
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -56,17 +56,17 @@
 
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 
 class PaintedDisplayItemLayerUserData;
 
-static nsTHashtable<nsPtrHashKey<DisplayItemData>>* sAliveDisplayItemDatas;
+static nsTHashtable<nsPtrHashKey<FrameLayerBuilder::DisplayItemData>>* sAliveDisplayItemDatas;
 
 /**
  * The address of gPaintedDisplayItemLayerUserData is used as the user
  * data key for PaintedLayers created by FrameLayerBuilder.
  * It identifies PaintedLayers used to draw non-layer content, which are
  * therefore eligible for recycling. We want display items to be able to
  * create their own dedicated PaintedLayers in BuildLayer, if necessary,
  * and we wouldn't want to accidentally recycle those.
@@ -130,100 +130,99 @@ FrameLayerBuilder::FrameLayerBuilder()
 }
 
 FrameLayerBuilder::~FrameLayerBuilder()
 {
   GetMaskLayerImageCache()->Sweep();
   MOZ_COUNT_DTOR(FrameLayerBuilder);
 }
 
-DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey,
-                                 Layer* aLayer, nsIFrame* aFrame)
-
-  : mRefCnt(0)
-  , mParent(aParent)
+FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey,
+                                                    Layer* aLayer, nsIFrame* aFrame)
+
+  : mParent(aParent)
   , mLayer(aLayer)
   , mDisplayItemKey(aKey)
   , mItem(nullptr)
   , mUsed(true)
   , mIsInvalid(false)
 {
-  MOZ_COUNT_CTOR(DisplayItemData);
+  MOZ_COUNT_CTOR(FrameLayerBuilder::DisplayItemData);
 
   if (!sAliveDisplayItemDatas) {
-    sAliveDisplayItemDatas = new nsTHashtable<nsPtrHashKey<DisplayItemData>>();
+    sAliveDisplayItemDatas = new nsTHashtable<nsPtrHashKey<FrameLayerBuilder::DisplayItemData>>();
   }
   MOZ_RELEASE_ASSERT(!sAliveDisplayItemDatas->Contains(this));
   sAliveDisplayItemDatas->PutEntry(this);
 
   MOZ_RELEASE_ASSERT(mLayer);
   if (aFrame) {
     AddFrame(aFrame);
   }
 
 }
 
 void
-DisplayItemData::AddFrame(nsIFrame* aFrame)
+FrameLayerBuilder::DisplayItemData::AddFrame(nsIFrame* aFrame)
 {
   MOZ_RELEASE_ASSERT(mLayer);
   mFrameList.AppendElement(aFrame);
 
   nsTArray<DisplayItemData*>* array =
     aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
   if (!array) {
     array = new nsTArray<DisplayItemData*>();
     aFrame->Properties().Set(FrameLayerBuilder::LayerManagerDataProperty(), array);
   }
   array->AppendElement(this);
 }
 
 void
-DisplayItemData::RemoveFrame(nsIFrame* aFrame)
+FrameLayerBuilder::DisplayItemData::RemoveFrame(nsIFrame* aFrame)
 {
   MOZ_RELEASE_ASSERT(mLayer);
   bool result = mFrameList.RemoveElement(aFrame);
   MOZ_RELEASE_ASSERT(result, "Can't remove a frame that wasn't added!");
 
   nsTArray<DisplayItemData*>* array =
     aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
   MOZ_RELEASE_ASSERT(array, "Must be already stored on the frame!");
   array->RemoveElement(this);
 }
 
 void
-DisplayItemData::EndUpdate()
+FrameLayerBuilder::DisplayItemData::EndUpdate()
 {
   MOZ_RELEASE_ASSERT(mLayer);
   MOZ_ASSERT(!mItem);
   mIsInvalid = false;
   mUsed = false;
 }
 
 void
-DisplayItemData::EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
+FrameLayerBuilder::DisplayItemData::EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
 {
   MOZ_RELEASE_ASSERT(mLayer);
   MOZ_ASSERT(mItem);
   MOZ_ASSERT(mGeometry || aGeometry);
 
   if (aGeometry) {
     mGeometry = aGeometry;
   }
   mClip = mItem->GetClip();
   mFrameListChanges.Clear();
 
   mItem = nullptr;
   EndUpdate();
 }
 
 void
-DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
-                             uint32_t aContainerLayerGeneration,
-                             nsDisplayItem* aItem /* = nullptr */)
+FrameLayerBuilder::DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
+                                                uint32_t aContainerLayerGeneration,
+                                                nsDisplayItem* aItem /* = nullptr */)
 {
   MOZ_RELEASE_ASSERT(mLayer);
   MOZ_RELEASE_ASSERT(aLayer);
   mLayer = aLayer;
   mOptLayer = nullptr;
   mInactiveManager = nullptr;
   mLayerState = aState;
   mContainerLayerGeneration = aContainerLayerGeneration;
@@ -256,61 +255,61 @@ DisplayItemData::BeginUpdate(Layer* aLay
 
   for (uint32_t i = 0; i < copy.Length(); i++) {
     RemoveFrame(copy[i]);
     mFrameListChanges.AppendElement(copy[i]);
   }
 }
 
 static const nsIFrame* sDestroyedFrame = nullptr;
-DisplayItemData::~DisplayItemData()
+FrameLayerBuilder::DisplayItemData::~DisplayItemData()
 {
-  MOZ_COUNT_DTOR(DisplayItemData);
+  MOZ_COUNT_DTOR(FrameLayerBuilder::DisplayItemData);
   MOZ_RELEASE_ASSERT(mLayer);
   for (uint32_t i = 0; i < mFrameList.Length(); i++) {
     nsIFrame* frame = mFrameList[i];
     if (frame == sDestroyedFrame) {
       continue;
     }
     nsTArray<DisplayItemData*> *array =
-      reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty()));
+      reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->Properties().Get(LayerManagerDataProperty()));
     array->RemoveElement(this);
   }
 
   MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && sAliveDisplayItemDatas->Contains(this));
   sAliveDisplayItemDatas->RemoveEntry(this);
   if (sAliveDisplayItemDatas->Count() == 0) {
     delete sAliveDisplayItemDatas;
     sAliveDisplayItemDatas = nullptr;
   }
 }
 
 void
-DisplayItemData::ClearAnimationCompositorState()
+FrameLayerBuilder::DisplayItemData::ClearAnimationCompositorState()
 {
   if (mDisplayItemKey != nsDisplayItem::TYPE_TRANSFORM &&
       mDisplayItemKey != nsDisplayItem::TYPE_OPACITY) {
     return;
   }
 
   for (nsIFrame* frame : mFrameList) {
     nsCSSPropertyID prop = mDisplayItemKey == nsDisplayItem::TYPE_TRANSFORM ?
       eCSSProperty_transform : eCSSProperty_opacity;
     EffectCompositor::ClearIsRunningOnCompositor(frame, prop);
   }
 }
 
 const nsTArray<nsIFrame*>&
-DisplayItemData::GetFrameListChanges()
+FrameLayerBuilder::DisplayItemData::GetFrameListChanges()
 {
   return mFrameListChanges;
 }
 
-DisplayItemData*
-DisplayItemData::AssertDisplayItemData(DisplayItemData* aData)
+FrameLayerBuilder::DisplayItemData*
+FrameLayerBuilder::DisplayItemData::AssertDisplayItemData(FrameLayerBuilder::DisplayItemData* aData)
 {
   MOZ_RELEASE_ASSERT(aData);
   MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && sAliveDisplayItemDatas->Contains(aData));
   MOZ_RELEASE_ASSERT(aData->mLayer);
   return aData;
 }
 
 /**
@@ -390,17 +389,17 @@ public:
 
   /**
    * Tracks which frames have layers associated with them.
    */
   LayerManager *mLayerManager;
 #ifdef DEBUG_DISPLAY_ITEM_DATA
   LayerManagerData *mParent;
 #endif
-  nsTHashtable<nsRefPtrHashKey<DisplayItemData> > mDisplayItems;
+  nsTHashtable<nsRefPtrHashKey<FrameLayerBuilder::DisplayItemData> > mDisplayItems;
   bool mInvalidateAllLayers;
 };
 
 /* static */ void
 FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
 {
   FrameProperties props = aFrame->Properties();
   props.Delete(LayerManagerDataProperty());
@@ -1809,17 +1808,17 @@ FrameLayerBuilder::FlashPaint(gfxContext
 {
   float r = float(rand()) / RAND_MAX;
   float g = float(rand()) / RAND_MAX;
   float b = float(rand()) / RAND_MAX;
   aContext->SetColor(Color(r, g, b, 0.4f));
   aContext->Paint();
 }
 
-DisplayItemData*
+FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetDisplayItemData(nsIFrame* aFrame, uint32_t aKey)
 {
   const nsTArray<DisplayItemData*>* array =
     aFrame->Properties().Get(LayerManagerDataProperty());
   if (array) {
     for (uint32_t i = 0; i < array->Length(); i++) {
       DisplayItemData* item = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
       if (item->mDisplayItemKey == aKey &&
@@ -2038,17 +2037,17 @@ FrameLayerBuilder::WillEndTransaction()
     } else {
       ComputeGeometryChangeForItem(data);
     }
   }
 
   data->mInvalidateAllLayers = false;
 }
 
-/* static */ DisplayItemData*
+/* static */ FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
                                                 LayerManager* aManager)
 {
   const nsTArray<DisplayItemData*>* array =
     aItem->Frame()->Properties().Get(LayerManagerDataProperty());
   if (array) {
     for (uint32_t i = 0; i < array->Length(); i++) {
       DisplayItemData* item = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
@@ -2088,17 +2087,17 @@ FrameLayerBuilder::IterateRetainedDataFo
   for (uint32_t i = 0; i < array->Length(); i++) {
     DisplayItemData* data = DisplayItemData::AssertDisplayItemData(array->ElementAt(i));
     if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO) {
       aCallback(aFrame, data);
     }
   }
 }
 
-DisplayItemData*
+FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey)
 {
   // If we need to build a new layer tree, then just refuse to recycle
   // anything.
   if (!mRetainingManager || mInvalidateAllLayers)
     return nullptr;
 
   DisplayItemData *data = GetDisplayItemData(aFrame, aDisplayItemKey);
@@ -4773,32 +4772,32 @@ FrameLayerBuilder::AddPaintedDisplayItem
     }
     ClippedDisplayItem* cdi =
       entry->mItems.AppendElement(ClippedDisplayItem(aItem,
                                                      mContainerLayerGeneration));
     cdi->mInactiveLayerManager = tempManager;
   }
 }
 
-DisplayItemData*
+FrameLayerBuilder::DisplayItemData*
 FrameLayerBuilder::StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState)
 {
   DisplayItemData* oldData = GetDisplayItemDataForManager(aItem, mRetainingManager);
   if (oldData) {
     if (!oldData->mUsed) {
       oldData->BeginUpdate(aLayer, aState, mContainerLayerGeneration, aItem);
     }
     return oldData;
   }
 
   LayerManagerData* lmd = static_cast<LayerManagerData*>
     (mRetainingManager->GetUserData(&gLayerManagerUserData));
 
   RefPtr<DisplayItemData> data =
-    new (aItem->Frame()->PresContext()) DisplayItemData(lmd, aItem->GetPerFrameKey(), aLayer);
+    new DisplayItemData(lmd, aItem->GetPerFrameKey(), aLayer);
 
   data->BeginUpdate(aLayer, aState, mContainerLayerGeneration, aItem);
 
   lmd->mDisplayItems.PutEntry(data);
   return data;
 }
 
 void
@@ -4812,17 +4811,17 @@ FrameLayerBuilder::StoreDataForFrame(nsI
     oldData->BeginUpdate(aLayer, aState, mContainerLayerGeneration);
     return;
   }
 
   LayerManagerData* lmd = static_cast<LayerManagerData*>
     (mRetainingManager->GetUserData(&gLayerManagerUserData));
 
   RefPtr<DisplayItemData> data =
-    new (aFrame->PresContext()) DisplayItemData(lmd, aDisplayItemKey, aLayer, aFrame);
+    new DisplayItemData(lmd, aDisplayItemKey, aLayer, aFrame);
 
   data->BeginUpdate(aLayer, aState, mContainerLayerGeneration);
 
   lmd->mDisplayItems.PutEntry(data);
 }
 
 FrameLayerBuilder::ClippedDisplayItem::ClippedDisplayItem(nsDisplayItem* aItem,
                                                           uint32_t aGeneration)
--- a/layout/painting/FrameLayerBuilder.h
+++ b/layout/painting/FrameLayerBuilder.h
@@ -37,159 +37,16 @@ class PaintedLayer;
 class ImageLayer;
 } // namespace layers
 
 class FrameLayerBuilder;
 class LayerManagerData;
 class PaintedLayerData;
 class ContainerState;
 
-/**
-  * Retained data storage:
-  *
-  * Each layer manager (widget, and inactive) stores a LayerManagerData object
-  * that keeps a hash-set of DisplayItemData items that were drawn into it.
-  * Each frame also keeps a list of DisplayItemData pointers that were
-  * created for that frame. DisplayItemData objects manage these lists automatically.
-  *
-  * During layer construction we update the data in the LayerManagerData object, marking
-  * items that are modified. At the end we sweep the LayerManagerData hash-set and remove
-  * all items that haven't been modified.
-  */
-
-/**
-  * Retained data for a display item.
-  */
-class DisplayItemData final {
-public:
-  friend class FrameLayerBuilder;
-
-  uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
-  layers::Layer* GetLayer() { return mLayer; }
-  nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); }
-  void Invalidate() { mIsInvalid = true; }
-  void ClearAnimationCompositorState();
-
-  static DisplayItemData* AssertDisplayItemData(DisplayItemData* aData);
-
-  void* operator new(size_t sz, nsPresContext* aPresContext)
-  {
-    // Check the recycle list first.
-    return aPresContext->PresShell()->
-      AllocateByObjectID(eArenaObjectID_DisplayItemData, sz);
-  }
-
-  nsrefcnt AddRef() {
-    if (mRefCnt == UINT32_MAX) {
-      NS_WARNING("refcount overflow, leaking object");
-      return mRefCnt;
-    }
-    ++mRefCnt;
-    NS_LOG_ADDREF(this, mRefCnt, "nsStyleContext", sizeof(nsStyleContext));
-    return mRefCnt;
-  }
-
-  nsrefcnt Release() {
-    if (mRefCnt == UINT32_MAX) {
-      NS_WARNING("refcount overflow, leaking object");
-      return mRefCnt;
-    }
-    --mRefCnt;
-    NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
-    if (mRefCnt == 0) {
-      Destroy();
-      return 0;
-    }
-    return mRefCnt;
-  }
-
-private:
-  DisplayItemData(LayerManagerData* aParent,
-                  uint32_t aKey,
-                  layers::Layer* aLayer,
-                  nsIFrame* aFrame = nullptr);
-
-  /**
-    * Removes any references to this object from frames
-    * in mFrameList.
-    */
-  ~DisplayItemData();
-
-  void Destroy()
-  {
-    // Get the pres context.
-    RefPtr<nsPresContext> presContext = mFrameList[0]->PresContext();
-
-    // Call our destructor.
-    this->~DisplayItemData();
-
-    // Don't let the memory be freed, since it will be recycled
-    // instead. Don't call the global operator delete.
-    presContext->PresShell()->
-      FreeByObjectID(eArenaObjectID_DisplayItemData, this);
-  }
-
-  /**
-    * Associates this DisplayItemData with a frame, and adds it
-    * to the LayerManagerDataProperty list on the frame.
-    */
-  void AddFrame(nsIFrame* aFrame);
-  void RemoveFrame(nsIFrame* aFrame);
-  const nsTArray<nsIFrame*>& GetFrameListChanges();
-
-  /**
-    * Updates the contents of this item to a new set of data, instead of allocating a new
-    * object.
-    * Set the passed in parameters, and clears the opt layer and inactive manager.
-    * Parent, and display item key are assumed to be the same.
-    *
-    * EndUpdate must be called before the end of the transaction to complete the update.
-    */
-  void BeginUpdate(layers::Layer* aLayer, LayerState aState,
-                    uint32_t aContainerLayerGeneration, nsDisplayItem* aItem = nullptr);
-
-  /**
-    * Completes the update of this, and removes any references to data that won't live
-    * longer than the transaction.
-    *
-    * Updates the geometry, frame list and clip.
-    * For items within a PaintedLayer, a geometry object must be specified to retain
-    * until the next transaction.
-    *
-    */
-  void EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
-  void EndUpdate();
-
-  uint32_t mRefCnt;
-  LayerManagerData* mParent;
-  RefPtr<layers::Layer> mLayer;
-  RefPtr<layers::Layer> mOptLayer;
-  RefPtr<layers::BasicLayerManager> mInactiveManager;
-  AutoTArray<nsIFrame*, 1> mFrameList;
-  nsAutoPtr<nsDisplayItemGeometry> mGeometry;
-  DisplayItemClip mClip;
-  uint32_t        mDisplayItemKey;
-  uint32_t        mContainerLayerGeneration;
-  LayerState      mLayerState;
-
-  /**
-    * Temporary stoarage of the display item being referenced, only valid between
-    * BeginUpdate and EndUpdate.
-    */
-  nsDisplayItem* mItem;
-  AutoTArray<nsIFrame*, 1> mFrameListChanges;
-
-  /**
-    * Used to track if data currently stored in mFramesWithLayers (from an existing
-    * paint) has been updated in the current paint.
-    */
-  bool            mUsed;
-  bool            mIsInvalid;
-};
-
 class RefCountedRegion {
 private:
   ~RefCountedRegion() {}
 public:
   NS_INLINE_DECL_REFCOUNTING(RefCountedRegion)
 
   RefCountedRegion() : mIsInfinite(false) {}
   nsRegion mRegion;
@@ -554,16 +411,17 @@ public:
   LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
 
   /**
    * Returns true if the given display item was rendered during the previous
    * paint. Returns false otherwise.
    */
   static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
 
+  class DisplayItemData;
   typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem);
 
   static void IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback);
 
   /**
    * Save transform that was in aLayer when we last painted, and the position
    * of the active scrolled root frame. It must be an integer
    * translation.
@@ -591,16 +449,117 @@ public:
    * Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the 
    * DisplayItemData so we can retrieve the layer from within layout.
    */
   void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer);
   
   NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
                                                nsTArray<DisplayItemData*>,
                                                RemoveFrameFromLayerManager)
+
+  /**
+   * Retained data storage:
+   *
+   * Each layer manager (widget, and inactive) stores a LayerManagerData object
+   * that keeps a hash-set of DisplayItemData items that were drawn into it.
+   * Each frame also keeps a list of DisplayItemData pointers that were
+   * created for that frame. DisplayItemData objects manage these lists automatically.
+   *
+   * During layer construction we update the data in the LayerManagerData object, marking
+   * items that are modified. At the end we sweep the LayerManagerData hash-set and remove
+   * all items that haven't been modified.
+   */
+
+  /**
+   * Retained data for a display item.
+   */
+  class DisplayItemData final {
+  public:
+    friend class FrameLayerBuilder;
+
+    uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
+    Layer* GetLayer() { return mLayer; }
+    nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); }
+    void Invalidate() { mIsInvalid = true; }
+    void ClearAnimationCompositorState();
+
+    static DisplayItemData* AssertDisplayItemData(DisplayItemData* aData);
+
+  private:
+    DisplayItemData(LayerManagerData* aParent,
+                    uint32_t aKey,
+                    Layer* aLayer,
+                    nsIFrame* aFrame = nullptr);
+
+    /**
+     * Removes any references to this object from frames
+     * in mFrameList.
+     */
+    ~DisplayItemData();
+
+    NS_INLINE_DECL_REFCOUNTING(DisplayItemData)
+
+
+    /**
+     * Associates this DisplayItemData with a frame, and adds it
+     * to the LayerManagerDataProperty list on the frame.
+     */
+    void AddFrame(nsIFrame* aFrame);
+    void RemoveFrame(nsIFrame* aFrame);
+    const nsTArray<nsIFrame*>& GetFrameListChanges();
+
+    /**
+     * Updates the contents of this item to a new set of data, instead of allocating a new
+     * object.
+     * Set the passed in parameters, and clears the opt layer and inactive manager.
+     * Parent, and display item key are assumed to be the same.
+     *
+     * EndUpdate must be called before the end of the transaction to complete the update.
+     */
+    void BeginUpdate(Layer* aLayer, LayerState aState,
+                     uint32_t aContainerLayerGeneration, nsDisplayItem* aItem = nullptr);
+
+    /**
+     * Completes the update of this, and removes any references to data that won't live
+     * longer than the transaction.
+     *
+     * Updates the geometry, frame list and clip.
+     * For items within a PaintedLayer, a geometry object must be specified to retain
+     * until the next transaction.
+     *
+     */
+    void EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
+    void EndUpdate();
+
+    LayerManagerData* mParent;
+    RefPtr<Layer> mLayer;
+    RefPtr<Layer> mOptLayer;
+    RefPtr<BasicLayerManager> mInactiveManager;
+    AutoTArray<nsIFrame*, 1> mFrameList;
+    nsAutoPtr<nsDisplayItemGeometry> mGeometry;
+    DisplayItemClip mClip;
+    uint32_t        mDisplayItemKey;
+    uint32_t        mContainerLayerGeneration;
+    LayerState      mLayerState;
+
+    /**
+     * Temporary stoarage of the display item being referenced, only valid between
+     * BeginUpdate and EndUpdate.
+     */
+    nsDisplayItem* mItem;
+    AutoTArray<nsIFrame*, 1> mFrameListChanges;
+
+    /**
+     * Used to track if data currently stored in mFramesWithLayers (from an existing
+     * paint) has been updated in the current paint.
+     */
+    bool            mUsed;
+    bool            mIsInvalid;
+  };
+
 protected:
 
   friend class LayerManagerData;
 
   static void RemoveFrameFromLayerManager(const nsIFrame* aFrame,
                                           nsTArray<DisplayItemData*>* aArray);
 
   /**
--- a/layout/style/ImageLoader.cpp
+++ b/layout/style/ImageLoader.cpp
@@ -310,17 +310,17 @@ ImageLoader::GetPresContext()
   if (!shell) {
     return nullptr;
   }
 
   return shell->GetPresContext();
 }
 
 void InvalidateImagesCallback(nsIFrame* aFrame, 
-                              DisplayItemData* aItem)
+                              FrameLayerBuilder::DisplayItemData* aItem)
 {
   nsDisplayItem::Type type = nsDisplayItem::GetDisplayItemTypeFromKey(aItem->GetDisplayItemKey());
   uint8_t flags = nsDisplayItem::GetDisplayItemFlagsForType(type);
 
   if (flags & nsDisplayItem::TYPE_RENDERS_NO_IMAGES) {
     return;
   }