Add parsed options for heap min free, heap max free, target utilization.

Added options in runtime for heap min free, max free, and target utilization.

Change-Id: Iaea988ffbf6cb7f07127640786168de7d341f1e1
diff --git a/src/common_test.h b/src/common_test.h
index 62ff907..560edeb 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -322,8 +322,8 @@
     java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName());
     boot_class_path_.push_back(java_lang_dex_file_);
 
-    std::string min_heap_string(StringPrintf("-Xms%zdm", Heap::kInitialSize / MB));
-    std::string max_heap_string(StringPrintf("-Xmx%zdm", Heap::kMaximumSize / MB));
+    std::string min_heap_string(StringPrintf("-Xms%zdm", Heap::kDefaultInitialSize / MB));
+    std::string max_heap_string(StringPrintf("-Xmx%zdm", Heap::kDefaultMaximumSize / MB));
 
     Runtime::Options options;
     options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
diff --git a/src/heap.cc b/src/heap.cc
index 6c13563..f91ce84 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -45,6 +45,8 @@
 
 namespace art {
 
+const double Heap::kDefaultTargetUtilization = 0.5;
+
 static bool GenerateImage(const std::string& image_file_name) {
   const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
   std::vector<std::string> boot_class_path;
@@ -127,7 +129,8 @@
   oat_file_map_.reset(NULL);
 }
 
-Heap::Heap(size_t initial_size, size_t growth_limit, size_t capacity,
+Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free,
+           double target_utilization, size_t capacity,
            const std::string& original_image_file_name, bool concurrent_gc)
     : alloc_space_(NULL),
       card_table_(NULL),
@@ -138,10 +141,10 @@
       last_gc_type_(kGcTypeNone),
       enforce_heap_growth_rate_(false),
       growth_limit_(growth_limit),
-      max_allowed_footprint_(kInitialSize),
-      concurrent_start_bytes_(std::numeric_limits<size_t>::max()),
+      max_allowed_footprint_(initial_size),
       concurrent_start_size_(128 * KB),
       concurrent_min_free_(256 * KB),
+      concurrent_start_bytes_(initial_size - concurrent_start_size_),
       sticky_gc_count_(0),
       total_bytes_freed_(0),
       total_objects_freed_(0),
@@ -163,7 +166,9 @@
       reference_queueNext_offset_(0),
       reference_pendingNext_offset_(0),
       finalizer_reference_zombie_offset_(0),
-      target_utilization_(0.5),
+      min_free_(min_free),
+      max_free_(max_free),
+      target_utilization_(target_utilization),
       total_paused_time_(0),
       total_wait_time_(0),
       measure_allocation_time_(false),
@@ -730,10 +735,6 @@
   return TryToAllocate(self, space, alloc_size, true);
 }
 
-float Heap::GetTargetHeapUtilization() const {
-  return target_utilization_;
-}
-
 void Heap::SetTargetHeapUtilization(float target) {
   DCHECK_GT(target, 0.0f);  // asserted in Java code
   DCHECK_LT(target, 1.0f);
@@ -1763,7 +1764,8 @@
   uint64_t pause_dirty = (dirty_end - dirty_begin) / 1000 * 1000;
   uint64_t duration = (NanoTime() - root_begin) / 1000 * 1000;
   total_paused_time_ += (pause_roots + pause_dirty) / kTimeAdjust;
-  if (pause_roots > MsToNs(5) || pause_dirty > MsToNs(5)) {
+  if (pause_roots > MsToNs(5) || pause_dirty > MsToNs(5) ||
+      (gc_cause == kGcCauseForAlloc && duration > MsToNs(20))) {
     const size_t percent_free = GetPercentFree();
     const size_t current_heap_size = GetUsedMemorySize();
     const size_t total_memory = GetTotalMemory();
@@ -1833,20 +1835,14 @@
   max_allowed_footprint_ = max_allowed_footprint;
 }
 
-// kHeapIdealFree is the ideal maximum free size, when we grow the heap for utilization.
-static const size_t kHeapIdealFree = 2 * MB;
-// kHeapMinFree guarantees that you always have at least 512 KB free, when you grow for utilization,
-// regardless of target utilization ratio.
-static const size_t kHeapMinFree = kHeapIdealFree / 4;
-
 void Heap::GrowForUtilization() {
   // We know what our utilization is at this moment.
   // This doesn't actually resize any memory. It just lets the heap grow more when necessary.
   size_t target_size = num_bytes_allocated_ / Heap::GetTargetHeapUtilization();
-  if (target_size > num_bytes_allocated_ + kHeapIdealFree) {
-    target_size = num_bytes_allocated_ + kHeapIdealFree;
-  } else if (target_size < num_bytes_allocated_ + kHeapMinFree) {
-    target_size = num_bytes_allocated_ + kHeapMinFree;
+  if (target_size > num_bytes_allocated_ + max_free_) {
+    target_size = num_bytes_allocated_ + max_free_;
+  } else if (target_size < num_bytes_allocated_ + min_free_) {
+    target_size = num_bytes_allocated_ + min_free_;
   }
 
   // Calculate when to perform the next ConcurrentGC.
diff --git a/src/heap.h b/src/heap.h
index d5f1ba7..6cd19d4 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -82,8 +82,14 @@
 
 class Heap {
  public:
-  static const size_t kInitialSize = 2 * MB;
-  static const size_t kMaximumSize = 32 * MB;
+  static const size_t kDefaultInitialSize = 2 * MB;
+  static const size_t kDefaultMaximumSize = 32 * MB;
+  static const size_t kDefaultMaxFree = 2 * MB;
+  static const size_t kDefaultMinFree = kDefaultMaxFree / 4;
+
+  // Default target utilization.
+  static const double kDefaultTargetUtilization;
+
   // Used so that we don't overflow the allocation time atomic integer.
   static const size_t kTimeAdjust = 1024;
 
@@ -93,8 +99,9 @@
   // Create a heap with the requested sizes. The possible empty
   // image_file_names names specify Spaces to load based on
   // ImageWriter output.
-  explicit Heap(size_t starting_size, size_t growth_limit, size_t capacity,
-                const std::string& image_file_name, bool concurrent_gc);
+  explicit Heap(size_t initial_size, size_t growth_limit, size_t min_free,
+                size_t max_free, double target_utilization, size_t capacity,
+                const std::string& original_image_file_name, bool concurrent_gc);
 
   ~Heap();
 
@@ -155,7 +162,9 @@
 
   // Target ideal heap utilization ratio, implements
   // dalvik.system.VMRuntime.getTargetHeapUtilization.
-  float GetTargetHeapUtilization() const;
+  double GetTargetHeapUtilization() const {
+    return target_utilization_;
+  }
 
   // Set target ideal heap utilization ratio, implements
   // dalvik.system.VMRuntime.setTargetHeapUtilization.
@@ -425,9 +434,9 @@
   size_t max_allowed_footprint_;
 
   // Bytes until concurrent GC starts.
-  volatile size_t concurrent_start_bytes_;
   size_t concurrent_start_size_;
   size_t concurrent_min_free_;
+  size_t concurrent_start_bytes_;
 
   // Number of bytes allocated since the last Gc, we use this to help determine when to schedule concurrent GCs.
   size_t bytes_since_last_gc_;
@@ -498,8 +507,15 @@
   // offset of java.lang.ref.FinalizerReference.zombie
   MemberOffset finalizer_reference_zombie_offset_;
 
+  // Minimum free guarantees that you always have at least min_free_ free bytes after growing for
+  // utilization, regardless of target utilization ratio.
+  size_t min_free_;
+
+  // The ideal maximum free size, when we grow the heap for utilization.
+  size_t max_free_;
+
   // Target ideal heap utilization ratio
-  float target_utilization_;
+  double target_utilization_;
 
   // Total time which mutators are paused or waiting for GC to complete.
   uint64_t total_paused_time_;
diff --git a/src/runtime.cc b/src/runtime.cc
index e3384df..e2e419a 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -347,8 +347,11 @@
   // -Xcheck:jni is off by default for regular builds but on by default in debug builds.
   parsed->check_jni_ = kIsDebugBuild;
 
-  parsed->heap_initial_size_ = Heap::kInitialSize;
-  parsed->heap_maximum_size_ = Heap::kMaximumSize;
+  parsed->heap_initial_size_ = Heap::kDefaultInitialSize;
+  parsed->heap_maximum_size_ = Heap::kDefaultMaximumSize;
+  parsed->heap_min_free_ = Heap::kDefaultMinFree;
+  parsed->heap_max_free_ = Heap::kDefaultMaxFree;
+  parsed->heap_target_utilization_ = Heap::kDefaultTargetUtilization;
   parsed->heap_growth_limit_ = 0;  // 0 means no growth limit.
   parsed->stack_size_ = 0; // 0 means default.
 
@@ -443,6 +446,42 @@
         return NULL;
       }
       parsed->heap_growth_limit_ = size;
+    } else if (StartsWith(option, "-XX:HeapMinFree=")) {
+      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapMinFree=")).c_str(), 1024);
+      if (size == 0) {
+        if (ignore_unrecognized) {
+          continue;
+        }
+        // TODO: usage
+        LOG(FATAL) << "Failed to parse " << option;
+        return NULL;
+      }
+      parsed->heap_min_free_ = size;
+    } else if (StartsWith(option, "-XX:HeapMaxFree=")) {
+      size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapMaxFree=")).c_str(), 1024);
+      if (size == 0) {
+        if (ignore_unrecognized) {
+          continue;
+        }
+        // TODO: usage
+        LOG(FATAL) << "Failed to parse " << option;
+        return NULL;
+      }
+      parsed->heap_max_free_ = size;
+    } else if (StartsWith(option, "-XX:HeapTargetUtilization=")) {
+      std::istringstream iss(option.substr(strlen("-XX:HeapTargetUtilization=")));
+      double value;
+      iss >> value;
+      // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
+      const bool sane_val = iss.good() && (value >= 0.1) && (value <= 0.9);
+      if (!sane_val) {
+        if (ignore_unrecognized) {
+          continue;
+        }
+        LOG(FATAL) << "Invalid option '" << option << "'";
+        return NULL;
+      }
+      parsed->heap_target_utilization_ = value;
     } else if (StartsWith(option, "-Xss")) {
       size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1);
       if (size == 0) {
@@ -720,6 +759,9 @@
 
   heap_ = new Heap(options->heap_initial_size_,
                    options->heap_growth_limit_,
+                   options->heap_min_free_,
+                   options->heap_max_free_,
+                   options->heap_target_utilization_,
                    options->heap_maximum_size_,
                    options->image_,
                    options->is_concurrent_gc_enabled_);
diff --git a/src/runtime.h b/src/runtime.h
index ba37f40..a6c662c 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -79,6 +79,9 @@
     size_t heap_initial_size_;
     size_t heap_maximum_size_;
     size_t heap_growth_limit_;
+    size_t heap_min_free_;
+    size_t heap_max_free_;
+    double heap_target_utilization_;
     size_t stack_size_;
     size_t jni_globals_max_;
     size_t lock_profiling_threshold_;