Commit 4e08b0af authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Use Is{First,Last}ForNode in MayHaveMultipleFragments

|MayHaveMultipleFragmentItems| turned out to be hot, and
|NGFragmentItem| version is slower than |NGPaintFragment|
version.

This patch uses |Is{First,Last}ForNode| flags added for the
block fragmentation. Also changes |FinalizeAfterLayout| to
compute them for non-block fragmented cases.

Bug: 982194
Change-Id: Idbc374b65ff39d877d727848431e50a521fe2008
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2203082
Commit-Queue: Koji Ishii <kojii@chromium.org>
Commit-Queue: Yoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#769619}
parent 47fd094f
......@@ -12,14 +12,6 @@
namespace blink {
namespace {
inline bool ShouldSetFirstAndLastForNode() {
return RuntimeEnabledFeatures::LayoutNGFragmentTraversalEnabled();
}
} // namespace
NGFragmentItems::NGFragmentItems(NGFragmentItemsBuilder* builder)
: text_content_(std::move(builder->text_content_)),
first_line_text_content_(std::move(builder->first_line_text_content_)),
......@@ -47,14 +39,17 @@ bool NGFragmentItems::IsSubSpan(const Span& span) const {
void NGFragmentItems::FinalizeAfterLayout(
const Vector<scoped_refptr<const NGLayoutResult>, 1>& results) {
HashMap<const LayoutObject*, const NGFragmentItem*> first_and_last;
struct LastItem {
const NGFragmentItem* item;
wtf_size_t item_index;
};
HashMap<const LayoutObject*, LastItem> last_items;
for (const auto& result : results) {
const auto& fragment =
To<NGPhysicalBoxFragment>(result->PhysicalFragment());
const NGFragmentItems* current = fragment.Items();
if (UNLIKELY(!current))
continue;
HashMap<const LayoutObject*, wtf_size_t> last_fragment_map;
const Span items = current->Items();
wtf_size_t index = 0;
for (const scoped_refptr<const NGFragmentItem>& item : items) {
......@@ -72,38 +67,43 @@ void NGFragmentItems::FinalizeAfterLayout(
DCHECK(layout_object->IsInLayoutNGInlineFormattingContext()) << *item;
item->SetDeltaToNextForSameLayoutObject(0);
if (ShouldSetFirstAndLastForNode()) {
// TODO(layout-dev): Make this work for multiple box fragments (block
// fragmentation).
if (!fragment.IsFirstForNode()) {
bool is_first_for_node =
first_and_last.Set(layout_object, item.get()).is_new_entry;
last_items.Set(layout_object, LastItem{item.get(), index})
.is_new_entry;
item->SetIsFirstForNode(is_first_for_node);
item->SetIsLastForNode(false);
continue;
}
// TODO(layout-dev): Make this work for multiple box fragments (block
// fragmentation).
if (!fragment.IsFirstForNode())
continue;
const auto last_item_result =
last_items.insert(layout_object, LastItem{item.get(), index});
auto insert_result = last_fragment_map.insert(layout_object, index);
if (insert_result.is_new_entry) {
if (last_item_result.is_new_entry) {
item->SetIsFirstForNode(true);
item->SetIsLastForNode(false);
DCHECK_EQ(layout_object->FirstInlineFragmentItemIndex(), 0u);
layout_object->SetFirstInlineFragmentItemIndex(index);
continue;
}
const wtf_size_t last_index = insert_result.stored_value->value;
insert_result.stored_value->value = index;
item->SetIsFirstForNode(false);
item->SetIsLastForNode(false);
LastItem* last = &last_item_result.stored_value->value;
const wtf_size_t last_index = last->item_index;
DCHECK_GT(last_index, 0u) << *item;
DCHECK_LT(last_index, items.size());
DCHECK_LT(last_index, index);
DCHECK_EQ(items[last_index - 1]->DeltaToNextForSameLayoutObject(), 0u);
items[last_index - 1]->SetDeltaToNextForSameLayoutObject(index -
last_index);
DCHECK_EQ(last->item->DeltaToNextForSameLayoutObject(), 0u);
last->item->SetDeltaToNextForSameLayoutObject(index - last_index);
last->item = item.get();
last->item_index = index;
}
}
if (!ShouldSetFirstAndLastForNode())
return;
for (const auto& iter : first_and_last)
iter.value->SetIsLastForNode(true);
for (const auto& iter : last_items)
iter.value.item->SetIsLastForNode(true);
}
void NGFragmentItems::ClearAssociatedFragments(LayoutObject* container) {
......
......@@ -33,23 +33,16 @@ inline bool HasMultiplePaintFragments(const LayoutObject& layout_object) {
return HasMultipleItems(NGPaintFragment::InlineFragmentsFor(&layout_object));
}
inline bool MayHaveMultipleFragmentItems(const LayoutObject& layout_object) {
// TODO(crbug.com/1061423): NGInlineCursor is currently unable to deal with
// objects split into multiple fragmentainers (e.g. columns). Just return true
// if it's possible that this object participates in a fragmentation
// context. This will give false positives, but that should be harmless, given
// the way the return value is used by the caller.
if (layout_object.IsInsideFlowThread())
return true;
NGInlineCursor cursor;
cursor.MoveTo(layout_object);
DCHECK(cursor);
if (cursor) {
cursor.MoveToNextForSameLayoutObject();
return cursor;
}
return false;
inline bool MayHaveMultipleFragmentItems(const NGFragmentItem& item,
const LayoutObject& layout_object) {
return !item.IsFirstForNode() || !item.IsLastForNode() ||
// TODO(crbug.com/1061423): NGInlineCursor is currently unable to deal
// with objects split into multiple fragmentainers (e.g. columns). Just
// return true if it's possible that this object participates in a
// fragmentation context. This will give false positives, but that
// should be harmless, given the way the return value is used by the
// caller.
UNLIKELY(layout_object.IsInsideFlowThread());
}
} // namespace
......@@ -121,9 +114,11 @@ void NGInlineBoxFragmentPainterBase::PaintBackgroundBorderShadow(
DCHECK(inline_box_fragment_.GetLayoutObject());
const LayoutObject& layout_object = *inline_box_fragment_.GetLayoutObject();
DCHECK(inline_box_paint_fragment_ || inline_box_item_);
bool object_may_have_multiple_boxes =
inline_box_paint_fragment_ ? HasMultiplePaintFragments(layout_object)
: MayHaveMultipleFragmentItems(layout_object);
inline_box_paint_fragment_
? HasMultiplePaintFragments(layout_object)
: MayHaveMultipleFragmentItems(*inline_box_item_, layout_object);
// TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry.
BackgroundImageGeometry geometry(*static_cast<const LayoutBoxModelObject*>(
......
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