Allocate memory for borders and padding members of NGPhysicalBoxFragment if needed
This patch changes memory layout of |NGPhysicalBoxFragment| based on value of
borders and padding as
- No borders and no padding
|NGPhysicalBoxFragment|, children[]
- having both borders no padding
|NGPhysicalBoxFragment|, children[], borders, padding
- borders and no padding
|NGPhysicalBoxFragment|, children[], borders
- no borders and padding
|NGPhysicalBoxFragment|, children[], padding
for reducing memory usage, since borders and padding are frequently zero.
(cherry picked from commit 8318aa75176654769ece376cd71fd9fc5deef823)
TBR=yosin@chromium.org
Bug: 962108
Change-Id: I2af0ed3a3c3f111d2d4cd567073ebcba628c7279
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1662094
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#335}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h b/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
index d1a4dce9..e4e8a9e 100644
--- a/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
+++ b/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
@@ -204,6 +204,8 @@
left == other.left;
}
+ bool IsZero() const { return !top && !right && !bottom && !left; }
+
LayoutUnit top;
LayoutUnit right;
LayoutUnit bottom;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index ef21edf..cea020a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -22,7 +22,7 @@
struct SameSizeAsNGPhysicalBoxFragment : NGPhysicalContainerFragment {
NGBaselineList baselines;
- NGPhysicalBoxStrut box_struts[2];
+ NGLink children[];
};
static_assert(sizeof(NGPhysicalBoxFragment) ==
@@ -43,21 +43,32 @@
scoped_refptr<const NGPhysicalBoxFragment> NGPhysicalBoxFragment::Create(
NGBoxFragmentBuilder* builder,
WritingMode block_or_line_writing_mode) {
+ const NGPhysicalBoxStrut borders =
+ builder->initial_fragment_geometry_->border.ConvertToPhysical(
+ builder->GetWritingMode(), builder->Direction());
+ const NGPhysicalBoxStrut padding =
+ builder->initial_fragment_geometry_->padding.ConvertToPhysical(
+ builder->GetWritingMode(), builder->Direction());
+ const size_t byte_size = sizeof(NGPhysicalBoxFragment) +
+ sizeof(NGLink) * builder->children_.size() +
+ (borders.IsZero() ? 0 : sizeof(borders)) +
+ (padding.IsZero() ? 0 : sizeof(padding));
// We store the children list inline in the fragment as a flexible
// array. Therefore, we need to make sure to allocate enough space for
// that array here, which requires a manual allocation + placement new.
// The initialization of the array is done by NGPhysicalContainerFragment;
// we pass the buffer as a constructor argument.
void* data = ::WTF::Partitions::FastMalloc(
- sizeof(NGPhysicalBoxFragment) +
- builder->children_.size() * sizeof(NGLink),
- ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>());
- new (data) NGPhysicalBoxFragment(builder, block_or_line_writing_mode);
+ byte_size, ::WTF::GetStringWithTypeName<NGPhysicalBoxFragment>());
+ new (data) NGPhysicalBoxFragment(builder, borders, padding,
+ block_or_line_writing_mode);
return base::AdoptRef(static_cast<NGPhysicalBoxFragment*>(data));
}
NGPhysicalBoxFragment::NGPhysicalBoxFragment(
NGBoxFragmentBuilder* builder,
+ const NGPhysicalBoxStrut& borders,
+ const NGPhysicalBoxStrut& padding,
WritingMode block_or_line_writing_mode)
: NGPhysicalContainerFragment(
builder,
@@ -67,14 +78,14 @@
? kFragmentRenderedLegend
: kFragmentBox,
builder->BoxType()),
- baselines_(builder->baselines_),
- borders_(builder->initial_fragment_geometry_->border.ConvertToPhysical(
- builder->GetWritingMode(),
- builder->Direction())),
- padding_(builder->initial_fragment_geometry_->padding.ConvertToPhysical(
- builder->GetWritingMode(),
- builder->Direction())) {
+ baselines_(builder->baselines_) {
DCHECK(GetLayoutObject() && GetLayoutObject()->IsBoxModelObject());
+ has_borders_ = !borders.IsZero();
+ if (has_borders_)
+ *const_cast<NGPhysicalBoxStrut*>(ComputeBordersAddress()) = borders;
+ has_padding_ = !padding.IsZero();
+ if (has_padding_)
+ *const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress()) = padding;
is_fieldset_container_ = builder->is_fieldset_container_;
is_legacy_layout_root_ = builder->is_legacy_layout_root_;
border_edge_ = builder->border_edges_.ToPhysical(builder->GetWritingMode());
@@ -278,8 +289,8 @@
// Legacy layout can (incorrectly) shift baseline position(s) during
// "simplified" layout.
DCHECK(IsLegacyLayoutRoot() || baselines_ == other.baselines_);
- DCHECK(borders_ == other.borders_);
- DCHECK(padding_ == other.padding_);
+ DCHECK(Borders() == other.Borders());
+ DCHECK(Padding() == other.Padding());
}
#endif
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
index ab1747ef7..ada1b07c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -33,12 +33,22 @@
return baselines_.Offset(request);
}
- const NGPhysicalBoxStrut Borders() const { return borders_; }
+ const NGPhysicalBoxStrut Borders() const {
+ if (!has_borders_)
+ return NGPhysicalBoxStrut();
+ return *ComputeBordersAddress();
+ }
- const NGPhysicalBoxStrut Padding() const { return padding_; }
+ const NGPhysicalBoxStrut Padding() const {
+ if (!has_padding_)
+ return NGPhysicalBoxStrut();
+ return *ComputePaddingAddress();
+ }
NGPixelSnappedPhysicalBoxStrut PixelSnappedPadding() const {
- return padding_.SnapToDevicePixels();
+ if (!has_padding_)
+ return NGPixelSnappedPhysicalBoxStrut();
+ return ComputePaddingAddress()->SnapToDevicePixels();
}
bool HasSelfPaintingLayer() const;
@@ -77,12 +87,27 @@
private:
NGPhysicalBoxFragment(NGBoxFragmentBuilder* builder,
+ const NGPhysicalBoxStrut& borders,
+ const NGPhysicalBoxStrut& padding,
WritingMode block_or_line_writing_mode);
+ const NGPhysicalBoxStrut* ComputeBordersAddress() const {
+ DCHECK(has_borders_);
+ return reinterpret_cast<const NGPhysicalBoxStrut*>(children_ +
+ Children().size());
+ }
+
+ const NGPhysicalBoxStrut* ComputePaddingAddress() const {
+ DCHECK(has_padding_);
+ const NGPhysicalBoxStrut* address =
+ reinterpret_cast<const NGPhysicalBoxStrut*>(children_ +
+ Children().size());
+ return has_borders_ ? address + 1 : address;
+ }
+
NGBaselineList baselines_;
- NGPhysicalBoxStrut borders_;
- NGPhysicalBoxStrut padding_;
NGLink children_[];
+ // borders and padding come from after |children_| if they are not zero.
};
template <>
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
index 868db0e..caa75ac 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -307,6 +307,8 @@
// (it's defined here to save memory, since that class has no bitfields).
unsigned children_inline_ : 1;
unsigned border_edge_ : 4; // NGBorderEdges::Physical
+ unsigned has_borders_ : 1;
+ unsigned has_padding_ : 1;
// The following are only used by NGPhysicalBoxFragment but are initialized
// for all types to allow methods using them to be inlined.