Bug 1744069 - Restore the previous behavior of merging RDL list traversal r=emilio
authorMiko Mynttinen <mikokm@gmail.com>
Mon, 14 Mar 2022 15:11:05 +0000
changeset 610562 844b96d8f690c6f0d997c1bed10c9a66c9d2ef85
parent 610561 76c68029dfca33c918cdb9abb6c66d4876aafcda
child 610563 8394e008936bc5b9870676618132a70738c65d60
push id159334
push usermikokm@gmail.com
push dateMon, 14 Mar 2022 16:30:49 +0000
treeherderautoland@844b96d8f690 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1744069
milestone100.0a1
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
Bug 1744069 - Restore the previous behavior of merging RDL list traversal r=emilio Differential Revision: https://phabricator.services.mozilla.com/D140920
layout/painting/RetainedDisplayListBuilder.cpp
layout/painting/nsDisplayList.h
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -198,18 +198,20 @@ bool RetainedDisplayListBuilder::PreProc
     MOZ_RELEASE_ASSERT(!initializeDAG);
   }
 
   MOZ_RELEASE_ASSERT(
       initializeDAG ||
       aList->mDAG.Length() ==
           (initializeOldItems ? aList->Length() : aList->mOldItems.Length()));
 
+  nsDisplayList out(Builder());
+
   size_t i = 0;
-  for (nsDisplayItem* item : aList->TakeItems()) {
+  while (nsDisplayItem* item = aList->RemoveBottom()) {
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     item->SetMergedPreProcessed(false, true);
 #endif
 
     // If we have a previously initialized old items list, then it can differ
     // from the current list due to items removed for having a deleted frame.
     // We can't easily remove these, since the DAG has entries for those indices
     // and it's hard to rewrite in-place.
@@ -336,23 +338,27 @@ bool RetainedDisplayListBuilder::PreProc
     if (aKeepLinked) {
       item->SetReused(true);
       if (item->GetChildren()) {
         item->UpdateBounds(Builder());
       }
       if (item->GetType() == DisplayItemType::TYPE_SUBDOCUMENT) {
         IncrementSubDocPresShellPaintCount(item);
       }
-      aList->AppendToTop(item);
+      out.AppendToTop(item);
     }
     i++;
   }
 
   MOZ_RELEASE_ASSERT(aList->mOldItems.Length() == aList->mDAG.Length());
 
+  if (aKeepLinked) {
+    aList->AppendToTop(&out);
+  }
+
   return true;
 }
 
 void IncrementPresShellPaintCount(nsDisplayListBuilder* aBuilder,
                                   nsDisplayItem* aItem) {
   MOZ_ASSERT(aItem->GetType() == DisplayItemType::TYPE_SUBDOCUMENT);
 
   nsSubDocumentFrame* subDocFrame =
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -3239,16 +3239,35 @@ class nsDisplayList {
   nsDisplayList TakeItems() {
     nsDisplayList list = std::move(*this);
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     list.mAllowNonEmptyDestruction = true;
 #endif
     return list;
   }
 
+  nsDisplayItem* RemoveBottom() {
+    if (!mBottom) {
+      return nullptr;
+    }
+
+    nsDisplayItem* bottom = mBottom->mValue;
+    mBottom = mBottom->mNext;
+
+    if (!mBottom) {
+      // No bottom item means no items at all.
+      mTop = nullptr;
+    }
+
+    MOZ_ASSERT(mLength > 0);
+    mLength--;
+
+    return bottom;
+  }
+
   /**
    * Paint the list to the rendering context. We assume that (0,0) in aCtx
    * corresponds to the origin of the reference frame. For best results,
    * aCtx's current transform should make (0,0) pixel-aligned. The
    * rectangle in aDirtyRect is painted, which *must* be contained in the
    * dirty rect used to construct the display list.
    *
    * If aFlags contains PAINT_USE_WIDGET_LAYERS and