Each space has its own bitmap(s)

Each alloc space now has One mark+live bitmap. Each image space has only one live bitmap.

Change-Id: I2e919d1bd7d9f4d35d0e95ed83a58df6f754df6e
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 63801a1..1a7bc83 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -37,10 +37,9 @@
 namespace art {
 
 MarkSweep::MarkSweep(MarkStack* mark_stack)
-    : mark_stack_(mark_stack),
+    : current_mark_bitmap_(NULL),
+      mark_stack_(mark_stack),
       heap_(NULL),
-      mark_bitmap_(NULL),
-      live_bitmap_(NULL),
       finger_(NULL),
       condemned_(NULL),
       soft_reference_list_(NULL),
@@ -54,25 +53,40 @@
 
 void MarkSweep::Init() {
   heap_ = Runtime::Current()->GetHeap();
-  mark_bitmap_ = heap_->GetMarkBits();
-  live_bitmap_ = heap_->GetLiveBits();
   mark_stack_->Reset();
 
+  const Spaces& spaces = heap_->GetSpaces();
+  // TODO: C++0x auto
+  for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
+    if ((*cur)->IsAllocSpace()) {
+      current_mark_bitmap_ = (*cur)->GetMarkBitmap();
+      break;
+    }
+  }
   // TODO: if concurrent, enable card marking in compiler
-
   // TODO: check that the mark bitmap is entirely clear.
 }
 
 void MarkSweep::MarkObject0(const Object* obj, bool check_finger) {
   DCHECK(obj != NULL);
+
+  SpaceBitmap* space_bitmap = NULL;
+  // Try to take advantage of locality of references within a space, failing this find the space
+  // the hard way.
+  if (current_mark_bitmap_->HasAddress(obj)) {
+    space_bitmap = current_mark_bitmap_;
+  } else {
+    space_bitmap = heap_->GetMarkBitmap()->GetSpaceBitmap(obj);
+  }
+
   if (obj < condemned_) {
     DCHECK(IsMarked(obj));
     return;
   }
-  bool is_marked = mark_bitmap_->Test(obj);
+  bool is_marked = space_bitmap->Test(obj);
   // This object was not previously marked.
   if (!is_marked) {
-    mark_bitmap_->Set(obj);
+    space_bitmap->Set(obj);
     if (check_finger && obj < finger_) {
       // The object must be pushed on to the mark stack.
       mark_stack_->Push(obj);
@@ -115,9 +129,7 @@
   DCHECK(root != NULL);
   DCHECK(arg != NULL);
   MarkSweep* mark_sweep = reinterpret_cast<MarkSweep*>(arg);
-  // Sanity tests
-  DCHECK(mark_sweep->live_bitmap_->Test(root));
-  mark_sweep->MarkObject0(root, false);
+  // We do not need to mark since live == marked for image spaces.
   mark_sweep->ScanObject(root);
 }
 
@@ -146,7 +158,7 @@
   DCHECK(root != NULL);
   DCHECK(arg != NULL);
   MarkSweep* mark_sweep = reinterpret_cast<MarkSweep*>(arg);
-  DCHECK(mark_sweep->IsMarked(root));
+  DCHECK(mark_sweep->heap_->GetMarkBitmap()->Test(root));
   mark_sweep->CheckObject(root);
 }
 
@@ -158,7 +170,7 @@
     if (spaces[i]->IsImageSpace()) {
       byte* begin = spaces[i]->Begin();
       byte* end = spaces[i]->End();
-      card_table->Scan(heap_->GetLiveBits(), begin, end, ScanImageRootVisitor, this);
+      card_table->Scan(spaces[i]->GetLiveBitmap(), begin, end, ScanImageRootVisitor, this);
     }
   }
 }
@@ -191,16 +203,8 @@
   for (size_t i = 0; i < spaces.size(); ++i) {
     byte* begin = spaces[i]->Begin();
     byte* end = spaces[i]->End();
-    // Normally, we only need to scan the black dirty objects
-    // But for image spaces, the roots will not be black objects.
-    // To address this we just scan the live bits instead of the mark bits.
-    if (spaces[i]->IsImageSpace()) {
-      // Image roots may not be marked so we may need to mark them.
-      // TODO: optimize this by offsetting some of the work to init.
-      card_table->Scan(heap_->GetLiveBits(), begin, end, ScanImageRootVisitor, this);
-    } else {
-      card_table->Scan(heap_->GetMarkBits(), begin, end, ScanDirtyCardCallback, this);
-    }
+    // Image spaces are handled properly since live == marked for them.
+    card_table->Scan(spaces[i]->GetMarkBitmap(), begin, end, ScanImageRootVisitor, this);
   }
 }
 
@@ -215,7 +219,9 @@
     if (spaces[i]->IsImageSpace()) {
       uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
       uintptr_t end = reinterpret_cast<uintptr_t>(spaces[i]->End());
-      live_bitmap_->ScanWalk(begin, end, &MarkSweep::CheckBitmapCallback, arg);
+      SpaceBitmap* live_bitmap = spaces[i]->GetLiveBitmap();
+      DCHECK(live_bitmap != NULL);
+      live_bitmap->ScanWalk(begin, end, CheckBitmapCallback, arg);
     }
   }
   finger_ = reinterpret_cast<Object*>(~0);
@@ -236,10 +242,11 @@
   void* arg = reinterpret_cast<void*>(this);
   const std::vector<Space*>& spaces = heap_->GetSpaces();
   for (size_t i = 0; i < spaces.size(); ++i) {
-    if (!spaces[i]->IsImageSpace()) {
+    if (spaces[i]->IsAllocSpace()) {
       uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
       uintptr_t end = reinterpret_cast<uintptr_t>(spaces[i]->End());
-      mark_bitmap_->ScanWalk(begin, end, &MarkSweep::ScanBitmapCallback, arg);
+      current_mark_bitmap_ = spaces[i]->GetMarkBitmap();
+      current_mark_bitmap_->ScanWalk(begin, end, &ScanBitmapCallback, arg);
     }
   }
   finger_ = reinterpret_cast<Object*>(~0);
@@ -263,7 +270,7 @@
   typedef IndirectReferenceTable::iterator It; // TODO: C++0x auto
   for (It it = table->begin(), end = table->end(); it != end; ++it) {
     const Object** entry = *it;
-    if (!IsMarked(*entry)) {
+    if (!heap_->GetMarkBitmap()->Test(*entry)) {
       *entry = kClearedJniWeakGlobal;
     }
   }
@@ -296,7 +303,7 @@
     for (size_t i = 0; i < num_ptrs; ++i) {
       Object* obj = static_cast<Object*>(ptrs[i]);
       freed_bytes += space->AllocationSize(obj);
-      heap->GetLiveBits()->Clear(obj);
+      heap->GetLiveBitmap()->Clear(obj);
     }
     // AllocSpace::FreeList clears the value in ptrs, so perform after clearing the live bit
     space->FreeList(num_ptrs, ptrs);
@@ -304,7 +311,7 @@
     for (size_t i = 0; i < num_ptrs; ++i) {
       Object* obj = static_cast<Object*>(ptrs[i]);
       freed_bytes += space->AllocationSize(obj);
-      heap->GetLiveBits()->Clear(obj);
+      heap->GetLiveBitmap()->Clear(obj);
       space->Free(obj);
     }
   }
@@ -325,7 +332,9 @@
       uintptr_t begin = reinterpret_cast<uintptr_t>(spaces[i]->Begin());
       uintptr_t end = reinterpret_cast<uintptr_t>(spaces[i]->End());
       scc.space = spaces[i]->AsAllocSpace();
-      HeapBitmap::SweepWalk(*live_bitmap_, *mark_bitmap_, begin, end,
+      SpaceBitmap* live_bitmap = scc.space->GetLiveBitmap();
+      SpaceBitmap* mark_bitmap = scc.space->GetMarkBitmap();
+      SpaceBitmap::SweepWalk(*live_bitmap, *mark_bitmap, begin, end,
                             &MarkSweep::SweepCallback, reinterpret_cast<void*>(&scc));
     }
   }
@@ -379,43 +388,46 @@
 }
 
 void MarkSweep::CheckReference(const Object* obj, const Object* ref, MemberOffset offset, bool is_static) {
-  AllocSpace* alloc_space = heap_->GetAllocSpace();
-  if (alloc_space->Contains(ref)) {
-    DCHECK(IsMarked(obj));
+  const Spaces& spaces = heap_->GetSpaces();
+  // TODO: C++0x auto
+  for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
+    if ((*cur)->IsAllocSpace() && (*cur)->Contains(ref)) {
+      DCHECK(IsMarked(obj));
 
-    bool is_marked = mark_bitmap_->Test(ref);
+      bool is_marked = IsMarked(ref);
+      if (!is_marked) {
+        LOG(INFO) << **cur;
+        LOG(WARNING) << (is_static ? "Static ref'" : "Instance ref'") << PrettyTypeOf(ref)
+                     << "' (" << reinterpret_cast<const void*>(ref) << ") in '" << PrettyTypeOf(obj)
+                     << "' (" << reinterpret_cast<const void*>(obj) << ") at offset "
+                     << reinterpret_cast<void*>(offset.Int32Value()) << " wasn't marked";
 
-    if (!is_marked) {
-      LOG(INFO) << *alloc_space;
-      LOG(WARNING) << (is_static ? "Static ref'" : "Instance ref'") << PrettyTypeOf(ref)
-                   << "' (" << reinterpret_cast<const void*>(ref) << ") in '" << PrettyTypeOf(obj)
-                   << "' (" << reinterpret_cast<const void*>(obj) << ") at offset "
-                   << reinterpret_cast<void*>(offset.Int32Value()) << " wasn't marked";
+        const Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+        DCHECK(klass != NULL);
+        const ObjectArray<Field>* fields = is_static ? klass->GetSFields() : klass->GetIFields();
+        DCHECK(fields != NULL);
+        bool found = false;
+        for (int32_t i = 0; i < fields->GetLength(); ++i) {
+          const Field* cur = fields->Get(i);
+          if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
+            LOG(WARNING) << "Field referencing the alloc space was " << PrettyField(cur);
+            found = true;
+            break;
+          }
+        }
+        if (!found) {
+          LOG(WARNING) << "Could not find field in object alloc space with offset " << offset.Int32Value();
+        }
 
-      const Class* klass = is_static ? obj->AsClass() : obj->GetClass();
-      DCHECK(klass != NULL);
-      const ObjectArray<Field>* fields = is_static ? klass->GetSFields() : klass->GetIFields();
-      DCHECK(fields != NULL);
-      bool found = false;
-      for (int32_t i = 0; i < fields->GetLength(); ++i) {
-        const Field* cur = fields->Get(i);
-        if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
-          LOG(WARNING) << "Field referencing the alloc space was " << PrettyField(cur);
-          found = true;
-          break;
+        bool obj_marked = heap_->GetCardTable()->IsDirty(obj);
+        if (!obj_marked) {
+          LOG(WARNING) << "Object '" << PrettyTypeOf(obj) << "' "
+                       << "(" << reinterpret_cast<const void*>(obj) << ") contains references to "
+                       << "the alloc space, but wasn't card marked";
         }
       }
-      if (!found) {
-        LOG(WARNING) << "Could not find field in object alloc space with offset " << offset.Int32Value();
-      }
-
-      bool obj_marked = heap_->GetCardTable()->IsDirty(obj);
-      if (!obj_marked) {
-        LOG(WARNING) << "Object '" << PrettyTypeOf(obj) << "' "
-                     << "(" << reinterpret_cast<const void*>(obj) << ") contains references to "
-                     << "the alloc space, but wasn't card marked";
-      }
     }
+    break;
   }
 }
 
@@ -489,7 +501,7 @@
 inline void MarkSweep::ScanObject(const Object* obj) {
   DCHECK(obj != NULL);
   DCHECK(obj->GetClass() != NULL);
-  DCHECK(IsMarked(obj));
+  DCHECK(heap_->GetMarkBitmap()->Test(obj));
   if (obj->IsClass()) {
     ScanClass(obj);
   } else if (obj->IsArrayInstance()) {
@@ -501,12 +513,9 @@
 
 // Scan anything that's on the mark stack.
 void MarkSweep::ProcessMarkStack() {
-  Space* alloc_space = heap_->GetAllocSpace();
   while (!mark_stack_->IsEmpty()) {
     const Object* obj = mark_stack_->Pop();
-    if (alloc_space->Contains(obj)) {
-      ScanObject(obj);
-    }
+    ScanObject(obj);
   }
 }
 
@@ -634,7 +643,14 @@
 #ifndef NDEBUG
   VLOG(heap) << "MarkSweep scanned classes=" << class_count_ << " arrays=" << array_count_ << " other=" << other_count_;
 #endif
-  mark_bitmap_->Clear();
+  // Clear all of the alloc spaces' mark bitmaps.
+  const Spaces& spaces = heap_->GetSpaces();
+  // TODO: C++0x auto
+  for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
+    if ((*cur)->IsAllocSpace()) {
+      (*cur)->GetMarkBitmap()->Clear();
+    }
+  }
   mark_stack_->Reset();
 }