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
-~----------~----~----~----~------~----~------~--~---

Reply via email to