Commit 98a6949d authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Eliminate destroyed or moved |LayoutObject| from |PostLayoutChildren|

This patch changes the iterator of |PostLayoutChildren| to
eliminate fragments for destroyed or moved |LayoutObject|.

The root cause is probably pre-paint with dirty tree, and
this patch does not address that, but makes fragment
traversal safer.

This patch is speculative.

Bug: 1099863
Change-Id: Ia78d55cc43a50f54f4b547ae8febc025770ac004
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2275944Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#784303}
parent 13647bfd
...@@ -2656,7 +2656,8 @@ const NGLayoutResult* LayoutBox::GetCachedLayoutResult() const { ...@@ -2656,7 +2656,8 @@ const NGLayoutResult* LayoutBox::GetCachedLayoutResult() const {
const NGLayoutResult* result = layout_results_[0].get(); const NGLayoutResult* result = layout_results_[0].get();
if (result->IsSingleUse()) if (result->IsSingleUse())
return nullptr; return nullptr;
DCHECK(result->PhysicalFragment().IsAlive() || BeingDestroyed()); DCHECK(!result->PhysicalFragment().IsLayoutObjectDestroyedOrMoved() ||
BeingDestroyed());
DCHECK_EQ(layout_results_.size(), 1u); DCHECK_EQ(layout_results_.size(), 1u);
return result; return result;
} }
......
...@@ -25,9 +25,10 @@ enum class NGOutlineType; ...@@ -25,9 +25,10 @@ enum class NGOutlineType;
class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment { class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
public: public:
// Same as |base::span<const NGLink>|, except that each |NGLink| has the // Same as |base::span<const NGLink>|, except that:
// latest generation of post-layout. See // * Each |NGLink| has the latest generation of post-layout. See
// |NGPhysicalFragment::UpdatedFragment()| for more details. // |NGPhysicalFragment::UpdatedFragment()| for more details.
// * The iterator skips fragments for destroyed or moved |LayoutObject|.
class PostLayoutChildLinkList { class PostLayoutChildLinkList {
public: public:
PostLayoutChildLinkList(wtf_size_t count, const NGLink* buffer) PostLayoutChildLinkList(wtf_size_t count, const NGLink* buffer)
...@@ -44,13 +45,17 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment { ...@@ -44,13 +45,17 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
using pointer = value_type*; using pointer = value_type*;
using reference = value_type&; using reference = value_type&;
ConstIterator(const NGLink* current) : current_(current) {} ConstIterator(const NGLink* current, wtf_size_t size)
: current_(current), end_(current + size) {
SkipDestroyedOrMoved();
}
const NGLink& operator*() const { return *PostLayoutOrCurrent(); } const NGLink& operator*() const { return *PostLayoutOrCurrent(); }
const NGLink* operator->() const { return PostLayoutOrCurrent(); } const NGLink* operator->() const { return PostLayoutOrCurrent(); }
ConstIterator& operator++() { ConstIterator& operator++() {
++current_; ++current_;
SkipDestroyedOrMoved();
return *this; return *this;
} }
bool operator==(const ConstIterator& other) const { bool operator==(const ConstIterator& other) const {
...@@ -69,13 +74,20 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment { ...@@ -69,13 +74,20 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
return &post_layout_; return &post_layout_;
} }
void SkipDestroyedOrMoved() {
while (current_ != end_ &&
current_->fragment->IsLayoutObjectDestroyedOrMoved())
++current_;
}
const NGLink* current_; const NGLink* current_;
const NGLink* end_;
mutable NGLink post_layout_; mutable NGLink post_layout_;
}; };
using const_iterator = ConstIterator; using const_iterator = ConstIterator;
const_iterator begin() const { return const_iterator(buffer_); } const_iterator begin() const { return const_iterator(buffer_, count_); }
const_iterator end() const { return const_iterator(buffer_ + count_); } const_iterator end() const { return const_iterator(buffer_ + count_, 0); }
const NGLink operator[](wtf_size_t idx) const { const NGLink operator[](wtf_size_t idx) const {
CHECK_LT(idx, count_); CHECK_LT(idx, count_);
......
...@@ -298,7 +298,7 @@ class CORE_EXPORT NGPhysicalFragment ...@@ -298,7 +298,7 @@ class CORE_EXPORT NGPhysicalFragment
// |NGPhysicalFragment| may live longer than the corresponding |LayoutObject|. // |NGPhysicalFragment| may live longer than the corresponding |LayoutObject|.
// Though |NGPhysicalFragment| is immutable, |layout_object_| is cleared to // Though |NGPhysicalFragment| is immutable, |layout_object_| is cleared to
// |nullptr| when it was destroyed to avoid reading destroyed objects. // |nullptr| when it was destroyed to avoid reading destroyed objects.
bool IsAlive() const { return layout_object_; } bool IsLayoutObjectDestroyedOrMoved() const { return !layout_object_; }
void LayoutObjectWillBeDestroyed() const { void LayoutObjectWillBeDestroyed() const {
const_cast<NGPhysicalFragment*>(this)->layout_object_ = nullptr; const_cast<NGPhysicalFragment*>(this)->layout_object_ = nullptr;
} }
......
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