Chromium Code Reviews| Index: src/heap/spaces.cc |
| diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc |
| index 62f6d628fc740d1be53b72a87b7b125ece6f3f8d..226c52f9b9614b042aaae9900988157ea67c30dc 100644 |
| --- a/src/heap/spaces.cc |
| +++ b/src/heap/spaces.cc |
| @@ -1195,6 +1195,8 @@ bool NewSpace::SetUp(int reserved_semispace_capacity, |
| // this chunk must be a power of two and it must be aligned to its size. |
| int initial_semispace_capacity = heap()->InitialSemiSpaceSize(); |
| + int target_semispace_capacity = heap()->TargetSemiSpaceSize(); |
| + |
| size_t size = 2 * reserved_semispace_capacity; |
| Address base = heap()->isolate()->memory_allocator()->ReserveAlignedMemory( |
| size, size, &reservation_); |
| @@ -1223,9 +1225,10 @@ bool NewSpace::SetUp(int reserved_semispace_capacity, |
| DCHECK(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0)); |
| to_space_.SetUp(chunk_base_, initial_semispace_capacity, |
| - maximum_semispace_capacity); |
| + target_semispace_capacity, maximum_semispace_capacity); |
| from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, |
| - initial_semispace_capacity, maximum_semispace_capacity); |
| + initial_semispace_capacity, target_semispace_capacity, |
| + maximum_semispace_capacity); |
| if (!to_space_.Commit()) { |
| return false; |
| } |
| @@ -1293,6 +1296,36 @@ void NewSpace::Grow() { |
| } |
| +bool NewSpace::GrowOnePage() { |
| + if (TotalCapacity() == MaximumCapacity()) return false; |
| + int new_capacity = TotalCapacity() + Page::kPageSize; |
| + if (to_space_.GrowTo(new_capacity)) { |
| + // Only grow from space if we managed to grow to-space and the from space |
| + // is actually committed. |
| + if (from_space_.is_committed()) { |
| + if (!from_space_.GrowTo(new_capacity)) { |
| + // If we managed to grow to-space but couldn't grow from-space, |
| + // attempt to shrink to-space. |
| + if (!to_space_.ShrinkTo(from_space_.TotalCapacity())) { |
| + // We are in an inconsistent state because we could not |
| + // commit/uncommit memory from new space. |
| + V8::FatalProcessOutOfMemory("Failed to grow new space."); |
|
ulan
2014/10/21 15:01:50
All V8::FatalProcessOutOfMemory here should be CHE
|
| + } |
| + return false; |
| + } |
| + } else { |
| + if (!from_space_.SetTotalCapacity(new_capacity)) { |
| + // Can't really happen, but better safe than sorry. |
| + V8::FatalProcessOutOfMemory("Failed to grow new space."); |
| + } |
| + } |
| + DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| + |
| void NewSpace::Shrink() { |
| int new_capacity = Max(InitialTotalCapacity(), 2 * SizeAsInt()); |
| int rounded_new_capacity = RoundUp(new_capacity, Page::kPageSize); |
| @@ -1367,8 +1400,19 @@ bool NewSpace::AddFreshPage() { |
| return false; |
| } |
| if (!to_space_.AdvancePage()) { |
| - // Failed to get a new page in to-space. |
| - return false; |
| + // Check if we reached the target capacity yet. If not, try to commit a page |
| + // and continue. |
| + if ((to_space_.TotalCapacity() < to_space_.TargetCapacity()) && |
| + GrowOnePage()) { |
| + if (!to_space_.AdvancePage()) { |
| + // It doesn't make sense that we managed to commit a page, but can't use |
| + // it. |
| + V8::FatalProcessOutOfMemory("Failed to grow new space."); |
| + } |
| + } else { |
| + // Failed to get a new page in to-space. |
| + return false; |
| + } |
| } |
| // Clear remainder of current page. |
| @@ -1472,7 +1516,7 @@ void NewSpace::Verify() { |
| // ----------------------------------------------------------------------------- |
| // SemiSpace implementation |
| -void SemiSpace::SetUp(Address start, int initial_capacity, |
| +void SemiSpace::SetUp(Address start, int initial_capacity, int target_capacity, |
| int maximum_capacity) { |
| // Creates a space in the young generation. The constructor does not |
| // allocate memory from the OS. A SemiSpace is given a contiguous chunk of |
| @@ -1481,8 +1525,11 @@ void SemiSpace::SetUp(Address start, int initial_capacity, |
| // space is used as the marking stack. It requires contiguous memory |
| // addresses. |
| DCHECK(maximum_capacity >= Page::kPageSize); |
| + DCHECK(initial_capacity <= target_capacity); |
| + DCHECK(target_capacity <= maximum_capacity); |
| initial_total_capacity_ = RoundDown(initial_capacity, Page::kPageSize); |
| total_capacity_ = initial_capacity; |
| + target_capacity_ = RoundDown(target_capacity, Page::kPageSize); |
| maximum_total_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); |
| maximum_committed_ = 0; |
| committed_ = false; |
| @@ -1611,6 +1658,17 @@ bool SemiSpace::ShrinkTo(int new_capacity) { |
| } |
| +bool SemiSpace::SetTotalCapacity(int new_capacity) { |
| + CHECK(!is_committed()); |
| + if (new_capacity >= initial_total_capacity_ && |
| + new_capacity <= maximum_total_capacity_) { |
| + total_capacity_ = new_capacity; |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| + |
| void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { |
| anchor_.set_owner(this); |
| // Fixup back-pointers to anchor. Address of anchor changes |