Revision: 2740
Author: [email protected]
Date: Fri Aug 21 06:14:53 2009
Log: Shrink new space on compacting collections.
Review URL: http://codereview.chromium.org/174219
http://code.google.com/p/v8/source/detail?r=2740
Modified:
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/spaces.cc
/branches/bleeding_edge/src/spaces.h
=======================================
--- /branches/bleeding_edge/src/heap.cc Fri Aug 21 01:52:24 2009
+++ /branches/bleeding_edge/src/heap.cc Fri Aug 21 06:14:53 2009
@@ -465,8 +465,9 @@
old_gen_allocation_limit_ =
old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2);
old_gen_exhausted_ = false;
- }
- Scavenge();
+ } else {
+ Scavenge();
+ }
Counters::objs_since_last_young.Set(0);
PostGarbageCollectionProcessing();
@@ -520,6 +521,12 @@
Counters::objs_since_last_full.Set(0);
context_disposed_pending_ = false;
+
+ Scavenge();
+
+ // Shrink new space as much as possible after compacting full
+ // garbage collections.
+ if (is_compacting) new_space_.Shrink();
}
@@ -668,8 +675,6 @@
survived_since_last_expansion_ > new_space_.Capacity()) {
// Grow the size of new space if there is room to grow and enough
// data has survived scavenge since the last expansion.
- // TODO(1240712): NewSpace::Grow has a return value which is
- // ignored here.
new_space_.Grow();
survived_since_last_expansion_ = 0;
}
=======================================
--- /branches/bleeding_edge/src/spaces.cc Thu Aug 20 01:12:30 2009
+++ /branches/bleeding_edge/src/spaces.cc Fri Aug 21 06:14:53 2009
@@ -951,15 +951,43 @@
}
-bool NewSpace::Grow() {
+void NewSpace::Grow() {
ASSERT(Capacity() < MaximumCapacity());
- // TODO(1240712): Failure to double the from space can result in
- // semispaces of different sizes. In the event of that failure, the
- // to space doubling should be rolled back before returning false.
- if (!to_space_.Grow() || !from_space_.Grow()) return false;
+ if (to_space_.Grow()) {
+ // Only grow from space if we managed to grow to space.
+ if (!from_space_.Grow()) {
+ // If we managed to grow to space but couldn't grow from space,
+ // attempt to shrink to space.
+ if (!to_space_.ShrinkTo(from_space_.Capacity())) {
+ // We are in an inconsistent state because we could not
+ // commit/uncommit memory from new space.
+ V8::FatalProcessOutOfMemory("Failed to grow new space.");
+ }
+ }
+ }
allocation_info_.limit = to_space_.high();
ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
- return true;
+}
+
+
+void NewSpace::Shrink() {
+ int new_capacity = Max(InitialCapacity(), 2 * Size());
+ int rounded_new_capacity = RoundUp(new_capacity,
OS::AllocateAlignment());
+ if (rounded_new_capacity < Capacity() &&
+ to_space_.ShrinkTo(rounded_new_capacity)) {
+ // Only shrink from space if we managed to shrink to space.
+ if (!from_space_.ShrinkTo(rounded_new_capacity)) {
+ // If we managed to shrink to space but couldn't shrink from
+ // space, attempt to grow to space again.
+ if (!to_space_.GrowTo(from_space_.Capacity())) {
+ // We are in an inconsistent state because we could not
+ // commit/uncommit memory from new space.
+ V8::FatalProcessOutOfMemory("Failed to shrink new space.");
+ }
+ }
+ }
+ allocation_info_.limit = to_space_.high();
+ ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
}
@@ -1058,6 +1086,7 @@
// otherwise. In the mark-compact collector, the memory region of the
from
// space is used as the marking stack. It requires contiguous memory
// addresses.
+ initial_capacity_ = initial_capacity;
capacity_ = initial_capacity;
maximum_capacity_ = maximum_capacity;
committed_ = false;
@@ -1089,6 +1118,32 @@
capacity_ += extra;
return true;
}
+
+
+bool SemiSpace::GrowTo(int new_capacity) {
+ ASSERT(new_capacity <= maximum_capacity_);
+ ASSERT(new_capacity > capacity_);
+ size_t delta = new_capacity - capacity_;
+ ASSERT(IsAligned(delta, OS::AllocateAlignment()));
+ if (!MemoryAllocator::CommitBlock(high(), delta, executable())) {
+ return false;
+ }
+ capacity_ = new_capacity;
+ return true;
+}
+
+
+bool SemiSpace::ShrinkTo(int new_capacity) {
+ ASSERT(new_capacity >= initial_capacity_);
+ ASSERT(new_capacity < capacity_);
+ size_t delta = capacity_ - new_capacity;
+ ASSERT(IsAligned(delta, OS::AllocateAlignment()));
+ if (!MemoryAllocator::UncommitBlock(high() - delta, delta)) {
+ return false;
+ }
+ capacity_ = new_capacity;
+ return true;
+}
#ifdef DEBUG
=======================================
--- /branches/bleeding_edge/src/spaces.h Wed Aug 19 03:36:19 2009
+++ /branches/bleeding_edge/src/spaces.h Fri Aug 21 06:14:53 2009
@@ -1010,6 +1010,15 @@
// address range to grow).
bool Grow();
+ // Grow the semispace to the new capacity. The new capacity
+ // requested must be larger than the current capacity.
+ bool GrowTo(int new_capacity);
+
+ // Shrinks the semispace to the new capacity. The new capacity
+ // requested must be more than the amount of used memory in the
+ // semispace and less than the current capacity.
+ bool ShrinkTo(int new_capacity);
+
// Returns the start address of the space.
Address low() { return start_; }
// Returns one past the end address of the space.
@@ -1057,11 +1066,14 @@
// Returns the maximum capacity of the semi space.
int MaximumCapacity() { return maximum_capacity_; }
+ // Returns the initial capacity of the semi space.
+ int InitialCapacity() { return initial_capacity_; }
private:
// The current and maximum capacity of the space.
int capacity_;
int maximum_capacity_;
+ int initial_capacity_;
// The start address of the space.
Address start_;
@@ -1152,8 +1164,11 @@
void Flip();
// Grow the capacity of the semispaces. Assumes that they are not at
- // their maximum capacity. Returns a flag indicating success or failure.
- bool Grow();
+ // their maximum capacity.
+ void Grow();
+
+ // Shrink the capacity of the semispaces.
+ void Shrink();
// True if the address or object lies in the address range of either
// semispace (not necessarily below the allocation pointer).
@@ -1180,6 +1195,12 @@
ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity());
return to_space_.MaximumCapacity();
}
+
+ // Returns the initial capacity of a semispace.
+ int InitialCapacity() {
+ ASSERT(to_space_.InitialCapacity() == from_space_.InitialCapacity());
+ return to_space_.InitialCapacity();
+ }
// Return the address of the allocation pointer in the active semispace.
Address top() { return allocation_info_.top; }
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---