Add low memory mode option to ART.

Useful so that we match the option I added here:
https://googleplex-android-review.googlesource.com/#/c/328940/

In ART low memory mode reduces the maximum number of histogram
buckets. We also trim no matter the utilization.

Change-Id: I655ba63312c0a6574569cdd5171ca81ea338c2aa
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index e2d2d4c..b58b0ac 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -113,7 +113,8 @@
   // Convert delta time to microseconds so that we don't overflow our counters.
   delta_time /= kAdjust;
   if (histograms_.size() <= index_) {
-    histograms_.push_back(new Histogram<uint64_t>(label.c_str(), 50));
+    const size_t max_buckets = Runtime::Current()->GetHeap()->IsLowMemoryMode() ? 16 : 100;
+    histograms_.push_back(new Histogram<uint64_t>(label.c_str(), 50, max_buckets));
     DCHECK_GT(histograms_.size(), index_);
   }
   histograms_[index_]->AddValue(delta_time);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 3cc60d9..47e9b75 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -68,12 +68,13 @@
 const double Heap::kDefaultTargetUtilization = 0.5;
 
 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, size_t num_gc_threads)
+           double target_utilization, size_t capacity, const std::string& original_image_file_name,
+           bool concurrent_gc, size_t num_gc_threads, bool low_memory_mode)
     : alloc_space_(NULL),
       card_table_(NULL),
       concurrent_gc_(concurrent_gc),
       num_gc_threads_(num_gc_threads),
+      low_memory_mode_(low_memory_mode),
       have_zygote_space_(false),
       reference_queue_lock_(NULL),
       is_gc_running_(false),
@@ -1855,9 +1856,9 @@
   uint64_t ms_time = MilliTime();
   float utilization =
       static_cast<float>(alloc_space_->GetBytesAllocated()) / alloc_space_->Size();
-  if ((utilization > 0.75f) || ((ms_time - last_trim_time_ms_) < 2 * 1000)) {
-    // Don't bother trimming the alloc space if it's more than 75% utilized, or if a
-    // heap trim occurred in the last two seconds.
+  if ((utilization > 0.75f && !IsLowMemoryMode()) || ((ms_time - last_trim_time_ms_) < 2 * 1000)) {
+    // Don't bother trimming the alloc space if it's more than 75% utilized and low memory mode is
+    // not enabled, or if a heap trim occurred in the last two seconds.
     return;
   }
 
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 7615f98..3f91553 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -137,7 +137,7 @@
   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,
-                size_t num_gc_threads);
+                size_t num_gc_threads, bool low_memory_mode);
 
   ~Heap();
 
@@ -276,6 +276,11 @@
         verify_object_mode_ > kHeapVerificationNotPermitted;
   }
 
+  // Returns true if low memory mode is enabled.
+  bool IsLowMemoryMode() const {
+    return low_memory_mode_;
+  }
+
   void RecordFree(size_t freed_objects, size_t freed_bytes);
 
   // Must be called if a field of an Object in the heap changes, and before any GC safe-point.
@@ -502,6 +507,9 @@
   // How many GC threads we may use for garbage collection.
   const bool num_gc_threads_;
 
+  // Boolean for if we are in low memory mode.
+  const bool low_memory_mode_;
+
   // If we have a zygote space.
   bool have_zygote_space_;
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 485c636..5298181 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -341,6 +341,7 @@
   // Default to number of processors minus one since the main GC thread also does work.
   parsed->heap_gc_threads_ = sysconf(_SC_NPROCESSORS_CONF) - 1;
   parsed->stack_size_ = 0;  // 0 means default.
+  parsed->low_memory_mode_ = false;
 
   parsed->is_compiler_ = false;
   parsed->is_zygote_ = false;
@@ -488,6 +489,8 @@
         return NULL;
       }
       parsed->stack_size_ = size;
+    } else if (option == "-XX:LowMemoryMode") {
+      parsed->low_memory_mode_ = true;
     } else if (StartsWith(option, "-D")) {
       parsed->properties_.push_back(option.substr(strlen("-D")));
     } else if (StartsWith(option, "-Xjnitrace:")) {
@@ -835,7 +838,8 @@
                        options->heap_maximum_size_,
                        options->image_,
                        options->is_concurrent_gc_enabled_,
-                       options->heap_gc_threads_);
+                       options->heap_gc_threads_,
+                       options->low_memory_mode_);
 
   BlockSignals();
   InitPlatformSignalHandlers();
diff --git a/runtime/runtime.h b/runtime/runtime.h
index d480e36..47fff29 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -97,6 +97,7 @@
     size_t heap_max_free_;
     double heap_target_utilization_;
     size_t stack_size_;
+    bool low_memory_mode_;
     size_t lock_profiling_threshold_;
     std::string stack_trace_file_;
     bool method_trace_;