[weakrefs] Update js_weak_refs worklist after scavenges

The js_weak_refs worklist is currently not updated after scavenges,
unlike other weak reference worklist.

Bug: v8:8179, chromium:1073981
Change-Id: I48172606995253edb8a0c96f2b7e2dc34cd3d0d6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2163827
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67350}
This commit is contained in:
Shu-yu Guo 2020-04-23 16:27:01 -07:00 committed by Commit Bot
parent 213016d65a
commit f684ef021a
2 changed files with 115 additions and 0 deletions

View File

@ -658,6 +658,27 @@ void IncrementalMarking::UpdateWeakReferencesAfterScavenge() {
DCHECK(!Heap::InYoungGeneration(candidate));
});
#endif
if (FLAG_harmony_weak_refs) {
weak_objects_->js_weak_refs.Update(
[](JSWeakRef js_weak_ref_in, JSWeakRef* js_weak_ref_out) -> bool {
JSWeakRef forwarded = ForwardingAddress(js_weak_ref_in);
if (!forwarded.is_null()) {
*js_weak_ref_out = forwarded;
return true;
}
return false;
});
#ifdef DEBUG
// TODO(syg, marja): Support WeakCells in the young generation.
weak_objects_->weak_cells.Iterate([](WeakCell weak_cell) {
DCHECK(!Heap::InYoungGeneration(weak_cell));
});
#endif
}
}
void IncrementalMarking::UpdateMarkedBytesAfterScavenge(

View File

@ -6,6 +6,7 @@
#include "src/execution/microtask-queue.h"
#include "src/handles/handles-inl.h"
#include "src/heap/factory-inl.h"
#include "src/heap/heap-inl.h"
#include "src/objects/js-objects.h"
#include "src/objects/js-weak-refs-inl.h"
#include "test/cctest/cctest.h"
@ -874,5 +875,98 @@ TEST(TestRemoveUnregisterToken) {
}
}
TEST(JSWeakRefScavengedInWorklist) {
FLAG_harmony_weak_refs = true;
if (!FLAG_incremental_marking) {
return;
}
ManualGCScope manual_gc_scope;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
{
HandleScope outer_scope(isolate);
Handle<JSWeakRef> weak_ref;
// Make a WeakRef that points to a target, both of which become unreachable.
{
HandleScope inner_scope(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<JSWeakRef> inner_weak_ref = ConstructJSWeakRef(js_object, isolate);
CHECK(Heap::InYoungGeneration(*js_object));
CHECK(Heap::InYoungGeneration(*inner_weak_ref));
weak_ref = inner_scope.CloseAndEscape(inner_weak_ref);
}
// Do marking. This puts the WeakRef above into the js_weak_refs worklist
// since its target isn't marked.
CHECK(
heap->mark_compact_collector()->weak_objects()->js_weak_refs.IsEmpty());
heap::SimulateIncrementalMarking(heap, true);
CHECK(!heap->mark_compact_collector()
->weak_objects()
->js_weak_refs.IsEmpty());
}
// Now collect both weak_ref and its target. The worklist should be empty.
CcTest::CollectGarbage(NEW_SPACE);
CHECK(heap->mark_compact_collector()->weak_objects()->js_weak_refs.IsEmpty());
// The mark-compactor shouldn't see zapped WeakRefs in the worklist.
CcTest::CollectAllGarbage();
}
TEST(JSWeakRefTenuredInWorklist) {
FLAG_harmony_weak_refs = true;
if (!FLAG_incremental_marking) {
return;
}
ManualGCScope manual_gc_scope;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
HandleScope outer_scope(isolate);
Handle<JSWeakRef> weak_ref;
// Make a WeakRef that points to a target. The target becomes unreachable.
{
HandleScope inner_scope(isolate);
Handle<JSObject> js_object =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<JSWeakRef> inner_weak_ref = ConstructJSWeakRef(js_object, isolate);
CHECK(Heap::InYoungGeneration(*js_object));
CHECK(Heap::InYoungGeneration(*inner_weak_ref));
weak_ref = inner_scope.CloseAndEscape(inner_weak_ref);
}
JSWeakRef old_weak_ref_location = *weak_ref;
// Do marking. This puts the WeakRef above into the js_weak_refs worklist
// since its target isn't marked.
CHECK(heap->mark_compact_collector()->weak_objects()->js_weak_refs.IsEmpty());
heap::SimulateIncrementalMarking(heap, true);
CHECK(
!heap->mark_compact_collector()->weak_objects()->js_weak_refs.IsEmpty());
// Now collect weak_ref's target. We still have a Handle to weak_ref, so it is
// moved and remains on the worklist.
CcTest::CollectGarbage(NEW_SPACE);
JSWeakRef new_weak_ref_location = *weak_ref;
CHECK_NE(old_weak_ref_location, new_weak_ref_location);
CHECK(
!heap->mark_compact_collector()->weak_objects()->js_weak_refs.IsEmpty());
// The mark-compactor should see the moved WeakRef in the worklist.
CcTest::CollectAllGarbage();
CHECK(heap->mark_compact_collector()->weak_objects()->js_weak_refs.IsEmpty());
CHECK(weak_ref->target().IsUndefined(isolate));
}
} // namespace internal
} // namespace v8