Commit 18040c0c authored by Christian Biesinger's avatar Christian Biesinger Committed by Commit Bot

[layoutng] Create the fragment's children vector with the exact capacity

This will let us avoid an allocation in many cases and is never worse
than the previous code, and saves heap memory.

Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: I0e63a318d495747c322224b70175954a889e4ea8
Reviewed-on: https://chromium-review.googlesource.com/c/1289082Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Commit-Queue: Christian Biesinger <cbiesinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600922}
parent ff7ce534
......@@ -130,21 +130,22 @@ scoped_refptr<NGLayoutResult> NGLineBoxFragmentBuilder::ToLineBoxFragment() {
WritingMode line_writing_mode(ToLineWritingMode(GetWritingMode()));
NGPhysicalSize physical_size = Size().ConvertToPhysical(line_writing_mode);
Vector<NGLink> children;
if (!children_.IsEmpty())
children.ReserveInitialCapacity(children_.size());
DCHECK_EQ(children_.size(), offsets_.size());
for (wtf_size_t i = 0; i < children_.size(); i++) {
auto& child = children_[i];
child.offset_ = offsets_[i].ConvertToPhysical(
line_writing_mode, Direction(), physical_size, child->Size());
children.emplace_back(
std::move(children_[i]),
offsets_[i].ConvertToPhysical(line_writing_mode, Direction(),
physical_size, child->Size()));
}
// Because this vector will be long-lived, make sure to not waaste space.
// (We reserve an initial capacity when adding the first child)
if (children_.size())
children_.ShrinkToReasonableCapacity();
scoped_refptr<const NGPhysicalLineBoxFragment> fragment =
base::AdoptRef(new NGPhysicalLineBoxFragment(
Style(), style_variant_, physical_size, children_, metrics_,
Style(), style_variant_, physical_size, children, metrics_,
base_direction_,
break_token_ ? std::move(break_token_)
: NGInlineBreakToken::Create(node_)));
......
......@@ -77,11 +77,7 @@ NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
has_last_resort_break_ = true;
}
}
// Assume that if we have one child, we may have more than one and try to
// limit the number of allocations we would do in that case.
if (!children_.capacity())
children_.ReserveCapacity(16);
children_.emplace_back(std::move(child), NGPhysicalOffset());
children_.emplace_back(std::move(child));
offsets_.push_back(child_offset);
return *this;
}
......
......@@ -31,6 +31,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGBaseFragmentBuilder {
STACK_ALLOCATED();
public:
typedef Vector<scoped_refptr<const NGPhysicalFragment>, 16> ChildrenVector;
typedef Vector<NGLogicalOffset, 16> OffsetVector;
~NGContainerFragmentBuilder() override;
......@@ -96,7 +97,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGBaseFragmentBuilder {
scoped_refptr<const NGPhysicalFragment>,
const NGLogicalOffset&);
const Vector<NGLink>& Children() const { return children_; }
const ChildrenVector& Children() const { return children_; }
// Builder has non-trivial out-of-flow descendant methods.
// These methods are building blocks for implementation of
......@@ -224,15 +225,7 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGBaseFragmentBuilder {
NGUnpositionedListMarker unpositioned_list_marker_;
// Store NGLinks rather than NGPhysicalOffsets even though we don't have the
// offsets yet to allow us to move the entire vector to the fragment at
// construction time.
// Unlike OffsetVector, we don't want to keep the inline capacity around
// because this vector will be long-lived, and it would be wasteful to reserve
// space for 16 children in every fragment. Instead, we reserve some initial
// capacity for it when adding the first child and shrink it down when
// creating the fragment.
Vector<NGLink> 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
......
......@@ -237,11 +237,16 @@ scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment(
NGPhysicalSize physical_size = Size().ConvertToPhysical(GetWritingMode());
Vector<NGLink> children;
children.ReserveInitialCapacity(children_.size());
DCHECK_EQ(children_.size(), offsets_.size());
for (wtf_size_t i = 0; i < children_.size(); i++) {
auto& child = children_[i];
child.offset_ = offsets_[i].ConvertToPhysical(
block_or_line_writing_mode, Direction(), physical_size, child->Size());
children.emplace_back(
std::move(children_[i]),
offsets_[i].ConvertToPhysical(block_or_line_writing_mode, Direction(),
physical_size, child->Size()));
}
scoped_refptr<NGBreakToken> break_token;
......@@ -263,13 +268,9 @@ scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment(
}
}
// Because this vector will be long-lived, make sure to not waste space.
// (We reserve an initial capacity when adding the first child)
if (children_.size())
children_.ShrinkToReasonableCapacity();
scoped_refptr<const NGPhysicalBoxFragment> fragment =
base::AdoptRef(new NGPhysicalBoxFragment(
layout_object_, Style(), style_variant_, physical_size, children_,
layout_object_, Style(), style_variant_, physical_size, children,
borders_.ConvertToPhysical(GetWritingMode(), Direction()),
padding_.ConvertToPhysical(GetWritingMode(), Direction()), baselines_,
BoxType(), is_fieldset_container_, is_rendered_legend,
......
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