Bug 1338921 - Collect and coalesce adjacent siblings for lazy frame construction. r=emilio
authorBobby Holley <bobbyholley@gmail.com>
Thu, 02 Mar 2017 22:51:39 -0800
changeset 345911 a57ff8701dc2a1132e404cf4c56a571eb1713c6d
parent 345910 52df7ecbca614921cfc86fd51c0582679ec5041d
child 345912 4a2a58be8c6c54dbf85b90aa85e4d4281e72088f
push id31451
push usercbook@mozilla.com
push dateMon, 06 Mar 2017 09:52:09 +0000
treeherdermozilla-central@7099e03837e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1338921
milestone54.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 1338921 - Collect and coalesce adjacent siblings for lazy frame construction. r=emilio
layout/base/RestyleManager.cpp
layout/base/nsStyleChangeList.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -1385,17 +1385,53 @@ RestyleManager::ProcessRestyledFrames(ns
   for (const nsStyleChangeData& data : aChangeList) {
     if (data.mFrame) {
       propTable->Set(data.mFrame, ChangeListProperty(), true);
     }
   }
 
   bool didUpdateCursor = false;
 
-  for (const nsStyleChangeData& data : aChangeList) {
+  for (size_t i = 0; i < aChangeList.Length(); ++i) {
+
+    // Collect and coalesce adjacent siblings for lazy frame construction.
+    // Eventually it would be even better to make RecreateFramesForContent
+    // accept a range and coalesce all adjacent reconstructs (bug 1344139).
+    size_t lazyRangeStart = i;
+    while (i < aChangeList.Length() &&
+           aChangeList[i].mContent &&
+           aChangeList[i].mContent->HasFlag(NODE_NEEDS_FRAME) &&
+           (i == lazyRangeStart ||
+            aChangeList[i - 1].mContent->GetNextSibling() == aChangeList[i].mContent))
+    {
+      MOZ_ASSERT(aChangeList[i].mHint & nsChangeHint_ReconstructFrame);
+      MOZ_ASSERT(!aChangeList[i].mFrame);
+      MOZ_ASSERT(!aChangeList[i].mContent->GetPrimaryFrame());
+      ++i;
+    }
+    if (i != lazyRangeStart) {
+      nsIContent* start = aChangeList[lazyRangeStart].mContent;
+      nsIContent* end = aChangeList[i-1].mContent->GetNextSibling();
+      nsIContent* container = start->GetFlattenedTreeParent();
+      MOZ_ASSERT(container);
+      if (!end) {
+        frameConstructor->ContentAppended(container, start, false);
+      } else {
+        frameConstructor->ContentRangeInserted(container, start, end, nullptr, false);
+      }
+    }
+    for (size_t j = lazyRangeStart; j < i; ++j) {
+      MOZ_ASSERT_IF(aChangeList[j].mContent->GetPrimaryFrame(),
+                    !aChangeList[j].mContent->HasFlag(NODE_NEEDS_FRAME));
+    }
+    if (i == aChangeList.Length()) {
+      break;
+    }
+
+    const nsStyleChangeData& data = aChangeList[i];
     nsIFrame* frame = data.mFrame;
     nsIContent* content = data.mContent;
     nsChangeHint hint = data.mHint;
     bool didReflowThisFrame = false;
 
     NS_ASSERTION(!(hint & nsChangeHint_AllReflowHints) ||
                  (hint & nsChangeHint_NeedReflow),
                  "Reflow hint bits set without actually asking for a reflow");
--- a/layout/base/nsStyleChangeList.h
+++ b/layout/base/nsStyleChangeList.h
@@ -31,15 +31,17 @@ class nsStyleChangeList : private AutoTA
   typedef AutoTArray<nsStyleChangeData, 10> base_type;
   nsStyleChangeList(const nsStyleChangeList&) = delete;
 
 public:
   using base_type::begin;
   using base_type::end;
   using base_type::IsEmpty;
   using base_type::Clear;
+  using base_type::Length;
+  using base_type::operator[];
 
   nsStyleChangeList() { MOZ_COUNT_CTOR(nsStyleChangeList); }
   ~nsStyleChangeList() { MOZ_COUNT_DTOR(nsStyleChangeList); }
   void AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChangeHint aHint);
 };
 
 #endif /* nsStyleChangeList_h___ */