Added support for -XX:HeapGrowthLimit switch

Runtime can now take in a growth limit for the heap, which can be
smaller than the maximum size of the heap, and will prevent the heap
from growing beyond that size. The growth limit can also be cleared to
increase the size of the heap to the specified maximum size. This gives
apps some control of the size of the heap, but should be removed when we
have better ways to resize the heap.

Change-Id: I338655bccd20bfd32e2318365f0f3283dbaaab1e
diff --git a/src/heap.cc b/src/heap.cc
index 9fe7750..6fd4ade 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -27,6 +27,8 @@
 
 size_t Heap::maximum_size_ = 0;
 
+size_t Heap::growth_size_ = 0;
+
 size_t Heap::num_bytes_allocated_ = 0;
 
 size_t Heap::num_objects_allocated_ = 0;
@@ -64,7 +66,7 @@
 };
 
 void Heap::Init(bool is_verbose_heap, bool is_verbose_gc,
-                size_t initial_size, size_t maximum_size,
+                size_t initial_size, size_t maximum_size, size_t growth_size,
                 const std::vector<std::string>& image_file_names) {
   is_verbose_heap_ = is_verbose_heap;
   is_verbose_gc_ = is_verbose_gc;
@@ -98,7 +100,7 @@
     limit = std::max(limit, space->GetLimit());
   }
 
-  alloc_space_ = Space::Create("alloc space", initial_size, maximum_size, requested_base);
+  alloc_space_ = Space::Create("alloc space", initial_size, maximum_size, growth_size, requested_base);
   if (alloc_space_ == NULL) {
     LOG(FATAL) << "Failed to create alloc space";
   }
@@ -121,6 +123,7 @@
 
   spaces_.push_back(alloc_space_);
   maximum_size_ = maximum_size;
+  growth_size_ = growth_size;
   live_bitmap_ = live_bitmap.release();
   mark_bitmap_ = mark_bitmap.release();
 
@@ -329,7 +332,7 @@
   DCHECK_EQ(Thread::Current()->GetState(), Thread::kRunnable);
 
   // Fail impossible allocations.  TODO: collect soft references.
-  if (size > maximum_size_) {
+  if (size > growth_size_) {
     return NULL;
   }
 
@@ -405,7 +408,7 @@
 }
 
 int64_t Heap::GetMaxMemory() {
-  return maximum_size_;
+  return growth_size_;
 }
 
 int64_t Heap::GetTotalMemory() {
@@ -563,12 +566,12 @@
 //
 void Heap::SetIdealFootprint(size_t max_allowed_footprint)
 {
-  if (max_allowed_footprint > Heap::maximum_size_) {
+  if (max_allowed_footprint > Heap::growth_size_) {
     if (is_verbose_gc_) {
       LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
-                << " to " << Heap::maximum_size_;
+                << " to " << Heap::growth_size_;
     }
-    max_allowed_footprint = Heap::maximum_size_;
+    max_allowed_footprint = Heap::growth_size_;
   }
 
   alloc_space_->SetMaxAllowedFootprint(max_allowed_footprint);
@@ -602,6 +605,14 @@
   SetIdealFootprint(target_size);
 }
 
+void Heap::ClearGrowthLimit() {
+  ScopedHeapLock lock;
+  WaitForConcurrentGcToComplete();
+  CHECK_GE(maximum_size_, growth_size_);
+  growth_size_ = maximum_size_;
+  alloc_space_->ClearGrowthLimit();
+}
+
 pid_t Heap::GetLockOwner() {
   return lock_->GetOwner();
 }