Bug 1235321 - Enable using line cursor to optimize reflowing absolute frames. r=bz
authorXidorn Quan <quanxunzhen@gmail.com>
Wed, 13 Apr 2016 13:42:28 +1000
changeset 331190 23aad06080afc4980fe516ac98cdc1d315b67115
parent 331189 e02a840a52f6df6a2a046b11c5a89caa444829be
child 331191 f7b174cd5ad1d71d77e58e9c3bffe2415ad22802
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1235321
milestone48.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 1235321 - Enable using line cursor to optimize reflowing absolute frames. r=bz MozReview-Commit-ID: 4tVq5S4eTtS
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1391,20 +1391,26 @@ nsBlockFrame::Reflow(nsPresContext*     
                              containingBlockSize.GetPhysicalSize(parentWM));
       AbsPosReflowFlags flags = AbsPosReflowFlags::eConstrainHeight;
       if (cbWidthChanged) {
         flags |= AbsPosReflowFlags::eCBWidthChanged;
       }
       if (cbHeightChanged) {
         flags |= AbsPosReflowFlags::eCBHeightChanged;
       }
+      // Setup the line cursor here to optimize line searching for
+      // calculating hypothetical position of absolutely-positioned
+      // frames. The line cursor is immediately cleared afterward to
+      // avoid affecting the display list generation.
+      SetupLineCursor();
       absoluteContainer->Reflow(this, aPresContext, *reflowState,
                                 state.mReflowStatus,
                                 containingBlock, flags,
                                 &aMetrics.mOverflowAreas);
+      ClearLineCursor();
     }
   }
 
   FinishAndStoreOverflow(&aMetrics);
 
   // Clear the float manager pointer in the block reflow state so we
   // don't waste time translating the coordinate system back on a dead
   // float manager.
@@ -5486,65 +5492,69 @@ nsBlockInFlowLineIterator::nsBlockInFlow
   : mFrame(aFrame), mLineList(&aFrame->mLines)
 {
   *aFoundValidLine = false;
 
   nsIFrame* child = FindChildContaining(aFrame, aFindFrame);
   if (!child)
     return;
 
+  line_iterator line_end = aFrame->end_lines();
   // Try to use the cursor if it exists, otherwise fall back to the first line
-  nsLineBox* cursor = aFrame->GetLineCursor();
-  if (!cursor) {
-    line_iterator iter = aFrame->begin_lines();
-    if (iter != aFrame->end_lines()) {
-      cursor = iter;
-    }
-  }
-
-  if (cursor) {
+  if (nsLineBox* const cursor = aFrame->GetLineCursor()) {
+    mLine = line_end;
     // Perform a simultaneous forward and reverse search starting from the
     // line cursor.
     nsBlockFrame::line_iterator line = aFrame->line(cursor);
     nsBlockFrame::reverse_line_iterator rline = aFrame->rline(cursor);
-    nsBlockFrame::line_iterator line_end = aFrame->end_lines();
     nsBlockFrame::reverse_line_iterator rline_end = aFrame->rend_lines();
     // rline is positioned on the line containing 'cursor', so it's not
     // rline_end. So we can safely increment it (i.e. move it to one line
     // earlier) to start searching there.
     ++rline;
     while (line != line_end || rline != rline_end) {
       if (line != line_end) {
         if (line->Contains(child)) {
-          *aFoundValidLine = true;
           mLine = line;
-          return;
+          break;
         }
         ++line;
       }
       if (rline != rline_end) {
         if (rline->Contains(child)) {
-          *aFoundValidLine = true;
           mLine = rline;
-          return;
+          break;
         }
         ++rline;
       }
     }
-    // Didn't find the line
-  }
+    if (mLine != line_end) {
+      *aFoundValidLine = true;
+      if (mLine != cursor) {
+        aFrame->Properties().Set(nsBlockFrame::LineCursorProperty(), mLine);
+      }
+      return;
+    }
+  } else {
+    for (mLine = aFrame->begin_lines(); mLine != line_end; ++mLine) {
+      if (mLine->Contains(child)) {
+        *aFoundValidLine = true;
+        return;
+      }
+    }
+  }
+  // Didn't find the line
+  MOZ_ASSERT(mLine == line_end, "mLine should be line_end at this point");
 
   // If we reach here, it means that we have not been able to find the
   // desired frame in our in-flow lines.  So we should start looking at
   // our overflow lines. In order to do that, we set mLine to the end
   // iterator so that FindValidLine starts to look at overflow lines,
   // if any.
 
-  mLine = aFrame->end_lines();
-
   if (!FindValidLine())
     return;
 
   do {
     if (mLine->Contains(child)) {
       *aFoundValidLine = true;
       return;
     }
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -167,18 +167,19 @@ public:
   void ClearLineCursor();
   // Get the first line that might contain y-coord 'y', or nullptr if you must search
   // all lines. If nonnull is returned then we guarantee that the lines'
   // combinedArea.ys and combinedArea.yMosts are non-decreasing.
   // The actual line returned might not contain 'y', but if not, it is guaranteed
   // to be before any line which does contain 'y'.
   nsLineBox* GetFirstLineContaining(nscoord y);
   // Set the line cursor to our first line. Only call this if you
-  // guarantee that the lines' combinedArea.ys and combinedArea.yMosts
-  // are non-decreasing.
+  // guarantee that either the lines' combinedArea.ys and combinedArea.
+  // yMosts are non-decreasing, or the line cursor is cleared before
+  // building the display list of this frame.
   void SetupLineCursor();
 
   virtual void ChildIsDirty(nsIFrame* aChild) override;
   virtual bool IsVisibleInSelection(nsISelection* aSelection) override;
 
   virtual bool IsEmpty() override;
   virtual bool CachedIsEmpty() override;
   virtual bool IsSelfEmpty() override;