<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[207219] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/207219">207219</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2016-10-12 09:45:55 -0700 (Wed, 12 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Refactor LineLayoutState's float box handling.
https://bugs.webkit.org/show_bug.cgi?id=163286

Reviewed by David Hyatt.

We keep track of float boxes both per line (RootInlineBox::m_floats) and
per flow block (LineLayoutState::m_floats) during layout.
As we lay out the lines and iterate through RootInlineBox::m_floats, we
increment LineLayoutState::m_floatIndex. This LineLayoutState::m_floatIndex is
later used to find the matching float box in the per-block-flow float list.
This logic works fine as long as the lists and the index manipulation are tightly coded.
However due to the complexity of the line/float layout code, this is no longer the case.

This patch makes float box handling more secure by changing this index based setup
to a list iterator. It helps to eliminate potential vector overflow issues.

LineLayoutState::FloatList (new class) keeps track of all the floats for the block flow.
It groups the float box related functions/members and provides an iterator interface to ensure safer
syncing between this and the line based floats.

No change in functionality.

* rendering/RenderBlockFlow.h:
* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlockFlow::appendFloatingObjectToLastLine):
(WebCore::repaintDirtyFloats):
(WebCore::RenderBlockFlow::layoutRunsAndFloats):
(WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange):
(WebCore::RenderBlockFlow::linkToEndLineIfNeeded):
(WebCore::RenderBlockFlow::layoutLineBoxes):
(WebCore::RenderBlockFlow::checkFloatInCleanLine):
(WebCore::RenderBlockFlow::determineStartPosition):
(WebCore::RenderBlockFlow::determineEndPosition):
(WebCore::RenderBlockFlow::repaintDirtyFloats): Deleted.
(WebCore::RenderBlockFlow::checkFloatsInCleanLine): Deleted.
* rendering/line/LineLayoutState.h:
(WebCore::FloatWithRect::create):
(WebCore::FloatWithRect::renderer):
(WebCore::FloatWithRect::rect):
(WebCore::FloatWithRect::everHadLayout):
(WebCore::FloatWithRect::adjustRect):
(WebCore::FloatWithRect::FloatWithRect):
(WebCore::LineLayoutState::FloatList::append):
(WebCore::LineLayoutState::FloatList::setLastFloat):
(WebCore::LineLayoutState::FloatList::lastFloat):
(WebCore::LineLayoutState::FloatList::setLastCleanFloat):
(WebCore::LineLayoutState::FloatList::lastCleanFloat):
(WebCore::LineLayoutState::FloatList::floatWithRect):
(WebCore::LineLayoutState::FloatList::begin):
(WebCore::LineLayoutState::FloatList::end):
(WebCore::LineLayoutState::FloatList::find):
(WebCore::LineLayoutState::FloatList::isEmpty):
(WebCore::LineLayoutState::LineLayoutState):
(WebCore::LineLayoutState::floatList):
(WebCore::LineLayoutState::lastFloat): Deleted.
(WebCore::LineLayoutState::setLastFloat): Deleted.
(WebCore::LineLayoutState::floats): Deleted.
(WebCore::LineLayoutState::floatIndex): Deleted.
(WebCore::LineLayoutState::setFloatIndex): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockFlowh">trunk/Source/WebCore/rendering/RenderBlockFlow.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockLineLayoutcpp">trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderinglineLineLayoutStateh">trunk/Source/WebCore/rendering/line/LineLayoutState.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (207218 => 207219)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-12 16:36:11 UTC (rev 207218)
+++ trunk/Source/WebCore/ChangeLog        2016-10-12 16:45:55 UTC (rev 207219)
</span><span class="lines">@@ -1,3 +1,65 @@
</span><ins>+2016-10-12  Zalan Bujtas  &lt;zalan@apple.com&gt;
+
+        Refactor LineLayoutState's float box handling.
+        https://bugs.webkit.org/show_bug.cgi?id=163286
+
+        Reviewed by David Hyatt.
+        
+        We keep track of float boxes both per line (RootInlineBox::m_floats) and
+        per flow block (LineLayoutState::m_floats) during layout.
+        As we lay out the lines and iterate through RootInlineBox::m_floats, we
+        increment LineLayoutState::m_floatIndex. This LineLayoutState::m_floatIndex is
+        later used to find the matching float box in the per-block-flow float list.
+        This logic works fine as long as the lists and the index manipulation are tightly coded.
+        However due to the complexity of the line/float layout code, this is no longer the case.
+
+        This patch makes float box handling more secure by changing this index based setup
+        to a list iterator. It helps to eliminate potential vector overflow issues.
+
+        LineLayoutState::FloatList (new class) keeps track of all the floats for the block flow.
+        It groups the float box related functions/members and provides an iterator interface to ensure safer
+        syncing between this and the line based floats.
+
+        No change in functionality.
+
+        * rendering/RenderBlockFlow.h:
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlockFlow::appendFloatingObjectToLastLine):
+        (WebCore::repaintDirtyFloats):
+        (WebCore::RenderBlockFlow::layoutRunsAndFloats):
+        (WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange):
+        (WebCore::RenderBlockFlow::linkToEndLineIfNeeded):
+        (WebCore::RenderBlockFlow::layoutLineBoxes):
+        (WebCore::RenderBlockFlow::checkFloatInCleanLine):
+        (WebCore::RenderBlockFlow::determineStartPosition):
+        (WebCore::RenderBlockFlow::determineEndPosition):
+        (WebCore::RenderBlockFlow::repaintDirtyFloats): Deleted.
+        (WebCore::RenderBlockFlow::checkFloatsInCleanLine): Deleted.
+        * rendering/line/LineLayoutState.h:
+        (WebCore::FloatWithRect::create):
+        (WebCore::FloatWithRect::renderer):
+        (WebCore::FloatWithRect::rect):
+        (WebCore::FloatWithRect::everHadLayout):
+        (WebCore::FloatWithRect::adjustRect):
+        (WebCore::FloatWithRect::FloatWithRect):
+        (WebCore::LineLayoutState::FloatList::append):
+        (WebCore::LineLayoutState::FloatList::setLastFloat):
+        (WebCore::LineLayoutState::FloatList::lastFloat):
+        (WebCore::LineLayoutState::FloatList::setLastCleanFloat):
+        (WebCore::LineLayoutState::FloatList::lastCleanFloat):
+        (WebCore::LineLayoutState::FloatList::floatWithRect):
+        (WebCore::LineLayoutState::FloatList::begin):
+        (WebCore::LineLayoutState::FloatList::end):
+        (WebCore::LineLayoutState::FloatList::find):
+        (WebCore::LineLayoutState::FloatList::isEmpty):
+        (WebCore::LineLayoutState::LineLayoutState):
+        (WebCore::LineLayoutState::floatList):
+        (WebCore::LineLayoutState::lastFloat): Deleted.
+        (WebCore::LineLayoutState::setLastFloat): Deleted.
+        (WebCore::LineLayoutState::floats): Deleted.
+        (WebCore::LineLayoutState::floatIndex): Deleted.
+        (WebCore::LineLayoutState::setFloatIndex): Deleted.
+
</ins><span class="cx"> 2016-10-12  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, fix Windows build break after r207182.
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockFlowh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.h (207218 => 207219)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlockFlow.h        2016-10-12 16:36:11 UTC (rev 207218)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.h        2016-10-12 16:45:55 UTC (rev 207219)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class FloatWithRect;
</ins><span class="cx"> class LayoutStateMaintainer;
</span><span class="cx"> class LineBreaker;
</span><span class="cx"> class LineInfo;
</span><span class="lines">@@ -41,7 +42,6 @@
</span><span class="cx"> class RenderNamedFlowFragment;
</span><span class="cx"> class RenderRubyRun;
</span><span class="cx"> 
</span><del>-struct FloatWithRect;
</del><span class="cx"> struct WordMeasurement;
</span><span class="cx"> 
</span><span class="cx"> template &lt;class Run&gt; class BidiRunList;
</span><span class="lines">@@ -566,7 +566,7 @@
</span><span class="cx">         float&amp; availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap&amp; textBoxDataMap, VerticalPositionCache&amp;, WordMeasurements&amp;);
</span><span class="cx">     void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&amp;, VerticalPositionCache&amp;);
</span><span class="cx">     BidiRun* handleTrailingSpaces(BidiRunList&lt;BidiRun&gt;&amp;, BidiContext*);
</span><del>-    void appendFloatingObjectToLastLine(FloatingObject*);
</del><ins>+    void appendFloatingObjectToLastLine(FloatingObject&amp;);
</ins><span class="cx">     // Helper function for layoutInlineChildren()
</span><span class="cx">     RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList&lt;BidiRun&gt;&amp;, const InlineIterator&amp; end, LineInfo&amp;, VerticalPositionCache&amp;, BidiRun* trailingSpaceRun, WordMeasurements&amp;);
</span><span class="cx">     void layoutRunsAndFloats(LineLayoutState&amp;, bool hasInlineChild);
</span><span class="lines">@@ -574,8 +574,8 @@
</span><span class="cx">     void layoutRunsAndFloatsInRange(LineLayoutState&amp;, InlineBidiResolver&amp;, const InlineIterator&amp; cleanLineStart, const BidiStatus&amp; cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
</span><span class="cx">     void reattachCleanLineFloats(RootInlineBox&amp; cleanLine, LayoutUnit delta, bool isFirstCleanLine);
</span><span class="cx">     void linkToEndLineIfNeeded(LineLayoutState&amp;);
</span><del>-    static void repaintDirtyFloats(Vector&lt;FloatWithRect&gt;&amp; floats);
-    void checkFloatsInCleanLine(RootInlineBox*, Vector&lt;FloatWithRect&gt;&amp;, size_t&amp; floatIndex, bool&amp; encounteredNewFloat, bool&amp; dirtiedByFloat);
</del><ins>+    void checkFloatInCleanLine(RootInlineBox&amp; cleanLine, RenderBox&amp; floatBoxOnCleanLine, FloatWithRect&amp; matchingFloatWithRect,
+        bool&amp; encounteredNewFloat, bool&amp; dirtiedByFloat);
</ins><span class="cx">     RootInlineBox* determineStartPosition(LineLayoutState&amp;, InlineBidiResolver&amp;);
</span><span class="cx">     void determineEndPosition(LineLayoutState&amp;, RootInlineBox* startBox, InlineIterator&amp; cleanLineStart, BidiStatus&amp; cleanLineBidiStatus);
</span><span class="cx">     bool checkPaginationAndFloatsAtEndLine(LineLayoutState&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockLineLayoutcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (207218 => 207219)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp        2016-10-12 16:36:11 UTC (rev 207218)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp        2016-10-12 16:45:55 UTC (rev 207219)
</span><span class="lines">@@ -1100,11 +1100,11 @@
</span><span class="cx">     return trailingSpaceRun;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
</del><ins>+void RenderBlockFlow::appendFloatingObjectToLastLine(FloatingObject&amp; floatingObject)
</ins><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject-&gt;originatingLine());
-    floatingObject-&gt;setOriginatingLine(lastRootBox());
-    lastRootBox()-&gt;appendFloat(floatingObject-&gt;renderer());
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject.originatingLine());
+    floatingObject.setOriginatingLine(lastRootBox());
+    lastRootBox()-&gt;appendFloat(floatingObject.renderer());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static inline void notifyResolverToResumeInIsolate(InlineBidiResolver&amp; resolver, RenderObject* root, RenderObject* startObject)
</span><span class="lines">@@ -1249,6 +1249,20 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void repaintDirtyFloats(LineLayoutState::FloatList&amp; floats)
+{
+    // Floats that did not have layout did not repaint when we laid them out. They would have
+    // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
+    // painted.
+    for (auto&amp; floatBox : floats) {
+        if (floatBox-&gt;everHadLayout())
+            continue;
+        auto&amp; box = floatBox-&gt;renderer();
+        if (!box.x() &amp;&amp; !box.y() &amp;&amp; box.checkForRepaintDuringLayout())
+            box.repaint();
+    }
+}
+
</ins><span class="cx"> void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState&amp; layoutState, bool hasInlineChild)
</span><span class="cx"> {
</span><span class="cx">     // We want to skip ahead to the first dirty line
</span><span class="lines">@@ -1279,7 +1293,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (containsFloats())
</span><del>-        layoutState.setLastFloat(m_floatingObjects-&gt;set().last().get());
</del><ins>+        layoutState.floatList().setLastFloat(m_floatingObjects-&gt;set().last().get());
</ins><span class="cx"> 
</span><span class="cx">     // We also find the first clean line and extract these lines.  We will add them back
</span><span class="cx">     // if we determine that we're able to synchronize after handling all our dirty lines.
</span><span class="lines">@@ -1312,7 +1326,7 @@
</span><span class="cx"> 
</span><span class="cx">     layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines);
</span><span class="cx">     linkToEndLineIfNeeded(layoutState);
</span><del>-    repaintDirtyFloats(layoutState.floats());
</del><ins>+    repaintDirtyFloats(layoutState.floatList());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
</span><span class="lines">@@ -1479,22 +1493,21 @@
</span><span class="cx">             const FloatingObjectSet&amp; floatingObjectSet = m_floatingObjects-&gt;set();
</span><span class="cx">             auto it = floatingObjectSet.begin();
</span><span class="cx">             auto end = floatingObjectSet.end();
</span><del>-            if (layoutState.lastFloat()) {
-                auto lastFloatIterator = floatingObjectSet.find&lt;FloatingObject&amp;, FloatingObjectHashTranslator&gt;(*layoutState.lastFloat());
</del><ins>+            if (auto* lastFloat = layoutState.floatList().lastFloat()) {
+                auto lastFloatIterator = floatingObjectSet.find&lt;FloatingObject&amp;, FloatingObjectHashTranslator&gt;(*lastFloat);
</ins><span class="cx">                 ASSERT(lastFloatIterator != end);
</span><span class="cx">                 ++lastFloatIterator;
</span><span class="cx">                 it = lastFloatIterator;
</span><span class="cx">             }
</span><span class="cx">             for (; it != end; ++it) {
</span><del>-                FloatingObject* f = it-&gt;get();
-                appendFloatingObjectToLastLine(f);
-                ASSERT(&amp;f-&gt;renderer() == &amp;layoutState.floats()[layoutState.floatIndex()].object);
</del><ins>+                auto&amp; floatingObject = *it;
+                appendFloatingObjectToLastLine(*floatingObject);
</ins><span class="cx">                 // If a float's geometry has changed, give up on syncing with clean lines.
</span><del>-                if (layoutState.floats()[layoutState.floatIndex()].rect != f-&gt;frameRect())
</del><ins>+                auto* floatWithRect = layoutState.floatList().floatWithRect(floatingObject-&gt;renderer());
+                if (!floatWithRect || floatWithRect-&gt;rect() != floatingObject-&gt;frameRect())
</ins><span class="cx">                     checkForEndLineMatch = false;
</span><del>-                layoutState.setFloatIndex(layoutState.floatIndex() + 1);
</del><span class="cx">             }
</span><del>-            layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
</del><ins>+            layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         lineWhitespaceCollapsingState.reset();
</span><span class="lines">@@ -1641,33 +1654,18 @@
</span><span class="cx">         const FloatingObjectSet&amp; floatingObjectSet = m_floatingObjects-&gt;set();
</span><span class="cx">         auto it = floatingObjectSet.begin();
</span><span class="cx">         auto end = floatingObjectSet.end();
</span><del>-        if (layoutState.lastFloat()) {
-            auto lastFloatIterator = floatingObjectSet.find&lt;FloatingObject&amp;, FloatingObjectHashTranslator&gt;(*layoutState.lastFloat());
</del><ins>+        if (auto* lastFloat = layoutState.floatList().lastFloat()) {
+            auto lastFloatIterator = floatingObjectSet.find&lt;FloatingObject&amp;, FloatingObjectHashTranslator&gt;(*lastFloat);
</ins><span class="cx">             ASSERT(lastFloatIterator != end);
</span><span class="cx">             ++lastFloatIterator;
</span><span class="cx">             it = lastFloatIterator;
</span><span class="cx">         }
</span><span class="cx">         for (; it != end; ++it)
</span><del>-            appendFloatingObjectToLastLine(it-&gt;get());
-        layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
</del><ins>+            appendFloatingObjectToLastLine(**it);
+        layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderBlockFlow::repaintDirtyFloats(Vector&lt;FloatWithRect&gt;&amp; floats)
-{
-    size_t floatCount = floats.size();
-    // Floats that did not have layout did not repaint when we laid them out. They would have
-    // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
-    // painted.
-    for (size_t i = 0; i &lt; floatCount; ++i) {
-        if (!floats[i].everHadLayout) {
-            RenderBox&amp; box = floats[i].object;
-            if (!box.x() &amp;&amp; !box.y() &amp;&amp; box.checkForRepaintDuringLayout())
-                box.repaint();
-        }
-    }
-}
-
</del><span class="cx"> void RenderBlockFlow::layoutLineBoxes(bool relayoutChildren, LayoutUnit&amp; repaintLogicalTop, LayoutUnit&amp; repaintLogicalBottom)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_simpleLineLayout);
</span><span class="lines">@@ -1729,7 +1727,7 @@
</span><span class="cx">                 if (box.isOutOfFlowPositioned())
</span><span class="cx">                     box.containingBlock()-&gt;insertPositionedObject(box);
</span><span class="cx">                 else if (box.isFloating())
</span><del>-                    layoutState.floats().append(FloatWithRect(box));
</del><ins>+                    layoutState.floatList().append(FloatWithRect::create(box));
</ins><span class="cx">                 else if (isFullLayout || box.needsLayout()) {
</span><span class="cx">                     // Replaced element.
</span><span class="cx">                     box.dirtyLineBoxes(isFullLayout);
</span><span class="lines">@@ -1785,129 +1783,131 @@
</span><span class="cx">         checkLinesForTextOverflow();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderBlockFlow::checkFloatsInCleanLine(RootInlineBox* line, Vector&lt;FloatWithRect&gt;&amp; floats, size_t&amp; floatIndex, bool&amp; encounteredNewFloat, bool&amp; dirtiedByFloat)
</del><ins>+void RenderBlockFlow::checkFloatInCleanLine(RootInlineBox&amp; cleanLine, RenderBox&amp; floatBoxOnCleanLine, FloatWithRect&amp; matchingFloatWithRect,
+    bool&amp; encounteredNewFloat, bool&amp; dirtiedByFloat)
</ins><span class="cx"> {
</span><del>-    Vector&lt;RenderBox*&gt;* cleanLineFloats = line-&gt;floatsPtr();
-    if (!cleanLineFloats)
</del><ins>+    ASSERT_WITH_SECURITY_IMPLICATION(!floatBoxOnCleanLine.style().deletionHasBegun());
+    if (&amp;matchingFloatWithRect.renderer() != &amp;floatBoxOnCleanLine) {
+        encounteredNewFloat = true;
</ins><span class="cx">         return;
</span><ins>+    }
+    floatBoxOnCleanLine.layoutIfNeeded();
+    LayoutRect originalFloatRect = matchingFloatWithRect.rect();
+    LayoutSize newSize(
+        floatBoxOnCleanLine.width() + floatBoxOnCleanLine.horizontalMarginExtent(),
+        floatBoxOnCleanLine.height() + floatBoxOnCleanLine.verticalMarginExtent());
</ins><span class="cx">     
</span><del>-    if (!floats.size()) {
-        encounteredNewFloat = true;
</del><ins>+    // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats as dirty.
+    if (originalFloatRect.size() == newSize &amp;&amp; (floatBoxOnCleanLine.style().styleType() != FIRST_LETTER || !floatBoxOnCleanLine.style().initialLetterDrop()))
</ins><span class="cx">         return;
</span><del>-    }
</del><span class="cx"> 
</span><del>-    for (auto it = cleanLineFloats-&gt;begin(), end = cleanLineFloats-&gt;end(); it != end; ++it) {
-        RenderBox* floatingBox = *it;
-        ASSERT_WITH_SECURITY_IMPLICATION(!floatingBox-&gt;style().deletionHasBegun());
-        floatingBox-&gt;layoutIfNeeded();
-        LayoutSize newSize(floatingBox-&gt;width() + floatingBox-&gt;horizontalMarginExtent(), floatingBox-&gt;height() + floatingBox-&gt;verticalMarginExtent());
-        ASSERT_WITH_SECURITY_IMPLICATION(floatIndex &lt; floats.size());
-        if (&amp;floats[floatIndex].object != floatingBox) {
-            encounteredNewFloat = true;
-            return;
-        }
-    
-        // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats
-        // as dirty.
-        if (floats[floatIndex].rect.size() != newSize || (floatingBox-&gt;style().styleType() == FIRST_LETTER &amp;&amp; floatingBox-&gt;style().initialLetterDrop() &gt; 0)) {
-            LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
-            LayoutUnit floatHeight = isHorizontalWritingMode() ? std::max(floats[floatIndex].rect.height(), newSize.height()) : std::max(floats[floatIndex].rect.width(), newSize.width());
-            floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop);
-            line-&gt;markDirty();
-            markLinesDirtyInBlockRange(line-&gt;lineBottomWithLeading(), floatTop + floatHeight, line);
-            floats[floatIndex].rect.setSize(newSize);
-            dirtiedByFloat = true;
-        }
-        floatIndex++;
-    }
</del><ins>+    LayoutUnit floatTop = isHorizontalWritingMode() ? originalFloatRect.y() : originalFloatRect.x();
+    LayoutUnit floatHeight = isHorizontalWritingMode() ? std::max(originalFloatRect.height(), newSize.height())
+        : std::max(originalFloatRect.width(), newSize.width());
+    floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop);
+    cleanLine.markDirty();
+    markLinesDirtyInBlockRange(cleanLine.lineBottomWithLeading(), floatTop + floatHeight, &amp;cleanLine);
+    LayoutRect newFloatRect = originalFloatRect;
+    newFloatRect.setSize(newSize);
+    matchingFloatWithRect.adjustRect(newFloatRect);
+    dirtiedByFloat = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState&amp; layoutState, InlineBidiResolver&amp; resolver)
</span><span class="cx"> {
</span><del>-    RootInlineBox* curr = 0;
-    RootInlineBox* last = 0;
</del><ins>+    RootInlineBox* currentLine = nullptr;
+    RootInlineBox* lastLine = nullptr;
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: This entire float-checking block needs to be broken into a new function.
</span><ins>+    auto&amp; floats = layoutState.floatList();
</ins><span class="cx">     bool dirtiedByFloat = false;
</span><span class="cx">     if (!layoutState.isFullLayout()) {
</span><span class="cx">         // Paginate all of the clean lines.
</span><span class="cx">         bool paginated = view().layoutState() &amp;&amp; view().layoutState()-&gt;isPaginated();
</span><span class="cx">         LayoutUnit paginationDelta = 0;
</span><del>-        size_t floatIndex = 0;
-        for (curr = firstRootBox(); curr &amp;&amp; !curr-&gt;isDirty(); curr = curr-&gt;nextRootBox()) {
</del><ins>+        auto floatsIterator = floats.begin();
+        auto end = floats.end();
+        for (currentLine = firstRootBox(); currentLine &amp;&amp; !currentLine-&gt;isDirty(); currentLine = currentLine-&gt;nextRootBox()) {
</ins><span class="cx">             if (paginated) {
</span><del>-                if (lineWidthForPaginatedLineChanged(curr, 0, layoutState.flowThread())) {
-                    curr-&gt;markDirty();
</del><ins>+                if (lineWidthForPaginatedLineChanged(currentLine, 0, layoutState.flowThread())) {
+                    currentLine-&gt;markDirty();
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                paginationDelta -= curr-&gt;paginationStrut();
</del><ins>+                paginationDelta -= currentLine-&gt;paginationStrut();
</ins><span class="cx">                 bool overflowsRegion;
</span><del>-                adjustLinePositionForPagination(curr, paginationDelta, overflowsRegion, layoutState.flowThread());
</del><ins>+                adjustLinePositionForPagination(currentLine, paginationDelta, overflowsRegion, layoutState.flowThread());
</ins><span class="cx">                 if (paginationDelta) {
</span><del>-                    if (containsFloats() || !layoutState.floats().isEmpty()) {
</del><ins>+                    if (containsFloats() || !floats.isEmpty()) {
</ins><span class="cx">                         // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
</span><span class="cx">                         layoutState.markForFullLayout();
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx"> 
</span><del>-                    layoutState.updateRepaintRangeFromBox(curr, paginationDelta);
-                    curr-&gt;adjustBlockDirectionPosition(paginationDelta);
</del><ins>+                    layoutState.updateRepaintRangeFromBox(currentLine, paginationDelta);
+                    currentLine-&gt;adjustBlockDirectionPosition(paginationDelta);
</ins><span class="cx">                 }
</span><span class="cx">                 if (layoutState.flowThread())
</span><del>-                    updateRegionForLine(curr);
</del><ins>+                    updateRegionForLine(currentLine);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            // If a new float has been inserted before this line or before its last known float, just do a full layout.
-            bool encounteredNewFloat = false;
-            checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
-            if (encounteredNewFloat)
-                layoutState.markForFullLayout();
-
-            if (dirtiedByFloat || layoutState.isFullLayout())
-                break;
</del><ins>+            if (auto* cleanLineFloats = currentLine-&gt;floatsPtr()) {
+                // If a new float has been inserted before this line or before its last known float, just do a full layout.
+                bool encounteredNewFloat = false;
+                for (auto* floatBoxOnCleanLine : *cleanLineFloats) {
+                    ASSERT(floatsIterator != end);
+                    checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat);
+                    ++floatsIterator;
+                    if (floatsIterator == end || encounteredNewFloat) {
+                        layoutState.markForFullLayout();
+                        break;
+                    }
+                }
+                if (dirtiedByFloat || encounteredNewFloat)
+                    break;
+            }
</ins><span class="cx">         }
</span><span class="cx">         // Check if a new float has been inserted after the last known float.
</span><del>-        if (!curr &amp;&amp; floatIndex &lt; layoutState.floats().size())
</del><ins>+        if (!currentLine &amp;&amp; floatsIterator != end)
</ins><span class="cx">             layoutState.markForFullLayout();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (layoutState.isFullLayout()) {
</span><span class="cx">         m_lineBoxes.deleteLineBoxTree();
</span><del>-        curr = 0;
-
</del><ins>+        currentLine = nullptr;
</ins><span class="cx">         ASSERT(!firstRootBox() &amp;&amp; !lastRootBox());
</span><span class="cx">     } else {
</span><del>-        if (curr) {
</del><ins>+        if (currentLine) {
</ins><span class="cx">             // We have a dirty line.
</span><del>-            if (RootInlineBox* prevRootBox = curr-&gt;prevRootBox()) {
</del><ins>+            if (RootInlineBox* prevRootBox = currentLine-&gt;prevRootBox()) {
</ins><span class="cx">                 // We have a previous line.
</span><del>-                if (!dirtiedByFloat &amp;&amp; !curr-&gt;hasAnonymousInlineBlock() &amp;&amp; (!prevRootBox-&gt;endsWithBreak() || !prevRootBox-&gt;lineBreakObj() || (is&lt;RenderText&gt;(*prevRootBox-&gt;lineBreakObj()) &amp;&amp; prevRootBox-&gt;lineBreakPos() &gt;= downcast&lt;RenderText&gt;(*prevRootBox-&gt;lineBreakObj()).textLength()))) {
</del><ins>+                if (!dirtiedByFloat &amp;&amp; !currentLine-&gt;hasAnonymousInlineBlock() &amp;&amp; (!prevRootBox-&gt;endsWithBreak()
+                    || !prevRootBox-&gt;lineBreakObj()
+                    || (is&lt;RenderText&gt;(*prevRootBox-&gt;lineBreakObj())
+                    &amp;&amp; prevRootBox-&gt;lineBreakPos() &gt;= downcast&lt;RenderText&gt;(*prevRootBox-&gt;lineBreakObj()).textLength()))) {
</ins><span class="cx">                     // The previous line didn't break cleanly or broke at a newline
</span><span class="cx">                     // that has been deleted, so treat it as dirty too.
</span><del>-                    curr = prevRootBox;
</del><ins>+                    currentLine = prevRootBox;
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         // If we have no dirty lines, then last is just the last root box.
</span><del>-        last = curr ? curr-&gt;prevRootBox() : lastRootBox();
</del><ins>+        lastLine = currentLine ? currentLine-&gt;prevRootBox() : lastRootBox();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    unsigned numCleanFloats = 0;
-    if (!layoutState.floats().isEmpty()) {
</del><ins>+    if (!floats.isEmpty()) {
</ins><span class="cx">         LayoutUnit savedLogicalHeight = logicalHeight();
</span><span class="cx">         // Restore floats from clean lines.
</span><span class="cx">         RootInlineBox* line = firstRootBox();
</span><del>-        while (line != curr) {
</del><ins>+        while (line != currentLine) {
</ins><span class="cx">             if (Vector&lt;RenderBox*&gt;* cleanLineFloats = line-&gt;floatsPtr()) {
</span><span class="cx">                 for (auto it = cleanLineFloats-&gt;begin(), end = cleanLineFloats-&gt;end(); it != end; ++it) {
</span><del>-                    RenderBox* floatingBox = *it;
-                    FloatingObject* floatingObject = insertFloatingObject(*floatingBox);
</del><ins>+                    auto* floatingBox = *it;
+                    auto* floatingObject = insertFloatingObject(*floatingBox);
</ins><span class="cx">                     ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject-&gt;originatingLine());
</span><span class="cx">                     floatingObject-&gt;setOriginatingLine(line);
</span><span class="cx">                     setLogicalHeight(logicalTopForChild(*floatingBox) - marginBeforeForChild(*floatingBox));
</span><span class="cx">                     positionNewFloats();
</span><del>-                    ASSERT(&amp;layoutState.floats()[numCleanFloats].object == floatingBox);
-                    numCleanFloats++;
</del><ins>+                    floats.setLastCleanFloat(*floatingBox);
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             line = line-&gt;nextRootBox();
</span><span class="lines">@@ -1914,16 +1914,15 @@
</span><span class="cx">         }
</span><span class="cx">         setLogicalHeight(savedLogicalHeight);
</span><span class="cx">     }
</span><del>-    layoutState.setFloatIndex(numCleanFloats);
</del><span class="cx"> 
</span><del>-    layoutState.lineInfo().setFirstLine(!last);
-    layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || last-&gt;endsWithBreak());
</del><ins>+    layoutState.lineInfo().setFirstLine(!lastLine);
+    layoutState.lineInfo().setPreviousLineBrokeCleanly(!lastLine || lastLine-&gt;endsWithBreak());
</ins><span class="cx"> 
</span><del>-    if (last) {
-        setLogicalHeight(last-&gt;lineBottomWithLeading());
-        InlineIterator iter = InlineIterator(this, last-&gt;lineBreakObj(), last-&gt;lineBreakPos());
</del><ins>+    if (lastLine) {
+        setLogicalHeight(lastLine-&gt;lineBottomWithLeading());
+        InlineIterator iter = InlineIterator(this, lastLine-&gt;lineBreakObj(), lastLine-&gt;lineBreakPos());
</ins><span class="cx">         resolver.setPosition(iter, numberOfIsolateAncestors(iter));
</span><del>-        resolver.setStatus(last-&gt;lineBreakBidiStatus());
</del><ins>+        resolver.setStatus(lastLine-&gt;lineBreakBidiStatus());
</ins><span class="cx">     } else {
</span><span class="cx">         TextDirection direction = style().direction();
</span><span class="cx">         if (style().unicodeBidi() == Plaintext)
</span><span class="lines">@@ -1932,44 +1931,59 @@
</span><span class="cx">         InlineIterator iter = InlineIterator(this, bidiFirstSkippingEmptyInlines(*this, &amp;resolver), 0);
</span><span class="cx">         resolver.setPosition(iter, numberOfIsolateAncestors(iter));
</span><span class="cx">     }
</span><del>-    return curr;
</del><ins>+    return currentLine;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderBlockFlow::determineEndPosition(LineLayoutState&amp; layoutState, RootInlineBox* startLine, InlineIterator&amp; cleanLineStart, BidiStatus&amp; cleanLineBidiStatus)
</span><span class="cx"> {
</span><ins>+    auto iteratorForFirstDirtyFloat = [](LineLayoutState::FloatList&amp; floats) {
+        auto lastCleanFloat = floats.lastCleanFloat();
+        if (!lastCleanFloat)
+            return floats.begin();
+        auto* lastCleanFloatWithRect = floats.floatWithRect(*lastCleanFloat);
+        ASSERT(lastCleanFloatWithRect);
+        return ++floats.find(*lastCleanFloatWithRect);
+    };
+
</ins><span class="cx">     ASSERT(!layoutState.endLine());
</span><del>-    size_t floatIndex = layoutState.floatIndex();
-    RootInlineBox* last = 0;
-    for (RootInlineBox* curr = startLine-&gt;nextRootBox(); curr; curr = curr-&gt;nextRootBox()) {
-        if (!curr-&gt;isDirty()) {
-            bool encounteredNewFloat = false;
-            bool dirtiedByFloat = false;
-            checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
-            if (encounteredNewFloat)
-                return;
</del><ins>+    auto floatsIterator = iteratorForFirstDirtyFloat(layoutState.floatList());
+    auto end = layoutState.floatList().end();
+    RootInlineBox* lastLine = nullptr;
+    for (RootInlineBox* currentLine = startLine-&gt;nextRootBox(); currentLine; currentLine = currentLine-&gt;nextRootBox()) {
+        if (!currentLine-&gt;isDirty()) {
+            if (auto* cleanLineFloats = currentLine-&gt;floatsPtr()) {
+                bool encounteredNewFloat = false;
+                bool dirtiedByFloat = false;
+                for (auto* floatBoxOnCleanLine : *cleanLineFloats) {
+                    ASSERT(floatsIterator != end);
+                    checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat);
+                    ++floatsIterator;
+                    if (floatsIterator == end || encounteredNewFloat)
+                        return;
+                }
+            }
</ins><span class="cx">         }
</span><del>-        if (curr-&gt;isDirty())
-            last = 0;
-        else if (!last)
-            last = curr;
</del><ins>+        if (currentLine-&gt;isDirty())
+            lastLine = nullptr;
+        else if (!lastLine)
+            lastLine = currentLine;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!last)
</del><ins>+    if (!lastLine)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // At this point, |last| is the first line in a run of clean lines that ends with the last line
</span><span class="cx">     // in the block.
</span><ins>+    RootInlineBox* previousLine = lastLine-&gt;prevRootBox();
+    cleanLineStart = InlineIterator(this, previousLine-&gt;lineBreakObj(), previousLine-&gt;lineBreakPos());
+    cleanLineBidiStatus = previousLine-&gt;lineBreakBidiStatus();
+    layoutState.setEndLineLogicalTop(previousLine-&gt;lineBottomWithLeading());
</ins><span class="cx"> 
</span><del>-    RootInlineBox* prev = last-&gt;prevRootBox();
-    cleanLineStart = InlineIterator(this, prev-&gt;lineBreakObj(), prev-&gt;lineBreakPos());
-    cleanLineBidiStatus = prev-&gt;lineBreakBidiStatus();
-    layoutState.setEndLineLogicalTop(prev-&gt;lineBottomWithLeading());
-
-    for (RootInlineBox* line = last; line; line = line-&gt;nextRootBox())
-        line-&gt;extractLine(); // Disconnect all line boxes from their render objects while preserving
-                             // their connections to one another.
-
-    layoutState.setEndLine(last);
</del><ins>+    for (RootInlineBox* line = lastLine; line; line = line-&gt;nextRootBox()) {
+        // Disconnect all line boxes from their render objects while preserving their connections to one another.
+        line-&gt;extractLine();
+    }
+    layoutState.setEndLine(lastLine);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool RenderBlockFlow::checkPaginationAndFloatsAtEndLine(LineLayoutState&amp; layoutState)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderinglineLineLayoutStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/line/LineLayoutState.h (207218 => 207219)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/line/LineLayoutState.h        2016-10-12 16:36:11 UTC (rev 207218)
+++ trunk/Source/WebCore/rendering/line/LineLayoutState.h        2016-10-12 16:45:55 UTC (rev 207219)
</span><span class="lines">@@ -36,20 +36,37 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;LayoutRect.h&quot;
</span><span class="cx"> #include &quot;RenderBlockFlow.h&quot;
</span><ins>+#include &lt;wtf/RefCounted.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-struct FloatWithRect {
-    FloatWithRect(RenderBox&amp; f)
-        : object(f)
-        , rect(LayoutRect(f.x() - f.marginLeft(), f.y() - f.marginTop(), f.width() + f.horizontalMarginExtent(), f.height() + f.verticalMarginExtent()))
-        , everHadLayout(f.everHadLayout())
</del><ins>+class FloatWithRect : public RefCounted&lt;FloatWithRect&gt; {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static Ref&lt;FloatWithRect&gt; create(RenderBox&amp; renderer)
</ins><span class="cx">     {
</span><ins>+        return adoptRef(*new FloatWithRect(renderer));
</ins><span class="cx">     }
</span><ins>+    
+    RenderBox&amp; renderer() const { return m_renderer; }
+    LayoutRect rect() const { return m_rect; }
+    bool everHadLayout() const { return m_everHadLayout; }
</ins><span class="cx"> 
</span><del>-    RenderBox&amp; object;
-    LayoutRect rect;
-    bool everHadLayout;
</del><ins>+    void adjustRect(const LayoutRect&amp; rect) { m_rect = rect; }
+
+private:
+    FloatWithRect() = default;
+    
+    FloatWithRect(RenderBox&amp; renderer)
+        : m_renderer(renderer)
+        , m_rect(LayoutRect(renderer.x() - renderer.marginLeft(), renderer.y() - renderer.marginTop(), renderer.width() + renderer.horizontalMarginExtent(), renderer.height() + renderer.verticalMarginExtent()))
+        , m_everHadLayout(renderer.everHadLayout())
+    {
+    }
+    
+    RenderBox&amp; m_renderer;
+    LayoutRect m_rect;
+    bool m_everHadLayout { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> // Like LayoutState for layout(), LineLayoutState keeps track of global information
</span><span class="lines">@@ -56,13 +73,36 @@
</span><span class="cx"> // during an entire linebox tree layout pass (aka layoutInlineChildren).
</span><span class="cx"> class LineLayoutState {
</span><span class="cx"> public:
</span><ins>+    class FloatList {
+    public:
+        void append(Ref&lt;FloatWithRect&gt;&amp;&amp; floatWithRect)
+        {
+            m_floats.add(floatWithRect.copyRef());
+            m_floatWithRectMap.add(&amp;floatWithRect-&gt;renderer(), WTFMove(floatWithRect));
+        }
+        void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
+        FloatingObject* lastFloat() const { return m_lastFloat; }
+
+        void setLastCleanFloat(RenderBox&amp; floatBox) { m_lastCleanFloat = &amp;floatBox; }
+        RenderBox* lastCleanFloat() const { return m_lastCleanFloat; }
+
+        FloatWithRect* floatWithRect(RenderBox&amp; floatBox) const { return m_floatWithRectMap.get(&amp;floatBox); }
+
+        using Iterator = ListHashSet&lt;Ref&lt;FloatWithRect&gt;&gt;::iterator;
+        Iterator begin() { return m_floats.begin(); }
+        Iterator end() { return m_floats.end(); }
+        Iterator find(FloatWithRect&amp; floatBoxWithRect) { return m_floats.find(floatBoxWithRect); }
+        bool isEmpty() const { return m_floats.isEmpty(); }
+
+    private:
+        ListHashSet&lt;Ref&lt;FloatWithRect&gt;&gt; m_floats;
+        HashMap&lt;RenderBox*, Ref&lt;FloatWithRect&gt;&gt; m_floatWithRectMap;
+        FloatingObject* m_lastFloat { nullptr };
+        RenderBox* m_lastCleanFloat { nullptr };
+    };
+
</ins><span class="cx">     LineLayoutState(const RenderBlockFlow&amp; blockFlow, bool fullLayout, LayoutUnit&amp; repaintLogicalTop, LayoutUnit&amp; repaintLogicalBottom, RenderFlowThread* flowThread)
</span><del>-        : m_endLineLogicalTop(0)
-        , m_endLine(0)
-        , m_lastFloat(0)
-        , m_floatIndex(0)
-        , m_adjustedLogicalLineTop(0)
-        , m_flowThread(flowThread)
</del><ins>+        : m_flowThread(flowThread)
</ins><span class="cx">         , m_repaintLogicalTop(repaintLogicalTop)
</span><span class="cx">         , m_repaintLogicalBottom(repaintLogicalBottom)
</span><span class="cx">         , m_marginInfo(blockFlow, blockFlow.borderAndPaddingBefore(), blockFlow.borderAndPaddingAfter() + blockFlow.scrollbarLogicalHeight())
</span><span class="lines">@@ -82,14 +122,6 @@
</span><span class="cx">     RootInlineBox* endLine() const { return m_endLine; }
</span><span class="cx">     void setEndLine(RootInlineBox* line) { m_endLine = line; }
</span><span class="cx"> 
</span><del>-    FloatingObject* lastFloat() const { return m_lastFloat; }
-    void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
-
-    Vector&lt;FloatWithRect&gt;&amp; floats() { return m_floats; }
-
-    unsigned floatIndex() const { return m_floatIndex; }
-    void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }
-
</del><span class="cx">     LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; }
</span><span class="cx">     void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; }
</span><span class="cx"> 
</span><span class="lines">@@ -124,19 +156,18 @@
</span><span class="cx">     LayoutUnit&amp; prevFloatBottomFromAnonymousInlineBlock() { return m_prevFloatBottomFromAnonymousInlineBlock; }
</span><span class="cx">     LayoutUnit&amp; maxFloatBottomFromAnonymousInlineBlock() { return m_maxFloatBottomFromAnonymousInlineBlock; }
</span><span class="cx"> 
</span><ins>+    FloatList&amp; floatList() { return m_floatList; }
+
</ins><span class="cx"> private:
</span><span class="cx">     LineInfo m_lineInfo;
</span><span class="cx">     LayoutUnit m_endLineLogicalTop;
</span><del>-    RootInlineBox* m_endLine;
</del><ins>+    RootInlineBox* m_endLine { nullptr };
</ins><span class="cx"> 
</span><del>-    FloatingObject* m_lastFloat;
-    Vector&lt;FloatWithRect&gt; m_floats;
-    unsigned m_floatIndex;
-
</del><span class="cx">     LayoutUnit m_adjustedLogicalLineTop;
</span><span class="cx"> 
</span><del>-    RenderFlowThread* m_flowThread;
</del><ins>+    RenderFlowThread* m_flowThread { nullptr };
</ins><span class="cx"> 
</span><ins>+    FloatList m_floatList;
</ins><span class="cx">     // FIXME: Should this be a range object instead of two ints?
</span><span class="cx">     LayoutUnit&amp; m_repaintLogicalTop;
</span><span class="cx">     LayoutUnit&amp; m_repaintLogicalBottom;
</span></span></pre>
</div>
</div>

</body>
</html>