Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Unified Diff: src/heap/spaces.cc

Issue 1853783002: [heap] Non-contiguous young generation (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Hannes comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/spaces.h ('k') | src/heap/spaces-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/spaces.cc
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index 6d30f31c7ca2c09196716cd64ef1b5183035fcc1..780a2d4926931bf2f88c9abe68f8ec8f147c4db1 100644
--- a/src/heap/spaces.cc
+++ b/src/heap/spaces.cc
@@ -315,15 +315,18 @@ bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable) {
void MemoryAllocator::TearDown() {
+ for (MemoryChunk* chunk : chunk_pool_) {
+ FreeMemory(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize,
+ NOT_EXECUTABLE);
+ }
// Check that spaces were torn down before MemoryAllocator.
- DCHECK(size_.Value() == 0);
+ DCHECK_EQ(size_.Value(), 0);
// TODO(gc) this will be true again when we fix FreeMemory.
// DCHECK(size_executable_ == 0);
capacity_ = 0;
capacity_executable_ = 0;
}
-
bool MemoryAllocator::CommitMemory(Address base, size_t size,
Executability executable) {
if (!base::VirtualMemory::CommitRegion(base, size,
@@ -335,20 +338,6 @@ bool MemoryAllocator::CommitMemory(Address base, size_t size,
}
-void MemoryAllocator::FreeNewSpaceMemory(Address addr,
- base::VirtualMemory* reservation,
- Executability executable) {
- LOG(isolate_, DeleteEvent("NewSpace", addr));
-
- DCHECK(reservation->IsReserved());
- const intptr_t size = static_cast<intptr_t>(reservation->size());
- DCHECK(size_.Value() >= size);
- size_.Increment(-size);
- isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size));
- FreeMemory(reservation, NOT_EXECUTABLE);
-}
-
-
void MemoryAllocator::FreeMemory(base::VirtualMemory* reservation,
Executability executable) {
// TODO(gc) make code_range part of memory allocator?
@@ -433,26 +422,6 @@ void Page::InitializeAsAnchor(PagedSpace* owner) {
set_next_page(this);
}
-
-NewSpacePage* NewSpacePage::Initialize(Heap* heap, Address start,
- SemiSpace* semi_space) {
- Address area_start = start + NewSpacePage::kObjectStartOffset;
- Address area_end = start + Page::kPageSize;
-
- MemoryChunk* chunk =
- MemoryChunk::Initialize(heap, start, Page::kPageSize, area_start,
- area_end, NOT_EXECUTABLE, semi_space, nullptr);
- bool in_to_space = (semi_space->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;
-}
-
-
void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) {
set_owner(semi_space);
set_next_chunk(this);
@@ -715,15 +684,6 @@ void Page::ResetFreeListStatistics() {
available_in_free_list_ = 0;
}
-
-Page* MemoryAllocator::AllocatePage(intptr_t size, PagedSpace* owner,
- Executability executable) {
- MemoryChunk* chunk = AllocateChunk(size, size, executable, owner);
- if (chunk == NULL) return NULL;
- return Page::Initialize(isolate_->heap(), chunk, executable, owner);
-}
-
-
LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size,
Space* owner,
Executability executable) {
@@ -782,12 +742,75 @@ void MemoryAllocator::PerformFreeMemory(MemoryChunk* chunk) {
}
}
-
+template <MemoryAllocator::AllocationMode mode>
void MemoryAllocator::Free(MemoryChunk* chunk) {
- PreFreeMemory(chunk);
- PerformFreeMemory(chunk);
+ if (mode == kRegular) {
+ PreFreeMemory(chunk);
+ PerformFreeMemory(chunk);
+ } else {
+ DCHECK_EQ(mode, kPooled);
+ FreePooled(chunk);
+ }
+}
+
+template void MemoryAllocator::Free<MemoryAllocator::kRegular>(
+ MemoryChunk* chunk);
+
+template void MemoryAllocator::Free<MemoryAllocator::kPooled>(
+ MemoryChunk* chunk);
+
+template <typename PageType, MemoryAllocator::AllocationMode mode,
+ typename SpaceType>
+PageType* MemoryAllocator::AllocatePage(intptr_t size, SpaceType* owner,
+ Executability executable) {
+ MemoryChunk* chunk = nullptr;
+ if (mode == kPooled) {
+ DCHECK_EQ(size, static_cast<intptr_t>(MemoryChunk::kAllocatableMemory));
+ DCHECK_EQ(executable, NOT_EXECUTABLE);
+ chunk = AllocatePagePooled(owner);
+ }
+ if (chunk == nullptr) {
+ chunk = AllocateChunk(size, size, executable, owner);
+ }
+ if (chunk == nullptr) return nullptr;
+ return PageType::Initialize(isolate_->heap(), chunk, executable, owner);
+}
+
+template Page* MemoryAllocator::AllocatePage<Page, MemoryAllocator::kRegular,
+ PagedSpace>(intptr_t, PagedSpace*,
+ Executability);
+
+template NewSpacePage* MemoryAllocator::AllocatePage<
+ NewSpacePage, MemoryAllocator::kPooled, SemiSpace>(intptr_t, SemiSpace*,
+ Executability);
+
+template <typename SpaceType>
+MemoryChunk* MemoryAllocator::AllocatePagePooled(SpaceType* owner) {
+ if (chunk_pool_.is_empty()) return nullptr;
+ const int size = MemoryChunk::kPageSize;
+ MemoryChunk* chunk = chunk_pool_.RemoveLast();
+ const Address start = reinterpret_cast<Address>(chunk);
+ const Address area_start = start + MemoryChunk::kObjectStartOffset;
+ const Address area_end = start + size;
+ CommitBlock(reinterpret_cast<Address>(chunk), size, NOT_EXECUTABLE);
+ base::VirtualMemory reservation(start, size);
+ MemoryChunk::Initialize(isolate_->heap(), start, size, area_start, area_end,
+ NOT_EXECUTABLE, owner, &reservation);
+ size_.Increment(size);
+ return chunk;
}
+void MemoryAllocator::FreePooled(MemoryChunk* chunk) {
+ DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize));
+ DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE);
+ chunk_pool_.Add(chunk);
+ intptr_t chunk_size = static_cast<intptr_t>(chunk->size());
+ if (chunk->executable() == EXECUTABLE) {
+ size_executable_.Increment(-chunk_size);
+ }
+ size_.Increment(-chunk_size);
+ UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize);
+}
bool MemoryAllocator::CommitBlock(Address start, size_t size,
Executability executable) {
@@ -1159,8 +1182,8 @@ bool PagedSpace::Expand() {
if (!CanExpand(size)) return false;
- Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this,
- executable());
+ Page* p = heap()->isolate()->memory_allocator()->AllocatePage<Page>(
+ size, this, executable());
if (p == NULL) return false;
AccountCommitted(static_cast<intptr_t>(p->size()));
@@ -1290,53 +1313,28 @@ void PagedSpace::Verify(ObjectVisitor* visitor) {
// -----------------------------------------------------------------------------
// NewSpace implementation
-
-bool NewSpace::SetUp(int reserved_semispace_capacity,
+bool NewSpace::SetUp(int initial_semispace_capacity,
int maximum_semispace_capacity) {
- // Set up new space based on the preallocated memory block defined by
- // start and size. The provided space is divided into two semi-spaces.
- // To support fast containment testing in the new space, the size of
- // this chunk must be a power of two and it must be aligned to its size.
- int initial_semispace_capacity = heap()->InitialSemiSpaceSize();
-
- size_t size = 2 * reserved_semispace_capacity;
- Address base = heap()->isolate()->memory_allocator()->ReserveAlignedMemory(
- size, size, &reservation_);
- if (base == NULL) return false;
-
- chunk_base_ = base;
- chunk_size_ = static_cast<uintptr_t>(size);
- LOG(heap()->isolate(), NewEvent("InitialChunk", chunk_base_, chunk_size_));
-
DCHECK(initial_semispace_capacity <= maximum_semispace_capacity);
DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity));
+ to_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity);
+ from_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity);
+ if (!to_space_.Commit()) {
+ return false;
+ }
+ DCHECK(!from_space_.is_committed()); // No need to use memory yet.
+ ResetAllocationInfo();
+
// Allocate and set up the histogram arrays if necessary.
allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1);
promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1);
-
#define SET_NAME(name) \
allocated_histogram_[name].set_name(#name); \
promoted_histogram_[name].set_name(#name);
INSTANCE_TYPE_LIST(SET_NAME)
#undef SET_NAME
- DCHECK(reserved_semispace_capacity == heap()->ReservedSemiSpaceSize());
- DCHECK(static_cast<intptr_t>(chunk_size_) >=
- 2 * heap()->ReservedSemiSpaceSize());
- DCHECK(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0));
-
- to_space_.SetUp(chunk_base_, initial_semispace_capacity,
- maximum_semispace_capacity);
- from_space_.SetUp(chunk_base_ + reserved_semispace_capacity,
- initial_semispace_capacity, maximum_semispace_capacity);
- if (!to_space_.Commit()) {
- return false;
- }
- DCHECK(!from_space_.is_committed()); // No need to use memory yet.
-
- ResetAllocationInfo();
-
return true;
}
@@ -1355,12 +1353,6 @@ void NewSpace::TearDown() {
to_space_.TearDown();
from_space_.TearDown();
-
- heap()->isolate()->memory_allocator()->FreeNewSpaceMemory(
- chunk_base_, &reservation_, NOT_EXECUTABLE);
-
- chunk_base_ = NULL;
- chunk_size_ = 0;
}
@@ -1677,43 +1669,41 @@ void NewSpace::Verify() {
// -----------------------------------------------------------------------------
// SemiSpace implementation
-void SemiSpace::SetUp(Address start, int initial_capacity,
- int maximum_capacity) {
+void SemiSpace::SetUp(int initial_capacity, int maximum_capacity) {
DCHECK_GE(maximum_capacity, Page::kPageSize);
minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize);
current_capacity_ = minimum_capacity_;
maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize);
committed_ = false;
- start_ = start;
- age_mark_ = start_ + NewSpacePage::kObjectStartOffset;
}
void SemiSpace::TearDown() {
- start_ = nullptr;
- current_capacity_ = 0;
+ // Properly uncommit memory to keep the allocator counters in sync.
+ if (is_committed()) Uncommit();
+ current_capacity_ = maximum_capacity_ = 0;
}
bool SemiSpace::Commit() {
DCHECK(!is_committed());
- if (!heap()->isolate()->memory_allocator()->CommitBlock(
- start_, current_capacity_, executable())) {
- return false;
- }
- AccountCommitted(current_capacity_);
-
NewSpacePage* current = anchor();
const int num_pages = current_capacity_ / Page::kPageSize;
for (int i = 0; i < num_pages; i++) {
NewSpacePage* new_page =
- NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this);
+ heap()
+ ->isolate()
+ ->memory_allocator()
+ ->AllocatePage<NewSpacePage, MemoryAllocator::kPooled>(
+ NewSpacePage::kAllocatableMemory, this, executable());
new_page->InsertAfter(current);
current = new_page;
}
Reset();
-
- set_current_capacity(current_capacity_);
+ AccountCommitted(current_capacity_);
+ if (age_mark_ == nullptr) {
+ age_mark_ = first_page()->area_start();
+ }
committed_ = true;
return true;
}
@@ -1721,16 +1711,14 @@ bool SemiSpace::Commit() {
bool SemiSpace::Uncommit() {
DCHECK(is_committed());
- Address start = start_ + maximum_capacity_ - current_capacity_;
- if (!heap()->isolate()->memory_allocator()->UncommitBlock(
- start, current_capacity_)) {
- return false;
+ NewSpacePageIterator it(this);
+ while (it.has_next()) {
+ heap()->isolate()->memory_allocator()->Free<MemoryAllocator::kPooled>(
+ it.next());
}
- AccountUncommitted(current_capacity_);
-
anchor()->set_next_page(anchor());
anchor()->set_prev_page(anchor());
-
+ AccountUncommitted(current_capacity_);
committed_ = false;
return true;
}
@@ -1751,62 +1739,57 @@ bool SemiSpace::GrowTo(int new_capacity) {
if (!is_committed()) {
if (!Commit()) return false;
}
- DCHECK_EQ(new_capacity & Page::kPageAlignmentMask, 0);
+ DCHECK_EQ(new_capacity & NewSpacePage::kPageAlignmentMask, 0);
DCHECK_LE(new_capacity, maximum_capacity_);
DCHECK_GT(new_capacity, current_capacity_);
- int pages_before = current_capacity_ / Page::kPageSize;
- int pages_after = new_capacity / Page::kPageSize;
-
- size_t delta = new_capacity - current_capacity_;
-
+ const int delta = new_capacity - current_capacity_;
DCHECK(IsAligned(delta, base::OS::AllocateAlignment()));
- if (!heap()->isolate()->memory_allocator()->CommitBlock(
- start_ + current_capacity_, delta, executable())) {
- return false;
- }
- AccountCommitted(static_cast<intptr_t>(delta));
- set_current_capacity(new_capacity);
+ int delta_pages = delta / NewSpacePage::kPageSize;
NewSpacePage* last_page = anchor()->prev_page();
DCHECK_NE(last_page, anchor());
- for (int i = pages_before; i < pages_after; i++) {
- Address page_address = start_ + i * Page::kPageSize;
+ while (delta_pages > 0) {
NewSpacePage* new_page =
- NewSpacePage::Initialize(heap(), page_address, this);
+ heap()
+ ->isolate()
+ ->memory_allocator()
+ ->AllocatePage<NewSpacePage, MemoryAllocator::kPooled>(
+ NewSpacePage::kAllocatableMemory, this, executable());
new_page->InsertAfter(last_page);
Bitmap::Clear(new_page);
// Duplicate the flags that was set on the old page.
new_page->SetFlags(last_page->GetFlags(),
NewSpacePage::kCopyOnFlipFlagsMask);
last_page = new_page;
+ delta_pages--;
}
+ AccountCommitted(static_cast<intptr_t>(delta));
+ current_capacity_ = new_capacity;
return true;
}
bool SemiSpace::ShrinkTo(int new_capacity) {
- DCHECK_EQ(new_capacity & Page::kPageAlignmentMask, 0);
+ DCHECK_EQ(new_capacity & NewSpacePage::kPageAlignmentMask, 0);
DCHECK_GE(new_capacity, minimum_capacity_);
DCHECK_LT(new_capacity, current_capacity_);
if (is_committed()) {
- size_t delta = current_capacity_ - new_capacity;
+ const int delta = current_capacity_ - new_capacity;
DCHECK(IsAligned(delta, base::OS::AllocateAlignment()));
-
- MemoryAllocator* allocator = heap()->isolate()->memory_allocator();
- if (!allocator->UncommitBlock(start_ + new_capacity, delta)) {
- return false;
+ int delta_pages = delta / NewSpacePage::kPageSize;
+ NewSpacePage* new_last_page;
+ NewSpacePage* last_page;
+ while (delta_pages > 0) {
+ last_page = anchor()->prev_page();
+ new_last_page = last_page->prev_page();
+ new_last_page->set_next_page(anchor());
+ anchor()->set_prev_page(new_last_page);
+ heap()->isolate()->memory_allocator()->Free<MemoryAllocator::kPooled>(
+ last_page);
+ delta_pages--;
}
AccountUncommitted(static_cast<intptr_t>(delta));
-
- int pages_after = new_capacity / Page::kPageSize;
- NewSpacePage* new_last_page =
- NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize);
- new_last_page->set_next_page(anchor());
- anchor()->set_prev_page(new_last_page);
- DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page));
}
-
- set_current_capacity(new_capacity);
-
+ current_capacity_ = new_capacity;
return true;
}
@@ -1853,7 +1836,6 @@ void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) {
std::swap(from->current_capacity_, to->current_capacity_);
std::swap(from->maximum_capacity_, to->maximum_capacity_);
std::swap(from->minimum_capacity_, to->minimum_capacity_);
- std::swap(from->start_, to->start_);
std::swap(from->age_mark_, to->age_mark_);
std::swap(from->committed_, to->committed_);
std::swap(from->anchor_, to->anchor_);
« no previous file with comments | « src/heap/spaces.h ('k') | src/heap/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698