Enable mod union table

Enable mod union table(bitmap). This change aims to reduce the second pause times by processing dirty image cards and cleaning them by storing their alloc space references in a bitmap. The bitmap is then scanned concurrently(if CMS) before recursive mark.

Reduces second pause time. Second pause time now typically < 5 ms instead of 30-40ms.

Change-Id: I831eeb8af7299d4e86cf2dd9c29d0b7e230cd387
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index 7b0272c..00fdcfb 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -20,12 +20,18 @@
 #include "macros.h"
 #include "mark_stack.h"
 #include "heap_bitmap.h"
+#include "object.h"
 #include "offsets.h"
 
 namespace art {
 
+class CheckObjectVisitor;
 class Class;
 class Heap;
+class MarkIfReachesAllocspaceVisitor;
+class ModUnionClearCardVisitor;
+class ModUnionVisitor;
+class ModUnionTableBitmap;
 class Object;
 
 class MarkSweep {
@@ -90,6 +96,8 @@
 
   static void ScanImageRootVisitor(Object* root, void* arg);
 
+  static void VerifyImageRootVisitor(Object* root, void* arg);
+
   static void ScanDirtyCardCallback(Object* obj, void* arg);
 
   // Marks an object.
@@ -102,6 +110,8 @@
 
   static void CheckBitmapCallback(Object* obj, void* finger, void* arg);
 
+  static void CheckBitmapNoFingerCallback(Object* obj, void* arg);
+
   static void SweepCallback(size_t num_ptrs, Object** ptrs, void* arg);
 
   void CheckReference(const Object* obj, const Object* ref, MemberOffset offset, bool is_static);
@@ -111,34 +121,107 @@
 
   void CheckObject(const Object* obj);
 
+  template <typename Visitor>
+  void VisitObjectReferences(const Object* obj, const Visitor& visitor) {
+    DCHECK(obj != NULL);
+    DCHECK(obj->GetClass() != NULL);
+    if (obj->IsClass()) {
+      VisitClassReferences(obj, visitor);
+    } else if (obj->IsArrayInstance()) {
+      VisitArrayReferences(obj, visitor);
+    } else {
+      VisitOtherReferences(obj, visitor);
+    }
+  }
+
   // Grays references in instance fields.
   void ScanInstanceFields(const Object* obj);
 
-  void CheckInstanceFields(const Object* obj);
+  template <typename Visitor>
+  void VisitInstanceFieldsReferences(const Object* obj, const Visitor& visitor) {
+    DCHECK(obj != NULL);
+    Class* klass = obj->GetClass();
+    DCHECK(klass != NULL);
+    VisitFieldsReferences(obj, klass->GetReferenceInstanceOffsets(), false, visitor);
+  }
 
   // Blackens a class object.
   void ScanClass(const Object* obj);
 
-  void CheckClass(const Object* obj);
+  template <typename Visitor>
+  void VisitClassReferences(const Object* obj, const Visitor& visitor) {
+    VisitInstanceFieldsReferences(obj, visitor);
+    VisitStaticFieldsReferences(obj->AsClass(), visitor);
+  }
 
   // Grays references in static fields.
   void ScanStaticFields(const Class* klass);
 
-  void CheckStaticFields(const Class* klass);
+  template <typename Visitor>
+  void VisitStaticFieldsReferences(const Class* klass, const Visitor& visitor) {
+    DCHECK(klass != NULL);
+    VisitFieldsReferences(klass, klass->GetReferenceStaticOffsets(), true, visitor);
+  }
 
   // Used by ScanInstanceFields and ScanStaticFields
   void ScanFields(const Object* obj, uint32_t ref_offsets, bool is_static);
 
-  void CheckFields(const Object* obj, uint32_t ref_offsets, bool is_static);
+  template <typename Visitor>
+  void VisitFieldsReferences(const Object* obj, uint32_t ref_offsets, bool is_static, const Visitor& visitor) {
+    if (ref_offsets != CLASS_WALK_SUPER) {
+      // Found a reference offset bitmap.  Mark the specified offsets.
+      while (ref_offsets != 0) {
+        size_t right_shift = CLZ(ref_offsets);
+        MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
+        const Object* ref = obj->GetFieldObject<const Object*>(field_offset, false);
+        visitor(obj, ref, field_offset, is_static);
+        ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
+      }
+    } else {
+      // There is no reference offset bitmap.  In the non-static case,
+      // walk up the class inheritance hierarchy and find reference
+      // offsets the hard way. In the static case, just consider this
+      // class.
+      for (const Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+           klass != NULL;
+           klass = is_static ? NULL : klass->GetSuperClass()) {
+        size_t num_reference_fields = (is_static
+                                       ? klass->NumReferenceStaticFields()
+                                       : klass->NumReferenceInstanceFields());
+        for (size_t i = 0; i < num_reference_fields; ++i) {
+          Field* field = (is_static
+                          ? klass->GetStaticField(i)
+                          : klass->GetInstanceField(i));
+          MemberOffset field_offset = field->GetOffset();
+          const Object* ref = obj->GetFieldObject<const Object*>(field_offset, false);
+          visitor(obj, ref, field_offset, is_static);
+        }
+      }
+    }
+  }
 
   // Grays references in an array.
   void ScanArray(const Object* obj);
 
-  void CheckArray(const Object* obj);
+  template <typename Visitor>
+  void VisitArrayReferences(const Object* obj, const Visitor& visitor) {
+    visitor(obj, obj->GetClass(), Object::ClassOffset(), false);
+    if (obj->IsObjectArray()) {
+      const ObjectArray<Object>* array = obj->AsObjectArray<Object>();
+      for (int32_t i = 0; i < array->GetLength(); ++i) {
+        const Object* element = array->GetWithoutChecks(i);
+        size_t width = sizeof(Object*);
+        visitor(obj, element, MemberOffset(i * width + Array::DataOffset(width).Int32Value()), false);
+      }
+    }
+  }
 
   void ScanOther(const Object* obj);
 
-  void CheckOther(const Object* obj);
+  template <typename Visitor>
+  void VisitOtherReferences(const Object* obj, const Visitor& visitor) {
+    return VisitInstanceFieldsReferences(obj, visitor);
+  }
 
   // Blackens objects grayed during a garbage collection.
   void ScanGrayObjects();
@@ -187,7 +270,12 @@
   size_t array_count_;
   size_t other_count_;
 
+  friend class CheckObjectVisitor;
   friend class InternTableEntryIsUnmarked;
+  friend class MarkIfReachesAllocspaceVisitor;
+  friend class ModUnionClearCardVisitor;
+  friend class ModUnionVisitor;
+  friend class ModUnionTableBitmap;
 
   DISALLOW_COPY_AND_ASSIGN(MarkSweep);
 };