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

[heap] Use target and current capacity counters to grow NewSpace.

Bug: chromium:1054771
Change-Id: I64d0d2a4f07add4adef78136b303881a900474a7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2560198Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Hannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71427}
parent d4c885de
...@@ -39,7 +39,7 @@ Page* SemiSpace::InitializePage(MemoryChunk* chunk) { ...@@ -39,7 +39,7 @@ Page* SemiSpace::InitializePage(MemoryChunk* chunk) {
bool SemiSpace::EnsureCurrentCapacity() { bool SemiSpace::EnsureCurrentCapacity() {
if (is_committed()) { if (is_committed()) {
const int expected_pages = const int expected_pages =
static_cast<int>(current_capacity_ / Page::kPageSize); static_cast<int>(target_capacity_ / Page::kPageSize);
MemoryChunk* current_page = first_page(); MemoryChunk* current_page = first_page();
int actual_pages = 0; int actual_pages = 0;
...@@ -91,7 +91,7 @@ bool SemiSpace::EnsureCurrentCapacity() { ...@@ -91,7 +91,7 @@ bool SemiSpace::EnsureCurrentCapacity() {
void SemiSpace::SetUp(size_t initial_capacity, size_t maximum_capacity) { void SemiSpace::SetUp(size_t initial_capacity, size_t maximum_capacity) {
DCHECK_GE(maximum_capacity, static_cast<size_t>(Page::kPageSize)); DCHECK_GE(maximum_capacity, static_cast<size_t>(Page::kPageSize));
minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize); minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize);
current_capacity_ = minimum_capacity_; target_capacity_ = minimum_capacity_;
maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize);
committed_ = false; committed_ = false;
} }
...@@ -101,12 +101,12 @@ void SemiSpace::TearDown() { ...@@ -101,12 +101,12 @@ void SemiSpace::TearDown() {
if (is_committed()) { if (is_committed()) {
Uncommit(); Uncommit();
} }
current_capacity_ = maximum_capacity_ = 0; target_capacity_ = maximum_capacity_ = 0;
} }
bool SemiSpace::Commit() { bool SemiSpace::Commit() {
DCHECK(!is_committed()); DCHECK(!is_committed());
const int num_pages = static_cast<int>(current_capacity_ / Page::kPageSize); const int num_pages = static_cast<int>(target_capacity_ / Page::kPageSize);
for (int pages_added = 0; pages_added < num_pages; pages_added++) { for (int pages_added = 0; pages_added < num_pages; pages_added++) {
// Pages in the new spaces can be moved to the old space by the full // Pages in the new spaces can be moved to the old space by the full
// collector. Therefore, they must be initialized with the same FreeList as // collector. Therefore, they must be initialized with the same FreeList as
...@@ -122,7 +122,7 @@ bool SemiSpace::Commit() { ...@@ -122,7 +122,7 @@ bool SemiSpace::Commit() {
memory_chunk_list_.PushBack(new_page); memory_chunk_list_.PushBack(new_page);
} }
Reset(); Reset();
AccountCommitted(current_capacity_); AccountCommitted(target_capacity_);
if (age_mark_ == kNullAddress) { if (age_mark_ == kNullAddress) {
age_mark_ = first_page()->area_start(); age_mark_ = first_page()->area_start();
} }
...@@ -138,7 +138,7 @@ bool SemiSpace::Uncommit() { ...@@ -138,7 +138,7 @@ bool SemiSpace::Uncommit() {
heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(chunk); heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(chunk);
} }
current_page_ = nullptr; current_page_ = nullptr;
AccountUncommitted(current_capacity_); AccountUncommitted(target_capacity_);
committed_ = false; committed_ = false;
heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
return true; return true;
...@@ -159,8 +159,8 @@ bool SemiSpace::GrowTo(size_t new_capacity) { ...@@ -159,8 +159,8 @@ bool SemiSpace::GrowTo(size_t new_capacity) {
} }
DCHECK_EQ(new_capacity & kPageAlignmentMask, 0u); DCHECK_EQ(new_capacity & kPageAlignmentMask, 0u);
DCHECK_LE(new_capacity, maximum_capacity_); DCHECK_LE(new_capacity, maximum_capacity_);
DCHECK_GT(new_capacity, current_capacity_); DCHECK_GT(new_capacity, target_capacity_);
const size_t delta = new_capacity - current_capacity_; const size_t delta = new_capacity - target_capacity_;
DCHECK(IsAligned(delta, AllocatePageSize())); DCHECK(IsAligned(delta, AllocatePageSize()));
const int delta_pages = static_cast<int>(delta / Page::kPageSize); const int delta_pages = static_cast<int>(delta / Page::kPageSize);
DCHECK(last_page()); DCHECK(last_page());
...@@ -181,7 +181,7 @@ bool SemiSpace::GrowTo(size_t new_capacity) { ...@@ -181,7 +181,7 @@ bool SemiSpace::GrowTo(size_t new_capacity) {
new_page->SetFlags(last_page()->GetFlags(), Page::kCopyOnFlipFlagsMask); new_page->SetFlags(last_page()->GetFlags(), Page::kCopyOnFlipFlagsMask);
} }
AccountCommitted(delta); AccountCommitted(delta);
current_capacity_ = new_capacity; target_capacity_ = new_capacity;
return true; return true;
} }
...@@ -199,16 +199,16 @@ void SemiSpace::RewindPages(int num_pages) { ...@@ -199,16 +199,16 @@ void SemiSpace::RewindPages(int num_pages) {
bool SemiSpace::ShrinkTo(size_t new_capacity) { bool SemiSpace::ShrinkTo(size_t new_capacity) {
DCHECK_EQ(new_capacity & kPageAlignmentMask, 0u); DCHECK_EQ(new_capacity & kPageAlignmentMask, 0u);
DCHECK_GE(new_capacity, minimum_capacity_); DCHECK_GE(new_capacity, minimum_capacity_);
DCHECK_LT(new_capacity, current_capacity_); DCHECK_LT(new_capacity, target_capacity_);
if (is_committed()) { if (is_committed()) {
const size_t delta = current_capacity_ - new_capacity; const size_t delta = target_capacity_ - new_capacity;
DCHECK(IsAligned(delta, Page::kPageSize)); DCHECK(IsAligned(delta, Page::kPageSize));
int delta_pages = static_cast<int>(delta / Page::kPageSize); int delta_pages = static_cast<int>(delta / Page::kPageSize);
RewindPages(delta_pages); RewindPages(delta_pages);
AccountUncommitted(delta); AccountUncommitted(delta);
heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
} }
current_capacity_ = new_capacity; target_capacity_ = new_capacity;
return true; return true;
} }
...@@ -234,7 +234,7 @@ void SemiSpace::Reset() { ...@@ -234,7 +234,7 @@ void SemiSpace::Reset() {
DCHECK(first_page()); DCHECK(first_page());
DCHECK(last_page()); DCHECK(last_page());
current_page_ = first_page(); current_page_ = first_page();
pages_used_ = 0; current_capacity_ = Page::kPageSize;
} }
void SemiSpace::RemovePage(Page* page) { void SemiSpace::RemovePage(Page* page) {
...@@ -255,7 +255,7 @@ void SemiSpace::PrependPage(Page* page) { ...@@ -255,7 +255,7 @@ void SemiSpace::PrependPage(Page* page) {
static_cast<uintptr_t>(Page::kCopyAllFlags)); static_cast<uintptr_t>(Page::kCopyAllFlags));
page->set_owner(this); page->set_owner(this);
memory_chunk_list_.PushFront(page); memory_chunk_list_.PushFront(page);
pages_used_++; current_capacity_ += Page::kPageSize;
for (size_t i = 0; i < ExternalBackingStoreType::kNumTypes; i++) { for (size_t i = 0; i < ExternalBackingStoreType::kNumTypes; i++) {
ExternalBackingStoreType t = static_cast<ExternalBackingStoreType>(i); ExternalBackingStoreType t = static_cast<ExternalBackingStoreType>(i);
IncrementExternalBackingStoreBytes(t, page->ExternalBackingStoreBytes(t)); IncrementExternalBackingStoreBytes(t, page->ExternalBackingStoreBytes(t));
...@@ -277,7 +277,7 @@ void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { ...@@ -277,7 +277,7 @@ void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) {
intptr_t saved_to_space_flags = to->current_page()->GetFlags(); intptr_t saved_to_space_flags = to->current_page()->GetFlags();
// We swap all properties but id_. // We swap all properties but id_.
std::swap(from->current_capacity_, to->current_capacity_); std::swap(from->target_capacity_, to->target_capacity_);
std::swap(from->maximum_capacity_, to->maximum_capacity_); std::swap(from->maximum_capacity_, to->maximum_capacity_);
std::swap(from->minimum_capacity_, to->minimum_capacity_); std::swap(from->minimum_capacity_, to->minimum_capacity_);
std::swap(from->age_mark_, to->age_mark_); std::swap(from->age_mark_, to->age_mark_);
...@@ -440,7 +440,7 @@ void NewSpace::Grow() { ...@@ -440,7 +440,7 @@ void NewSpace::Grow() {
if (!from_space_.GrowTo(new_capacity)) { if (!from_space_.GrowTo(new_capacity)) {
// If we managed to grow to-space but couldn't grow from-space, // If we managed to grow to-space but couldn't grow from-space,
// attempt to shrink to-space. // attempt to shrink to-space.
if (!to_space_.ShrinkTo(from_space_.current_capacity())) { if (!to_space_.ShrinkTo(from_space_.target_capacity())) {
// We are in an inconsistent state because we could not // We are in an inconsistent state because we could not
// commit/uncommit memory from new space. // commit/uncommit memory from new space.
FATAL("inconsistent state"); FATAL("inconsistent state");
...@@ -460,7 +460,7 @@ void NewSpace::Shrink() { ...@@ -460,7 +460,7 @@ void NewSpace::Shrink() {
if (!from_space_.ShrinkTo(rounded_new_capacity)) { if (!from_space_.ShrinkTo(rounded_new_capacity)) {
// If we managed to shrink to-space but couldn't shrink from // If we managed to shrink to-space but couldn't shrink from
// space, attempt to grow to-space again. // space, attempt to grow to-space again.
if (!to_space_.GrowTo(from_space_.current_capacity())) { if (!to_space_.GrowTo(from_space_.target_capacity())) {
// We are in an inconsistent state because we could not // We are in an inconsistent state because we could not
// commit/uncommit memory from new space. // commit/uncommit memory from new space.
FATAL("inconsistent state"); FATAL("inconsistent state");
......
...@@ -44,13 +44,13 @@ class SemiSpace : public Space { ...@@ -44,13 +44,13 @@ class SemiSpace : public Space {
SemiSpace(Heap* heap, SemiSpaceId semispace) SemiSpace(Heap* heap, SemiSpaceId semispace)
: Space(heap, NEW_SPACE, new NoFreeList()), : Space(heap, NEW_SPACE, new NoFreeList()),
current_capacity_(0), current_capacity_(0),
target_capacity_(0),
maximum_capacity_(0), maximum_capacity_(0),
minimum_capacity_(0), minimum_capacity_(0),
age_mark_(kNullAddress), age_mark_(kNullAddress),
committed_(false), committed_(false),
id_(semispace), id_(semispace),
current_page_(nullptr), current_page_(nullptr) {}
pages_used_(0) {}
inline bool Contains(HeapObject o) const; inline bool Contains(HeapObject o) const;
inline bool Contains(Object o) const; inline bool Contains(Object o) const;
...@@ -81,7 +81,6 @@ class SemiSpace : public Space { ...@@ -81,7 +81,6 @@ class SemiSpace : public Space {
} }
Page* current_page() { return current_page_; } Page* current_page() { return current_page_; }
int pages_used() { return pages_used_; }
// Returns the start address of the current page of the space. // Returns the start address of the current page of the space.
Address page_low() { return current_page_->area_start(); } Address page_low() { return current_page_->area_start(); }
...@@ -91,15 +90,14 @@ class SemiSpace : public Space { ...@@ -91,15 +90,14 @@ class SemiSpace : public Space {
bool AdvancePage() { bool AdvancePage() {
Page* next_page = current_page_->next_page(); Page* next_page = current_page_->next_page();
// We cannot expand if we reached the maximum number of pages already. Note // We cannot expand if we reached the target capcity. Note
// that we need to account for the next page already for this check as we // that we need to account for the next page already for this check as we
// could potentially fill the whole page after advancing. // could potentially fill the whole page after advancing.
const bool reached_max_pages = (pages_used_ + 1) == max_pages(); if (next_page == nullptr || (current_capacity_ == target_capacity_)) {
if (next_page == nullptr || reached_max_pages) {
return false; return false;
} }
current_page_ = next_page; current_page_ = next_page;
pages_used_++; current_capacity_ += Page::kPageSize;
return true; return true;
} }
...@@ -119,6 +117,9 @@ class SemiSpace : public Space { ...@@ -119,6 +117,9 @@ class SemiSpace : public Space {
// Returns the current capacity of the semispace. // Returns the current capacity of the semispace.
size_t current_capacity() { return current_capacity_; } size_t current_capacity() { return current_capacity_; }
// Returns the target capacity of the semispace.
size_t target_capacity() { return target_capacity_; }
// Returns the maximum capacity of the semispace. // Returns the maximum capacity of the semispace.
size_t maximum_capacity() { return maximum_capacity_; } size_t maximum_capacity() { return maximum_capacity_; }
...@@ -172,16 +173,15 @@ class SemiSpace : public Space { ...@@ -172,16 +173,15 @@ class SemiSpace : public Space {
private: private:
void RewindPages(int num_pages); void RewindPages(int num_pages);
inline int max_pages() {
return static_cast<int>(current_capacity_ / Page::kPageSize);
}
// Copies the flags into the masked positions on all pages in the space. // Copies the flags into the masked positions on all pages in the space.
void FixPagesFlags(intptr_t flags, intptr_t flag_mask); void FixPagesFlags(intptr_t flags, intptr_t flag_mask);
// The currently committed space capacity. // The currently committed space capacity.
size_t current_capacity_; size_t current_capacity_;
// The targetted committed space capacity.
size_t target_capacity_;
// The maximum capacity that can be used by this space. A space cannot grow // The maximum capacity that can be used by this space. A space cannot grow
// beyond that size. // beyond that size.
size_t maximum_capacity_; size_t maximum_capacity_;
...@@ -197,8 +197,6 @@ class SemiSpace : public Space { ...@@ -197,8 +197,6 @@ class SemiSpace : public Space {
Page* current_page_; Page* current_page_;
int pages_used_;
friend class NewSpace; friend class NewSpace;
friend class SemiSpaceObjectIterator; friend class SemiSpaceObjectIterator;
}; };
...@@ -264,7 +262,7 @@ class V8_EXPORT_PRIVATE NewSpace ...@@ -264,7 +262,7 @@ class V8_EXPORT_PRIVATE NewSpace
// Return the allocated bytes in the active semispace. // Return the allocated bytes in the active semispace.
size_t Size() final { size_t Size() final {
DCHECK_GE(top(), to_space_.page_low()); DCHECK_GE(top(), to_space_.page_low());
return to_space_.pages_used() * return (to_space_.current_capacity() - Page::kPageSize) / Page::kPageSize *
MemoryChunkLayout::AllocatableMemoryInDataPage() + MemoryChunkLayout::AllocatableMemoryInDataPage() +
static_cast<size_t>(top() - to_space_.page_low()); static_cast<size_t>(top() - to_space_.page_low());
} }
...@@ -273,16 +271,16 @@ class V8_EXPORT_PRIVATE NewSpace ...@@ -273,16 +271,16 @@ class V8_EXPORT_PRIVATE NewSpace
// Return the allocatable capacity of a semispace. // Return the allocatable capacity of a semispace.
size_t Capacity() { size_t Capacity() {
SLOW_DCHECK(to_space_.current_capacity() == from_space_.current_capacity()); SLOW_DCHECK(to_space_.target_capacity() == from_space_.target_capacity());
return (to_space_.current_capacity() / Page::kPageSize) * return (to_space_.target_capacity() / Page::kPageSize) *
MemoryChunkLayout::AllocatableMemoryInDataPage(); MemoryChunkLayout::AllocatableMemoryInDataPage();
} }
// Return the current size of a semispace, allocatable and non-allocatable // Return the current size of a semispace, allocatable and non-allocatable
// memory. // memory.
size_t TotalCapacity() { size_t TotalCapacity() {
DCHECK(to_space_.current_capacity() == from_space_.current_capacity()); DCHECK(to_space_.target_capacity() == from_space_.target_capacity());
return to_space_.current_capacity(); return to_space_.target_capacity();
} }
// Committed memory for NewSpace is the committed memory of both semi-spaces // Committed memory for NewSpace is the committed memory of both semi-spaces
......
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