[heap] Only main thread handles may reference left-trimmed objects

Left-trimming only works when there is a single reference to the
backing store from the JS object. Main thread handles are an exception
to this rule because it is not feasible to ensure that no such
leftover handles may store such stale pointers.

FixStaleLeftTrimmedHandlesVisitor clears such references
in main thread handles, such that the GC never tries to visit them. This
CL renames this class to ClearStaleLeftTrimmedHandlesVisitor to
emphasize that such slots are cleared rather than "fixed up" to point
to the new object start.

Previously ClearStaleLeftTrimmedHandlesVisitor was used for local
and persistent handles as well. Starting with this CL, stale references
to left-trimmed objects are only allowed in main thread handles.
https://crrev.com/c/2928502 enabled us to be more restrictive here.

Change-Id: If4db0630f1df2d6c3fe5f242bf866c57a8ae2969
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2944807
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74989}
This commit is contained in:
Dominik Inführ 2021-06-07 16:02:16 +02:00 committed by V8 LUCI CQ
parent f9857fdf74
commit c2297cae36

View File

@ -4559,9 +4559,9 @@ void Heap::IterateSmiRoots(RootVisitor* v) {
// sure all handles still needed are updated. Filter out a stale pointer // sure all handles still needed are updated. Filter out a stale pointer
// and clear the slot to allow post processing of handles (needed because // and clear the slot to allow post processing of handles (needed because
// the sweeper might actually free the underlying page). // the sweeper might actually free the underlying page).
class FixStaleLeftTrimmedHandlesVisitor : public RootVisitor { class ClearStaleLeftTrimmedHandlesVisitor : public RootVisitor {
public: public:
explicit FixStaleLeftTrimmedHandlesVisitor(Heap* heap) : heap_(heap) { explicit ClearStaleLeftTrimmedHandlesVisitor(Heap* heap) : heap_(heap) {
USE(heap_); USE(heap_);
} }
@ -4676,19 +4676,22 @@ void Heap::IterateRoots(RootVisitor* v, base::EnumSet<SkipRoot> options) {
v->Synchronize(VisitorSynchronization::kStackRoots); v->Synchronize(VisitorSynchronization::kStackRoots);
} }
// Iterate over local handles in handle scopes.
FixStaleLeftTrimmedHandlesVisitor left_trim_visitor(this);
#ifndef V8_ENABLE_CONSERVATIVE_STACK_SCANNING #ifndef V8_ENABLE_CONSERVATIVE_STACK_SCANNING
// Iterate over main thread handles in handle scopes.
if (!options.contains(SkipRoot::kMainThreadHandles)) { if (!options.contains(SkipRoot::kMainThreadHandles)) {
// Clear main thread handles with stale references to left-trimmed
// objects. The GC would crash on such stale references.
ClearStaleLeftTrimmedHandlesVisitor left_trim_visitor(this);
isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor); isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor);
isolate_->handle_scope_implementer()->Iterate(v); isolate_->handle_scope_implementer()->Iterate(v);
} }
#endif #endif
safepoint_->Iterate(&left_trim_visitor); // Iterate local handles for all local heaps.
safepoint_->Iterate(v); safepoint_->Iterate(v);
isolate_->persistent_handles_list()->Iterate(&left_trim_visitor, isolate_); // Iterates all persistent handles.
isolate_->persistent_handles_list()->Iterate(v, isolate_); isolate_->persistent_handles_list()->Iterate(v, isolate_);
v->Synchronize(VisitorSynchronization::kHandleScope); v->Synchronize(VisitorSynchronization::kHandleScope);