Changed card table to use less cards when heap size is limited.

The card table uses the growth limit of the heap to limit the number of
cards it makes available for use. This gives it less cards to clean up
while the heap is limited.

Change-Id: Ia6520231d4abeda9604993ba28fd7ee7729a1ecb
diff --git a/src/card_table.cc b/src/card_table.cc
index e8eec38..4b57aa1 100644
--- a/src/card_table.cc
+++ b/src/card_table.cc
@@ -45,9 +45,9 @@
  * byte is equal to GC_DIRTY_CARD. See CardTable::Init for details.
  */
 
-CardTable* CardTable::Create(const byte* heap_base, size_t heap_max_size) {
+CardTable* CardTable::Create(const byte* heap_base, size_t heap_max_size, size_t growth_size) {
   UniquePtr<CardTable> bitmap(new CardTable);
-  if (!bitmap->Init(heap_base, heap_max_size)) {
+  if (!bitmap->Init(heap_base, heap_max_size, growth_size)) {
     return NULL;
   } else {
     return bitmap.release();
@@ -58,7 +58,7 @@
  * Initializes the card table; must be called before any other
  * CardTable functions.
  */
-bool CardTable::Init(const byte* heap_base, size_t heap_max_size) {
+bool CardTable::Init(const byte* heap_base, size_t heap_max_size, size_t growth_size) {
   /* Set up the card table */
   size_t length = heap_max_size / GC_CARD_SIZE;
   /* Allocate an extra 256 bytes to allow fixed low-byte of base */
@@ -68,7 +68,8 @@
     return false;
   }
   base_ = alloc_base;
-  length_ = length;
+  length_ = growth_size / GC_CARD_SIZE;
+  max_length_ = length;
   offset_ = 0;
   /* All zeros is the correct initial value; all clean. */
   CHECK_EQ(GC_CARD_CLEAN, 0);
diff --git a/src/card_table.h b/src/card_table.h
index 19629c3..a2616be 100644
--- a/src/card_table.h
+++ b/src/card_table.h
@@ -27,7 +27,7 @@
  public:
   typedef void Callback(Object* obj, void* arg);
 
-  static CardTable* Create(const byte* heap_base, size_t heap_max_size);
+  static CardTable* Create(const byte* heap_base, size_t heap_max_size, size_t growth_size);
 
   /*
    * Set the card associated with the given address to GC_CARD_DIRTY.
@@ -47,6 +47,11 @@
     return *CardFromAddr(obj) == GC_CARD_DIRTY;
   }
 
+  void ClearGrowthLimit() {
+    CHECK_GE(max_length_, length_);
+    length_ = max_length_;
+  }
+
  private:
 
   CardTable() {}
@@ -55,7 +60,7 @@
    * Initializes the card table; must be called before any other
    * CardTable functions.
    */
-  bool Init(const byte* heap_base, size_t heap_max_size);
+  bool Init(const byte* heap_base, size_t heap_max_size, size_t growth_size);
 
   /*
    * Resets all of the bytes in the card table to clean.
@@ -96,6 +101,7 @@
   byte* base_;
   byte* biased_base_;
   size_t length_;
+  size_t max_length_;
   size_t offset_;
 };
 
diff --git a/src/heap.cc b/src/heap.cc
index 57a3ce2..6b0677c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -72,9 +72,10 @@
 
   // bounds of all spaces for allocating live and mark bitmaps
   // there will be at least one space (the alloc space),
-  // so set to base to max and limit to min to start
+  // so set base to max, and limit and min to start
   byte* base = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::max());
   byte* max = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::min());
+  byte* limit = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::min());
 
   byte* requested_base = NULL;
   std::vector<Space*> image_spaces;
@@ -92,6 +93,7 @@
     }
     base = std::min(base, space->GetBase());
     max = std::max(max, space->GetMax());
+    limit = std::max(limit, space->GetLimit());
   }
 
   alloc_space_ = Space::Create("alloc space", initial_size, maximum_size, growth_size, requested_base);
@@ -100,8 +102,11 @@
   }
   base = std::min(base, alloc_space_->GetBase());
   max = std::max(max, alloc_space_->GetMax());
+  limit = std::max(limit, alloc_space_->GetLimit());
   DCHECK_LT(base, max);
+  DCHECK_LT(base, limit);
   size_t num_bytes = max - base;
+  size_t limit_bytes = limit - base;
 
   // Allocate the initial live bitmap.
   UniquePtr<HeapBitmap> live_bitmap(HeapBitmap::Create(base, num_bytes));
@@ -116,7 +121,7 @@
   }
 
   // Allocate the card table
-  UniquePtr<CardTable> card_table(CardTable::Create(base, num_bytes));
+  UniquePtr<CardTable> card_table(CardTable::Create(base, num_bytes, limit_bytes));
   if (card_table.get() == NULL) {
     LOG(FATAL) << "Failed to create card table";
   }
@@ -629,6 +634,7 @@
   CHECK_GE(maximum_size_, growth_size_);
   growth_size_ = maximum_size_;
   alloc_space_->ClearGrowthLimit();
+  card_table_->ClearGrowthLimit();
 }
 
 pid_t Heap::GetLockOwner() {