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 374938 a57ff8701dc2a1132e404cf4c56a571eb1713c6d
parent 374937 52df7ecbca614921cfc86fd51c0582679ec5041d
child 374939 4a2a58be8c6c54dbf85b90aa85e4d4281e72088f
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1338921
milestone54.0a1
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___ */