Commit a549ff56 authored by Hannes Payer's avatar Hannes Payer Committed by Commit Bot

[heap] Allocation buffer parking in NewSpace.

Change-Id: If01a247f2bae3c90708f9f8355325fa5b7113913
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2560196Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Hannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71402}
parent ff8258bc
...@@ -1100,6 +1100,7 @@ DEFINE_BOOL(memory_reducer_for_small_heaps, true, ...@@ -1100,6 +1100,7 @@ DEFINE_BOOL(memory_reducer_for_small_heaps, true,
DEFINE_INT(heap_growing_percent, 0, DEFINE_INT(heap_growing_percent, 0,
"specifies heap growing factor as (1 + heap_growing_percent/100)") "specifies heap growing factor as (1 + heap_growing_percent/100)")
DEFINE_INT(v8_os_page_size, 0, "override OS page size (in KBytes)") DEFINE_INT(v8_os_page_size, 0, "override OS page size (in KBytes)")
DEFINE_BOOL(allocation_buffer_parking, true, "allocation buffer parking")
DEFINE_BOOL(always_compact, false, "Perform compaction on every full GC") DEFINE_BOOL(always_compact, false, "Perform compaction on every full GC")
DEFINE_BOOL(never_compact, false, DEFINE_BOOL(never_compact, false,
"Never perform compaction on full GC - testing only") "Never perform compaction on full GC - testing only")
......
...@@ -863,6 +863,7 @@ void Heap::GarbageCollectionPrologueInSafepoint() { ...@@ -863,6 +863,7 @@ void Heap::GarbageCollectionPrologueInSafepoint() {
UpdateNewSpaceAllocationCounter(); UpdateNewSpaceAllocationCounter();
CheckNewSpaceExpansionCriteria(); CheckNewSpaceExpansionCriteria();
new_space_->ResetParkedAllocationBuffers();
} }
size_t Heap::SizeOfObjects() { size_t Heap::SizeOfObjects() {
......
...@@ -262,6 +262,13 @@ void SemiSpace::PrependPage(Page* page) { ...@@ -262,6 +262,13 @@ void SemiSpace::PrependPage(Page* page) {
} }
} }
void SemiSpace::MovePageToTheEnd(Page* page) {
DCHECK_EQ(page->owner(), this);
memory_chunk_list_.Remove(page);
memory_chunk_list_.PushBack(page);
current_page_ = page;
}
void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) {
// We won't be swapping semispaces without data in them. // We won't be swapping semispaces without data in them.
DCHECK(from->first_page()); DCHECK(from->first_page());
...@@ -415,6 +422,10 @@ void NewSpace::TearDown() { ...@@ -415,6 +422,10 @@ void NewSpace::TearDown() {
from_space_.TearDown(); from_space_.TearDown();
} }
void NewSpace::ResetParkedAllocationBuffers() {
parked_allocation_buffers_.clear();
}
void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); } void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); }
void NewSpace::Grow() { void NewSpace::Grow() {
...@@ -465,10 +476,10 @@ bool NewSpace::Rebalance() { ...@@ -465,10 +476,10 @@ bool NewSpace::Rebalance() {
from_space_.EnsureCurrentCapacity(); from_space_.EnsureCurrentCapacity();
} }
void NewSpace::UpdateLinearAllocationArea() { void NewSpace::UpdateLinearAllocationArea(Address known_top) {
AdvanceAllocationObservers(); AdvanceAllocationObservers();
Address new_top = to_space_.page_low(); Address new_top = known_top == 0 ? to_space_.page_low() : known_top;
BasicMemoryChunk::UpdateHighWaterMark(allocation_info_.top()); BasicMemoryChunk::UpdateHighWaterMark(allocation_info_.top());
allocation_info_.Reset(new_top, to_space_.page_high()); allocation_info_.Reset(new_top, to_space_.page_high());
// The order of the following two stores is important. // The order of the following two stores is important.
...@@ -509,15 +520,23 @@ bool NewSpace::AddFreshPage() { ...@@ -509,15 +520,23 @@ bool NewSpace::AddFreshPage() {
Address top = allocation_info_.top(); Address top = allocation_info_.top();
DCHECK(!OldSpace::IsAtPageStart(top)); DCHECK(!OldSpace::IsAtPageStart(top));
// Clear remainder of current page.
Address limit = Page::FromAllocationAreaAddress(top)->area_end();
int remaining_in_page = static_cast<int>(limit - top);
heap()->CreateFillerObjectAt(top, remaining_in_page, ClearRecordedSlots::kNo);
if (!to_space_.AdvancePage()) { if (!to_space_.AdvancePage()) {
// No more pages left to advance. // No more pages left to advance.
return false; return false;
} }
// Clear remainder of current page. // We park unused allocation buffer space of allocations happenting from the
Address limit = Page::FromAllocationAreaAddress(top)->area_end(); // mutator.
int remaining_in_page = static_cast<int>(limit - top); if (FLAG_allocation_buffer_parking && heap()->gc_state() == Heap::NOT_IN_GC &&
heap()->CreateFillerObjectAt(top, remaining_in_page, ClearRecordedSlots::kNo); remaining_in_page >= kAllocationBufferParkingThreshold) {
parked_allocation_buffers_.push_back(
ParkedAllocationBuffer(remaining_in_page, top));
}
UpdateLinearAllocationArea(); UpdateLinearAllocationArea();
return true; return true;
...@@ -528,6 +547,30 @@ bool NewSpace::AddFreshPageSynchronized() { ...@@ -528,6 +547,30 @@ bool NewSpace::AddFreshPageSynchronized() {
return AddFreshPage(); return AddFreshPage();
} }
bool NewSpace::AddParkedAllocationBuffer(int size_in_bytes,
AllocationAlignment alignment) {
int parked_size = 0;
Address start = 0;
for (auto it = parked_allocation_buffers_.begin();
it != parked_allocation_buffers_.end();) {
parked_size = it->first;
start = it->second;
int filler_size = Heap::GetFillToAlign(start, alignment);
if (size_in_bytes + filler_size <= parked_size) {
parked_allocation_buffers_.erase(it);
Page* page = Page::FromAddress(start);
// We move a page with a parked allocaiton to the end of the pages list
// to maintain the invariant that the last page is the used one.
to_space_.MovePageToTheEnd(page);
UpdateLinearAllocationArea(start);
return true;
} else {
it++;
}
}
return false;
}
bool NewSpace::EnsureAllocation(int size_in_bytes, bool NewSpace::EnsureAllocation(int size_in_bytes,
AllocationAlignment alignment) { AllocationAlignment alignment) {
AdvanceAllocationObservers(); AdvanceAllocationObservers();
...@@ -544,7 +587,10 @@ bool NewSpace::EnsureAllocation(int size_in_bytes, ...@@ -544,7 +587,10 @@ bool NewSpace::EnsureAllocation(int size_in_bytes,
// Not enough room in the page, try to allocate a new one. // Not enough room in the page, try to allocate a new one.
if (!AddFreshPage()) { if (!AddFreshPage()) {
return false; // When we cannot grow NewSpace anymore we query for parked allocations.
if (!FLAG_allocation_buffer_parking ||
!AddParkedAllocationBuffer(size_in_bytes, alignment))
return false;
} }
old_top = allocation_info_.top(); old_top = allocation_info_.top();
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#define V8_HEAP_NEW_SPACES_H_ #define V8_HEAP_NEW_SPACES_H_
#include <atomic> #include <atomic>
#include <map>
#include <memory> #include <memory>
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/platform/mutex.h" #include "src/base/platform/mutex.h"
#include "src/common/globals.h"
#include "src/heap/heap.h" #include "src/heap/heap.h"
#include "src/heap/spaces.h" #include "src/heap/spaces.h"
#include "src/logging/log.h" #include "src/logging/log.h"
...@@ -23,6 +25,9 @@ class MemoryChunk; ...@@ -23,6 +25,9 @@ class MemoryChunk;
enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 }; enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 };
using ParkedAllocationBuffer = std::pair<int, Address>;
using ParkedAllocationBuffersVector = std::vector<ParkedAllocationBuffer>;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// SemiSpace in young generation // SemiSpace in young generation
// //
...@@ -105,6 +110,7 @@ class SemiSpace : public Space { ...@@ -105,6 +110,7 @@ class SemiSpace : public Space {
void RemovePage(Page* page); void RemovePage(Page* page);
void PrependPage(Page* page); void PrependPage(Page* page);
void MovePageToTheEnd(Page* page);
Page* InitializePage(MemoryChunk* chunk); Page* InitializePage(MemoryChunk* chunk);
...@@ -248,6 +254,8 @@ class V8_EXPORT_PRIVATE NewSpace ...@@ -248,6 +254,8 @@ class V8_EXPORT_PRIVATE NewSpace
// is not deallocated here. // is not deallocated here.
void TearDown(); void TearDown();
void ResetParkedAllocationBuffers();
// Flip the pair of spaces. // Flip the pair of spaces.
void Flip(); void Flip();
...@@ -415,6 +423,9 @@ class V8_EXPORT_PRIVATE NewSpace ...@@ -415,6 +423,9 @@ class V8_EXPORT_PRIVATE NewSpace
bool AddFreshPage(); bool AddFreshPage();
bool AddFreshPageSynchronized(); bool AddFreshPageSynchronized();
bool AddParkedAllocationBuffer(int size_in_bytes,
AllocationAlignment alignment);
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
// Verify the active semispace. // Verify the active semispace.
virtual void Verify(Isolate* isolate); virtual void Verify(Isolate* isolate);
...@@ -463,8 +474,10 @@ class V8_EXPORT_PRIVATE NewSpace ...@@ -463,8 +474,10 @@ class V8_EXPORT_PRIVATE NewSpace
void MaybeFreeUnusedLab(LinearAllocationArea info); void MaybeFreeUnusedLab(LinearAllocationArea info);
private: private:
static const int kAllocationBufferParkingThreshold = 4 * KB;
// Update linear allocation area to match the current to-space page. // Update linear allocation area to match the current to-space page.
void UpdateLinearAllocationArea(); void UpdateLinearAllocationArea(Address known_top = 0);
base::Mutex mutex_; base::Mutex mutex_;
...@@ -478,6 +491,8 @@ class V8_EXPORT_PRIVATE NewSpace ...@@ -478,6 +491,8 @@ class V8_EXPORT_PRIVATE NewSpace
SemiSpace from_space_; SemiSpace from_space_;
VirtualMemory reservation_; VirtualMemory reservation_;
ParkedAllocationBuffersVector parked_allocation_buffers_;
// Internal allocation methods. // Internal allocation methods.
V8_WARN_UNUSED_RESULT V8_INLINE AllocationResult V8_WARN_UNUSED_RESULT V8_INLINE AllocationResult
AllocateFastAligned(int size_in_bytes, int* aligned_size_in_bytes, AllocateFastAligned(int size_in_bytes, int* aligned_size_in_bytes,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment