Bug 1416448 - Don't update the ASR during merging for an empty container item, since we can't compute the ASR of the contents. r=miko
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 13 Nov 2017 09:02:48 +1300
changeset 391469 2ec68ec7ff01827c8b12e9b0c1817920de967b9a
parent 391468 559f4487dc65fa76687447282d40b0eee60f20bf
child 391470 d5e1ed773fefe2eb9d52402dd74b5fea19b8b4a4
push id32888
push usernbeleuzu@mozilla.com
push dateMon, 13 Nov 2017 09:54:04 +0000
treeherdermozilla-central@fc194660762d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmiko
bugs1416448
milestone58.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 1416448 - Don't update the ASR during merging for an empty container item, since we can't compute the ASR of the contents. r=miko
layout/painting/RetainedDisplayListBuilder.cpp
layout/painting/RetainedDisplayListBuilder.h
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -278,27 +278,31 @@ RetainedDisplayListBuilder::IncrementSub
 
   nsIPresShell* presShell = subDocFrame->GetSubdocumentPresShellForPainting(0);
   MOZ_ASSERT(presShell);
 
   mBuilder.IncrementPresShellPaintCount(presShell);
 }
 
 void UpdateASR(nsDisplayItem* aItem,
-               const ActiveScrolledRoot* aContainerASR)
+               Maybe<const ActiveScrolledRoot*>& aContainerASR)
 {
+  if (!aContainerASR) {
+    return;
+  }
+
   nsDisplayWrapList* wrapList = aItem->AsDisplayWrapList();
   if (!wrapList) {
-    aItem->SetActiveScrolledRoot(aContainerASR);
+    aItem->SetActiveScrolledRoot(aContainerASR.value());
     return;
   }
 
   wrapList->SetActiveScrolledRoot(
     ActiveScrolledRoot::PickAncestor(wrapList->GetFrameActiveScrolledRoot(),
-                                     aContainerASR));
+                                     aContainerASR.value()));
 }
 
 /**
  * Takes two display lists and merges them into an output list.
  *
  * The basic algorithm is:
  *
  * For-each item in the new list:
@@ -342,32 +346,30 @@ void UpdateASR(nsDisplayItem* aItem,
  * instance of A.
  *
  * Merged List: A, B
  */
 void
 RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
                                               nsDisplayList* aOldList,
                                               nsDisplayList* aOutList,
-                                              const ActiveScrolledRoot** aOutContainerASR)
+                                              Maybe<const ActiveScrolledRoot*>& aOutContainerASR)
 {
   nsDisplayList merged(&mBuilder);
-  const ActiveScrolledRoot* containerASR = nullptr;
-
   const auto UseItem = [&](nsDisplayItem* aItem) {
     const ActiveScrolledRoot* itemClipASR =
       aItem->GetClipChain() ? aItem->GetClipChain()->mASR : nullptr;
 
     const ActiveScrolledRoot* finiteBoundsASR = ActiveScrolledRoot::PickDescendant(
       itemClipASR, aItem->GetActiveScrolledRoot());
-    if (merged.IsEmpty()) {
-      containerASR = finiteBoundsASR;
+    if (!aOutContainerASR) {
+      aOutContainerASR = Some(finiteBoundsASR);
     } else {
-      containerASR =
-        ActiveScrolledRoot::PickAncestor(containerASR, finiteBoundsASR);
+      aOutContainerASR =
+        Some(ActiveScrolledRoot::PickAncestor(aOutContainerASR.value(), finiteBoundsASR));
     }
 
     merged.AppendToTop(aItem);
   };
 
   const auto ReuseItem = [&](nsDisplayItem* aItem) {
     UseItem(aItem);
     aItem->SetReused(true);
@@ -407,19 +409,19 @@ RetainedDisplayListBuilder::MergeDisplay
     if (nsDisplayItem* oldItem = oldListLookup.Get({ newItem->Frame(), newItem->GetPerFrameKey() })) {
       if (oldItem->IsReused()) {
         // If there's a matching item in the old list, but we've already put it into the
         // merged list then stick with that one. Merge any child lists, and then delete the
         // new item. This solves example 2 from above.
 
         if (oldItem->GetChildren()) {
           MOZ_ASSERT(newItem->GetChildren());
-          const ActiveScrolledRoot* containerASRForChildren;
+          Maybe<const ActiveScrolledRoot*> containerASRForChildren;
           MergeDisplayLists(newItem->GetChildren(), oldItem->GetChildren(),
-                            oldItem->GetChildren(), &containerASRForChildren);
+                            oldItem->GetChildren(), containerASRForChildren);
           UpdateASR(oldItem, containerASRForChildren);
           oldItem->UpdateBounds(&mBuilder);
         }
         if (oldItem->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
           MergeLayerEventRegions(oldItem, newItem);
         }
         newItem->Destroy(&mBuilder);
       } else {
@@ -427,19 +429,19 @@ RetainedDisplayListBuilder::MergeDisplay
         // items from the old list into the merged list until we get to the matched item.
         nsDisplayItem* old = nullptr;
         while ((old = aOldList->RemoveBottom()) && !IsSameItem(newItem, old)) {
           if (!IsAnyAncestorModified(old->FrameForInvalidation())) {
             // Recurse into the child list (without a matching new list) to
             // ensure that we find and remove any invalidated items.
             if (old->GetChildren()) {
               nsDisplayList empty(&mBuilder);
-              const ActiveScrolledRoot* containerASRForChildren;
+              Maybe<const ActiveScrolledRoot*> containerASRForChildren;
               MergeDisplayLists(&empty, old->GetChildren(),
-                                old->GetChildren(), &containerASRForChildren);
+                                old->GetChildren(), containerASRForChildren);
               UpdateASR(old, containerASRForChildren);
               old->UpdateBounds(&mBuilder);
             }
             ReuseItem(old);
           } else {
             oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
             old->Destroy(&mBuilder);
           }
@@ -457,19 +459,19 @@ RetainedDisplayListBuilder::MergeDisplay
           // likely to have the bigger lists and merging will be quicker.
           MergeLayerEventRegions(old, newItem);
           ReuseItem(old);
           newItem->Destroy(&mBuilder);
         } else {
           if (!IsAnyAncestorModified(old->FrameForInvalidation()) &&
               old->GetChildren()) {
             MOZ_ASSERT(newItem->GetChildren());
-            const ActiveScrolledRoot* containerASRForChildren;
+            Maybe<const ActiveScrolledRoot*> containerASRForChildren;
             MergeDisplayLists(newItem->GetChildren(), old->GetChildren(),
-                              newItem->GetChildren(), &containerASRForChildren);
+                              newItem->GetChildren(), containerASRForChildren);
             UpdateASR(newItem, containerASRForChildren);
             newItem->UpdateBounds(&mBuilder);
           }
 
           old->Destroy(&mBuilder);
           UseItem(newItem);
         }
       }
@@ -484,36 +486,33 @@ RetainedDisplayListBuilder::MergeDisplay
   while (nsDisplayItem* old = aOldList->RemoveBottom()) {
     if (!IsAnyAncestorModified(old->FrameForInvalidation())) {
       if (old->GetChildren()) {
         // We are calling MergeDisplayLists() to ensure that the display items
         // with modified or deleted children will be correctly handled.
         // Passing an empty new display list as an argument skips the merging
         // loop above and jumps back here.
         nsDisplayList empty(&mBuilder);
-        const ActiveScrolledRoot* containerASRForChildren;
+        Maybe<const ActiveScrolledRoot*> containerASRForChildren;
 
         MergeDisplayLists(&empty, old->GetChildren(),
-                          old->GetChildren(), &containerASRForChildren);
+                          old->GetChildren(), containerASRForChildren);
         UpdateASR(old, containerASRForChildren);
         old->UpdateBounds(&mBuilder);
       }
       if (old->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
         MergeLayerEventRegions(old, nullptr);
       }
       ReuseItem(old);
     } else {
       old->Destroy(&mBuilder);
     }
   }
 
   aOutList->AppendToTop(&merged);
-  if (aOutContainerASR) {
-    *aOutContainerASR = containerASR;
-  }
 }
 
 static void
 TakeAndAddModifiedFramesFromRootFrame(nsTArray<nsIFrame*>& aFrames,
                                       nsIFrame* aRootFrame)
 {
   MOZ_ASSERT(aRootFrame);
 
@@ -845,17 +844,18 @@ RetainedDisplayListBuilder::AttemptParti
       // printf_stderr("Skipping display list building since nothing needed to be done\n");
     }
 
     // |modifiedDL| can sometimes be empty here. We still perform the
     // display list merging to prune unused items (for example, items that
     // are not visible anymore) from the old list.
     // TODO: Optimization opportunity. In this case, MergeDisplayLists()
     // unnecessarily creates a hashtable of the old items.
-    MergeDisplayLists(&modifiedDL, &mList, &mList, nullptr);
+    Maybe<const ActiveScrolledRoot*> dummy;
+    MergeDisplayLists(&modifiedDL, &mList, &mList, dummy);
 
     //printf_stderr("Painting --- Merged list:\n");
     //nsFrame::PrintDisplayList(&mBuilder, mList);
 
     merged = true;
   }
 
   mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), &mList);
--- a/layout/painting/RetainedDisplayListBuilder.h
+++ b/layout/painting/RetainedDisplayListBuilder.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef RETAINEDDISPLAYLISTBUILDER_H_
 #define RETAINEDDISPLAYLISTBUILDER_H_
 
 #include "nsDisplayList.h"
+#include "mozilla/Maybe.h"
 
 struct RetainedDisplayListBuilder {
   RetainedDisplayListBuilder(nsIFrame* aReferenceFrame,
                              nsDisplayListBuilderMode aMode,
                              bool aBuildCaret)
     : mBuilder(aReferenceFrame, aMode, aBuildCaret, true)
     , mList(&mBuilder)
   {}
@@ -30,17 +31,17 @@ struct RetainedDisplayListBuilder {
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(Cached, RetainedDisplayListBuilder)
 
 private:
   void PreProcessDisplayList(nsDisplayList* aList, AnimatedGeometryRoot* aAGR);
 
   void MergeDisplayLists(nsDisplayList* aNewList,
                          nsDisplayList* aOldList,
                          nsDisplayList* aOutList,
-                         const mozilla::ActiveScrolledRoot** aOutContainerASR = nullptr);
+                         mozilla::Maybe<const mozilla::ActiveScrolledRoot*>& aOutContainerASR);
 
   bool ComputeRebuildRegion(nsTArray<nsIFrame*>& aModifiedFrames,
                             nsRect* aOutDirty,
                             AnimatedGeometryRoot** aOutModifiedAGR,
                             nsTArray<nsIFrame*>* aOutFramesWithProps);
 
   void IncrementSubDocPresShellPaintCount(nsDisplayItem* aItem);