| Index: src/heap/spaces.cc
|
| diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
|
| index 62f6d628fc740d1be53b72a87b7b125ece6f3f8d..85281aabbfe001b37eb540202684799492bc1c18 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;
|
| }
|
| @@ -1285,7 +1288,7 @@ void NewSpace::Grow() {
|
| 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.");
|
| + CHECK(false);
|
| }
|
| }
|
| }
|
| @@ -1293,6 +1296,36 @@ void NewSpace::Grow() {
|
| }
|
|
|
|
|
| +bool NewSpace::GrowOnePage() {
|
| + if (TotalCapacity() == MaximumCapacity()) return false;
|
| + int new_capacity = static_cast<int>(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.
|
| + CHECK(false);
|
| + }
|
| + return false;
|
| + }
|
| + } else {
|
| + if (!from_space_.SetTotalCapacity(new_capacity)) {
|
| + // Can't really happen, but better safe than sorry.
|
| + CHECK(false);
|
| + }
|
| + }
|
| + 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);
|
| @@ -1306,7 +1339,7 @@ void NewSpace::Shrink() {
|
| if (!to_space_.GrowTo(from_space_.TotalCapacity())) {
|
| // We are in an inconsistent state because we could not
|
| // commit/uncommit memory from new space.
|
| - V8::FatalProcessOutOfMemory("Failed to shrink new space.");
|
| + CHECK(false);
|
| }
|
| }
|
| }
|
| @@ -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.
|
| + CHECK(false);
|
| + }
|
| + } 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
|
|
|