Avoid containingBlock() calls when no writing mode flipping is needed.
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Apr 2015 18:36:56 +0000 (18:36 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Apr 2015 18:36:56 +0000 (18:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144407

Reviewed by Simon Fraser.

Add a bool to RenderView that indicates whether or not any flipped blocks have been
added to the view. Once tainted, the view just stays dirty forever. If no flipped
blocks are ever seen, we can then optimize away calls to containingBlock().

The motivation for this patch is to improve layer position updating, which makes many
calls to topLeftLocationOffset(), one of the functions that can be optimized by this
change.

* rendering/RenderBox.cpp:
(WebCore::RenderBox::layoutOverflowRectForPropagation):
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::updateFromStyle):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::calculateClipRects):
* rendering/RenderLineBoxList.cpp:
(WebCore::RenderLineBoxList::rangeIntersectsRect):
* rendering/RenderView.cpp:
(WebCore::RenderView::RenderView):
* rendering/RenderView.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@183636 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLineBoxList.cpp
Source/WebCore/rendering/RenderView.cpp
Source/WebCore/rendering/RenderView.h

index 0309e0f..ea22507 100644 (file)
@@ -1,3 +1,30 @@
+2015-04-29  David Hyatt  <hyatt@apple.com>
+
+        Avoid containingBlock() calls when no writing mode flipping is needed.
+        https://bugs.webkit.org/show_bug.cgi?id=144407
+
+        Reviewed by Simon Fraser.
+
+        Add a bool to RenderView that indicates whether or not any flipped blocks have been
+        added to the view. Once tainted, the view just stays dirty forever. If no flipped
+        blocks are ever seen, we can then optimize away calls to containingBlock().
+
+        The motivation for this patch is to improve layer position updating, which makes many
+        calls to topLeftLocationOffset(), one of the functions that can be optimized by this
+        change.
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::layoutOverflowRectForPropagation):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::updateFromStyle):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::calculateClipRects):
+        * rendering/RenderLineBoxList.cpp:
+        (WebCore::RenderLineBoxList::rangeIntersectsRect):
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::RenderView):
+        * rendering/RenderView.h:
+
 2015-04-29  Jer Noble  <jer.noble@apple.com>
 
         Make GenericTaskQueue even more generic (and usable inside platform/)
index e8a0421..340996e 100644 (file)
@@ -4828,6 +4828,9 @@ void RenderBox::flipForWritingMode(FloatRect& rect) const
 
 LayoutPoint RenderBox::topLeftLocation() const
 {
+    if (!view().hasFlippedBlockDescendants())
+        return location();
+    
     RenderBlock* containerBlock = containingBlock();
     if (!containerBlock || containerBlock == this)
         return location();
@@ -4836,6 +4839,9 @@ LayoutPoint RenderBox::topLeftLocation() const
 
 LayoutSize RenderBox::topLeftLocationOffset() const
 {
+    if (!view().hasFlippedBlockDescendants())
+        return LayoutSize(m_frameRect.x(), m_frameRect.y());
+
     RenderBlock* containerBlock = containingBlock();
     if (!containerBlock || containerBlock == this)
         return locationOffset();
index 91021af..9a3d074 100644 (file)
@@ -219,6 +219,8 @@ void RenderBoxModelObject::updateFromStyle()
     setInline(styleToUse.isDisplayInlineType());
     setPositionState(styleToUse.position());
     setHorizontalWritingMode(styleToUse.isHorizontalWritingMode());
+    if (styleToUse.isFlippedBlocksWritingMode())
+        view().setHasFlippedBlockDescendants(true);
 }
 
 static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child)
index 97f7ed1..fc282f1 100644 (file)
@@ -5819,11 +5819,13 @@ LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) const
 LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, const LayoutSize& offsetFromRoot, CalculateLayerBoundsFlags flags) const
 {    
     LayoutRect result = localBoundingBox(flags);
-    if (renderer().isBox())
-        renderBox()->flipForWritingMode(result);
-    else
-        renderer().containingBlock()->flipForWritingMode(result);
-    
+    if (renderer().view().hasFlippedBlockDescendants()) {
+        if (renderer().isBox())
+            renderBox()->flipForWritingMode(result);
+        else
+            renderer().containingBlock()->flipForWritingMode(result);
+    }
+
     PaginationInclusionMode inclusionMode = ExcludeCompositedPaginatedLayers;
     if (flags & UseFragmentBoxesIncludingCompositing)
         inclusionMode = IncludeCompositedPaginatedLayers;
@@ -5899,10 +5901,12 @@ LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, c
 
     LayoutRect boundingBoxRect = localBoundingBox(flags);
 
-    if (is<RenderBox>(renderer()))
-        downcast<RenderBox>(renderer()).flipForWritingMode(boundingBoxRect);
-    else
-        renderer().containingBlock()->flipForWritingMode(boundingBoxRect);
+    if (renderer().view().hasFlippedBlockDescendants()) {
+        if (is<RenderBox>(renderer()))
+            downcast<RenderBox>(renderer()).flipForWritingMode(boundingBoxRect);
+        else
+            renderer().containingBlock()->flipForWritingMode(boundingBoxRect);
+    }
 
     if (renderer().isRoot()) {
         // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
index 5f3bea4..58884fc 100644 (file)
@@ -152,13 +152,18 @@ void RenderLineBoxList::dirtyLineBoxes()
 // FIXME: This should take a RenderBoxModelObject&.
 bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, LayoutUnit logicalTop, LayoutUnit logicalBottom, const LayoutRect& rect, const LayoutPoint& offset) const
 {
-    RenderBox* block;
-    if (is<RenderBox>(*renderer))
-        block = downcast<RenderBox>(renderer);
-    else
-        block = renderer->containingBlock();
-    LayoutUnit physicalStart = block->flipForWritingMode(logicalTop);
-    LayoutUnit physicalEnd = block->flipForWritingMode(logicalBottom);
+    LayoutUnit physicalStart = logicalTop;
+    LayoutUnit physicalEnd = logicalBottom;
+    if (renderer->view().hasFlippedBlockDescendants()) {
+        RenderBox* block;
+        if (is<RenderBox>(*renderer))
+            block = downcast<RenderBox>(renderer);
+        else
+            block = renderer->containingBlock();
+        physicalStart = block->flipForWritingMode(logicalTop);
+        physicalEnd = block->flipForWritingMode(logicalBottom);
+    }
+
     LayoutUnit physicalExtent = absoluteValue(physicalEnd - physicalStart);
     physicalStart = std::min(physicalStart, physicalEnd);
     
index aabd4c7..bc1351a 100644 (file)
@@ -111,6 +111,7 @@ RenderView::RenderView(Document& document, Ref<RenderStyle>&& style)
     , m_renderCounterCount(0)
     , m_selectionWasCaret(false)
     , m_hasSoftwareFilters(false)
+    , m_hasFlippedBlockDescendants(false)
 #if ENABLE(SERVICE_CONTROLS)
     , m_selectionRectGatherer(*this)
 #endif
index 0eea80b..c1aa9fa 100644 (file)
@@ -102,6 +102,9 @@ public:
 
     LayoutRect viewRect() const;
 
+    bool hasFlippedBlockDescendants() const { return m_hasFlippedBlockDescendants; }
+    void setHasFlippedBlockDescendants(bool b) { m_hasFlippedBlockDescendants = b; }
+
     // layoutDelta is used transiently during layout to store how far an object has moved from its
     // last layout location, in order to repaint correctly.
     // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
@@ -356,6 +359,7 @@ private:
 
     bool m_selectionWasCaret;
     bool m_hasSoftwareFilters;
+    bool m_hasFlippedBlockDescendants;
 
     HashSet<RenderElement*> m_renderersWithPausedImageAnimation;