Map RootInlineBox to containing region via bit+hashmap.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Jan 2014 22:33:08 +0000 (22:33 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Jan 2014 22:33:08 +0000 (22:33 +0000)
<https://webkit.org/b/126917>

The vas majority of RootInlineBox objects don't have a containing
RenderRegion, so let's store that in a bit+hashmap configuration
instead of having a dedicated pointer member for it.

148 kB progression on Membuster3.

Reviewed by Antti Koivisto.

* rendering/InlineFlowBox.h:
(WebCore::InlineFlowBox::InlineFlowBox):
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::RootInlineBox):

    Added m_hasContainingRegion bit.

(WebCore::containingRegionMap):

    Global map between RootInlineBox and RenderRegion.

(WebCore::RootInlineBox::~RootInlineBox):

    Remove self from aforementioned global map if needed.

(WebCore::RootInlineBox::paint):

    Tweak a condition to avoid double hash lookup.

* rendering/RootInlineBox.h:
(WebCore::RootInlineBox::containingRegion):
(WebCore::RootInlineBox::clearContainingRegion):
(WebCore::RootInlineBox::setContainingRegion):

    Store the containing region in a bit+hashmap.

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

Source/WebCore/ChangeLog
Source/WebCore/rendering/InlineFlowBox.h
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RootInlineBox.cpp
Source/WebCore/rendering/RootInlineBox.h

index 45321efcbcc8c1390a4cf06c67bd96c146bfed9c..0ab63980d7c2b8168dce25bd78b16dac1e5baefc 100644 (file)
@@ -1,3 +1,42 @@
+2014-01-13  Andreas Kling  <akling@apple.com>
+
+        Map RootInlineBox to containing region via bit+hashmap.
+        <https://webkit.org/b/126917>
+
+        The vas majority of RootInlineBox objects don't have a containing
+        RenderRegion, so let's store that in a bit+hashmap configuration
+        instead of having a dedicated pointer member for it.
+
+        148 kB progression on Membuster3.
+
+        Reviewed by Antti Koivisto.
+
+        * rendering/InlineFlowBox.h:
+        (WebCore::InlineFlowBox::InlineFlowBox):
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::RootInlineBox):
+
+            Added m_hasContainingRegion bit.
+
+        (WebCore::containingRegionMap):
+
+            Global map between RootInlineBox and RenderRegion.
+
+        (WebCore::RootInlineBox::~RootInlineBox):
+
+            Remove self from aforementioned global map if needed.
+
+        (WebCore::RootInlineBox::paint):
+
+            Tweak a condition to avoid double hash lookup.
+
+        * rendering/RootInlineBox.h:
+        (WebCore::RootInlineBox::containingRegion):
+        (WebCore::RootInlineBox::clearContainingRegion):
+        (WebCore::RootInlineBox::setContainingRegion):
+
+            Store the containing region in a bit+hashmap.
+
 2014-01-13  Brent Fulgham  <bfulgham@apple.com>
 
         [WebGL] Invalid range checking in WebGLRenderingContext::validateTexFuncLevel
index c846d3c858071f403c02ab3710d3428c093db265..f128c1618f8637291e1bea44d1985e3843ca7c58 100644 (file)
@@ -53,6 +53,7 @@ public:
         , m_hasAnnotationsBefore(false)
         , m_hasAnnotationsAfter(false)
         , m_isFirstAfterPageBreak(false)
+        , m_hasContainingRegion(false)
 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
         , m_hasBadChildList(false)
 #endif
@@ -340,6 +341,8 @@ protected:
 
     unsigned m_isFirstAfterPageBreak : 1;
 
+    unsigned m_hasContainingRegion : 1;
+
     // End of RootInlineBox-specific members.
 
 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
index 05677e67f0387c94939d5f2627128588b4b448ac..65ec76773735fe9be059c171dd95f36a2c181fa8 100644 (file)
@@ -2157,7 +2157,11 @@ LayoutUnit RenderBlockFlow::startAlignedOffsetForLine(LayoutUnit position, bool
 void RenderBlockFlow::updateRegionForLine(RootInlineBox* lineBox) const
 {
     ASSERT(lineBox);
-    lineBox->setContainingRegion(regionAtBlockOffset(lineBox->lineTopWithLeading()));
+
+    if (auto containingRegion = regionAtBlockOffset(lineBox->lineTopWithLeading()))
+        lineBox->setContainingRegion(*containingRegion);
+    else
+        lineBox->clearContainingRegion();
 
     RootInlineBox* prevLineBox = lineBox->prevRootBox();
     if (!prevLineBox)
index d6bacbc26d810e6ff04a7cf0659e0893342898cb..d519fab8c4c8b426473cf920567516e1b4884d10 100644 (file)
 #include "RenderFlowThread.h"
 #include "RenderView.h"
 #include "VerticalPositionCache.h"
+#include <wtf/NeverDestroyed.h>
 #include <wtf/unicode/Unicode.h>
 
 namespace WebCore {
     
 struct SameSizeAsRootInlineBox : public InlineFlowBox {
     unsigned variables[7];
-    void* pointers[4];
+    void* pointers[3];
 };
 
 COMPILE_ASSERT(sizeof(RootInlineBox) == sizeof(SameSizeAsRootInlineBox), RootInlineBox_should_stay_small);
@@ -49,11 +50,17 @@ COMPILE_ASSERT(sizeof(RootInlineBox) == sizeof(SameSizeAsRootInlineBox), RootInl
 typedef WTF::HashMap<const RootInlineBox*, std::unique_ptr<EllipsisBox>> EllipsisBoxMap;
 static EllipsisBoxMap* gEllipsisBoxMap = 0;
 
+typedef HashMap<const RootInlineBox*, RenderRegion*> ContainingRegionMap;
+static ContainingRegionMap& containingRegionMap()
+{
+    static NeverDestroyed<ContainingRegionMap> map;
+    return map;
+}
+
 RootInlineBox::RootInlineBox(RenderBlockFlow& block)
     : InlineFlowBox(block)
     , m_lineBreakPos(0)
     , m_lineBreakObj(nullptr)
-    , m_containingRegion(nullptr)
 {
     setIsHorizontal(block.isHorizontalWritingMode());
 }
@@ -61,6 +68,9 @@ RootInlineBox::RootInlineBox(RenderBlockFlow& block)
 RootInlineBox::~RootInlineBox()
 {
     detachEllipsisBox();
+
+    if (m_hasContainingRegion)
+        containingRegionMap().remove(this);
 }
 
 void RootInlineBox::detachEllipsisBox()
@@ -194,7 +204,7 @@ void RootInlineBox::paintCustomHighlight(PaintInfo& paintInfo, const LayoutPoint
 void RootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
 {
     // Check if we are in the correct region.
-    if (paintInfo.renderRegion && containingRegion() && containingRegion() != paintInfo.renderRegion)
+    if (paintInfo.renderRegion && m_hasContainingRegion && containingRegion() != paintInfo.renderRegion)
         return;
     
     InlineFlowBox::paint(paintInfo, paintOffset, lineTop, lineBottom);
@@ -243,21 +253,34 @@ void RootInlineBox::childRemoved(InlineBox* box)
 RenderRegion* RootInlineBox::containingRegion() const
 {
 #ifndef NDEBUG
-    if (m_containingRegion) {
+    if (m_hasContainingRegion) {
         RenderFlowThread* flowThread = blockFlow().flowThreadContainingBlock();
         const RenderRegionList& regionList = flowThread->renderRegionList();
-        ASSERT(regionList.contains(m_containingRegion));
+        ASSERT(regionList.contains(containingRegionMap().get(this)));
     }
 #endif
+    return m_hasContainingRegion ? containingRegionMap().get(this) : nullptr;
+}
+
+void RootInlineBox::clearContainingRegion()
+{
+    ASSERT(!isDirty());
+    ASSERT(blockFlow().flowThreadContainingBlock());
 
-    return m_containingRegion;
+    if (!m_hasContainingRegion)
+        return;
+
+    containingRegionMap().remove(this);
+    m_hasContainingRegion = false;
 }
 
-void RootInlineBox::setContainingRegion(RenderRegion* region)
+void RootInlineBox::setContainingRegion(RenderRegion& region)
 {
     ASSERT(!isDirty());
     ASSERT(blockFlow().flowThreadContainingBlock());
-    m_containingRegion = region;
+
+    containingRegionMap().set(this, &region);
+    m_hasContainingRegion = true;
 }
 
 LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache)
index ab4c14f6782eca5fc496700935b0487c79023639..de086a62e5bfd9b2c351886e58a94499b36082f2 100644 (file)
@@ -64,8 +64,11 @@ public:
     LayoutUnit paginatedLineWidth() const { return m_paginatedLineWidth; }
     void setPaginatedLineWidth(LayoutUnit width) { m_paginatedLineWidth = width; }
 
+    // It should not be assumed the containingRegion() is always valid.
+    // It can also be nullptr if the flow has no region chain.
     RenderRegion* containingRegion() const;
-    void setContainingRegion(RenderRegion*);
+    void setContainingRegion(RenderRegion&);
+    void clearContainingRegion();
 
     LayoutUnit selectionTop() const;
     LayoutUnit selectionBottom() const;
@@ -218,10 +221,6 @@ private:
     LayoutUnit m_lineTopWithLeading;
     LayoutUnit m_lineBottomWithLeading;
 
-    // It should not be assumed the |containingRegion| is always valid.
-    // It can also be nullptr if the flow has no region chain.
-    RenderRegion* m_containingRegion;
-
     LayoutUnit m_paginationStrut;
     LayoutUnit m_paginatedLineWidth;