Commit 3f921372 authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Non-contiguous young generation

This change removes the large contiguous backing store from the young generation
and replaces it regular pages.

We keep a pool of pages that are committed/uncommitted to avoid creating virtual
memory maps during growing and shrinking.

BUG=chromium:581412
LOG=N

Review URL: https://codereview.chromium.org/1853783002

Cr-Commit-Position: refs/heads/master@{#35261}
parent cf951dfb
...@@ -291,6 +291,10 @@ class VirtualMemory { ...@@ -291,6 +291,10 @@ class VirtualMemory {
// by address(). // by address().
VirtualMemory(size_t size, size_t alignment); VirtualMemory(size_t size, size_t alignment);
// Construct a virtual memory by assigning it some already mapped address
// and size.
VirtualMemory(void* address, size_t size) : address_(address), size_(size) {}
// Releases the reserved memory, if any, controlled by this VirtualMemory // Releases the reserved memory, if any, controlled by this VirtualMemory
// object. // object.
~VirtualMemory(); ~VirtualMemory();
......
...@@ -75,7 +75,6 @@ Heap::Heap() ...@@ -75,7 +75,6 @@ Heap::Heap()
code_range_size_(0), code_range_size_(0),
// semispace_size_ should be a power of 2 and old_generation_size_ should // semispace_size_ should be a power of 2 and old_generation_size_ should
// be a multiple of Page::kPageSize. // be a multiple of Page::kPageSize.
reserved_semispace_size_(8 * (kPointerSize / 4) * MB),
max_semi_space_size_(8 * (kPointerSize / 4) * MB), max_semi_space_size_(8 * (kPointerSize / 4) * MB),
initial_semispace_size_(Page::kPageSize), initial_semispace_size_(Page::kPageSize),
max_old_generation_size_(700ul * (kPointerSize / 4) * MB), max_old_generation_size_(700ul * (kPointerSize / 4) * MB),
...@@ -4915,32 +4914,10 @@ bool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size, ...@@ -4915,32 +4914,10 @@ bool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size,
max_semi_space_size_ = Page::kPageSize; max_semi_space_size_ = Page::kPageSize;
} }
if (isolate()->snapshot_available()) {
// If we are using a snapshot we always reserve the default amount
// of memory for each semispace because code in the snapshot has
// write-barrier code that relies on the size and alignment of new
// space. We therefore cannot use a larger max semispace size
// than the default reserved semispace size.
if (max_semi_space_size_ > reserved_semispace_size_) {
max_semi_space_size_ = reserved_semispace_size_;
if (FLAG_trace_gc) {
PrintIsolate(isolate_,
"Max semi-space size cannot be more than %d kbytes\n",
reserved_semispace_size_ >> 10);
}
}
} else {
// If we are not using snapshots we reserve space for the actual
// max semispace size.
reserved_semispace_size_ = max_semi_space_size_;
}
// The new space size must be a power of two to support single-bit testing // The new space size must be a power of two to support single-bit testing
// for containment. // for containment.
max_semi_space_size_ = max_semi_space_size_ =
base::bits::RoundUpToPowerOfTwo32(max_semi_space_size_); base::bits::RoundUpToPowerOfTwo32(max_semi_space_size_);
reserved_semispace_size_ =
base::bits::RoundUpToPowerOfTwo32(reserved_semispace_size_);
if (FLAG_min_semi_space_size > 0) { if (FLAG_min_semi_space_size > 0) {
int initial_semispace_size = FLAG_min_semi_space_size * MB; int initial_semispace_size = FLAG_min_semi_space_size * MB;
...@@ -5284,7 +5261,7 @@ bool Heap::SetUp() { ...@@ -5284,7 +5261,7 @@ bool Heap::SetUp() {
incremental_marking_ = new IncrementalMarking(this); incremental_marking_ = new IncrementalMarking(this);
// Set up new space. // Set up new space.
if (!new_space_.SetUp(reserved_semispace_size_, max_semi_space_size_)) { if (!new_space_.SetUp(initial_semispace_size_, max_semi_space_size_)) {
return false; return false;
} }
new_space_top_after_last_gc_ = new_space()->top(); new_space_top_after_last_gc_ = new_space()->top();
......
...@@ -1174,16 +1174,11 @@ class Heap { ...@@ -1174,16 +1174,11 @@ class Heap {
// GC statistics. ============================================================ // GC statistics. ============================================================
// =========================================================================== // ===========================================================================
// Returns the maximum amount of memory reserved for the heap. For // Returns the maximum amount of memory reserved for the heap.
// the young generation, we reserve 4 times the amount needed for a
// semi space. The young generation consists of two semi spaces and
// we reserve twice the amount needed for those in order to ensure
// that new space can be aligned to its size.
intptr_t MaxReserved() { intptr_t MaxReserved() {
return 4 * reserved_semispace_size_ + max_old_generation_size_; return 2 * max_semi_space_size_ + max_old_generation_size_;
} }
int MaxSemiSpaceSize() { return max_semi_space_size_; } int MaxSemiSpaceSize() { return max_semi_space_size_; }
int ReservedSemiSpaceSize() { return reserved_semispace_size_; }
int InitialSemiSpaceSize() { return initial_semispace_size_; } int InitialSemiSpaceSize() { return initial_semispace_size_; }
intptr_t MaxOldGenerationSize() { return max_old_generation_size_; } intptr_t MaxOldGenerationSize() { return max_old_generation_size_; }
intptr_t MaxExecutableSize() { return max_executable_size_; } intptr_t MaxExecutableSize() { return max_executable_size_; }
...@@ -1995,10 +1990,8 @@ class Heap { ...@@ -1995,10 +1990,8 @@ class Heap {
Object* roots_[kRootListLength]; Object* roots_[kRootListLength];
size_t code_range_size_; size_t code_range_size_;
int reserved_semispace_size_;
int max_semi_space_size_; int max_semi_space_size_;
int initial_semispace_size_; int initial_semispace_size_;
int target_semispace_size_;
intptr_t max_old_generation_size_; intptr_t max_old_generation_size_;
intptr_t initial_old_generation_size_; intptr_t initial_old_generation_size_;
bool old_generation_size_configured_; bool old_generation_size_configured_;
......
...@@ -251,6 +251,19 @@ AllocationSpace AllocationResult::RetrySpace() { ...@@ -251,6 +251,19 @@ AllocationSpace AllocationResult::RetrySpace() {
return static_cast<AllocationSpace>(Smi::cast(object_)->value()); return static_cast<AllocationSpace>(Smi::cast(object_)->value());
} }
NewSpacePage* NewSpacePage::Initialize(Heap* heap, MemoryChunk* chunk,
Executability executable,
SemiSpace* owner) {
DCHECK_EQ(executable, Executability::NOT_EXECUTABLE);
bool in_to_space = (owner->id() != kFromSpace);
chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE
: MemoryChunk::IN_FROM_SPACE);
DCHECK(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE
: MemoryChunk::IN_TO_SPACE));
NewSpacePage* page = static_cast<NewSpacePage*>(chunk);
heap->incremental_marking()->SetNewSpacePageFlags(page);
return page;
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// PagedSpace // PagedSpace
...@@ -261,6 +274,7 @@ Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable, ...@@ -261,6 +274,7 @@ Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable,
page->mutex_ = new base::Mutex(); page->mutex_ = new base::Mutex();
DCHECK(page->area_size() <= kAllocatableMemory); DCHECK(page->area_size() <= kAllocatableMemory);
DCHECK(chunk->owner() == owner); DCHECK(chunk->owner() == owner);
owner->IncreaseCapacity(page->area_size()); owner->IncreaseCapacity(page->area_size());
heap->incremental_marking()->SetOldSpacePageFlags(chunk); heap->incremental_marking()->SetOldSpacePageFlags(chunk);
......
This diff is collapsed.
This diff is collapsed.
...@@ -2333,11 +2333,7 @@ TEST(GrowAndShrinkNewSpace) { ...@@ -2333,11 +2333,7 @@ TEST(GrowAndShrinkNewSpace) {
Heap* heap = CcTest::heap(); Heap* heap = CcTest::heap();
NewSpace* new_space = heap->new_space(); NewSpace* new_space = heap->new_space();
if (heap->ReservedSemiSpaceSize() == heap->InitialSemiSpaceSize() || if (heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
// The max size cannot exceed the reserved size, since semispaces must be
// always within the reserved space. We can't test new space growing and
// shrinking if the reserved size is the same as the minimum (initial) size.
return; return;
} }
...@@ -2382,11 +2378,7 @@ TEST(GrowAndShrinkNewSpace) { ...@@ -2382,11 +2378,7 @@ TEST(GrowAndShrinkNewSpace) {
TEST(CollectingAllAvailableGarbageShrinksNewSpace) { TEST(CollectingAllAvailableGarbageShrinksNewSpace) {
CcTest::InitializeVM(); CcTest::InitializeVM();
Heap* heap = CcTest::heap(); Heap* heap = CcTest::heap();
if (heap->ReservedSemiSpaceSize() == heap->InitialSemiSpaceSize() || if (heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
heap->MaxSemiSpaceSize() == heap->InitialSemiSpaceSize()) {
// The max size cannot exceed the reserved size, since semispaces must be
// always within the reserved space. We can't test new space growing and
// shrinking if the reserved size is the same as the minimum (initial) size.
return; return;
} }
......
...@@ -317,8 +317,9 @@ TEST(MemoryAllocator) { ...@@ -317,8 +317,9 @@ TEST(MemoryAllocator) {
{ {
int total_pages = 0; int total_pages = 0;
OldSpace faked_space(heap, OLD_SPACE, NOT_EXECUTABLE); OldSpace faked_space(heap, OLD_SPACE, NOT_EXECUTABLE);
Page* first_page = memory_allocator->AllocatePage( Page* first_page = memory_allocator->AllocatePage<Page>(
faked_space.AreaSize(), &faked_space, NOT_EXECUTABLE); faked_space.AreaSize(), static_cast<PagedSpace*>(&faked_space),
NOT_EXECUTABLE);
first_page->InsertAfter(faked_space.anchor()->prev_page()); first_page->InsertAfter(faked_space.anchor()->prev_page());
CHECK(first_page->is_valid()); CHECK(first_page->is_valid());
...@@ -330,8 +331,9 @@ TEST(MemoryAllocator) { ...@@ -330,8 +331,9 @@ TEST(MemoryAllocator) {
} }
// Again, we should get n or n - 1 pages. // Again, we should get n or n - 1 pages.
Page* other = memory_allocator->AllocatePage(faked_space.AreaSize(), Page* other = memory_allocator->AllocatePage<Page>(
&faked_space, NOT_EXECUTABLE); faked_space.AreaSize(), static_cast<PagedSpace*>(&faked_space),
NOT_EXECUTABLE);
CHECK(other->is_valid()); CHECK(other->is_valid());
total_pages++; total_pages++;
other->InsertAfter(first_page); other->InsertAfter(first_page);
...@@ -362,8 +364,8 @@ TEST(NewSpace) { ...@@ -362,8 +364,8 @@ TEST(NewSpace) {
NewSpace new_space(heap); NewSpace new_space(heap);
CHECK(new_space.SetUp(CcTest::heap()->ReservedSemiSpaceSize(), CHECK(new_space.SetUp(CcTest::heap()->InitialSemiSpaceSize(),
CcTest::heap()->ReservedSemiSpaceSize())); CcTest::heap()->InitialSemiSpaceSize()));
CHECK(new_space.HasBeenSetUp()); CHECK(new_space.HasBeenSetUp());
while (new_space.Available() >= Page::kMaxRegularHeapObjectSize) { while (new_space.Available() >= Page::kMaxRegularHeapObjectSize) {
......
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