[heap] Make ExpandBackground more resilient against OOM

It could happen that a background thread expands the heap by one page,
but by the time the thread tries to allocate on it the space is already
used by other background threads. If this happens three times in a row,
V8 would crash with an OOM error. This CL prevents such situations by
always allocating the object immediately at area_start().

Bug: v8:10315
Change-Id: I6390c84e742bf4105e70e930c21557ff1f4d952d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2743881
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73305}
This commit is contained in:
Dominik Inführ 2021-03-09 17:30:30 +01:00 committed by Commit Bot
parent a192820e4f
commit e3072158f0
2 changed files with 20 additions and 12 deletions

View File

@ -320,14 +320,17 @@ Page* PagedSpace::Expand() {
return page;
}
Page* PagedSpace::ExpandBackground(LocalHeap* local_heap) {
base::Optional<std::pair<Address, size_t>> PagedSpace::ExpandBackground(
LocalHeap* local_heap, size_t size_in_bytes) {
Page* page = AllocatePage();
if (page == nullptr) return nullptr;
if (page == nullptr) return {};
base::MutexGuard lock(&space_mutex_);
AddPage(page);
Free(page->area_start(), page->area_size(),
Address object_start = page->area_start();
CHECK_LE(size_in_bytes, page->area_size());
Free(page->area_start() + size_in_bytes, page->area_size() - size_in_bytes,
SpaceAccountingMode::kSpaceAccounted);
return page;
return std::make_pair(object_start, size_in_bytes);
}
int PagedSpace::CountTotalPages() {
@ -589,13 +592,12 @@ base::Optional<std::pair<Address, size_t>> PagedSpace::RawRefillLabBackground(
}
if (heap()->ShouldExpandOldGenerationOnSlowAllocation(local_heap) &&
heap()->CanExpandOldGenerationBackground(AreaSize()) &&
ExpandBackground(local_heap)) {
DCHECK((CountTotalPages() > 1) ||
(min_size_in_bytes <= free_list_->Available()));
auto result = TryAllocationFromFreeListBackground(
local_heap, min_size_in_bytes, max_size_in_bytes, alignment, origin);
if (result) return result;
heap()->CanExpandOldGenerationBackground(AreaSize())) {
auto result = ExpandBackground(local_heap, max_size_in_bytes);
if (result) {
DCHECK_EQ(Heap::GetFillToAlign(result->first, alignment), 0);
return result;
}
}
if (collector->sweeping_in_progress()) {

View File

@ -354,7 +354,13 @@ class V8_EXPORT_PRIVATE PagedSpace
// it cannot allocate requested number of pages from OS, or if the hard heap
// size limit has been hit.
virtual Page* Expand();
Page* ExpandBackground(LocalHeap* local_heap);
// Expands the space by a single page from a background thread and allocates
// a memory area of the given size in it. If successful the method returns
// the address and size of the area.
base::Optional<std::pair<Address, size_t>> ExpandBackground(
LocalHeap* local_heap, size_t size_in_bytes);
Page* AllocatePage();
// Sets up a linear allocation area that fits the given number of bytes.