[objects] Add WeakCell::relaxed_target method

Loads target but with relaxed load. Concurrent marking needs to load
field with relaxed load, since the main thread could change this field when unregistering.

Change-Id: I809b1d4db1dd58c92bdb998601c2f709073104af
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2192661
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67707}
This commit is contained in:
Dominik Inführ 2020-05-11 12:14:26 +02:00 committed by Commit Bot
parent 0056effb20
commit ace32e55ea
3 changed files with 24 additions and 20 deletions

View File

@ -323,26 +323,23 @@ int MarkingVisitorBase<ConcreteVisitor, MarkingState>::VisitWeakCell(
int size = WeakCell::BodyDescriptor::SizeOf(map, weak_cell);
this->VisitMapPointer(weak_cell);
WeakCell::BodyDescriptor::IterateBody(map, weak_cell, size, this);
if (weak_cell.target().IsHeapObject()) {
HeapObject target = HeapObject::cast(weak_cell.target());
HeapObject unregister_token =
HeapObject::cast(weak_cell.unregister_token());
concrete_visitor()->SynchronizePageAccess(target);
concrete_visitor()->SynchronizePageAccess(unregister_token);
if (concrete_visitor()->marking_state()->IsBlackOrGrey(target) &&
concrete_visitor()->marking_state()->IsBlackOrGrey(unregister_token)) {
// Record the slots inside the WeakCell, since the IterateBody above
// didn't visit it.
ObjectSlot slot = weak_cell.RawField(WeakCell::kTargetOffset);
concrete_visitor()->RecordSlot(weak_cell, slot, target);
slot = weak_cell.RawField(WeakCell::kUnregisterTokenOffset);
concrete_visitor()->RecordSlot(weak_cell, slot, unregister_token);
} else {
// WeakCell points to a potentially dead object or a dead unregister
// token. We have to process them when we know the liveness of the whole
// transitive closure.
weak_objects_->weak_cells.Push(task_id_, weak_cell);
}
HeapObject target = weak_cell.relaxed_target();
HeapObject unregister_token = HeapObject::cast(weak_cell.unregister_token());
concrete_visitor()->SynchronizePageAccess(target);
concrete_visitor()->SynchronizePageAccess(unregister_token);
if (concrete_visitor()->marking_state()->IsBlackOrGrey(target) &&
concrete_visitor()->marking_state()->IsBlackOrGrey(unregister_token)) {
// Record the slots inside the WeakCell, since the IterateBody above
// didn't visit it.
ObjectSlot slot = weak_cell.RawField(WeakCell::kTargetOffset);
concrete_visitor()->RecordSlot(weak_cell, slot, target);
slot = weak_cell.RawField(WeakCell::kUnregisterTokenOffset);
concrete_visitor()->RecordSlot(weak_cell, slot, unregister_token);
} else {
// WeakCell points to a potentially dead object or a dead unregister
// token. We have to process them when we know the liveness of the whole
// transitive closure.
weak_objects_->weak_cells.Push(task_id_, weak_cell);
}
return size;
}

View File

@ -177,6 +177,10 @@ bool JSFinalizationRegistry::NeedsCleanup() const {
return cleared_cells().IsWeakCell();
}
HeapObject WeakCell::relaxed_target() const {
return TaggedField<HeapObject>::Relaxed_Load(*this, kTargetOffset);
}
template <typename GCNotifyUpdatedSlotCallback>
void WeakCell::Nullify(Isolate* isolate,
GCNotifyUpdatedSlotCallback gc_notify_updated_slot) {

View File

@ -89,6 +89,9 @@ class WeakCell : public TorqueGeneratedWeakCell<WeakCell, HeapObject> {
class BodyDescriptor;
// Provide relaxed load access to target field.
inline HeapObject relaxed_target() const;
// Nullify is called during GC and it modifies the pointers in WeakCell and
// JSFinalizationRegistry. Thus we need to tell the GC about the modified
// slots via the gc_notify_updated_slot function. The normal write barrier is