Bug 1151243 part 1 - Replace three bool params for nsAbsoluteContainingBlock::Reflow with a flag param (idempotent patch). r=dholbert
authorMats Palmgren <mats@mozilla.com>
Tue, 22 Dec 2015 23:03:16 +0100
changeset 277423 0937bbc778f348a0ad6e55cfca523688ee7667b3
parent 277422 5e1c24beaa5bea7fd9e088ad2c49c9aa94ccb78a
child 277424 a296d149c69e229d6c633da0d2f91ec3d4e5f1de
push id29822
push usercbook@mozilla.com
push dateWed, 23 Dec 2015 11:00:24 +0000
treeherdermozilla-central@35b211eaad1f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1151243
milestone46.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 1151243 part 1 - Replace three bool params for nsAbsoluteContainingBlock::Reflow with a flag param (idempotent patch). r=dholbert
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsAbsoluteContainingBlock.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsViewportFrame.cpp
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -108,19 +108,17 @@ nsAbsoluteContainingBlock::RemoveFrame(n
 }
 
 void
 nsAbsoluteContainingBlock::Reflow(nsContainerFrame*        aDelegatingFrame,
                                   nsPresContext*           aPresContext,
                                   const nsHTMLReflowState& aReflowState,
                                   nsReflowStatus&          aReflowStatus,
                                   const nsRect&            aContainingBlock,
-                                  bool                     aConstrainHeight,
-                                  bool                     aCBWidthChanged,
-                                  bool                     aCBHeightChanged,
+                                  AbsPosReflowFlags        aFlags,
                                   nsOverflowAreas*         aOverflowAreas)
 {
   nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
 
   bool reflowAll = aReflowState.ShouldReflowAllKids();
 
   // The 'width' check below is an optimization to avoid the virtual GetType()
   // call in most cases.  'aContainingBlock' isn't used for grid items,
@@ -129,25 +127,26 @@ nsAbsoluteContainingBlock::Reflow(nsCont
   const bool isGrid =
     aContainingBlock.width == nsGridContainerFrame::VERY_LIKELY_A_GRID_CONTAINER &&
     aDelegatingFrame->GetType() == nsGkAtoms::gridContainerFrame;
 
   nsIFrame* kidFrame;
   nsOverflowContinuationTracker tracker(aDelegatingFrame, true);
   for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
     bool kidNeedsReflow = reflowAll || NS_SUBTREE_DIRTY(kidFrame) ||
-      FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged);
+      FrameDependsOnContainer(kidFrame,
+                              !!(aFlags & AbsPosReflowFlags::eCBWidthChanged),
+                              !!(aFlags & AbsPosReflowFlags::eCBHeightChanged));
     if (kidNeedsReflow && !aPresContext->HasPendingInterrupt()) {
       // Reflow the frame
       nsReflowStatus  kidStatus = NS_FRAME_COMPLETE;
       const nsRect& cb = isGrid ? nsGridContainerFrame::GridItemCB(kidFrame)
                                 : aContainingBlock;
       ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, cb,
-                          aConstrainHeight, kidFrame, kidStatus,
-                          aOverflowAreas);
+                          aFlags, kidFrame, kidStatus, aOverflowAreas);
       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
       if (!NS_FRAME_IS_FULLY_COMPLETE(kidStatus) &&
           aDelegatingFrame->IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
         // Need a continuation
         if (!nextFrame) {
           nextFrame =
             aPresContext->PresShell()->FrameConstructor()->
               CreateContinuingFrame(aPresContext, kidFrame, aDelegatingFrame);
@@ -349,17 +348,17 @@ nsAbsoluteContainingBlock::DoMarkFramesD
 // mChildListID == kFixedList, the height is unconstrained.
 // since we don't allow replicated frames to split.
 
 void
 nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame*                aDelegatingFrame,
                                                nsPresContext*           aPresContext,
                                                const nsHTMLReflowState& aReflowState,
                                                const nsRect&            aContainingBlock,
-                                               bool                     aConstrainBSize,
+                                               AbsPosReflowFlags        aFlags,
                                                nsIFrame*                aKidFrame,
                                                nsReflowStatus&          aStatus,
                                                nsOverflowAreas*         aOverflowAreas)
 {
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent);
     printf("abs pos ");
@@ -399,17 +398,17 @@ nsAbsoluteContainingBlock::ReflowAbsolut
 
   // Get the border values
   WritingMode outerWM = aReflowState.GetWritingMode();
   const LogicalMargin border(outerWM,
                              aReflowState.mStyleBorder->GetComputedBorder());
   const LogicalMargin margin =
     kidReflowState.ComputedLogicalMargin().ConvertTo(outerWM, wm);
   bool constrainBSize = (aReflowState.AvailableBSize() != NS_UNCONSTRAINEDSIZE)
-    && aConstrainBSize
+    && (aFlags & AbsPosReflowFlags::eConstrainHeight)
        // Don't split if told not to (e.g. for fixed frames)
     && (aDelegatingFrame->GetType() != nsGkAtoms::inlineFrame)
        //XXX we don't handle splitting frames for inline absolute containing blocks yet
     && (aKidFrame->GetLogicalRect(aContainingBlock.Size()).BStart(wm) <=
         aReflowState.AvailableBSize());
        // Don't split things below the fold. (Ideally we shouldn't *have*
        // anything totally below the fold, but we can't position frames
        // across next-in-flow breaks yet.
--- a/layout/generic/nsAbsoluteContainingBlock.h
+++ b/layout/generic/nsAbsoluteContainingBlock.h
@@ -8,16 +8,17 @@
  * object that is a containing block for them
  */
 
 #ifndef nsAbsoluteContainingBlock_h___
 #define nsAbsoluteContainingBlock_h___
 
 #include "nsFrameList.h"
 #include "nsIFrame.h"
+#include "mozilla/TypedEnumBits.h"
 
 class nsContainerFrame;
 struct nsHTMLReflowState;
 class nsPresContext;
 
 /**
  * This class contains the logic for being an absolute containing block.  This
  * class is used within viewport frames (for frames representing content with
@@ -63,38 +64,45 @@ public:
   void InsertFrames(nsIFrame*      aDelegatingFrame,
                     ChildListID    aListID,
                     nsIFrame*      aPrevFrame,
                     nsFrameList&   aFrameList);
   void RemoveFrame(nsIFrame*      aDelegatingFrame,
                    ChildListID    aListID,
                    nsIFrame*      aOldFrame);
 
+  enum class AbsPosReflowFlags {
+    eConstrainHeight = 0x1,
+    eCBWidthChanged  = 0x2,
+    eCBHeightChanged = 0x4,
+    eCBWidthAndHeightChanged = eCBWidthChanged | eCBHeightChanged,
+  };
+
   /**
    * Called by the delegating frame after it has done its reflow first. This
    * function will reflow any absolutely positioned child frames that need to
    * be reflowed, e.g., because the absolutely positioned child frame has
    * 'auto' for an offset, or a percentage based width or height.
    *
    * @param aOverflowAreas, if non-null, is unioned with (in the local
    * coordinate space) the overflow areas of the absolutely positioned
    * children.
    *
    * @param aReflowStatus is assumed to be already-initialized, e.g. with the
    * status of the delegating frame's main reflow. This function merges in the
    * statuses of the absolutely positioned children's reflows.
+   *
+   * @param aFlags zero or more AbsPosReflowFlags
    */
   void Reflow(nsContainerFrame*        aDelegatingFrame,
               nsPresContext*           aPresContext,
               const nsHTMLReflowState& aReflowState,
               nsReflowStatus&          aReflowStatus,
               const nsRect&            aContainingBlock,
-              bool                     aConstrainHeight,
-              bool                     aCBWidthChanged,
-              bool                     aCBHeightChanged,
+              AbsPosReflowFlags        aFlags,
               nsOverflowAreas*         aOverflowAreas);
 
   void DestroyFrames(nsIFrame* aDelegatingFrame,
                      nsIFrame* aDestructRoot);
 
   bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); }
 
   /**
@@ -116,17 +124,17 @@ protected:
    */
   bool FrameDependsOnContainer(nsIFrame* aFrame, bool aCBWidthChanged,
                                bool aCBHeightChanged);
 
   void ReflowAbsoluteFrame(nsIFrame*                aDelegatingFrame,
                            nsPresContext*           aPresContext,
                            const nsHTMLReflowState& aReflowState,
                            const nsRect&            aContainingBlockRect,
-                           bool                     aConstrainHeight,
+                           AbsPosReflowFlags        aFlags,
                            nsIFrame*                aKidFrame,
                            nsReflowStatus&          aStatus,
                            nsOverflowAreas*         aOverflowAreas);
 
   /**
    * Mark our absolute frames dirty.
    * @param aMarkAllDirty if true, all will be marked with NS_FRAME_IS_DIRTY.
    * Otherwise, the size-dependant ones will be marked with
@@ -137,9 +145,12 @@ protected:
 protected:
   nsFrameList mAbsoluteFrames;  // additional named child list
 
 #ifdef DEBUG
   ChildListID const mChildListID; // kFixedList or kAbsoluteList
 #endif
 };
 
+namespace mozilla {
+  MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsAbsoluteContainingBlock::AbsPosReflowFlags)
+}
 #endif /* nsnsAbsoluteContainingBlock_h___ */
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -56,16 +56,17 @@
 
 static const int MIN_LINES_NEEDING_CURSOR = 20;
 
 static const char16_t kDiscCharacter = 0x2022;
 
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::layout;
+typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 
 static void MarkAllDescendantLinesDirty(nsBlockFrame* aBlock)
 {
   nsLineList::iterator line = aBlock->begin_lines();
   nsLineList::iterator endLine = aBlock->end_lines();
   while (line != endLine) {
     if (line->IsBlock()) {
       nsIFrame* f = line->mFirstChild;
@@ -1361,20 +1362,26 @@ nsBlockFrame::Reflow(nsPresContext*     
       // viewport height, which can't change during incremental
       // reflow.
       bool cbHeightChanged =
         !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) &&
         aMetrics.Height() != oldSize.height;
 
       nsRect containingBlock(nsPoint(0, 0),
                              containingBlockSize.GetPhysicalSize(parentWM));
+      AbsPosReflowFlags flags = AbsPosReflowFlags::eConstrainHeight;
+      if (cbWidthChanged) {
+        flags |= AbsPosReflowFlags::eCBWidthChanged;
+      }
+      if (cbHeightChanged) {
+        flags |= AbsPosReflowFlags::eCBHeightChanged;
+      }
       absoluteContainer->Reflow(this, aPresContext, *reflowState,
                                 state.mReflowStatus,
-                                containingBlock, true,
-                                cbWidthChanged, cbHeightChanged,
+                                containingBlock, flags,
                                 &aMetrics.mOverflowAreas);
     }
   }
 
   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
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -103,16 +103,17 @@
 #include "nsThemeConstants.h"
 
 using namespace mozilla;
 using namespace mozilla::css;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
+typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 
 namespace mozilla {
 namespace gfx {
 class VRHMDInfo;
 } // namespace gfx
 } // namespace mozilla
 
 // Struct containing cached metrics for box-wrapped frames.
@@ -4661,19 +4662,23 @@ nsFrame::ReflowAbsoluteFrames(nsPresCont
     nscoord containingBlockHeight =
       aDesiredSize.Height() - usedBorder.TopBottom();
     MOZ_ASSERT(containingBlockHeight >= 0);
 
     nsContainerFrame* container = do_QueryFrame(this);
     NS_ASSERTION(container, "Abs-pos children only supported on container frames for now");
 
     nsRect containingBlock(0, 0, containingBlockWidth, containingBlockHeight);
+    AbsPosReflowFlags flags =
+      AbsPosReflowFlags::eCBWidthAndHeightChanged; // XXX could be optimized
+    if (aConstrainBSize) {
+      flags |= AbsPosReflowFlags::eConstrainHeight;
+    }
     absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus,
-                              containingBlock,
-                              aConstrainBSize, true, true, // XXX could be optimized
+                              containingBlock, flags,
                               &aDesiredSize.mOverflowAreas);
   }
 }
 
 void
 nsFrame::PushDirtyBitToAbsoluteFrames()
 {
   if (!(GetStateBits() & NS_FRAME_IS_DIRTY)) {
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -22,16 +22,17 @@
 #include "nsIFrameInlines.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
 #include "nsReadableUtils.h"
 #include "nsRuleNode.h"
 #include "nsStyleContext.h"
 
 using namespace mozilla;
+typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 typedef nsGridContainerFrame::TrackSize TrackSize;
 const uint32_t nsGridContainerFrame::kTranslatedMaxLine =
   uint32_t(nsStyleGridLine::kMaxLine - nsStyleGridLine::kMinLine);
 const uint32_t nsGridContainerFrame::kAutoLine = kTranslatedMaxLine + 3457U;
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TrackSize::StateBits)
 
 class nsGridContainerFrame::GridItemCSSOrderIterator
@@ -3242,19 +3243,21 @@ nsGridContainerFrame::ReflowChildren(Gri
           child->Properties().Set(GridItemContainingBlockRect(), cb);
         }
         *cb = itemCB.GetPhysicalRect(wm, gridCBPhysicalSize);
       }
       // This rect isn't used at all for layout so we use it to optimize
       // away the virtual GetType() call in the callee in most cases.
       // @see nsAbsoluteContainingBlock::Reflow
       nsRect dummyRect(0, 0, VERY_LIKELY_A_GRID_CONTAINER, 0);
+      AbsPosReflowFlags flags =
+        AbsPosReflowFlags::eCBWidthAndHeightChanged; // XXX could be optimized
+      flags |= AbsPosReflowFlags::eConstrainHeight;
       GetAbsoluteContainingBlock()->Reflow(this, pc, *aState.mReflowState,
-                                           aStatus, dummyRect, true,
-                                           true, true, // XXX could be optimized
+                                           aStatus, dummyRect, flags,
                                            &aDesiredSize.mOverflowAreas);
     }
   }
 }
 
 void
 nsGridContainerFrame::Reflow(nsPresContext*           aPresContext,
                              nsHTMLReflowMetrics&     aDesiredSize,
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -13,16 +13,17 @@
 #include "nsIScrollableFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsCanvasFrame.h"
 #include "nsAbsoluteContainingBlock.h"
 #include "GeckoProfiler.h"
 #include "nsIMozBrowserFrame.h"
 
 using namespace mozilla;
+typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 
 ViewportFrame*
 NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) ViewportFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(ViewportFrame)
@@ -345,20 +346,20 @@ ViewportFrame::Reflow(nsPresContext*    
 
     nsRect rect = AdjustReflowStateAsContainingBlock(&reflowState);
     nsOverflowAreas* overflowAreas = &aDesiredSize.mOverflowAreas;
     nsIScrollableFrame* rootScrollFrame =
                     aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
     if (rootScrollFrame && !rootScrollFrame->IsIgnoringViewportClipping()) {
       overflowAreas = nullptr;
     }
+    AbsPosReflowFlags flags =
+      AbsPosReflowFlags::eCBWidthAndHeightChanged; // XXX could be optimized
     GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus,
-                                         rect,
-                                         false, true, true, // XXX could be optimized
-                                         overflowAreas);
+                                         rect, flags, overflowAreas);
   }
 
   if (mFrames.NotEmpty()) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild());
   }
 
   // If we were dirty then do a repaint
   if (GetStateBits() & NS_FRAME_IS_DIRTY) {