Commit 06ff523b authored by Michael Lippautz's avatar Michael Lippautz Committed by V8 LUCI CQ

cppgc-js: Fix pending edges crasher

Back references to C++ objects may point to objects that never have
their graph nodes materializes through other C++ edges. We can just
create a graph node in this case, and avoid delaying the merging
completetly.

Bug: chromium:1244522
Change-Id: I0e9cb7a89ee90bfba217bc8475ac40bd7fe92a0b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3129426Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76583}
parent b7364a49
...@@ -51,7 +51,7 @@ class EmbedderNode : public v8::EmbedderGraph::Node { ...@@ -51,7 +51,7 @@ class EmbedderNode : public v8::EmbedderGraph::Node {
// TODO(chromium:1218404): Add a DCHECK() to avoid overriding an already // TODO(chromium:1218404): Add a DCHECK() to avoid overriding an already
// set `wrapper_node_`. This can currently happen with global proxies that // set `wrapper_node_`. This can currently happen with global proxies that
// are rewired (and still kept alive) after reloading a page, see // are rewired (and still kept alive) after reloading a page, see
// `CreateMergedNode`. We accept overriding the wrapper node in such cases, // `AddEdge`. We accept overriding the wrapper node in such cases,
// leading to a random merged node and separated nodes for all other // leading to a random merged node and separated nodes for all other
// proxies. // proxies.
wrapper_node_ = wrapper_node; wrapper_node_ = wrapper_node;
...@@ -433,12 +433,6 @@ class CppGraphBuilderImpl final { ...@@ -433,12 +433,6 @@ class CppGraphBuilderImpl final {
} }
if (!current.get_node()) { if (!current.get_node()) {
current.set_node(AddNode(header)); current.set_node(AddNode(header));
const auto& it = pending_back_states_.find(&current);
if (it != pending_back_states_.end()) {
CreateMergedNode(current, it->second);
pending_back_states_.erase(it);
}
} }
if (!edge_name.empty()) { if (!edge_name.empty()) {
...@@ -468,16 +462,28 @@ class CppGraphBuilderImpl final { ...@@ -468,16 +462,28 @@ class CppGraphBuilderImpl final {
reinterpret_cast<v8::internal::Isolate*>(cpp_heap_.isolate()), reinterpret_cast<v8::internal::Isolate*>(cpp_heap_.isolate()),
v8_value); v8_value);
if (back_reference_object) { if (back_reference_object) {
auto& back_state = states_.GetExistingState( auto& back_header = HeapObjectHeader::FromObject(back_reference_object);
HeapObjectHeader::FromObject(back_reference_object)); auto& back_state = states_.GetExistingState(back_header);
DCHECK_EQ(pending_back_states_.end(),
pending_back_states_.find(&back_state)); // Generally the back reference will point to `parent.header()`. In the
const MergedNodeItem back_ref_item{v8_node, v8_value, // case of global proxy set up the backreference will point to a
ref.WrapperClassId()}; // different object, which may not have a node at t his point. Merge the
// nodes nevertheless as Window objects need to be able to query their
// detachedness state.
//
// TODO(chromium:1218404): See bug description on how to fix this
// inconsistency and only merge states when the backref points back
// to the same object.
if (!back_state.get_node()) { if (!back_state.get_node()) {
pending_back_states_.emplace(&back_state, back_ref_item); back_state.set_node(AddNode(back_header));
} else { }
CreateMergedNode(back_state, back_ref_item); back_state.get_node()->SetWrapperNode(v8_node);
auto* profiler =
reinterpret_cast<Isolate*>(cpp_heap_.isolate())->heap_profiler();
if (profiler->HasGetDetachednessCallback()) {
back_state.get_node()->SetDetachedness(
profiler->GetDetachedness(v8_value, ref.WrapperClassId()));
} }
} }
} }
...@@ -512,30 +518,10 @@ class CppGraphBuilderImpl final { ...@@ -512,30 +518,10 @@ class CppGraphBuilderImpl final {
uint16_t wrapper_class_id_; uint16_t wrapper_class_id_;
}; };
void CreateMergedNode(State& back_state, const MergedNodeItem& item) {
// Generally the back reference will point to `parent.header()`. In the
// case of global proxy set up the backreference will point to a
// different object. Merge the nodes nevertheless as Window objects need
// to be able to query their detachedness state.
//
// TODO(chromium:1218404): See bug description on how to fix this
// inconsistency and only merge states when the backref points back
// to the same object.
back_state.get_node()->SetWrapperNode(item.node_);
auto* profiler =
reinterpret_cast<Isolate*>(cpp_heap_.isolate())->heap_profiler();
if (profiler->HasGetDetachednessCallback()) {
back_state.get_node()->SetDetachedness(
profiler->GetDetachedness(item.value_, item.wrapper_class_id_));
}
}
CppHeap& cpp_heap_; CppHeap& cpp_heap_;
v8::EmbedderGraph& graph_; v8::EmbedderGraph& graph_;
StateStorage states_; StateStorage states_;
std::vector<std::unique_ptr<WorkstackItemBase>> workstack_; std::vector<std::unique_ptr<WorkstackItemBase>> workstack_;
std::unordered_map<State*, const MergedNodeItem> pending_back_states_;
}; };
// Iterating live objects to mark them as visible if needed. // Iterating live objects to mark them as visible if needed.
...@@ -848,7 +834,6 @@ void CppGraphBuilderImpl::Run() { ...@@ -848,7 +834,6 @@ void CppGraphBuilderImpl::Run() {
cppgc::internal::PersistentRegionLock guard; cppgc::internal::PersistentRegionLock guard;
cpp_heap_.GetStrongCrossThreadPersistentRegion().Trace(&object_visitor); cpp_heap_.GetStrongCrossThreadPersistentRegion().Trace(&object_visitor);
} }
CHECK(pending_back_states_.empty());
} }
// static // static
......
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