diff --git a/src/heap/heap.cc b/src/heap/heap.cc index a3ad62b509..0574eebb12 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -4317,6 +4317,7 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { FixStaleLeftTrimmedHandlesVisitor left_trim_visitor(this); isolate_->handle_scope_implementer()->Iterate(&left_trim_visitor); isolate_->handle_scope_implementer()->Iterate(v); + isolate_->IterateDeferredHandles(&left_trim_visitor); isolate_->IterateDeferredHandles(v); v->Synchronize(VisitorSynchronization::kHandleScope); diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc index efc63f0c42..bea34ae1ef 100644 --- a/test/cctest/heap/test-heap.cc +++ b/test/cctest/heap/test-heap.cc @@ -3666,6 +3666,55 @@ TEST(DeferredHandles) { deferred.Detach(); } +static void TestFillersFromDeferredHandles(bool promote) { + // We assume that the fillers can only arise when left-trimming arrays. + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + v8::HandleScope scope(reinterpret_cast(isolate)); + + const size_t n = 10; + Handle array = isolate->factory()->NewFixedArray(n); + + if (promote) { + // Age the array so it's ready for promotion on next GC. + CcTest::CollectGarbage(NEW_SPACE); + } + CHECK(Heap::InYoungGeneration(*array)); + + DeferredHandleScope deferred_scope(isolate); + + // Trim the array three times to different sizes so all kinds of fillers are + // created and tracked by the deferred handles. + Handle filler_1 = Handle(*array, isolate); + Handle filler_2 = + Handle(heap->LeftTrimFixedArray(*filler_1, 1), isolate); + Handle filler_3 = + Handle(heap->LeftTrimFixedArray(*filler_2, 2), isolate); + Handle tail = + Handle(heap->LeftTrimFixedArray(*filler_3, 3), isolate); + + std::unique_ptr deferred_handles(deferred_scope.Detach()); + + // GC should retain the trimmed array but drop all of the three fillers. + CcTest::CollectGarbage(NEW_SPACE); + if (promote) { + CHECK(heap->InOldSpace(*tail)); + } else { + CHECK(Heap::InYoungGeneration(*tail)); + } + CHECK_EQ(n - 6, (*tail).length()); + CHECK(!filler_1->IsHeapObject()); + CHECK(!filler_2->IsHeapObject()); + CHECK(!filler_3->IsHeapObject()); +} + +TEST(DoNotEvacuateFillersFromDeferredHandles) { + TestFillersFromDeferredHandles(false /*promote*/); +} + +TEST(DoNotPromoteFillersFromDeferredHandles) { + TestFillersFromDeferredHandles(true /*promote*/); +} TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) { if (!FLAG_incremental_marking) return;