Fix large object space overlapping map error

The free list version of the large object space was being occasionally mapped where the oat file
is supposed to be. We now map it after the alloc_space.

Added a padding word with checks to the alloc space if debug spaces is set to enabled.

Change-Id: I5e931e263798d33ca90d0f635d2042683be059d3
diff --git a/src/heap.cc b/src/heap.cc
index eafe272..fa044c2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -199,6 +199,12 @@
     }
   }
 
+  // Allocate the large object space (placed after the alloc space).
+  large_object_space_.reset(FreeListSpace::Create("large object space", requested_begin + capacity,
+                                                  capacity));
+  live_bitmap_->SetLargeObjects(large_object_space_->GetLiveObjects());
+  mark_bitmap_->SetLargeObjects(large_object_space_->GetMarkObjects());
+
   UniquePtr<AllocSpace> alloc_space(AllocSpace::Create("alloc space", initial_size, growth_limit,
                                                        capacity, requested_begin));
   alloc_space_ = alloc_space.release();
@@ -222,11 +228,6 @@
     }
   }
 
-  // Allocate the large object space.
-  large_object_space_.reset(FreeListSpace::Create("large object space", 64 * MB));
-  live_bitmap_->SetLargeObjects(large_object_space_->GetLiveObjects());
-  mark_bitmap_->SetLargeObjects(large_object_space_->GetMarkObjects());
-
   // Allocate the card table.
   card_table_.reset(CardTable::Create(heap_begin, heap_capacity));
   CHECK(card_table_.get() != NULL) << "Failed to create card table";
diff --git a/src/space.cc b/src/space.cc
index 74e719a..58476ad 100644
--- a/src/space.cc
+++ b/src/space.cc
@@ -29,10 +29,12 @@
 namespace art {
 
 #ifndef NDEBUG
-#define DEBUG_SPACES 1
+static const bool kDebugSpaces = true;
 #else
-#define DEBUG_SPACES 0
+static const bool kDebugSpaces = false;
 #endif
+// Magic padding value that we use to check for buffer overruns.
+static const word kPaddingValue = 0xBAC0BAC0;
 
 // TODO: Remove define macro
 #define CHECK_MEMORY_CALL(call, args, what) \
@@ -189,10 +191,17 @@
 }
 
 Object* AllocSpace::AllocWithoutGrowthLocked(size_t num_bytes) {
+  if (kDebugSpaces) {
+    num_bytes += sizeof(word);
+  }
+
   Object* result = reinterpret_cast<Object*>(mspace_calloc(mspace_, 1, num_bytes));
-  if (DEBUG_SPACES && result != NULL) {
+  if (kDebugSpaces && result != NULL) {
     CHECK(Contains(result)) << "Allocation (" << reinterpret_cast<void*>(result)
         << ") not in bounds of allocation space " << *this;
+    // Put a magic pattern before and after the allocation.
+    *reinterpret_cast<word*>(reinterpret_cast<byte*>(result) + AllocationSize(result)
+        - sizeof(word) - kChunkOverhead) = kPaddingValue;
   }
   num_bytes_allocated_ += AllocationSize(result);
   ++num_objects_allocated_;
@@ -216,7 +225,7 @@
   mspace_set_footprint_limit(mspace_, footprint);
   // Return the new allocation or NULL.
   Object* result = reinterpret_cast<Object*>(ptr);
-  CHECK(!DEBUG_SPACES || result == NULL || Contains(result));
+  CHECK(!kDebugSpaces || result == NULL || Contains(result));
   return result;
 }
 
@@ -277,9 +286,12 @@
 
 void AllocSpace::Free(Object* ptr) {
   MutexLock mu(lock_);
-  if (DEBUG_SPACES) {
+  if (kDebugSpaces) {
     CHECK(ptr != NULL);
     CHECK(Contains(ptr)) << "Free (" << ptr << ") not in bounds of heap " << *this;
+    CHECK_EQ(
+        *reinterpret_cast<word*>(reinterpret_cast<byte*>(ptr) + AllocationSize(ptr) -
+            sizeof(word) - kChunkOverhead), kPaddingValue);
   }
   num_bytes_allocated_ -= AllocationSize(ptr);
   --num_objects_allocated_;
@@ -288,7 +300,7 @@
 
 void AllocSpace::FreeList(size_t num_ptrs, Object** ptrs) {
   MutexLock mu(lock_);
-  if (DEBUG_SPACES) {
+  if (kDebugSpaces) {
     CHECK(ptrs != NULL);
     size_t num_broken_ptrs = 0;
     for (size_t i = 0; i < num_ptrs; i++) {
@@ -609,9 +621,10 @@
   return mem_maps_.find(const_cast<Object*>(obj)) != mem_maps_.end();
 }
 
-FreeListSpace* FreeListSpace::Create(const std::string& name, size_t size) {
+FreeListSpace* FreeListSpace::Create(const std::string& name, byte* requested_begin, size_t size) {
   CHECK(size % kAlignment == 0);
-  MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), NULL, size, PROT_READ | PROT_WRITE);
+  MemMap* mem_map = MemMap::MapAnonymous(name.c_str(), requested_begin, size,
+                                         PROT_READ | PROT_WRITE);
   CHECK(mem_map != NULL) << "Failed to allocate large object space mem map";
   return new FreeListSpace(name, mem_map, mem_map->Begin(), mem_map->End());
 }
diff --git a/src/space.h b/src/space.h
index 9f03904..12682f9 100644
--- a/src/space.h
+++ b/src/space.h
@@ -490,7 +490,7 @@
 class FreeListSpace : public LargeObjectSpace {
  public:
   virtual ~FreeListSpace();
-  static FreeListSpace* Create(const std::string& name, size_t capacity);
+  static FreeListSpace* Create(const std::string& name, byte* requested_begin, size_t capacity);
 
   virtual size_t AllocationSize(const Object* obj);
   virtual Object* Alloc(size_t num_bytes);