Improve the offsetWidth/Height layout optimization
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Mar 2015 19:09:24 +0000 (19:09 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Mar 2015 19:09:24 +0000 (19:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143008

Reviewed by Zalan Bujtas.

* dom/Document.cpp:
(WebCore::Document::updateLayoutIfDimensionsOutOfDate):
* dom/Document.h:
Change Element* to Element&. Clean up the dimension bits to use shifting. Remove both the inline and
the positioning restrictions on the optimization check.

* dom/Element.cpp:
(WebCore::Element::offsetWidth):
(WebCore::Element::offsetHeight):
Change to use Element& instead of Element*.

(WebCore::Element::clientWidth):
(WebCore::Element::clientHeight):
(WebCore::Element::scrollWidth):
(WebCore::Element::scrollHeight):
Turn on the optimization for clientWidth/Height and scrollWidth/Height.

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

Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Element.cpp

index 2b00b0f..c586ae7 100644 (file)
@@ -1,3 +1,27 @@
+2015-03-25  David Hyatt  <hyatt@apple.com>
+
+        Improve the offsetWidth/Height layout optimization
+        https://bugs.webkit.org/show_bug.cgi?id=143008
+
+        Reviewed by Zalan Bujtas.
+
+        * dom/Document.cpp:
+        (WebCore::Document::updateLayoutIfDimensionsOutOfDate):
+        * dom/Document.h:
+        Change Element* to Element&. Clean up the dimension bits to use shifting. Remove both the inline and
+        the positioning restrictions on the optimization check.
+
+        * dom/Element.cpp:
+        (WebCore::Element::offsetWidth):
+        (WebCore::Element::offsetHeight):
+        Change to use Element& instead of Element*.
+
+        (WebCore::Element::clientWidth):
+        (WebCore::Element::clientHeight):
+        (WebCore::Element::scrollWidth):
+        (WebCore::Element::scrollHeight):
+        Turn on the optimization for clientWidth/Height and scrollWidth/Height.
+
 2015-03-26  Brady Eidson  <beidson@apple.com>
 
         Apply ContentExtension actions after redirects.
 2015-03-26  Brady Eidson  <beidson@apple.com>
 
         Apply ContentExtension actions after redirects.
index 668564d..404d57f 100644 (file)
@@ -1896,7 +1896,7 @@ Ref<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element* el
     return ensureStyleResolver().styleForElement(element, element->parentNode() ? element->parentNode()->computedStyle() : nullptr);
 }
 
     return ensureStyleResolver().styleForElement(element, element->parentNode() ? element->parentNode()->computedStyle() : nullptr);
 }
 
-bool Document::updateLayoutIfDimensionsOutOfDate(Element* element, DimensionsCheck dimensionsCheck)
+bool Document::updateLayoutIfDimensionsOutOfDate(Element& element, DimensionsCheck dimensionsCheck)
 {
     ASSERT(isMainThread());
     
 {
     ASSERT(isMainThread());
     
@@ -1920,15 +1920,19 @@ bool Document::updateLayoutIfDimensionsOutOfDate(Element* element, DimensionsChe
     // layout.
     bool requireFullLayout = false;
     if (HTMLFrameOwnerElement* owner = ownerElement()) {
     // layout.
     bool requireFullLayout = false;
     if (HTMLFrameOwnerElement* owner = ownerElement()) {
-        if (owner->document().updateLayoutIfDimensionsOutOfDate(owner))
+        if (owner->document().updateLayoutIfDimensionsOutOfDate(*owner))
             requireFullLayout = true;
     }
     
     updateStyleIfNeeded();
             requireFullLayout = true;
     }
     
     updateStyleIfNeeded();
-    
-    RenderObject* renderer = element->renderer();
-    if (!renderer || renderer->needsLayout())
+
+    RenderObject* renderer = element.renderer();
+    if (!renderer || renderer->needsLayout() || element.renderNamedFlowFragment()) {
+        // If we don't have a renderer or if the renderer needs layout for any reason, give up.
+        // Named flows can have auto height, so don't try to enforce the optimization in this case.
+        // The 2-pass nature of auto height named flow layout means the region may not be dirty yet.
         requireFullLayout = true;
         requireFullLayout = true;
+    }
 
     bool isVertical = renderer && !renderer->isHorizontalWritingMode();
     bool checkingLogicalWidth = ((dimensionsCheck & WidthDimensionsCheck) && !isVertical) || ((dimensionsCheck & HeightDimensionsCheck) && isVertical);
 
     bool isVertical = renderer && !renderer->isHorizontalWritingMode();
     bool checkingLogicalWidth = ((dimensionsCheck & WidthDimensionsCheck) && !isVertical) || ((dimensionsCheck & HeightDimensionsCheck) && isVertical);
@@ -1940,7 +1944,7 @@ bool Document::updateLayoutIfDimensionsOutOfDate(Element* element, DimensionsChe
         RenderBox* currentBox = nullptr;
         
         // Check our containing block chain. If anything in the chain needs a layout, then require a full layout.
         RenderBox* currentBox = nullptr;
         
         // Check our containing block chain. If anything in the chain needs a layout, then require a full layout.
-        for (RenderObject* currRenderer = element->renderer(); currRenderer && !currRenderer->isRenderView(); currRenderer = currRenderer->container()) {
+        for (RenderObject* currRenderer = element.renderer(); currRenderer && !currRenderer->isRenderView(); currRenderer = currRenderer->container()) {
             
             // Require the entire container chain to be boxes.
             if (!is<RenderBox>(currRenderer)) {
             
             // Require the entire container chain to be boxes.
             if (!is<RenderBox>(currRenderer)) {
@@ -1969,9 +1973,8 @@ bool Document::updateLayoutIfDimensionsOutOfDate(Element* element, DimensionsChe
                 }
             }
             
                 }
             }
             
-            if (!currentBox->isRenderBlockFlow() || currentBox->isInline() || currentBox->isOutOfFlowPositioned() || currentBox->flowThreadContainingBlock() || currentBox->isWritingModeRoot()) {
-                // FIXME: For now require only block-level non-positioned
-                // block flows all the way back to the root. This limits the optimization
+            if (!currentBox->isRenderBlockFlow() || currentBox->flowThreadContainingBlock() || currentBox->isWritingModeRoot()) {
+                // FIXME: For now require only block flows all the way back to the root. This limits the optimization
                 // for now, and we'll expand it in future patches to apply to more and more scenarios.
                 // Disallow regions/columns from having the optimization.
                 // Give up if the writing mode changes at all in the containing block chain.
                 // for now, and we'll expand it in future patches to apply to more and more scenarios.
                 // Disallow regions/columns from having the optimization.
                 // Give up if the writing mode changes at all in the containing block chain.
index 81c9f6a..e0a4279 100644 (file)
@@ -260,7 +260,7 @@ enum class DocumentCompatibilityMode : unsigned char {
     LimitedQuirksMode = 1 << 2
 };
 
     LimitedQuirksMode = 1 << 2
 };
 
-enum DimensionsCheck { WidthDimensionsCheck = 0x1, HeightDimensionsCheck = 0x2, AllDimensionsCheck = 0x3 };
+enum DimensionsCheck { WidthDimensionsCheck = 1 << 0, HeightDimensionsCheck = 1 << 1, AllDimensionsCheck = 1 << 2 };
 
 class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext, public FontSelectorClient {
 public:
 
 class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext, public FontSelectorClient {
 public:
@@ -569,7 +569,7 @@ public:
     bool renderTreeBeingDestroyed() const { return m_renderTreeBeingDestroyed; }
     bool hasLivingRenderTree() const { return renderView() && !renderTreeBeingDestroyed(); }
     
     bool renderTreeBeingDestroyed() const { return m_renderTreeBeingDestroyed; }
     bool hasLivingRenderTree() const { return renderView() && !renderTreeBeingDestroyed(); }
     
-    bool updateLayoutIfDimensionsOutOfDate(Element*, DimensionsCheck = AllDimensionsCheck);
+    bool updateLayoutIfDimensionsOutOfDate(Element&, DimensionsCheck = AllDimensionsCheck);
     
     AXObjectCache* existingAXObjectCache() const;
     WEBCORE_EXPORT AXObjectCache* axObjectCache() const;
     
     AXObjectCache* existingAXObjectCache() const;
     WEBCORE_EXPORT AXObjectCache* axObjectCache() const;
index e94b9cc..8c33e8f 100644 (file)
@@ -729,7 +729,7 @@ double Element::offsetTop()
 
 double Element::offsetWidth()
 {
 
 double Element::offsetWidth()
 {
-    document().updateLayoutIfDimensionsOutOfDate(this, WidthDimensionsCheck);
+    document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
         LayoutUnit offsetWidth = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetWidth() : LayoutUnit(renderer->pixelSnappedOffsetWidth());
         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetWidth, *renderer).toDouble(), renderer->document());
     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
         LayoutUnit offsetWidth = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetWidth() : LayoutUnit(renderer->pixelSnappedOffsetWidth());
         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetWidth, *renderer).toDouble(), renderer->document());
@@ -739,7 +739,7 @@ double Element::offsetWidth()
 
 double Element::offsetHeight()
 {
 
 double Element::offsetHeight()
 {
-    document().updateLayoutIfDimensionsOutOfDate(this, HeightDimensionsCheck);
+    document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
         LayoutUnit offsetHeight = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetHeight() : LayoutUnit(renderer->pixelSnappedOffsetHeight());
         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetHeight, *renderer).toDouble(), renderer->document());
     if (RenderBoxModelObject* renderer = renderBoxModelObject()) {
         LayoutUnit offsetHeight = subpixelMetricsEnabled(renderer->document()) ? renderer->offsetHeight() : LayoutUnit(renderer->pixelSnappedOffsetHeight());
         return convertToNonSubpixelValueIfNeeded(adjustLayoutUnitForAbsoluteZoom(offsetHeight, *renderer).toDouble(), renderer->document());
@@ -791,7 +791,7 @@ double Element::clientTop()
 
 double Element::clientWidth()
 {
 
 double Element::clientWidth()
 {
-    document().updateLayoutIgnorePendingStylesheets();
+    document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
 
     if (!document().hasLivingRenderTree())
         return 0;
 
     if (!document().hasLivingRenderTree())
         return 0;
@@ -812,8 +812,7 @@ double Element::clientWidth()
 
 double Element::clientHeight()
 {
 
 double Element::clientHeight()
 {
-    document().updateLayoutIgnorePendingStylesheets();
-
+    document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
     if (!document().hasLivingRenderTree())
         return 0;
     RenderView& renderView = *document().renderView();
     if (!document().hasLivingRenderTree())
         return 0;
     RenderView& renderView = *document().renderView();
@@ -873,7 +872,7 @@ void Element::setScrollTop(int newTop)
 
 int Element::scrollWidth()
 {
 
 int Element::scrollWidth()
 {
-    document().updateLayoutIgnorePendingStylesheets();
+    document().updateLayoutIfDimensionsOutOfDate(*this, WidthDimensionsCheck);
     if (RenderBox* rend = renderBox())
         return adjustForAbsoluteZoom(rend->scrollWidth(), *rend);
     return 0;
     if (RenderBox* rend = renderBox())
         return adjustForAbsoluteZoom(rend->scrollWidth(), *rend);
     return 0;
@@ -881,7 +880,7 @@ int Element::scrollWidth()
 
 int Element::scrollHeight()
 {
 
 int Element::scrollHeight()
 {
-    document().updateLayoutIgnorePendingStylesheets();
+    document().updateLayoutIfDimensionsOutOfDate(*this, HeightDimensionsCheck);
     if (RenderBox* rend = renderBox())
         return adjustForAbsoluteZoom(rend->scrollHeight(), *rend);
     return 0;
     if (RenderBox* rend = renderBox())
         return adjustForAbsoluteZoom(rend->scrollHeight(), *rend);
     return 0;