Fix race with Heap::ClampGrowthLimit and GC

Aded logic for handling the temp bitmap if the GC is running and
the live bitmap is clamped to the mark bitmap. This fixes the SIGABRT
from ClampGrowthLimit if the GC clamped the bitmaps at this point.

Also added locking of the heap_bitmap_lock_ so that added a lock so
that the temp bitmap doesn't change from underneath us.

Bug: 20043461

Change-Id: Ib427e40bcdf149de0408b4b53e6524f51463f0af
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 7e967f9..be7344a 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3145,6 +3145,8 @@
 }
 
 void Heap::ClampGrowthLimit() {
+  // Use heap bitmap lock to guard against races with BindLiveToMarkBitmap.
+  WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
   capacity_ = growth_limit_;
   for (const auto& space : continuous_spaces_) {
     if (space->IsMallocSpace()) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 959ff18..603cbfd 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -309,7 +309,7 @@
 
   // Make the current growth limit the new maximum capacity, unmaps pages at the end of spaces
   // which will never be used. Used to implement dalvik.system.VMRuntime.clampGrowthLimit.
-  void ClampGrowthLimit();
+  void ClampGrowthLimit() LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
 
   // Target ideal heap utilization ratio, implements
   // dalvik.system.VMRuntime.getTargetHeapUtilization.
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index 67e8847..b09de6f 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -253,6 +253,10 @@
   CHECK_LE(new_capacity, NonGrowthLimitCapacity());
   GetLiveBitmap()->SetHeapSize(new_capacity);
   GetMarkBitmap()->SetHeapSize(new_capacity);
+  if (temp_bitmap_.get() != nullptr) {
+    // If the bitmaps are clamped, then the temp bitmap is actually the mark bitmap.
+    temp_bitmap_->SetHeapSize(new_capacity);
+  }
   GetMemMap()->SetSize(new_capacity);
   limit_ = Begin() + new_capacity;
   CHECK(temp_bitmap_.get() == nullptr);