Bug 1509579 - Part 1: Do not mark frames modified after the rebuild limit has been reached r=mattwoodrow
authorMiko Mynttinen <mikokm@gmail.com>
Thu, 29 Nov 2018 05:19:36 +0000
changeset 505313 6a516d21eae63a07573958fedb5ff291e2c393b8
parent 505312 76a737a5a6e94e14b5fad10ca62ab259a27e2615
child 505314 57816e067da5bac79091eb33436e2d45c8699079
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1509579
milestone65.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 1509579 - Part 1: Do not mark frames modified after the rebuild limit has been reached r=mattwoodrow Differential Revision: https://phabricator.services.mozilla.com/D13279
layout/generic/nsFrame.cpp
layout/painting/RetainedDisplayListBuilder.cpp
layout/painting/RetainedDisplayListBuilder.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1028,17 +1028,26 @@ nsIFrame::MarkNeedsDisplayItemRebuild()
   nsIFrame* rootFrame = PresShell()->GetRootFrame();
   MOZ_ASSERT(rootFrame);
 
   if (rootFrame->IsFrameModified()) {
     return;
   }
 
   RetainedDisplayListData* data = GetOrSetRetainedDisplayListData(rootFrame);
-  data->Flags(this) |= RetainedDisplayListData::FrameFlags::Modified;
+
+  if (data->ModifiedFramesCount() > gfxPrefs::LayoutRebuildFrameLimit()) {
+    // If the modified frames count is above the rebuild limit, mark the root
+    // frame modified, and stop marking additional frames modified.
+    data->AddModifiedFrame(rootFrame);
+    rootFrame->SetFrameIsModified(true);
+    return;
+  }
+
+  data->AddModifiedFrame(this);
   SetFrameIsModified(true);
 
   MOZ_ASSERT(
     PresContext()->LayoutPhaseCount(eLayoutPhase_DisplayListBuilding) == 0);
 
   // Hopefully this is cheap, but we could use a frame state bit to note
   // the presence of dependencies to speed it up.
   DisplayItemArray* items = GetProperty(DisplayItems());
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -36,16 +36,24 @@
  * ordering in the DAG, since they need to intersect to have an ordering and
  * we would have built both in the new list if they intersected. Given that, we
  * can align items that appear in both lists, and any items that appear between
  * matched items can be inserted into the merged list in any order.
  */
 
 using namespace mozilla;
 
+void
+RetainedDisplayListData::AddModifiedFrame(nsIFrame* aFrame)
+{
+  MOZ_ASSERT(!aFrame->IsFrameModified());
+  Flags(aFrame) |= RetainedDisplayListData::FrameFlags::Modified;
+  mModifiedFramesCount++;
+}
+
 RetainedDisplayListData*
 GetRetainedDisplayListData(nsIFrame* aRootFrame)
 {
   RetainedDisplayListData* data =
     aRootFrame->GetProperty(RetainedDisplayListData::DisplayListData());
 
   return data;
 }
--- a/layout/painting/RetainedDisplayListBuilder.h
+++ b/layout/painting/RetainedDisplayListBuilder.h
@@ -28,20 +28,30 @@ struct RetainedDisplayListData
   enum class FrameFlags : uint8_t
   {
     None = 0,
     Modified = 1 << 0,
     HasProps = 1 << 1,
     HadWillChange = 1 << 2
   };
 
+  RetainedDisplayListData()
+    : mModifiedFramesCount(0)
+  {
+  }
+
+  /**
+   * Adds the frame to modified frames list.
+   */
+  void AddModifiedFrame(nsIFrame* aFrame);
+
   /**
    * Removes all the frames from this RetainedDisplayListData.
    */
-  void Clear() { mFrames.Clear(); }
+  void Clear() { mFrames.Clear(); mModifiedFramesCount = 0; }
 
   /**
    * Returns a mutable reference to flags set for the given |aFrame|. If the
    * frame does not exist in this RetainedDisplayListData, it is added with
    * default constructible flags FrameFlags::None.
    */
   FrameFlags& Flags(nsIFrame* aFrame) { return mFrames.GetOrInsert(aFrame); }
 
@@ -52,22 +62,28 @@ struct RetainedDisplayListData
   FrameFlags GetFlags(nsIFrame* aFrame) const { return mFrames.Get(aFrame); }
 
   /**
    * Returns an iterator to the underlying frame storage.
    */
   auto Iterator() { return mFrames.Iter(); }
 
   /**
+   * Returns the count of modified frames in this RetainedDisplayListData.
+   */
+  uint32_t ModifiedFramesCount() const { return mModifiedFramesCount; }
+
+  /**
    * Removes the given |aFrame| from this RetainedDisplayListData.
    */
   bool Remove(nsIFrame* aFrame) { return mFrames.Remove(aFrame); }
 
 private:
   nsDataHashtable<nsPtrHashKey<nsIFrame>, FrameFlags> mFrames;
+  uint32_t mModifiedFramesCount;
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(RetainedDisplayListData::FrameFlags)
 
 /**
  * Returns RetainedDisplayListData property for the given |aRootFrame|, or
  * nullptr if the property is not set.
  */