Commit f007b805 authored by Ian Kilpatrick's avatar Ian Kilpatrick Committed by Commit Bot

[LayoutNG] Merge NGContainerFragmentBuilder::children_ and offsets_ vectors.

This merges the two vectors into one using a new struct
"ChildWithOffset".

There might be a (slight) positive perf impact with this change, as well
as a (very slight) decrease in stack.

Bug: 635619
Change-Id: I44a981bcf36379ffd94a1490c532c6b70a343e33
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1633019
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664158}
parent b625beba
...@@ -16,7 +16,6 @@ namespace blink { ...@@ -16,7 +16,6 @@ namespace blink {
void NGLineBoxFragmentBuilder::Reset() { void NGLineBoxFragmentBuilder::Reset() {
children_.Shrink(0); children_.Shrink(0);
offsets_.Shrink(0);
child_break_tokens_.Shrink(0); child_break_tokens_.Shrink(0);
inline_break_tokens_.Shrink(0); inline_break_tokens_.Shrink(0);
oof_positioned_candidates_.Shrink(0); oof_positioned_candidates_.Shrink(0);
...@@ -78,7 +77,6 @@ void NGLineBoxFragmentBuilder::ChildList::MoveInBlockDirection(LayoutUnit delta, ...@@ -78,7 +77,6 @@ void NGLineBoxFragmentBuilder::ChildList::MoveInBlockDirection(LayoutUnit delta,
} }
void NGLineBoxFragmentBuilder::AddChildren(ChildList& children) { void NGLineBoxFragmentBuilder::AddChildren(ChildList& children) {
offsets_.ReserveCapacity(children.size());
children_.ReserveCapacity(children.size()); children_.ReserveCapacity(children.size());
for (auto& child : children) { for (auto& child : children) {
......
...@@ -2198,23 +2198,23 @@ LayoutUnit NGBlockLayoutAlgorithm::ComputeLineBoxBaselineOffset( ...@@ -2198,23 +2198,23 @@ LayoutUnit NGBlockLayoutAlgorithm::ComputeLineBoxBaselineOffset(
// Add a baseline from a child box fragment. // Add a baseline from a child box fragment.
// @return false if the specified child is not a box or is OOF. // @return false if the specified child is not a box or is OOF.
bool NGBlockLayoutAlgorithm::AddBaseline(const NGBaselineRequest& request, bool NGBlockLayoutAlgorithm::AddBaseline(const NGBaselineRequest& request,
const NGPhysicalFragment* child, const NGPhysicalFragment& child,
LayoutUnit child_offset) { LayoutUnit child_offset) {
if (child->IsLineBox()) { if (child.IsLineBox()) {
const auto* line_box = To<NGPhysicalLineBoxFragment>(child); const auto& line_box = To<NGPhysicalLineBoxFragment>(child);
// Skip over a line-box which is empty. These don't have any baselines which // Skip over a line-box which is empty. These don't have any baselines which
// should be added. // should be added.
if (line_box->IsEmptyLineBox()) if (line_box.IsEmptyLineBox())
return false; return false;
LayoutUnit offset = LayoutUnit offset =
ComputeLineBoxBaselineOffset(request, *line_box, child_offset); ComputeLineBoxBaselineOffset(request, line_box, child_offset);
container_builder_.AddBaseline(request, offset); container_builder_.AddBaseline(request, offset);
return true; return true;
} }
if (child->IsFloatingOrOutOfFlowPositioned()) if (child.IsFloatingOrOutOfFlowPositioned())
return false; return false;
if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(child)) { if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(child)) {
...@@ -2236,21 +2236,20 @@ void NGBlockLayoutAlgorithm::PropagateBaselinesFromChildren() { ...@@ -2236,21 +2236,20 @@ void NGBlockLayoutAlgorithm::PropagateBaselinesFromChildren() {
for (const auto& request : requests) { for (const auto& request : requests) {
switch (request.AlgorithmType()) { switch (request.AlgorithmType()) {
case NGBaselineAlgorithmType::kAtomicInline: case NGBaselineAlgorithmType::kAtomicInline: {
if (Node().UseLogicalBottomMarginEdgeForInlineBlockBaseline()) if (Node().UseLogicalBottomMarginEdgeForInlineBlockBaseline())
break; break;
for (unsigned i = container_builder_.Children().size(); i--;) { const auto& children = container_builder_.Children();
if (AddBaseline(request, container_builder_.Children()[i].get(), for (auto it = children.rbegin(); it != children.rend(); ++it) {
container_builder_.Offsets()[i].block_offset)) if (AddBaseline(request, *it->fragment, it->offset.block_offset))
break; break;
} }
break; break;
}
case NGBaselineAlgorithmType::kFirstLine: case NGBaselineAlgorithmType::kFirstLine:
for (unsigned i = 0; i < container_builder_.Children().size(); i++) { for (const auto& child : container_builder_.Children()) {
if (AddBaseline(request, container_builder_.Children()[i].get(), if (AddBaseline(request, *child.fragment, child.offset.block_offset))
container_builder_.Offsets()[i].block_offset))
break; break;
} }
break; break;
......
...@@ -233,7 +233,7 @@ class CORE_EXPORT NGBlockLayoutAlgorithm ...@@ -233,7 +233,7 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
void PropagateBaselinesFromChildren(); void PropagateBaselinesFromChildren();
bool AddBaseline(const NGBaselineRequest&, bool AddBaseline(const NGBaselineRequest&,
const NGPhysicalFragment*, const NGPhysicalFragment&,
LayoutUnit child_offset); LayoutUnit child_offset);
// Compute the baseline offset of a line box from the content box. // Compute the baseline offset of a line box from the content box.
......
...@@ -31,9 +31,10 @@ using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*, ...@@ -31,9 +31,10 @@ using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*,
void GatherInlineContainerFragmentsFromLinebox( void GatherInlineContainerFragmentsFromLinebox(
NGBoxFragmentBuilder::InlineContainingBlockMap* inline_containing_block_map, NGBoxFragmentBuilder::InlineContainingBlockMap* inline_containing_block_map,
HashMap<const LayoutObject*, LineBoxPair>* containing_linebox_map, HashMap<const LayoutObject*, LineBoxPair>* containing_linebox_map,
const NGPhysicalLineBoxFragment* linebox, const NGPhysicalLineBoxFragment& linebox,
const PhysicalOffset linebox_offset) { const PhysicalOffset linebox_offset) {
for (auto& descendant : NGInlineFragmentTraversal::DescendantsOf(*linebox)) { for (const auto& descendant :
NGInlineFragmentTraversal::DescendantsOf(linebox)) {
if (!descendant.fragment->IsBox()) if (!descendant.fragment->IsBox())
continue; continue;
const LayoutObject* key = descendant.fragment->GetLayoutObject(); const LayoutObject* key = descendant.fragment->GetLayoutObject();
...@@ -58,19 +59,19 @@ void GatherInlineContainerFragmentsFromLinebox( ...@@ -58,19 +59,19 @@ void GatherInlineContainerFragmentsFromLinebox(
PhysicalRect fragment_rect( PhysicalRect fragment_rect(
linebox_offset + descendant.offset_to_container_box, linebox_offset + descendant.offset_to_container_box,
descendant.fragment->Size()); descendant.fragment->Size());
if (containing_lineboxes.first == linebox) { if (containing_lineboxes.first == &linebox) {
containing_block_geometry->start_fragment_union_rect.Unite(fragment_rect); containing_block_geometry->start_fragment_union_rect.Unite(fragment_rect);
} else if (!containing_lineboxes.first) { } else if (!containing_lineboxes.first) {
containing_lineboxes.first = linebox; containing_lineboxes.first = &linebox;
containing_block_geometry = containing_block_geometry =
NGBoxFragmentBuilder::InlineContainingBlockGeometry{fragment_rect, NGBoxFragmentBuilder::InlineContainingBlockGeometry{fragment_rect,
PhysicalRect()}; PhysicalRect()};
} }
// Skip fragments within an empty line boxes for the end fragment. // Skip fragments within an empty line boxes for the end fragment.
if (containing_lineboxes.second == linebox) { if (containing_lineboxes.second == &linebox) {
containing_block_geometry->end_fragment_union_rect.Unite(fragment_rect); containing_block_geometry->end_fragment_union_rect.Unite(fragment_rect);
} else if (!containing_lineboxes.second || !linebox->IsEmptyLineBox()) { } else if (!containing_lineboxes.second || !linebox.IsEmptyLineBox()) {
containing_lineboxes.second = linebox; containing_lineboxes.second = &linebox;
containing_block_geometry->end_fragment_union_rect = fragment_rect; containing_block_geometry->end_fragment_union_rect = fragment_rect;
} }
} }
...@@ -82,7 +83,6 @@ void NGBoxFragmentBuilder::RemoveChildren() { ...@@ -82,7 +83,6 @@ void NGBoxFragmentBuilder::RemoveChildren() {
child_break_tokens_.resize(0); child_break_tokens_.resize(0);
inline_break_tokens_.resize(0); inline_break_tokens_.resize(0);
children_.resize(0); children_.resize(0);
offsets_.resize(0);
} }
NGBoxFragmentBuilder& NGBoxFragmentBuilder::AddBreakBeforeChild( NGBoxFragmentBuilder& NGBoxFragmentBuilder::AddBreakBeforeChild(
...@@ -121,13 +121,12 @@ NGBoxFragmentBuilder& NGBoxFragmentBuilder::AddBreakBeforeLine( ...@@ -121,13 +121,12 @@ NGBoxFragmentBuilder& NGBoxFragmentBuilder::AddBreakBeforeLine(
DCHECK_GT(children_.size(), 0UL); DCHECK_GT(children_.size(), 0UL);
for (int i = children_.size() - 1; i >= 0; i--) { for (int i = children_.size() - 1; i >= 0; i--) {
DCHECK_NE(i, 0); DCHECK_NE(i, 0);
if (!children_[i]->IsLineBox()) if (!children_[i].fragment->IsLineBox())
continue; continue;
if (!--lines_to_remove) { if (!--lines_to_remove) {
// This is the first line that is going to the next fragment. Remove it, // This is the first line that is going to the next fragment. Remove it,
// and everything after it. // and everything after it.
children_.resize(i); children_.resize(i);
offsets_.resize(i);
break; break;
} }
} }
...@@ -287,20 +286,20 @@ void NGBoxFragmentBuilder::ComputeInlineContainerFragments( ...@@ -287,20 +286,20 @@ void NGBoxFragmentBuilder::ComputeInlineContainerFragments(
#endif #endif
HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map; HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map;
for (wtf_size_t i = 0; i < children_.size(); i++) { for (const auto& child : children_) {
if (children_[i]->IsLineBox()) { if (child.fragment->IsLineBox()) {
const auto* linebox = To<NGPhysicalLineBoxFragment>(children_[i].get()); const auto& linebox = To<NGPhysicalLineBoxFragment>(*child.fragment);
const PhysicalOffset linebox_offset = offsets_[i].ConvertToPhysical( const PhysicalOffset linebox_offset = child.offset.ConvertToPhysical(
GetWritingMode(), Direction(), GetWritingMode(), Direction(),
ToPhysicalSize(Size(), GetWritingMode()), linebox->Size()); ToPhysicalSize(Size(), GetWritingMode()), linebox.Size());
GatherInlineContainerFragmentsFromLinebox(inline_containing_block_map, GatherInlineContainerFragmentsFromLinebox(inline_containing_block_map,
&containing_linebox_map, &containing_linebox_map,
linebox, linebox_offset); linebox, linebox_offset);
} else if (children_[i]->IsBox()) { } else if (child.fragment->IsBox()) {
const auto* box_fragment = To<NGPhysicalBoxFragment>(children_[i].get()); const auto& box_fragment = To<NGPhysicalBoxFragment>(*child.fragment);
bool is_anonymous_container = bool is_anonymous_container =
box_fragment->GetLayoutObject() && box_fragment.GetLayoutObject() &&
box_fragment->GetLayoutObject()->IsAnonymousBlock(); box_fragment.GetLayoutObject()->IsAnonymousBlock();
if (!is_anonymous_container) if (!is_anonymous_container)
continue; continue;
// If child is an anonymous container, this might be a special case of // If child is an anonymous container, this might be a special case of
...@@ -309,15 +308,15 @@ void NGBoxFragmentBuilder::ComputeInlineContainerFragments( ...@@ -309,15 +308,15 @@ void NGBoxFragmentBuilder::ComputeInlineContainerFragments(
// lineboxes inside anonymous box. // lineboxes inside anonymous box.
// For more on this special case, see "css container is an inline, with // For more on this special case, see "css container is an inline, with
// inline splitting" comment in NGOutOfFlowLayoutPart::LayoutDescendant. // inline splitting" comment in NGOutOfFlowLayoutPart::LayoutDescendant.
const PhysicalOffset box_offset = offsets_[i].ConvertToPhysical( const PhysicalOffset box_offset = child.offset.ConvertToPhysical(
GetWritingMode(), Direction(), GetWritingMode(), Direction(),
ToPhysicalSize(Size(), GetWritingMode()), box_fragment->Size()); ToPhysicalSize(Size(), GetWritingMode()), box_fragment.Size());
// Traverse lineboxes of anonymous box. // Traverse lineboxes of anonymous box.
for (const auto& child : box_fragment->Children()) { for (const auto& box_child : box_fragment.Children()) {
if (child->IsLineBox()) { if (box_child->IsLineBox()) {
const auto* linebox = To<NGPhysicalLineBoxFragment>(child.get()); const auto& linebox = To<NGPhysicalLineBoxFragment>(*box_child);
const PhysicalOffset linebox_offset = child.Offset() + box_offset; const PhysicalOffset linebox_offset = box_child.Offset() + box_offset;
GatherInlineContainerFragmentsFromLinebox(inline_containing_block_map, GatherInlineContainerFragmentsFromLinebox(inline_containing_block_map,
&containing_linebox_map, &containing_linebox_map,
linebox, linebox_offset); linebox, linebox_offset);
......
...@@ -172,9 +172,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final ...@@ -172,9 +172,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
scoped_refptr<const NGLayoutResult> Abort( scoped_refptr<const NGLayoutResult> Abort(
NGLayoutResult::NGLayoutResultStatus); NGLayoutResult::NGLayoutResultStatus);
// A vector of child offsets. Initially set by AddChild().
const OffsetVector& Offsets() const { return offsets_; }
NGPhysicalFragment::NGBoxType BoxType() const; NGPhysicalFragment::NGBoxType BoxType() const;
NGBoxFragmentBuilder& SetBoxType(NGPhysicalFragment::NGBoxType box_type) { NGBoxFragmentBuilder& SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
box_type_ = box_type; box_type_ = box_type;
......
...@@ -142,34 +142,32 @@ void NGContainerFragmentBuilder::AddChildInternal( ...@@ -142,34 +142,32 @@ void NGContainerFragmentBuilder::AddChildInternal(
// In order to know where list-markers are within the children list (for the // In order to know where list-markers are within the children list (for the
// |NGSimplifiedLayoutAlgorithm|) we always place them as the first child. // |NGSimplifiedLayoutAlgorithm|) we always place them as the first child.
if (child->IsListMarker()) { if (child->IsListMarker()) {
children_.push_front(std::move(child)); children_.push_front(ChildWithOffset(child_offset, std::move(child)));
offsets_.push_front(child_offset);
return; return;
} }
children_.emplace_back(std::move(child)); children_.emplace_back(child_offset, std::move(child));
offsets_.push_back(child_offset);
} }
LogicalOffset NGContainerFragmentBuilder::GetChildOffset( LogicalOffset NGContainerFragmentBuilder::GetChildOffset(
const LayoutObject* child) const { const LayoutObject* object) const {
for (wtf_size_t i = 0; i < children_.size(); ++i) { for (const auto& child : children_) {
if (children_[i]->GetLayoutObject() == child) if (child.fragment->GetLayoutObject() == object)
return offsets_[i]; return child.offset;
// TODO(layout-dev): ikilpatrick thinks we may need to traverse // TODO(layout-dev): ikilpatrick thinks we may need to traverse
// further than the initial line-box children for a nested inline // further than the initial line-box children for a nested inline
// container. We could not come up with a testcase, it would be // container. We could not come up with a testcase, it would be
// something with split inlines, and nested oof/fixed descendants maybe. // something with split inlines, and nested oof/fixed descendants maybe.
if (children_[i]->IsLineBox()) { if (child.fragment->IsLineBox()) {
const auto& line_box_fragment = const auto& line_box_fragment =
To<NGPhysicalLineBoxFragment>(*children_[i]); To<NGPhysicalLineBoxFragment>(*child.fragment);
for (const auto& line_box_child : line_box_fragment.Children()) { for (const auto& line_box_child : line_box_fragment.Children()) {
if (line_box_child->GetLayoutObject() == child) { if (line_box_child->GetLayoutObject() == object) {
return offsets_[i] + line_box_child.Offset().ConvertToLogical( return child.offset + line_box_child.Offset().ConvertToLogical(
GetWritingMode(), Direction(), GetWritingMode(), Direction(),
line_box_fragment.Size(), line_box_fragment.Size(),
line_box_child->Size()); line_box_child->Size());
} }
} }
} }
...@@ -275,7 +273,7 @@ String NGContainerFragmentBuilder::ToString() const { ...@@ -275,7 +273,7 @@ String NGContainerFragmentBuilder::ToString() const {
InlineSize().ToFloat(), BlockSize().ToFloat(), InlineSize().ToFloat(), BlockSize().ToFloat(),
children_.size()); children_.size());
for (auto& child : children_) { for (auto& child : children_) {
builder.Append(child->DumpFragmentTree( builder.Append(child.fragment->DumpFragmentTree(
NGPhysicalFragment::DumpAll & ~NGPhysicalFragment::DumpHeaderText)); NGPhysicalFragment::DumpAll & ~NGPhysicalFragment::DumpHeaderText));
} }
return builder.ToString(); return builder.ToString();
......
...@@ -31,8 +31,18 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -31,8 +31,18 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
STACK_ALLOCATED(); STACK_ALLOCATED();
public: public:
typedef Vector<scoped_refptr<const NGPhysicalFragment>, 4> ChildrenVector; struct ChildWithOffset {
typedef Vector<LogicalOffset, 4> OffsetVector; DISALLOW_NEW();
ChildWithOffset(LogicalOffset offset,
scoped_refptr<const NGPhysicalFragment> fragment)
: offset(offset), fragment(std::move(fragment)) {}
// We store logical offsets (instead of the final physical), as we can't
// convert into the physical coordinate space until we know our final size.
LogicalOffset offset;
scoped_refptr<const NGPhysicalFragment> fragment;
};
typedef Vector<ChildWithOffset, 4> ChildrenVector;
LayoutUnit BfcLineOffset() const { return bfc_line_offset_; } LayoutUnit BfcLineOffset() const { return bfc_line_offset_; }
NGContainerFragmentBuilder& SetBfcLineOffset(LayoutUnit bfc_line_offset) { NGContainerFragmentBuilder& SetBfcLineOffset(LayoutUnit bfc_line_offset) {
...@@ -40,8 +50,8 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -40,8 +50,8 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
return *this; return *this;
} }
// The NGBfcOffset is where this fragment was positioned within the BFC. If // The BFC block-offset is where this fragment was positioned within the BFC.
// it is not set, this fragment may be placed anywhere within the BFC. // If it is not set, this fragment may be placed anywhere within the BFC.
const base::Optional<LayoutUnit>& BfcBlockOffset() const { const base::Optional<LayoutUnit>& BfcBlockOffset() const {
return bfc_block_offset_; return bfc_block_offset_;
} }
...@@ -241,11 +251,6 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -241,11 +251,6 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
ChildrenVector children_; ChildrenVector children_;
// Logical offsets for the children. Stored as logical offsets as we can't
// convert to physical offsets until layout of all children has been
// determined.
OffsetVector offsets_;
// Only used by the NGBoxFragmentBuilder subclass, but defined here to avoid // Only used by the NGBoxFragmentBuilder subclass, but defined here to avoid
// a virtual function call. // a virtual function call.
NGBreakTokenVector child_break_tokens_; NGBreakTokenVector child_break_tokens_;
...@@ -267,4 +272,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder { ...@@ -267,4 +272,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
} // namespace blink } // namespace blink
WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
blink::NGContainerFragmentBuilder::ChildWithOffset)
#endif // NGContainerFragmentBuilder #endif // NGContainerFragmentBuilder
...@@ -45,17 +45,16 @@ NGPhysicalContainerFragment::NGPhysicalContainerFragment( ...@@ -45,17 +45,16 @@ NGPhysicalContainerFragment::NGPhysicalContainerFragment(
builder->may_have_descendant_above_block_start_; builder->may_have_descendant_above_block_start_;
depends_on_percentage_block_size_ = DependsOnPercentageBlockSize(*builder); depends_on_percentage_block_size_ = DependsOnPercentageBlockSize(*builder);
DCHECK_EQ(builder->children_.size(), builder->offsets_.size());
// Because flexible arrays need to be the last member in a class, we need to // Because flexible arrays need to be the last member in a class, we need to
// have the buffer passed as a constructor argument and have the actual // have the buffer passed as a constructor argument and have the actual
// storage be part of the subclass. // storage be part of the subclass.
wtf_size_t i = 0; wtf_size_t i = 0;
for (auto& child : builder->children_) { for (auto& child : builder->children_) {
buffer[i].fragment = child.get(); buffer[i].fragment = child.fragment.get();
buffer[i].fragment->AddRef(); buffer[i].fragment->AddRef();
buffer[i].offset = builder->offsets_[i].ConvertToPhysical( buffer[i].offset = child.offset.ConvertToPhysical(
block_or_line_writing_mode, builder->Direction(), Size(), block_or_line_writing_mode, builder->Direction(), Size(),
child->Size()); child.fragment->Size());
++i; ++i;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment