[heap] Reuse promoted quarantined pages
Build a freelist while sweeping so that the page can be used for
evactuating objects in the next Scavenge cycle.
Bug: 379788114
Change-Id: I3a61d682dc3c544a63544902aa4af1675a0929a0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6087923
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#98095}
diff --git a/src/heap/scavenger.cc b/src/heap/scavenger.cc
index 060eb97..ec29775 100644
--- a/src/heap/scavenger.cc
+++ b/src/heap/scavenger.cc
@@ -572,28 +572,28 @@
base::RandomNumberGenerator* const rng_;
double stressing_threshold_;
};
-
+template <typename FreeSpaceHandler>
size_t SweepQuarantinedPage(
- Heap* heap, MemoryChunk* chunk,
+ FreeSpaceHandler& free_space_handler, MemoryChunk* chunk,
std::vector<std::pair<Address, size_t>>& pinned_objects_and_sizes) {
- Address start = chunk->Metadata()->area_start();
+ MemoryChunkMetadata* metadata = chunk->Metadata();
+ Address start = metadata->area_start();
std::sort(pinned_objects_and_sizes.begin(), pinned_objects_and_sizes.end());
size_t quarantined_objects_size = 0;
for (const auto& [object, size] : pinned_objects_and_sizes) {
DCHECK_LE(start, object);
if (start != object) {
- heap->CreateFillerObjectAt(start, static_cast<int>(object - start));
+ free_space_handler(start, object - start);
}
quarantined_objects_size += size;
start = object + size;
}
- Address end = chunk->Metadata()->area_end();
+ Address end = metadata->area_end();
if (start != end) {
- heap->CreateFillerObjectAt(start, static_cast<int>(end - start));
+ free_space_handler(start, end - start);
}
- DCHECK(static_cast<MutablePageMetadata*>(chunk->Metadata())
- ->marking_bitmap()
- ->IsClean());
+ DCHECK(
+ static_cast<MutablePageMetadata*>(metadata)->marking_bitmap()->IsClean());
DCHECK_LT(0, quarantined_objects_size);
return quarantined_objects_size;
}
@@ -618,23 +618,45 @@
}
DCHECK_EQ(0, new_space.QuarantinedPageCount());
// Sweep quarantined pages to make them iterable.
+ Heap* const heap = new_space.heap();
+ auto create_filler = [heap](Address address, size_t size) {
+ if (heap::ShouldZapGarbage()) {
+ heap::ZapBlock(address, size, heap::ZapValue());
+ }
+ heap->CreateFillerObjectAt(address, static_cast<int>(size));
+ };
+ auto create_filler_and_add_to_freelist = [heap, create_filler](
+ Address address, size_t size) {
+ create_filler(address, size);
+ PageMetadata* page = PageMetadata::FromAddress(address);
+ DCHECK_EQ(OLD_SPACE, page->owner()->identity());
+ DCHECK(page->SweepingDone());
+ OldSpace* const old_space = heap->old_space();
+ FreeList* const free_list = old_space->free_list();
+ const size_t wasted = free_list->Free(
+ WritableFreeSpace::ForNonExecutableMemory(address, size),
+ kLinkCategory);
+ old_space->DecreaseAllocatedBytes(size, page);
+ free_list->increase_wasted_bytes(wasted);
+ };
size_t quarantined_objects_size = 0;
for (auto it : pages_with_pinned_objects) {
MemoryChunk* chunk = it.first;
std::vector<std::pair<Address, size_t>>& pinned_objects_and_sizes =
it.second;
DCHECK(chunk->IsFromPage());
- const size_t quarantined_objects_size_on_page =
- SweepQuarantinedPage(new_space.heap(), chunk, pinned_objects_and_sizes);
if (new_space.ShouldPageBePromoted(chunk->address())) {
new_space.PromotePageToOldSpace(
static_cast<PageMetadata*>(chunk->Metadata()));
DCHECK(!chunk->InYoungGeneration());
+ SweepQuarantinedPage(create_filler_and_add_to_freelist, chunk,
+ pinned_objects_and_sizes);
} else {
- quarantined_objects_size += quarantined_objects_size_on_page;
new_space.MoveQuarantinedPage(chunk);
DCHECK(!chunk->IsFromPage());
DCHECK(chunk->IsToPage());
+ quarantined_objects_size +=
+ SweepQuarantinedPage(create_filler, chunk, pinned_objects_and_sizes);
}
}
new_space.SetQuarantinedSize(quarantined_objects_size);