[LFC][IFC] Allocate InlineItems in a vector
https://bugs.webkit.org/show_bug.cgi?id=206411

Reviewed by Zalan Bujtas.

Even the largest InlineItem (InlineTextItem) is small (fits to 24 bytes), and they are allocated
in large numbers (one per word and per whitespace typically). Reduce heap allocations by turning
InlineItem into a fixed size type.

The InlineItem vector is immutable during layout so pointer to items can still be safely used.

* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::collectInlineContentIfNeeded):
* layout/inlineformatting/InlineFormattingState.h:
(WebCore::Layout::InlineFormattingState::addInlineItem):
* layout/inlineformatting/InlineItem.cpp:
(WebCore::Layout::InlineItem::InlineItem): Deleted.
* layout/inlineformatting/InlineItem.h:
(WebCore::Layout::InlineItem::layoutBox const):
(WebCore::Layout::InlineItem::style const):
(WebCore::Layout::InlineItem::InlineItem):

Gather members from the subclasses as protected fields.

* layout/inlineformatting/InlineSoftLineBreakItem.h:

Move the field to the base class.

(WebCore::Layout::InlineSoftLineBreakItem::position const):
(WebCore::Layout::InlineSoftLineBreakItem::createSoftLineBreakItem):
(WebCore::Layout::InlineSoftLineBreakItem::InlineSoftLineBreakItem):
(): Deleted.
* layout/inlineformatting/InlineTextItem.cpp:
(WebCore::Layout::InlineTextItem::createWhitespaceItem): Deleted.
(WebCore::Layout::InlineTextItem::createNonWhitespaceItem): Deleted.
(WebCore::Layout::InlineTextItem::createEmptyItem): Deleted.
(WebCore::Layout::InlineTextItem::InlineTextItem): Deleted.
* layout/inlineformatting/InlineTextItem.h:

Move the fields to the base class.

(WebCore::Layout::InlineTextItem::start const):
(WebCore::Layout::InlineTextItem::width const):

Place width optional into a separate bit and a value as this allows better packing of members.

(WebCore::Layout::InlineTextItem::createWhitespaceItem):
(WebCore::Layout::InlineTextItem::createNonWhitespaceItem):
(WebCore::Layout::InlineTextItem::createEmptyItem):
(WebCore::Layout::InlineTextItem::InlineTextItem):

Inline construction functions.

(): Deleted.
* layout/inlineformatting/LineLayoutContext.cpp:
(WebCore::Layout::nextWrapOpportunity):
(WebCore::Layout::LineCandidateContent::appendFloat):

Use a raw pointer instead of a WeakPtr. InlineItems are immuttable during layout.

(WebCore::Layout::LineLayoutContext::close):
(WebCore::Layout::LineLayoutContext::nextContentForLine):
* layout/inlineformatting/LineLayoutContext.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254749 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 4bf4945..b69b899 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,69 @@
+2020-01-17  Antti Koivisto  <antti@apple.com>
+
+        [LFC][IFC] Allocate InlineItems in a vector
+        https://bugs.webkit.org/show_bug.cgi?id=206411
+
+        Reviewed by Zalan Bujtas.
+
+        Even the largest InlineItem (InlineTextItem) is small (fits to 24 bytes), and they are allocated
+        in large numbers (one per word and per whitespace typically). Reduce heap allocations by turning
+        InlineItem into a fixed size type.
+
+        The InlineItem vector is immutable during layout so pointer to items can still be safely used.
+
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::collectInlineContentIfNeeded):
+        * layout/inlineformatting/InlineFormattingState.h:
+        (WebCore::Layout::InlineFormattingState::addInlineItem):
+        * layout/inlineformatting/InlineItem.cpp:
+        (WebCore::Layout::InlineItem::InlineItem): Deleted.
+        * layout/inlineformatting/InlineItem.h:
+        (WebCore::Layout::InlineItem::layoutBox const):
+        (WebCore::Layout::InlineItem::style const):
+        (WebCore::Layout::InlineItem::InlineItem):
+
+        Gather members from the subclasses as protected fields.
+
+        * layout/inlineformatting/InlineSoftLineBreakItem.h:
+
+        Move the field to the base class.
+
+        (WebCore::Layout::InlineSoftLineBreakItem::position const):
+        (WebCore::Layout::InlineSoftLineBreakItem::createSoftLineBreakItem):
+        (WebCore::Layout::InlineSoftLineBreakItem::InlineSoftLineBreakItem):
+        (): Deleted.
+        * layout/inlineformatting/InlineTextItem.cpp:
+        (WebCore::Layout::InlineTextItem::createWhitespaceItem): Deleted.
+        (WebCore::Layout::InlineTextItem::createNonWhitespaceItem): Deleted.
+        (WebCore::Layout::InlineTextItem::createEmptyItem): Deleted.
+        (WebCore::Layout::InlineTextItem::InlineTextItem): Deleted.
+        * layout/inlineformatting/InlineTextItem.h:
+
+        Move the fields to the base class.
+
+        (WebCore::Layout::InlineTextItem::start const):
+        (WebCore::Layout::InlineTextItem::width const):
+
+        Place width optional into a separate bit and a value as this allows better packing of members.
+
+        (WebCore::Layout::InlineTextItem::createWhitespaceItem):
+        (WebCore::Layout::InlineTextItem::createNonWhitespaceItem):
+        (WebCore::Layout::InlineTextItem::createEmptyItem):
+        (WebCore::Layout::InlineTextItem::InlineTextItem):
+
+        Inline construction functions.
+
+        (): Deleted.
+        * layout/inlineformatting/LineLayoutContext.cpp:
+        (WebCore::Layout::nextWrapOpportunity):
+        (WebCore::Layout::LineCandidateContent::appendFloat):
+
+        Use a raw pointer instead of a WeakPtr. InlineItems are immuttable during layout.
+
+        (WebCore::Layout::LineLayoutContext::close):
+        (WebCore::Layout::LineLayoutContext::nextContentForLine):
+        * layout/inlineformatting/LineLayoutContext.h:
+
 2020-01-17  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][IFC] Optimize nextWrapOpportunity/isAtSoftWrapOpportunity for the most common inline content
diff --git a/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp b/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
index 0273660..ab6cc2e 100644
--- a/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
@@ -345,7 +345,7 @@
             if (!treatAsInlineContainer(layoutBox))
                 break;
             // This is the start of an inline container (e.g. <span>).
-            formattingState.addInlineItem(makeUnique<InlineItem>(layoutBox, InlineItem::Type::ContainerStart));
+            formattingState.addInlineItem({ layoutBox, InlineItem::Type::ContainerStart });
             auto& container = downcast<Container>(layoutBox);
             if (!container.hasInFlowOrFloatingChild())
                 break;
@@ -356,17 +356,17 @@
             auto& layoutBox = *layoutQueue.takeLast();
             // This is the end of an inline container (e.g. </span>).
             if (treatAsInlineContainer(layoutBox))
-                formattingState.addInlineItem(makeUnique<InlineItem>(layoutBox, InlineItem::Type::ContainerEnd));
+                formattingState.addInlineItem({ layoutBox, InlineItem::Type::ContainerEnd });
             else if (layoutBox.isLineBreakBox())
-                formattingState.addInlineItem(makeUnique<InlineItem>(layoutBox, InlineItem::Type::HardLineBreak));
+                formattingState.addInlineItem({ layoutBox, InlineItem::Type::HardLineBreak });
             else if (layoutBox.isFloatingPositioned())
-                formattingState.addInlineItem(makeUnique<InlineItem>(layoutBox, InlineItem::Type::Float));
+                formattingState.addInlineItem({ layoutBox, InlineItem::Type::Float });
             else {
                 ASSERT(layoutBox.isInlineLevelBox());
                 if (layoutBox.hasTextContent())
                     InlineTextItem::createAndAppendTextItems(formattingState.inlineItems(), layoutBox);
                 else
-                    formattingState.addInlineItem(makeUnique<InlineItem>(layoutBox, InlineItem::Type::Box));
+                    formattingState.addInlineItem({ layoutBox, InlineItem::Type::Box });
             }
 
             if (auto* nextSibling = layoutBox.nextInFlowOrFloatingSibling()) {
diff --git a/Source/WebCore/layout/inlineformatting/InlineFormattingState.h b/Source/WebCore/layout/inlineformatting/InlineFormattingState.h
index f351654..3cf4442 100644
--- a/Source/WebCore/layout/inlineformatting/InlineFormattingState.h
+++ b/Source/WebCore/layout/inlineformatting/InlineFormattingState.h
@@ -35,7 +35,7 @@
 namespace WebCore {
 namespace Layout {
 
-using InlineItems = Vector<std::unique_ptr<InlineItem>, 30>;
+using InlineItems = Vector<InlineItem, 30>;
 
 // InlineFormattingState holds the state for a particular inline formatting context tree.
 class InlineFormattingState : public FormattingState {
@@ -46,7 +46,7 @@
 
     InlineItems& inlineItems() { return m_inlineItems; }
     const InlineItems& inlineItems() const { return m_inlineItems; }
-    void addInlineItem(std::unique_ptr<InlineItem>&& inlineItem) { m_inlineItems.append(WTFMove(inlineItem)); }
+    void addInlineItem(InlineItem&& inlineItem) { m_inlineItems.append(WTFMove(inlineItem)); }
 
     const Display::InlineContent* displayInlineContent() const { return m_displayInlineContent.get(); }
     Display::InlineContent& ensureDisplayInlineContent();
diff --git a/Source/WebCore/layout/inlineformatting/InlineItem.cpp b/Source/WebCore/layout/inlineformatting/InlineItem.cpp
index 52e4fca..5ca9882 100644
--- a/Source/WebCore/layout/inlineformatting/InlineItem.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineItem.cpp
@@ -33,11 +33,17 @@
 namespace WebCore {
 namespace Layout {
 
-InlineItem::InlineItem(const Box& layoutBox, Type type)
-    : m_layoutBox(layoutBox)
-    , m_type(type)
-{
-}
+struct SameSizeAsInlineItem {
+    void* layoutBox;
+    uint8_t enum1;
+    uint8_t enum2;
+    bool widthBool;
+    InlineLayoutUnit width;
+    unsigned start;
+    unsigned length;
+};
+
+static_assert(sizeof(InlineItem) == sizeof(SameSizeAsInlineItem), "");
 
 }
 }
diff --git a/Source/WebCore/layout/inlineformatting/InlineItem.h b/Source/WebCore/layout/inlineformatting/InlineItem.h
index daf3574..1064cf9 100644
--- a/Source/WebCore/layout/inlineformatting/InlineItem.h
+++ b/Source/WebCore/layout/inlineformatting/InlineItem.h
@@ -28,20 +28,19 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "LayoutBox.h"
-#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 namespace Layout {
 
-class InlineItem : public CanMakeWeakPtr<InlineItem> {
+class InlineItem {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    enum class Type { Text, HardLineBreak, SoftLineBreak, Box, Float, ContainerStart, ContainerEnd };
+    enum class Type : uint8_t { Text, HardLineBreak, SoftLineBreak, Box, Float, ContainerStart, ContainerEnd };
     InlineItem(const Box& layoutBox, Type);
 
     Type type() const { return m_type; }
-    const Box& layoutBox() const { return m_layoutBox; }
-    const RenderStyle& style() const { return m_layoutBox.style(); }
+    const Box& layoutBox() const { return *m_layoutBox; }
+    const RenderStyle& style() const { return layoutBox().style(); }
 
     bool isText() const { return type() == Type::Text; }
     bool isBox() const { return type() == Type::Box; }
@@ -53,10 +52,27 @@
     bool isContainerEnd() const { return type() == Type::ContainerEnd; }
 
 private:
-    const Box& m_layoutBox;
-    const Type m_type;
+    const Box* m_layoutBox { nullptr };
+    Type m_type { };
+
+protected:
+    // For InlineTextItem
+    enum class TextItemType  : uint8_t { Undefined, Whitespace, NonWhitespace };
+    TextItemType m_textItemType { TextItemType::Undefined };
+    bool m_hasWidth { false };
+    InlineLayoutUnit m_width { };
+    unsigned m_length { 0 };
+
+    // For InlineTextItem and InlineSoftLineBreakItem
+    unsigned m_startOrPosition { 0 };
 };
 
+inline InlineItem::InlineItem(const Box& layoutBox, Type type)
+    : m_layoutBox(&layoutBox)
+    , m_type(type)
+{
+}
+
 #define SPECIALIZE_TYPE_TRAITS_INLINE_ITEM(ToValueTypeName, predicate) \
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Layout::ToValueTypeName) \
     static bool isType(const WebCore::Layout::InlineItem& inlineItem) { return inlineItem.predicate; } \
diff --git a/Source/WebCore/layout/inlineformatting/InlineSoftLineBreakItem.h b/Source/WebCore/layout/inlineformatting/InlineSoftLineBreakItem.h
index 720b75e..f6d2c0d 100644
--- a/Source/WebCore/layout/inlineformatting/InlineSoftLineBreakItem.h
+++ b/Source/WebCore/layout/inlineformatting/InlineSoftLineBreakItem.h
@@ -34,24 +34,22 @@
 
 class InlineSoftLineBreakItem : public InlineItem {
 public:
-    static std::unique_ptr<InlineSoftLineBreakItem> createSoftLineBreakItem(const Box&, unsigned position);
+    static InlineSoftLineBreakItem createSoftLineBreakItem(const Box&, unsigned position);
 
-    unsigned position() const { return m_position; }
+    unsigned position() const { return m_startOrPosition; }
 
     InlineSoftLineBreakItem(const Box&, unsigned position);
-private:
-    unsigned m_position { 0 };
 };
 
-std::unique_ptr<InlineSoftLineBreakItem> InlineSoftLineBreakItem::createSoftLineBreakItem(const Box& inlineBox, unsigned position)
+inline InlineSoftLineBreakItem InlineSoftLineBreakItem::createSoftLineBreakItem(const Box& inlineBox, unsigned position)
 {
-    return makeUnique<InlineSoftLineBreakItem>(inlineBox, position);
+    return { inlineBox, position };
 }
 
-InlineSoftLineBreakItem::InlineSoftLineBreakItem(const Box& inlineBox, unsigned position)
+inline InlineSoftLineBreakItem::InlineSoftLineBreakItem(const Box& inlineBox, unsigned position)
     : InlineItem(inlineBox, Type::SoftLineBreak)
-    , m_position(position)
 {
+    m_startOrPosition = position;
 }
 
 }
diff --git a/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp b/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp
index db51dd4..2f789a3 100644
--- a/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp
@@ -36,6 +36,8 @@
 namespace WebCore {
 namespace Layout {
 
+static_assert(sizeof(InlineItem) == sizeof(InlineTextItem), "");
+
 static inline bool isWhitespaceCharacter(UChar character, bool preserveNewline)
 {
     return character == ' ' || character == '\t' || (character == '\n' && !preserveNewline);
@@ -119,35 +121,6 @@
     }
 }
 
-std::unique_ptr<InlineTextItem> InlineTextItem::createWhitespaceItem(const Box& inlineBox, unsigned start, unsigned length, Optional<InlineLayoutUnit> width)
-{
-    return makeUnique<InlineTextItem>(inlineBox, start, length, width, TextItemType::Whitespace);
-}
-
-std::unique_ptr<InlineTextItem> InlineTextItem::createNonWhitespaceItem(const Box& inlineBox, unsigned start, unsigned length, Optional<InlineLayoutUnit> width)
-{
-    return makeUnique<InlineTextItem>(inlineBox, start, length, width, TextItemType::NonWhitespace);
-}
-
-std::unique_ptr<InlineTextItem> InlineTextItem::createEmptyItem(const Box& inlineBox)
-{
-    return makeUnique<InlineTextItem>(inlineBox);
-}
-
-InlineTextItem::InlineTextItem(const Box& inlineBox, unsigned start, unsigned length, Optional<InlineLayoutUnit> width, TextItemType textItemType)
-    : InlineItem(inlineBox, Type::Text)
-    , m_start(start)
-    , m_length(length)
-    , m_width(width)
-    , m_textItemType(textItemType)
-{
-}
-
-InlineTextItem::InlineTextItem(const Box& inlineBox)
-    : InlineItem(inlineBox, Type::Text)
-{
-}
-
 bool InlineTextItem::isEmptyContent() const
 {
     // FIXME: We should check for more zero width content and not just U+200B.
diff --git a/Source/WebCore/layout/inlineformatting/InlineTextItem.h b/Source/WebCore/layout/inlineformatting/InlineTextItem.h
index 6ed58ac..2f724a7 100644
--- a/Source/WebCore/layout/inlineformatting/InlineTextItem.h
+++ b/Source/WebCore/layout/inlineformatting/InlineTextItem.h
@@ -37,33 +37,58 @@
 public:
     static void createAndAppendTextItems(InlineItems&, const Box&);
 
-    static std::unique_ptr<InlineTextItem> createWhitespaceItem(const Box&, unsigned start, unsigned length, Optional<InlineLayoutUnit> width);
-    static std::unique_ptr<InlineTextItem> createNonWhitespaceItem(const Box&, unsigned start, unsigned length, Optional<InlineLayoutUnit> width);
-    static std::unique_ptr<InlineTextItem> createEmptyItem(const Box&);
+    static InlineTextItem createWhitespaceItem(const Box&, unsigned start, unsigned length, Optional<InlineLayoutUnit> width);
+    static InlineTextItem createNonWhitespaceItem(const Box&, unsigned start, unsigned length, Optional<InlineLayoutUnit> width);
+    static InlineTextItem createEmptyItem(const Box&);
 
-    unsigned start() const { return m_start; }
+    unsigned start() const { return m_startOrPosition; }
     unsigned end() const { return start() + length(); }
     unsigned length() const { return m_length; }
 
     bool isWhitespace() const { return m_textItemType == TextItemType::Whitespace; }
     bool isCollapsible() const { return isWhitespace() && style().collapseWhiteSpace(); }
-    Optional<InlineLayoutUnit> width() const { return m_width; }
+    Optional<InlineLayoutUnit> width() const { return m_hasWidth ? makeOptional(m_width) : Optional<InlineLayoutUnit> { }; }
     bool isEmptyContent() const;
 
     std::unique_ptr<InlineTextItem> left(unsigned length) const;
     std::unique_ptr<InlineTextItem> right(unsigned length) const;
 
-    enum class TextItemType { Undefined, Whitespace, NonWhitespace };
+    using InlineItem::TextItemType;
+
     InlineTextItem(const Box&, unsigned start, unsigned length, Optional<InlineLayoutUnit> width, TextItemType);
     InlineTextItem(const Box&);
-
-private:
-    unsigned m_start { 0 };
-    unsigned m_length { 0 };
-    Optional<InlineLayoutUnit> m_width;
-    TextItemType m_textItemType { TextItemType::Undefined };
 };
 
+inline InlineTextItem InlineTextItem::createWhitespaceItem(const Box& inlineBox, unsigned start, unsigned length, Optional<InlineLayoutUnit> width)
+{
+    return { inlineBox, start, length, width, TextItemType::Whitespace };
+}
+
+inline InlineTextItem InlineTextItem::createNonWhitespaceItem(const Box& inlineBox, unsigned start, unsigned length, Optional<InlineLayoutUnit> width)
+{
+    return { inlineBox, start, length, width, TextItemType::NonWhitespace };
+}
+
+inline InlineTextItem InlineTextItem::createEmptyItem(const Box& inlineBox)
+{
+    return { inlineBox };
+}
+
+inline InlineTextItem::InlineTextItem(const Box& inlineBox, unsigned start, unsigned length, Optional<InlineLayoutUnit> width, TextItemType textItemType)
+    : InlineItem(inlineBox, Type::Text)
+{
+    m_startOrPosition = start;
+    m_length = length;
+    m_hasWidth = !!width;
+    m_width = width.valueOr(0);
+    m_textItemType = textItemType;
+}
+
+inline InlineTextItem::InlineTextItem(const Box& inlineBox)
+    : InlineItem(inlineBox, Type::Text)
+{
+}
+
 }
 }
 
diff --git a/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp b/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp
index 5060983..b7aab31 100644
--- a/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp
+++ b/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp
@@ -121,7 +121,7 @@
     auto inlineItemIndexWithContent = [&] (auto index) {
         // Break at the first text/box/line break inline item.
         for (; index < inlineItemCount; ++index) {
-            auto& inlineItem = *inlineContent[index];
+            auto& inlineItem = inlineContent[index];
             if (inlineItem.isText() || inlineItem.isBox())
                 return index;
             if (inlineItem.isLineBreak()) {
@@ -150,13 +150,13 @@
             // We always stop at line breaks. The wrap position is after the line break.
             return nextContentIndex + 1;
         }
-        if (isAtSoftWrapOpportunity(*inlineContent[startContentIndex], *inlineContent[nextContentIndex])) {
+        if (isAtSoftWrapOpportunity(inlineContent[startContentIndex], inlineContent[nextContentIndex])) {
             // There's a soft wrap opportunity between the start and the nextContent.
             // Now forward-find from the start position to see where we can actually wrap.
             // [ex-][ample] vs. [ex-][container start][container end][ample]
             // where [ex-] is startContent and [ample] is the nextContent.
             for (auto candidateIndex = startContentIndex + 1; candidateIndex < nextContentIndex; ++candidateIndex) {
-                if (inlineContent[candidateIndex]->isContainerStart()) {
+                if (inlineContent[candidateIndex].isContainerStart()) {
                     // inline content and [container start] and [container end] form unbreakable content.
                     // ex-<span></span>ample  : wrap opportunity is after "ex-".
                     // ex-</span></span>ample : wrap opportunity is after "ex-</span></span>".
@@ -175,7 +175,7 @@
 struct LineCandidateContent {
     void appendInlineContent(const InlineItem&, InlineLayoutUnit logicalWidth);
     void appendLineBreak(const InlineItem& inlineItem) { setTrailingLineBreak(inlineItem); }
-    void appendFloat(const InlineItem& inlineItem) { m_floats.append(makeWeakPtr(inlineItem)); }
+    void appendFloat(const InlineItem& inlineItem) { m_floats.append(&inlineItem); }
 
     bool hasIntrusiveFloats() const { return !m_floats.isEmpty(); }
     const LineBreaker::RunList& inlineRuns() const { return m_inlineRuns; }
@@ -325,7 +325,7 @@
             return LineBuilder::IsLastLineWithInlineContent::No;
         // Omit floats to see if this is the last line with inline content.
         for (auto i = m_inlineItems.size(); i--;) {
-            if (!m_inlineItems[i]->isFloat())
+            if (!m_inlineItems[i].isFloat())
                 return i == trailingInlineItemIndex ? LineBuilder::IsLastLineWithInlineContent::Yes : LineBuilder::IsLastLineWithInlineContent::No;
         }
         // There has to be at least one non-float item.
@@ -349,7 +349,7 @@
     if (partialLeadingContentLength) {
         // Handle leading partial content first (split text from the previous line).
         // Construct a partial leading inline item.
-        m_partialLeadingTextItem = downcast<InlineTextItem>(*m_inlineItems[inlineItemIndex]).right(*partialLeadingContentLength);
+        m_partialLeadingTextItem = downcast<InlineTextItem>(m_inlineItems[inlineItemIndex]).right(*partialLeadingContentLength);
         auto itemWidth = inlineItemWidth(*m_partialLeadingTextItem, currentLogicalRight);
         candidateContent.appendInlineContent(*m_partialLeadingTextItem, itemWidth);
         currentLogicalRight += itemWidth;
@@ -357,7 +357,7 @@
     }
 
     for (auto index = inlineItemIndex; index < softWrapOpportunityIndex; ++index) {
-        auto& inlineItem = *m_inlineItems[index];
+        auto& inlineItem = m_inlineItems[index];
         if (inlineItem.isText() || inlineItem.isContainerStart() || inlineItem.isContainerEnd()) {
             auto inlineItenmWidth = inlineItemWidth(inlineItem, currentLogicalRight);
             candidateContent.appendInlineContent(inlineItem, inlineItenmWidth);
diff --git a/Source/WebCore/layout/inlineformatting/LineLayoutContext.h b/Source/WebCore/layout/inlineformatting/LineLayoutContext.h
index 9cc65a3..efd2614 100644
--- a/Source/WebCore/layout/inlineformatting/LineLayoutContext.h
+++ b/Source/WebCore/layout/inlineformatting/LineLayoutContext.h
@@ -46,12 +46,12 @@
         };
         Optional<unsigned> trailingInlineItemIndex;
         Optional<PartialContent> partialContent;
-        Vector<WeakPtr<InlineItem>> floats;
+        Vector<const InlineItem*> floats;
         const LineBuilder::RunList runList;
         const Display::LineBox lineBox;
     };
     LineContent layoutLine(LineBuilder&, unsigned leadingInlineItemIndex, Optional<unsigned> partialLeadingContentLength);
-    using FloatList = Vector<WeakPtr<InlineItem>>;
+    using FloatList = Vector<const InlineItem*>;
 
 private:
     void nextContentForLine(LineCandidateContent&, unsigned inlineItemIndex, Optional<unsigned> overflowLength, InlineLayoutUnit currentLogicalRight);