Bug 1468426 - Change LayerManagerData::mDisplayItems to a vector instead of hashtable. r?mattwoodrow draft
authorJamie Nicol <jnicol@mozilla.com>
Thu, 14 Jun 2018 10:04:02 -0700
changeset 807773 15cf30592e0c87a61da4c350c196d3d6069f814c
parent 807714 0b5495dc100dd3bfda0886a4ad563a3c729c9b72
push id113209
push userbmo:jnicol@mozilla.com
push dateFri, 15 Jun 2018 18:30:48 +0000
reviewersmattwoodrow
bugs1468426
milestone62.0a1
Bug 1468426 - Change LayerManagerData::mDisplayItems to a vector instead of hashtable. r?mattwoodrow This should improve cache locality and help speed up layer building. MozReview-Commit-ID: 9IvU23alnaa
layout/painting/FrameLayerBuilder.cpp
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -433,28 +433,26 @@ public:
 #endif
     , mInvalidateAllLayers(false)
   {
     MOZ_COUNT_CTOR(LayerManagerData);
   }
   ~LayerManagerData() {
     MOZ_COUNT_DTOR(LayerManagerData);
 
-    for (auto iter = mDisplayItems.Iter(); !iter.Done(); iter.Next()) {
-      iter.Get()->GetKey()->Disconnect();
+    for (auto& item : mDisplayItems) {
+      item->Disconnect();
     }
   }
 
 #ifdef DEBUG_DISPLAY_ITEM_DATA
   void Dump(const char *aPrefix = "") {
     printf_stderr("%sLayerManagerData %p\n", aPrefix, this);
 
-    for (auto iter = mDisplayItems.Iter(); !iter.Done(); iter.Next()) {
-      FrameLayerBuilder::DisplayItemData* data = iter.Get()->GetKey();
-
+    for (auto& data : mDisplayItems) {
       nsAutoCString prefix;
       prefix += aPrefix;
       prefix += "  ";
 
       const char* layerState;
       switch (data->mLayerState) {
       case LAYER_NONE:
         layerState = "LAYER_NONE"; break;
@@ -502,17 +500,17 @@ public:
 
   /**
    * Tracks which frames have layers associated with them.
    */
   LayerManager *mLayerManager;
 #ifdef DEBUG_DISPLAY_ITEM_DATA
   LayerManagerData *mParent;
 #endif
-  nsTHashtable<nsRefPtrHashKey<DisplayItemData> > mDisplayItems;
+  std::vector<RefPtr<DisplayItemData>> mDisplayItems;
   bool mInvalidateAllLayers;
 };
 
 /* static */ void
 FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
 {
   RemoveFrameFromLayerManager(aFrame, aFrame->DisplayItemData());
   aFrame->DisplayItemData().Clear();
@@ -2141,17 +2139,22 @@ FrameLayerBuilder::RemoveFrameFromLayerM
         nsIntRegion rgn = old.ScaleToOutsidePixels(paintedData->mXScale, paintedData->mYScale, paintedData->mAppUnitsPerDevPixel);
         rgn.MoveBy(-GetTranslationForPaintedLayer(t));
         paintedData->mRegionToInvalidate.Or(paintedData->mRegionToInvalidate, rgn);
         paintedData->mRegionToInvalidate.SimplifyOutward(8);
       }
     }
 
     data->Disconnect();
-    data->mParent->mDisplayItems.RemoveEntry(data);
+    auto it = std::find(data->mParent->mDisplayItems.begin(),
+                        data->mParent->mDisplayItems.end(),
+                        data);
+    MOZ_ASSERT(it != data->mParent->mDisplayItems.end());
+    std::iter_swap(it, data->mParent->mDisplayItems.end() - 1);
+    data->mParent->mDisplayItems.pop_back();
   }
 
   arrayCopy.Clear();
   sDestroyedFrame = nullptr;
 }
 
 void
 FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager)
@@ -2181,38 +2184,52 @@ FrameLayerBuilder::WillEndTransaction()
   }
 
   // We need to save the data we'll need to support retaining.
   LayerManagerData* data = static_cast<LayerManagerData*>
     (mRetainingManager->GetUserData(&gLayerManagerUserData));
   NS_ASSERTION(data, "Must have data!");
 
   // Update all the frames that used to have layers.
-  for (auto iter = data->mDisplayItems.Iter(); !iter.Done(); iter.Next()) {
-    DisplayItemData* data = iter.Get()->GetKey();
-    if (!data->mUsed) {
+  auto iter = data->mDisplayItems.begin();
+  while (iter != data->mDisplayItems.end()) {
+    DisplayItemData* did = iter->get();
+    if (!did->mUsed) {
       // This item was visible, but isn't anymore.
-      PaintedLayer* t = data->mLayer->AsPaintedLayer();
-      if (t && data->mGeometry) {
+      PaintedLayer* t = did->mLayer->AsPaintedLayer();
+      if (t && did->mGeometry) {
 #ifdef MOZ_DUMP_PAINTING
         if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
-          printf_stderr("Invalidating unused display item (%i) belonging to frame %p from layer %p\n", data->mDisplayItemKey, data->mFrameList[0], t);
+          printf_stderr("Invalidating unused display item (%i) belonging to frame %p from layer %p\n", did->mDisplayItemKey, did->mFrameList[0], t);
         }
 #endif
         InvalidatePostTransformRegion(t,
-                                      data->mGeometry->ComputeInvalidationRegion(),
-                                      data->mClip,
+                                      did->mGeometry->ComputeInvalidationRegion(),
+                                      did->mClip,
                                       GetLastPaintOffset(t));
       }
 
-      data->ClearAnimationCompositorState();
-      data->Disconnect();
-      iter.Remove();
+      did->ClearAnimationCompositorState();
+      did->Disconnect();
+
+      // Remove this item. Swapping it with the last element first is
+      // quicker than erasing from the middle.
+      if (iter != data->mDisplayItems.end() - 1) {
+        std::iter_swap(iter, data->mDisplayItems.end() - 1);
+        data->mDisplayItems.pop_back();
+      } else {
+        data->mDisplayItems.pop_back();
+        break;
+      }
+
+      // Don't increment iter because we still need to process the item which was moved.
+
     } else {
-      ComputeGeometryChangeForItem(data);
+      ComputeGeometryChangeForItem(did);
+      iter++;
     }
   }
 
   data->mInvalidateAllLayers = false;
 }
 
 /* static */ DisplayItemData*
 FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
@@ -5113,17 +5130,17 @@ FrameLayerBuilder::StoreDataForFrame(nsD
     new (aItem->Frame()->PresContext()) DisplayItemData(lmd, aItem->GetPerFrameKey(), aLayer);
 
   if (!data->HasMergedFrames()) {
     aItem->SetDisplayItemData(data);
   }
 
   data->BeginUpdate(aLayer, aState, true, aItem);
 
-  lmd->mDisplayItems.PutEntry(data);
+  lmd->mDisplayItems.push_back(data);
   return data;
 }
 
 void
 FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame,
                                      uint32_t aDisplayItemKey,
                                      Layer* aLayer,
                                      LayerState aState)
@@ -5137,17 +5154,17 @@ FrameLayerBuilder::StoreDataForFrame(nsI
   LayerManagerData* lmd = static_cast<LayerManagerData*>
     (mRetainingManager->GetUserData(&gLayerManagerUserData));
 
   RefPtr<DisplayItemData> data =
     new (aFrame->PresContext()) DisplayItemData(lmd, aDisplayItemKey, aLayer, aFrame);
 
   data->BeginUpdate(aLayer, aState, true);
 
-  lmd->mDisplayItems.PutEntry(data);
+  lmd->mDisplayItems.push_back(data);
 }
 
 AssignedDisplayItem::AssignedDisplayItem(nsDisplayItem* aItem,
                                          LayerState aLayerState,
                                          DisplayItemData* aData,
                                          const nsRect& aContentRect,
                                          DisplayItemEntryType aType,
                                          const bool aHasOpacity)