Bug 1367906: Cache the presence of rounded corners upon style changes. r=dbaron r=mattwoodrow
authorBas Schouten <bschouten@mozilla.com>
Fri, 26 May 2017 16:56:55 +0000
changeset 409064 bfa432683e279c14b37912a5c45638005f2b0b07
parent 408994 8b19b5019913ad412b7826a2b7c296b0bc6a230a
child 409065 4787ff70ae13e6ae43b89a09dd620df5a5ad3824
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, mattwoodrow
bugs1367906
milestone55.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 1367906: Cache the presence of rounded corners upon style changes. r=dbaron r=mattwoodrow Profiling indicates a significant amount of time is spent during displaylist building accessing style information in order to detect border radii. This is a cost that for frames with no border radii only needs to be paid when the style changes. Since nsIFrame still has 16 bits available for storing data without growing it in size, this patch recomputes whether there are border radii upon DidGetStyleContext and stores that information in one of these unused bits. MozReview-Commit-ID: 4Jm29qUwXq3
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1008,16 +1008,18 @@ nsFrame::DidSetStyleContext(nsStyleConte
   // bidi algorithm, we need to call |SetBidiEnabled| on the pres
   // context before reflow starts.  See bug 115921.
   if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
     PresContext()->SetBidiEnabled();
   }
 
   RemoveStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS |
                   NS_FRAME_SIMPLE_DISPLAYLIST);
+
+  mMayHaveRoundedCorners = true;
 }
 
 void
 nsIFrame::ReparentFrameViewTo(nsViewManager* aViewManager,
                               nsView*        aNewParentView,
                               nsView*        aOldParentView)
 {
   if (HasView()) {
@@ -1582,32 +1584,40 @@ nsIFrame::OutsetBorderRadii(nscoord aRad
     }
   }
 }
 
 /* virtual */ bool
 nsIFrame::GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
                          Sides aSkipSides, nscoord aRadii[8]) const
 {
+  if (!mMayHaveRoundedCorners) {
+    memset(aRadii, 0, sizeof(nscoord) * 8);
+    return false;
+  }
+
   if (IsThemed()) {
     // When we're themed, the native theme code draws the border and
     // background, and therefore it doesn't make sense to tell other
     // code that's interested in border-radius that we have any radii.
     //
     // In an ideal world, we might have a way for the them to tell us an
     // border radius, but since we don't, we're better off assuming
     // zero.
     NS_FOR_CSS_HALF_CORNERS(corner) {
       aRadii[corner] = 0;
     }
     return false;
   }
-  return ComputeBorderRadii(StyleBorder()->mBorderRadius,
-                            aFrameSize, aBorderArea,
-                            aSkipSides, aRadii);
+
+  const_cast<nsIFrame*>(this)->mMayHaveRoundedCorners =
+    ComputeBorderRadii(StyleBorder()->mBorderRadius,
+                       aFrameSize, aBorderArea,
+                       aSkipSides, aRadii);
+  return mMayHaveRoundedCorners;
 }
 
 bool
 nsIFrame::GetBorderRadii(nscoord aRadii[8]) const
 {
   nsSize sz = GetSize();
   return GetBorderRadii(sz, sz, GetSkipSides(), aRadii);
 }
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -611,16 +611,17 @@ public:
     : mRect()
     , mContent(nullptr)
     , mStyleContext(nullptr)
     , mParent(nullptr)
     , mNextSibling(nullptr)
     , mPrevSibling(nullptr)
     , mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY)
     , mClass(aID)
+    , mMayHaveRoundedCorners(false)
   {
     mozilla::PodZero(&mOverflow);
   }
 
   nsPresContext* PresContext() const {
     return StyleContext()->PresContext();
   }
 
@@ -3916,16 +3917,19 @@ protected:
   } mOverflow;
 
   /** @see GetWritingMode() */
   mozilla::WritingMode mWritingMode;
 
   /** The ClassID of the concrete class of this instance. */
   ClassID mClass; // 1 byte
 
+  bool mMayHaveRoundedCorners : 1;
+  // There should be a 15-bit gap left here.
+
   // Helpers
   /**
    * Can we stop inside this frame when we're skipping non-rendered whitespace?
    * @param  aForward [in] Are we moving forward (or backward) in content order.
    * @param  aOffset [in/out] At what offset into the frame to start looking.
    *         on output - what offset was reached (whether or not we found a place to stop).
    * @return STOP: An appropriate offset was found within this frame,
    *         and is given by aOffset.