Fix non concurrent GC ergonomics.

If we dont have concurrent GC enabled, we need to force GC for alloc
when we hit the maximum allowed footprint so that our heap doesn't
keep growing until it hits the growth limit.

Refactored a bit of stuff.

Change-Id: I8eceac4ef01e969fd286ebde3a735a09d0a6dfc1
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index fa2ab27..c5e8812 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -65,8 +65,8 @@
       (reinterpret_cast<uintptr_t>(card_end) & (sizeof(uintptr_t) - 1));
 
   // Now we have the words, we can send these to be processed in parallel.
-  auto* word_cur = reinterpret_cast<uintptr_t*>(card_cur);
-  auto* word_end = reinterpret_cast<uintptr_t*>(aligned_end);
+  uintptr_t* word_cur = reinterpret_cast<uintptr_t*>(card_cur);
+  uintptr_t* word_end = reinterpret_cast<uintptr_t*>(aligned_end);
   for (;;) {
     while (LIKELY(*word_cur == 0)) {
       ++word_cur;
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index 039415e..b7641a4 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -80,7 +80,7 @@
     uint64_t pause_end = NanoTime();
     pause_times_.push_back(pause_end - pause_start);
   } else {
-    auto* self = Thread::Current();
+    Thread* self = Thread::Current();
     {
       ReaderMutexLock mu(self, *Locks::mutator_lock_);
       MarkingPhase();
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 5c31eb1..9c69fdf 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -268,7 +268,7 @@
 
 void MarkSweep::ReclaimPhase() {
   base::TimingLogger::ScopedSplit split("ReclaimPhase", &timings_);
-  auto* self = Thread::Current();
+  Thread* self = Thread::Current();
 
   if (!IsConcurrent()) {
     base::TimingLogger::ScopedSplit split("ProcessReferences", &timings_);
@@ -745,14 +745,14 @@
   ThreadPool* thread_pool = GetHeap()->GetThreadPool();
   const bool parallel = kParallelCardScan && thread_pool != nullptr;
   if (parallel) {
-    auto* self = Thread::Current();
+    Thread* self = Thread::Current();
     // Can't have a different split for each space since multiple spaces can have their cards being
     // scanned at the same time.
     timings_.StartSplit(paused ? "(Paused)ScanGrayObjects" : "ScanGrayObjects");
     // Try to take some of the mark stack since we can pass this off to the worker tasks.
     const Object** mark_stack_begin = const_cast<const Object**>(mark_stack_->Begin());
     const Object** mark_stack_end = const_cast<const Object**>(mark_stack_->End());
-    const auto mark_stack_size = mark_stack_end - mark_stack_begin;
+    const size_t mark_stack_size = mark_stack_end - mark_stack_begin;
     const size_t thread_count = thread_pool->GetThreadCount() + 1;
     // Estimated number of work tasks we will create.
     const size_t mark_stack_tasks = GetHeap()->GetContinuousSpaces().size() * thread_count;
@@ -1209,8 +1209,8 @@
       sweep_space = (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect);
     }
     if (sweep_space) {
-      auto begin = reinterpret_cast<uintptr_t>(space->Begin());
-      auto end = reinterpret_cast<uintptr_t>(space->End());
+      uintptr_t begin = reinterpret_cast<uintptr_t>(space->Begin());
+      uintptr_t end = reinterpret_cast<uintptr_t>(space->End());
       scc.space = space->AsDlMallocSpace();
       accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap();
       accounting::SpaceBitmap* mark_bitmap = space->GetMarkBitmap();
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 5b01104..e89dd66 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -59,17 +59,16 @@
 namespace gc {
 
 // When to create a log message about a slow GC, 100ms.
-static const uint64_t kSlowGcThreshold = MsToNs(100);
+static constexpr uint64_t kSlowGcThreshold = MsToNs(100);
 // When to create a log message about a long pause, 5ms.
-static const uint64_t kLongGcPauseThreshold = MsToNs(5);
-static const bool kGCALotMode = false;
-static const size_t kGcAlotInterval = KB;
-static const bool kDumpGcPerformanceOnShutdown = false;
+static constexpr uint64_t kLongGcPauseThreshold = MsToNs(5);
+static constexpr bool kGCALotMode = false;
+static constexpr size_t kGcAlotInterval = KB;
+static constexpr bool kDumpGcPerformanceOnShutdown = false;
 // Minimum amount of remaining bytes before a concurrent GC is triggered.
-static const size_t kMinConcurrentRemainingBytes = 128 * KB;
-const double Heap::kDefaultTargetUtilization = 0.5;
+static constexpr size_t kMinConcurrentRemainingBytes = 128 * KB;
 // If true, measure the total allocation time.
-static const bool kMeasureAllocationTime = false;
+static constexpr bool kMeasureAllocationTime = false;
 
 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,
@@ -100,8 +99,8 @@
       // Initially care about pauses in case we never get notified of process states, or if the JNI
       // code becomes broken.
       care_about_pause_times_(true),
-      concurrent_start_bytes_(concurrent_gc ? initial_size - kMinConcurrentRemainingBytes
-                                            :  std::numeric_limits<size_t>::max()),
+      concurrent_start_bytes_(concurrent_gc_ ? initial_size - kMinConcurrentRemainingBytes
+          :  std::numeric_limits<size_t>::max()),
       total_bytes_freed_ever_(0),
       total_objects_freed_ever_(0),
       large_object_threshold_(3 * kPageSize),
@@ -793,13 +792,26 @@
   }
 }
 
-inline bool Heap::IsOutOfMemoryOnAllocation(size_t alloc_size) {
-  return num_bytes_allocated_ + alloc_size > growth_limit_;
+inline bool Heap::IsOutOfMemoryOnAllocation(size_t alloc_size, bool grow) {
+  size_t new_footprint = num_bytes_allocated_ + alloc_size;
+  if (UNLIKELY(new_footprint > max_allowed_footprint_)) {
+    if (UNLIKELY(new_footprint > growth_limit_)) {
+      return true;
+    }
+    if (!concurrent_gc_) {
+      if (!grow) {
+        return true;
+      } else {
+        max_allowed_footprint_ = new_footprint;
+      }
+    }
+  }
+  return false;
 }
 
 inline mirror::Object* Heap::TryToAllocate(Thread* self, space::AllocSpace* space, size_t alloc_size,
                                            bool grow, size_t* bytes_allocated) {
-  if (IsOutOfMemoryOnAllocation(alloc_size)) {
+  if (UNLIKELY(IsOutOfMemoryOnAllocation(alloc_size, grow))) {
     return NULL;
   }
   return space->Alloc(self, alloc_size, bytes_allocated);
@@ -808,10 +820,10 @@
 // DlMallocSpace-specific version.
 inline mirror::Object* Heap::TryToAllocate(Thread* self, space::DlMallocSpace* space, size_t alloc_size,
                                            bool grow, size_t* bytes_allocated) {
-  if (IsOutOfMemoryOnAllocation(alloc_size)) {
+  if (UNLIKELY(IsOutOfMemoryOnAllocation(alloc_size, grow))) {
     return NULL;
   }
-  if (!running_on_valgrind_) {
+  if (LIKELY(!running_on_valgrind_)) {
     return space->AllocNonvirtual(self, alloc_size, bytes_allocated);
   } else {
     return space->Alloc(self, alloc_size, bytes_allocated);
@@ -819,7 +831,8 @@
 }
 
 template <class T>
-inline mirror::Object* Heap::Allocate(Thread* self, T* space, size_t alloc_size, size_t* bytes_allocated) {
+inline mirror::Object* Heap::Allocate(Thread* self, T* space, size_t alloc_size,
+                                      size_t* bytes_allocated) {
   // Since allocation can cause a GC which will need to SuspendAll, make sure all allocations are
   // done in the runnable state where suspension is expected.
   DCHECK_EQ(self->GetState(), kRunnable);
@@ -832,8 +845,8 @@
   return AllocateInternalWithGc(self, space, alloc_size, bytes_allocated);
 }
 
-mirror::Object* Heap::AllocateInternalWithGc(Thread* self, space::AllocSpace* space, size_t alloc_size,
-                                             size_t* bytes_allocated) {
+mirror::Object* Heap::AllocateInternalWithGc(Thread* self, space::AllocSpace* space,
+                                             size_t alloc_size, size_t* bytes_allocated) {
   mirror::Object* ptr;
 
   // The allocation failed. If the GC is running, block until it completes, and then retry the
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 72e6e43..cda252e 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -99,20 +99,20 @@
   kVerifyAllFast,  // Sanity check all heap accesses with quick(er) tests.
   kVerifyAll  // Sanity check all heap accesses.
 };
-const HeapVerificationMode kDesiredHeapVerification = kNoHeapVerification;
+static constexpr HeapVerificationMode kDesiredHeapVerification = kNoHeapVerification;
 
 class Heap {
  public:
-  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;
+  static constexpr size_t kDefaultInitialSize = 2 * MB;
+  static constexpr size_t kDefaultMaximumSize = 32 * MB;
+  static constexpr size_t kDefaultMaxFree = 2 * MB;
+  static constexpr size_t kDefaultMinFree = kDefaultMaxFree / 4;
 
   // Default target utilization.
-  static const double kDefaultTargetUtilization;
+  static constexpr double kDefaultTargetUtilization = 0.5;
 
   // Used so that we don't overflow the allocation time atomic integer.
-  static const size_t kTimeAdjust = 1024;
+  static constexpr size_t kTimeAdjust = 1024;
 
   // Create a heap with the requested sizes. The possible empty
   // image_file_names names specify Spaces to load based on
@@ -434,7 +434,7 @@
       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool IsOutOfMemoryOnAllocation(size_t alloc_size);
+  bool IsOutOfMemoryOnAllocation(size_t alloc_size, bool grow);
 
   // Pushes a list of cleared references out to the managed heap.
   void EnqueueClearedReferences(mirror::Object** cleared_references);
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index f7fdcfb..39d30bb2 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -23,7 +23,7 @@
 
 namespace art {
 
-static const bool kMeasureWaitTime = false;
+static constexpr bool kMeasureWaitTime = false;
 
 ThreadPoolWorker::ThreadPoolWorker(ThreadPool* thread_pool, const std::string& name,
                                    size_t stack_size)
diff --git a/runtime/utils.h b/runtime/utils.h
index bd81114..fcbb992 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -289,12 +289,12 @@
 uint64_t ThreadCpuNanoTime();
 
 // Converts the given number of nanoseconds to milliseconds.
-static inline uint64_t NsToMs(uint64_t ns) {
+static constexpr inline uint64_t NsToMs(uint64_t ns) {
   return ns / 1000 / 1000;
 }
 
 // Converts the given number of milliseconds to nanoseconds
-static inline uint64_t MsToNs(uint64_t ns) {
+static constexpr inline uint64_t MsToNs(uint64_t ns) {
   return ns * 1000 * 1000;
 }