| Index: src/heap/spaces.cc
|
| diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
|
| index 070b72c7bd9e8a035ade3f8c86d3eec3b2482703..d264cd07f8f1fc732dee6dfca26148137e8589d3 100644
|
| --- a/src/heap/spaces.cc
|
| +++ b/src/heap/spaces.cc
|
| @@ -1295,6 +1295,15 @@ void PagedSpace::RefillFreeList() {
|
| p->Unlink();
|
| p->set_owner(this);
|
| p->InsertAfter(anchor_.prev_page());
|
| + } else {
|
| + CHECK_EQ(this, p->owner());
|
| + // Regular refill on main thread. Pages are already linked into the
|
| + // space but might require relinking.
|
| + if (p->available_in_free_list() < kPageReuseThreshold) {
|
| + // Relink categories with only little memory left previous to anchor.
|
| + p->Unlink();
|
| + p->InsertAfter(anchor()->prev_page());
|
| + }
|
| }
|
| added += RelinkFreeListCategories(p);
|
| added += p->wasted_memory();
|
| @@ -1331,7 +1340,12 @@ void PagedSpace::MergeCompactionSpace(CompactionSpace* other) {
|
|
|
| p->Unlink();
|
| p->set_owner(this);
|
| - p->InsertAfter(anchor_.prev_page());
|
| + if (p->available_in_free_list() < kPageReuseThreshold) {
|
| + // Relink categories with only little memory left previous to anchor.
|
| + p->InsertAfter(anchor()->prev_page());
|
| + } else {
|
| + p->InsertAfter(anchor());
|
| + }
|
| RelinkFreeListCategories(p);
|
| DCHECK_EQ(p->AvailableInFreeList(), p->available_in_free_list());
|
| }
|
| @@ -1356,6 +1370,31 @@ bool PagedSpace::ContainsSlow(Address addr) {
|
| return false;
|
| }
|
|
|
| +Page* PagedSpace::RemovePageSafe() {
|
| + base::LockGuard<base::Mutex> guard(mutex());
|
| + Page* page = anchor()->next_page();
|
| +
|
| + while (!page->CanUseForAllocation()) page = page->next_page();
|
| + if (page == anchor() || page->available_in_free_list() < kPageReuseThreshold)
|
| + return nullptr;
|
| +
|
| + AccountUncommitted(page->size());
|
| + accounting_stats_.DeallocateBytes(page->LiveBytesFromFreeList());
|
| + accounting_stats_.DecreaseCapacity(page->area_size());
|
| + page->Unlink();
|
| + UnlinkFreeListCategories(page);
|
| + return page;
|
| +}
|
| +
|
| +void PagedSpace::AddPage(Page* page) {
|
| + AccountCommitted(page->size());
|
| + accounting_stats_.IncreaseCapacity(page->area_size());
|
| + accounting_stats_.AllocateBytes(page->LiveBytesFromFreeList());
|
| + page->set_owner(this);
|
| + RelinkFreeListCategories(page);
|
| + page->InsertAfter(anchor()->prev_page());
|
| +}
|
| +
|
| void PagedSpace::ShrinkImmortalImmovablePages() {
|
| DCHECK(!heap()->deserialization_complete());
|
| MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
|
| @@ -1371,6 +1410,8 @@ void PagedSpace::ShrinkImmortalImmovablePages() {
|
| }
|
|
|
| bool PagedSpace::Expand() {
|
| + base::LockGuard<base::Mutex> guard(mutex());
|
| +
|
| const int size = AreaSize();
|
|
|
| if (!heap()->CanExpandOldGeneration(size)) return false;
|
| @@ -2918,6 +2959,17 @@ HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
|
| object = free_list_.Allocate(static_cast<size_t>(size_in_bytes));
|
| if (object != nullptr) return object;
|
| }
|
| + } else if (is_local()) {
|
| + // Sweeping not in progress and we are on a {CompactionSpace}. This can
|
| + // only happen when we are evacuating for the young generation.
|
| + PagedSpace* main_space = heap()->paged_space(identity());
|
| + Page* page = main_space->RemovePageSafe();
|
| + if (page != nullptr) {
|
| + AddPage(page);
|
| + HeapObject* object =
|
| + free_list_.Allocate(static_cast<size_t>(size_in_bytes));
|
| + if (object != nullptr) return object;
|
| + }
|
| }
|
|
|
| if (heap()->ShouldExpandOldGenerationOnSlowAllocation() && Expand()) {
|
|
|