Changeset 252928 in webkit
- Timestamp:
- Nov 28, 2019 8:06:10 AM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r252927 r252928 1 2019-11-28 Antti Koivisto <antti@apple.com> 2 3 [LFC][IFC] Vector allocate InlineItemRuns 4 https://bugs.webkit.org/show_bug.cgi?id=204680 5 6 Reviewed by Zalan Bujtas. 7 8 Reduce heap allocations during inline layout. 9 10 This is ~15% speedup in PerformanceTests/Layout/line-layout-simple.html with LFC-in-render-tree enabled. 11 With other improvements it makes LFC path faster than simple line layout in this test. 12 13 * layout/inlineformatting/InlineLineBuilder.cpp: 14 (WebCore::Layout::LineBuilder::ContinousContent::ContinousContent): 15 (WebCore::Layout::LineBuilder::ContinousContent::append): 16 (WebCore::Layout::LineBuilder::ContinousContent::close): 17 18 Move to LineBuilder namespace. 19 20 (WebCore::Layout::LineBuilder::close): 21 (WebCore::Layout::LineBuilder::removeTrailingTrimmableContent): 22 (WebCore::Layout::LineBuilder::appendNonBreakableSpace): 23 (WebCore::Layout::LineBuilder::appendTextContent): 24 (WebCore::Layout::LineBuilder::appendNonReplacedInlineBox): 25 (WebCore::Layout::LineBuilder::appendLineBreak): 26 (WebCore::Layout::LineBuilder::TrimmableContent::append): 27 (WebCore::Layout::LineBuilder::formattingContext const): 28 (WebCore::Layout::LineBuilder::InlineItemRun::InlineItemRun): 29 (WebCore::Layout::LineBuilder::InlineItemRun::setCollapsesToZeroAdvanceWidth): 30 (WebCore::Layout::InlineItemRun::layoutBox const): Deleted. 31 (WebCore::Layout::InlineItemRun::logicalRect const): Deleted. 32 (WebCore::Layout::InlineItemRun::textContext const): Deleted. 33 (WebCore::Layout::InlineItemRun::isText const): Deleted. 34 (WebCore::Layout::InlineItemRun::isBox const): Deleted. 35 (WebCore::Layout::InlineItemRun::isContainerStart const): Deleted. 36 (WebCore::Layout::InlineItemRun::isContainerEnd const): Deleted. 37 (WebCore::Layout::InlineItemRun::isForcedLineBreak const): Deleted. 38 (WebCore::Layout::InlineItemRun::type const): Deleted. 39 (WebCore::Layout::InlineItemRun::setIsCollapsed): Deleted. 40 (WebCore::Layout::InlineItemRun::isCollapsed const): Deleted. 41 (WebCore::Layout::InlineItemRun::isCollapsedToZeroAdvanceWidth const): Deleted. 42 (WebCore::Layout::InlineItemRun::isCollapsible const): Deleted. 43 (WebCore::Layout::InlineItemRun::isWhitespace const): Deleted. 44 (WebCore::Layout::InlineItemRun::hasExpansionOpportunity const): Deleted. 45 (WebCore::Layout::InlineItemRun::InlineItemRun): Deleted. 46 (WebCore::Layout::InlineItemRun::setCollapsesToZeroAdvanceWidth): Deleted. 47 48 Move InlineItemRun to header in LineBuilder namespace so we can use directly in m_inlineItemRuns vector. 49 50 (WebCore::Layout::ContinousContent::canBeExpanded): Deleted. 51 (WebCore::Layout::ContinousContent::canBeMerged const): Deleted. 52 (WebCore::Layout::ContinousContent::ContinousContent): Deleted. 53 (WebCore::Layout::ContinousContent::append): Deleted. 54 (WebCore::Layout::ContinousContent::close): Deleted. 55 * layout/inlineformatting/InlineLineBuilder.h: 56 (WebCore::Layout::LineBuilder::InlineItemRun::layoutBox const): 57 (WebCore::Layout::LineBuilder::InlineItemRun::logicalRect const): 58 (WebCore::Layout::LineBuilder::InlineItemRun::textContext const): 59 (WebCore::Layout::LineBuilder::InlineItemRun::isText const): 60 (WebCore::Layout::LineBuilder::InlineItemRun::isBox const): 61 (WebCore::Layout::LineBuilder::InlineItemRun::isContainerStart const): 62 (WebCore::Layout::LineBuilder::InlineItemRun::isContainerEnd const): 63 (WebCore::Layout::LineBuilder::InlineItemRun::isForcedLineBreak const): 64 (WebCore::Layout::LineBuilder::InlineItemRun::type const): 65 (WebCore::Layout::LineBuilder::InlineItemRun::setIsCollapsed): 66 (WebCore::Layout::LineBuilder::InlineItemRun::isCollapsed const): 67 (WebCore::Layout::LineBuilder::InlineItemRun::isCollapsedToZeroAdvanceWidth const): 68 (WebCore::Layout::LineBuilder::InlineItemRun::isCollapsible const): 69 (WebCore::Layout::LineBuilder::InlineItemRun::isWhitespace const): 70 (WebCore::Layout::LineBuilder::InlineItemRun::hasExpansionOpportunity const): 71 (WebCore::Layout::LineBuilder::TrimmableContent::runIndexes): 72 73 Make TrimmableContent collect indexes to InlineItemRun vector instead of pointer. 74 We only ever append to the vector so the indexes stay valid for TrimmableContent lifetime. 75 76 (WebCore::Layout::LineBuilder::TrimmableContent::isEmpty const): 77 (WebCore::Layout::LineBuilder::TrimmableContent::clear): 78 (WebCore::Layout::LineBuilder::TrimmableContent::runs): Deleted. 79 1 80 2019-11-28 Antti Koivisto <antti@apple.com> 2 81 -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp
r252924 r252928 36 36 namespace Layout { 37 37 38 class InlineItemRun { 39 WTF_MAKE_ISO_ALLOCATED_INLINE(InlineItemRun); 40 public: 41 InlineItemRun(const InlineItem&, const Display::Rect&, WTF::Optional<Display::Run::TextContext> = WTF::nullopt); 42 43 const Box& layoutBox() const { return m_inlineItem.layoutBox(); } 44 const Display::Rect& logicalRect() const { return m_logicalRect; } 45 const Optional<Display::Run::TextContext>& textContext() const { return m_textContext; } 46 47 bool isText() const { return m_inlineItem.isText(); } 48 bool isBox() const { return m_inlineItem.isBox(); } 49 bool isContainerStart() const { return m_inlineItem.isContainerStart(); } 50 bool isContainerEnd() const { return m_inlineItem.isContainerEnd(); } 51 bool isForcedLineBreak() const { return m_inlineItem.isForcedLineBreak(); } 52 InlineItem::Type type() const { return m_inlineItem.type(); } 53 54 void setIsCollapsed() { m_isCollapsed = true; } 55 bool isCollapsed() const { return m_isCollapsed; } 56 57 void setCollapsesToZeroAdvanceWidth(); 58 bool isCollapsedToZeroAdvanceWidth() const { return m_collapsedToZeroAdvanceWidth; } 59 60 bool isCollapsible() const { return is<InlineTextItem>(m_inlineItem) && downcast<InlineTextItem>(m_inlineItem).isCollapsible(); } 61 bool isWhitespace() const { return is<InlineTextItem>(m_inlineItem) && downcast<InlineTextItem>(m_inlineItem).isWhitespace(); } 62 63 bool hasExpansionOpportunity() const { return isWhitespace() && !isCollapsedToZeroAdvanceWidth(); } 64 65 private: 66 const InlineItem& m_inlineItem; 67 Display::Rect m_logicalRect; 68 const Optional<Display::Run::TextContext> m_textContext; 69 bool m_isCollapsed { false }; 70 bool m_collapsedToZeroAdvanceWidth { false }; 71 }; 72 73 InlineItemRun::InlineItemRun(const InlineItem& inlineItem, const Display::Rect& logicalRect, WTF::Optional<Display::Run::TextContext> textContext) 74 : m_inlineItem(inlineItem) 75 , m_logicalRect(logicalRect) 76 , m_textContext(textContext) 77 { 78 } 79 80 void InlineItemRun::setCollapsesToZeroAdvanceWidth() 81 { 82 m_collapsedToZeroAdvanceWidth = true; 83 m_logicalRect.setWidth({ }); 84 } 85 86 struct ContinousContent { 38 struct LineBuilder::ContinousContent { 87 39 public: 88 40 ContinousContent(const InlineItemRun&, bool textIsAlignJustify); … … 104 56 }; 105 57 106 ContinousContent::ContinousContent(const InlineItemRun& initialInlineRun, bool textIsAlignJustify)58 LineBuilder::ContinousContent::ContinousContent(const InlineItemRun& initialInlineRun, bool textIsAlignJustify) 107 59 : m_initialInlineRun(initialInlineRun) 108 60 , m_textIsAlignJustify(textIsAlignJustify) … … 111 63 } 112 64 113 bool ContinousContent::append(const InlineItemRun& inlineItemRun)65 bool LineBuilder::ContinousContent::append(const InlineItemRun& inlineItemRun) 114 66 { 115 67 // Merged content needs to be continuous. … … 133 85 } 134 86 135 LineBuilder::Run ContinousContent::close()87 LineBuilder::Run LineBuilder::ContinousContent::close() 136 88 { 137 89 if (!m_expandedLength) … … 264 216 while (runIndex < m_inlineItemRuns.size()) { 265 217 // Merge eligible runs. 266 auto continousContent = ContinousContent { *m_inlineItemRuns[runIndex], isTextAlignJustify() };218 auto continousContent = ContinousContent { m_inlineItemRuns[runIndex], isTextAlignJustify() }; 267 219 while (++runIndex < m_inlineItemRuns.size()) { 268 if (!continousContent.append( *m_inlineItemRuns[runIndex]))220 if (!continousContent.append(m_inlineItemRuns[runIndex])) 269 221 break; 270 222 } … … 430 382 431 383 // Collapse trimmable trailing content 432 for (auto* trimmableRun : m_trimmableContent.runs()) { 433 ASSERT(trimmableRun->isText()); 384 for (auto trimmableRunIndex : m_trimmableContent.runIndexes()) { 385 auto& trimmableRun = m_inlineItemRuns[trimmableRunIndex]; 386 ASSERT(trimmableRun.isText()); 434 387 // FIXME: We might need to be able to differentiate between trimmed and collapsed runs. 435 trimmableRun ->setCollapsesToZeroAdvanceWidth();388 trimmableRun.setCollapsesToZeroAdvanceWidth(); 436 389 } 437 390 m_lineBox.shrinkHorizontally(m_trimmableContent.width()); … … 444 397 auto lineIsVisuallyEmpty = [&] { 445 398 for (auto& run : m_inlineItemRuns) { 446 if (isVisuallyNonEmpty( *run))399 if (isVisuallyNonEmpty(run)) 447 400 return false; 448 401 } … … 490 443 // Check if this freshly appended content makes the line visually non-empty. 491 444 ASSERT(!m_inlineItemRuns.isEmpty()); 492 if (m_lineBox.isConsideredEmpty() && isVisuallyNonEmpty( *m_inlineItemRuns.last()))445 if (m_lineBox.isConsideredEmpty() && isVisuallyNonEmpty(m_inlineItemRuns.last())) 493 446 m_lineBox.setIsConsideredNonEmpty(); 494 447 } … … 496 449 void LineBuilder::appendNonBreakableSpace(const InlineItem& inlineItem, const Display::Rect& logicalRect) 497 450 { 498 m_inlineItemRuns.append( makeUnique<InlineItemRun>(inlineItem, logicalRect));451 m_inlineItemRuns.append({ inlineItem, logicalRect }); 499 452 m_lineBox.expandHorizontally(logicalRect.width()); 500 453 } … … 533 486 for (auto i = m_inlineItemRuns.size(); i--;) { 534 487 auto& run = m_inlineItemRuns[i]; 535 if (run ->isBox())488 if (run.isBox()) 536 489 return false; 537 490 // https://drafts.csswg.org/css-text-3/#white-space-phase-1 … … 540 493 // : "<span> </span> " <- the trailing whitespace collapses completely. 541 494 // Not that when the inline container has preserve whitespace style, "<span style="white-space: pre"> </span> " <- this whitespace stays around. 542 if (run ->isText())543 return run ->isCollapsible();544 ASSERT(run ->isContainerStart() || run->isContainerEnd());495 if (run.isText()) 496 return run.isCollapsible(); 497 ASSERT(run.isContainerStart() || run.isContainerEnd()); 545 498 } 546 499 return true; … … 550 503 auto contentStart = inlineItem.start(); 551 504 auto contentLength = collapsedRun ? 1 : inlineItem.length(); 552 auto lineRun = makeUnique<InlineItemRun>(inlineItem, Display::Rect { 0, contentLogicalWidth(), logicalWidth, { } },553 Display::Run::TextContext { contentStart, contentLength, inlineItem.layoutBox().textContext()->content } );505 auto lineRun = InlineItemRun { inlineItem, Display::Rect { 0, contentLogicalWidth(), logicalWidth, { } }, 506 Display::Run::TextContext { contentStart, contentLength, inlineItem.layoutBox().textContext()->content } }; 554 507 555 508 auto collapsesToZeroAdvanceWidth = willCollapseCompletely(); 556 509 if (collapsesToZeroAdvanceWidth) 557 lineRun ->setCollapsesToZeroAdvanceWidth();510 lineRun.setCollapsesToZeroAdvanceWidth(); 558 511 559 512 if (collapsedRun) 560 lineRun->setIsCollapsed(); 513 lineRun.setIsCollapsed(); 514 515 auto lineRunWidth = lineRun.logicalRect().width(); 561 516 if (isTrimmable) { 562 517 // If we ever trim this content, we need to know if the line visibility state needs to be recomputed. 563 518 if (m_trimmableContent.isEmpty()) 564 519 m_lineIsVisuallyEmptyBeforeTrimmableContent = isVisuallyEmpty(); 565 m_trimmableContent.append( *lineRun);566 } 567 568 m_lineBox.expandHorizontally(lineRun ->logicalRect().width());520 m_trimmableContent.append(lineRunWidth, m_inlineItemRuns.size()); 521 } 522 523 m_lineBox.expandHorizontally(lineRunWidth); 569 524 m_inlineItemRuns.append(WTFMove(lineRun)); 570 525 } … … 575 530 auto& boxGeometry = formattingContext().geometryForBox(layoutBox); 576 531 auto horizontalMargin = boxGeometry.horizontalMargin(); 577 m_inlineItemRuns.append( makeUnique<InlineItemRun>(inlineItem, Display::Rect { 0, contentLogicalWidth() + horizontalMargin.start, logicalWidth, { } }));532 m_inlineItemRuns.append({ inlineItem, Display::Rect { 0, contentLogicalWidth() + horizontalMargin.start, logicalWidth, { } } }); 578 533 m_lineBox.expandHorizontally(logicalWidth + horizontalMargin.start + horizontalMargin.end); 579 534 m_trimmableContent.clear(); … … 589 544 void LineBuilder::appendLineBreak(const InlineItem& inlineItem) 590 545 { 591 m_inlineItemRuns.append( makeUnique<InlineItemRun>(inlineItem, Display::Rect { 0, contentLogicalWidth(), { }, { } }));546 m_inlineItemRuns.append({ inlineItem, Display::Rect { 0, contentLogicalWidth(), { }, { } } }); 592 547 } 593 548 … … 733 688 } 734 689 735 void LineBuilder::TrimmableContent::append(InlineItemRun& inlineItemRun)736 {737 ASSERT(inlineItemRun.logicalRect().width() >= 0);738 m_width += inlineItemRun.logicalRect().width();739 m_inlineItemRuns.append(&inlineItemRun);740 }741 742 690 LineBox::Baseline LineBuilder::halfLeadingMetrics(const FontMetrics& fontMetrics, LayoutUnit lineLogicalHeight) 743 691 { … … 760 708 { 761 709 return m_inlineFormattingContext; 762 } 710 } 711 712 void LineBuilder::TrimmableContent::append(LayoutUnit itemRunWidth, size_t runIndex) 713 { 714 ASSERT(itemRunWidth >= 0); 715 m_width += itemRunWidth; 716 m_runIndexes.append(runIndex); 717 } 718 719 LineBuilder::InlineItemRun::InlineItemRun(const InlineItem& inlineItem, const Display::Rect& logicalRect, WTF::Optional<Display::Run::TextContext> textContext) 720 : m_inlineItem(inlineItem) 721 , m_logicalRect(logicalRect) 722 , m_textContext(textContext) 723 { 724 } 725 726 void LineBuilder::InlineItemRun::setCollapsesToZeroAdvanceWidth() 727 { 728 m_collapsedToZeroAdvanceWidth = true; 729 m_logicalRect.setWidth({ }); 730 } 763 731 764 732 } -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h
r252924 r252928 36 36 namespace Layout { 37 37 38 struct ContinousContent;39 38 class InlineFormattingContext; 40 class InlineItemRun;41 39 42 40 class LineBuilder { 41 class InlineItemRun; 42 struct ContinousContent; 43 43 44 public: 44 45 struct Constraints { … … 53 54 Optional<HeightAndBaseline> heightAndBaseline; 54 55 }; 56 55 57 enum class SkipAlignment { No, Yes }; 56 58 LineBuilder(const InlineFormattingContext&, Optional<TextAlignMode>, SkipAlignment); … … 149 151 150 152 LayoutState& layoutState() const; 151 const InlineFormattingContext& formattingContext() const; 153 const InlineFormattingContext& formattingContext() const; 154 155 class InlineItemRun { 156 public: 157 InlineItemRun(const InlineItem&, const Display::Rect&, WTF::Optional<Display::Run::TextContext> = WTF::nullopt); 158 159 const Box& layoutBox() const { return m_inlineItem.layoutBox(); } 160 const Display::Rect& logicalRect() const { return m_logicalRect; } 161 const Optional<Display::Run::TextContext>& textContext() const { return m_textContext; } 162 163 bool isText() const { return m_inlineItem.isText(); } 164 bool isBox() const { return m_inlineItem.isBox(); } 165 bool isContainerStart() const { return m_inlineItem.isContainerStart(); } 166 bool isContainerEnd() const { return m_inlineItem.isContainerEnd(); } 167 bool isForcedLineBreak() const { return m_inlineItem.isForcedLineBreak(); } 168 InlineItem::Type type() const { return m_inlineItem.type(); } 169 170 void setIsCollapsed() { m_isCollapsed = true; } 171 bool isCollapsed() const { return m_isCollapsed; } 172 173 void setCollapsesToZeroAdvanceWidth(); 174 bool isCollapsedToZeroAdvanceWidth() const { return m_collapsedToZeroAdvanceWidth; } 175 176 bool isCollapsible() const { return is<InlineTextItem>(m_inlineItem) && downcast<InlineTextItem>(m_inlineItem).isCollapsible(); } 177 bool isWhitespace() const { return is<InlineTextItem>(m_inlineItem) && downcast<InlineTextItem>(m_inlineItem).isWhitespace(); } 178 179 bool hasExpansionOpportunity() const { return isWhitespace() && !isCollapsedToZeroAdvanceWidth(); } 180 181 private: 182 const InlineItem& m_inlineItem; 183 Display::Rect m_logicalRect; 184 const Optional<Display::Run::TextContext> m_textContext; 185 bool m_isCollapsed { false }; 186 bool m_collapsedToZeroAdvanceWidth { false }; 187 }; 188 189 struct TrimmableContent { 190 void append(LayoutUnit itemRunWidth, size_t runIndex); 191 void clear(); 192 193 LayoutUnit width() const { return m_width; } 194 Vector<size_t, 5>& runIndexes() { return m_runIndexes; } 195 bool isEmpty() const { return m_runIndexes.isEmpty(); } 196 197 private: 198 Vector<size_t, 5> m_runIndexes; 199 LayoutUnit m_width; 200 }; 152 201 153 202 const InlineFormattingContext& m_inlineFormattingContext; 154 Vector<std::unique_ptr<InlineItemRun>, 50> m_inlineItemRuns; 155 struct TrimmableContent { 156 void append(InlineItemRun&); 157 void clear(); 158 159 LayoutUnit width() const { return m_width; } 160 using TrimmableList = Vector<InlineItemRun*, 5>; 161 TrimmableList& runs() { return m_inlineItemRuns; } 162 bool isEmpty() const { return m_inlineItemRuns.isEmpty(); } 163 164 private: 165 TrimmableList m_inlineItemRuns; 166 LayoutUnit m_width; 167 }; 203 Vector<InlineItemRun, 50> m_inlineItemRuns; 168 204 TrimmableContent m_trimmableContent; 169 205 Optional<LineBox::Baseline> m_initialStrut; … … 178 214 inline void LineBuilder::TrimmableContent::clear() 179 215 { 180 m_ inlineItemRuns.clear();216 m_runIndexes.clear(); 181 217 m_width = { }; 182 218 }
Note: See TracChangeset
for help on using the changeset viewer.