Refactor object reference visiting logic.

Refactored the reference visiting logic to be in mirror::Object
instead of MarkSweep.

Change-Id: I773249478dc463d83b465e85c2402320488577c0
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index f73a50f..1cb2adb 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -22,137 +22,30 @@
 #include "gc/heap.h"
 #include "mirror/art_field.h"
 #include "mirror/class.h"
-#include "mirror/object_array.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/reference.h"
 
 namespace art {
 namespace gc {
 namespace collector {
 
-template <typename MarkVisitor>
-inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor) {
+template<typename MarkVisitor, typename ReferenceVisitor>
+inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor,
+                                       const ReferenceVisitor& ref_visitor) {
   if (kIsDebugBuild && !IsMarked(obj)) {
     heap_->DumpSpaces();
     LOG(FATAL) << "Scanning unmarked object " << obj;
   }
-  // The GetClass verifies the object, don't need to reverify after.
-  mirror::Class* klass = obj->GetClass();
-  // IsArrayClass verifies klass.
-  if (UNLIKELY(klass->IsArrayClass())) {
-    if (kCountScannedTypes) {
-      ++array_count_;
-    }
-    if (klass->IsObjectArrayClass<kVerifyNone>()) {
-      VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object, kVerifyNone>(), visitor);
-    }
-  } else if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
-    if (kCountScannedTypes) {
+  obj->VisitReferences<false>(visitor, ref_visitor);
+  if (kCountScannedTypes) {
+    mirror::Class* klass = obj->GetClass<kVerifyNone>();
+    if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
       ++class_count_;
-    }
-    VisitClassReferences<false>(klass, obj, visitor);
-  } else {
-    if (kCountScannedTypes) {
+    } else if (UNLIKELY(klass->IsArrayClass<kVerifyNone>())) {
+      ++array_count_;
+    } else {
       ++other_count_;
     }
-    VisitInstanceFieldsReferences<false>(klass, obj, visitor);
-    if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
-      DelayReferenceReferent(klass, obj);
-    }
-  }
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitObjectReferences(mirror::Object* obj, const Visitor& visitor)
-    SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_,
-                          Locks::mutator_lock_) {
-  mirror::Class* klass = obj->GetClass();
-  if (klass->IsArrayClass()) {
-    if (kVisitClass) {
-      visitor(obj, klass, mirror::Object::ClassOffset(), false);
-    }
-    if (klass->IsObjectArrayClass<kVerifyNone>()) {
-      VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object, kVerifyNone>(), visitor);
-    }
-  } else if (klass == mirror::Class::GetJavaLangClass()) {
-    DCHECK_EQ(klass->GetClass<kVerifyNone>(), mirror::Class::GetJavaLangClass());
-    VisitClassReferences<kVisitClass>(klass, obj, visitor);
-  } else {
-    VisitInstanceFieldsReferences<kVisitClass>(klass, obj, visitor);
-  }
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitInstanceFieldsReferences(mirror::Class* klass,
-                                                     mirror::Object* obj, const Visitor& visitor)
-    SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-  VisitFieldsReferences<kVisitClass>(obj, klass->GetReferenceInstanceOffsets<kVerifyNone>(), false,
-                                     visitor);
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitClassReferences(mirror::Class* klass, mirror::Object* obj,
-                                            const Visitor& visitor)
-    SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-  VisitInstanceFieldsReferences<kVisitClass>(klass, obj, visitor);
-  VisitStaticFieldsReferences<kVisitClass>(obj->AsClass<kVerifyNone>(), visitor);
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor)
-    SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-  VisitFieldsReferences<kVisitClass>(klass, klass->GetReferenceStaticOffsets<kVerifyNone>(), true,
-                                     visitor);
-}
-
-template <bool kVisitClass, typename Visitor>
-inline void MarkSweep::VisitFieldsReferences(mirror::Object* obj, uint32_t ref_offsets,
-                                             bool is_static, const Visitor& visitor) {
-  if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
-    if (!kVisitClass) {
-      // Currently the class bit is always set in the word. Since we count leading zeros to find
-      // the offset and the class bit is at offset 0, it means that the highest bit is the class
-      // bit. We can quickly clear this using xor.
-      ref_offsets ^= kWordHighBitMask;
-      DCHECK_EQ(mirror::Object::ClassOffset().Uint32Value(), 0U);
-    }
-    // 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);
-      mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyReads>(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 (mirror::Class* klass = is_static ? obj->AsClass<kVerifyNone>() : obj->GetClass<kVerifyNone>();
-         klass != nullptr;
-         klass = is_static ? nullptr : klass->GetSuperClass()) {
-      size_t num_reference_fields = (is_static
-                                     ? klass->NumReferenceStaticFields()
-                                     : klass->NumReferenceInstanceFields());
-      for (size_t i = 0; i < num_reference_fields; ++i) {
-        mirror::ArtField* field = (is_static ? klass->GetStaticField(i)
-                                             : klass->GetInstanceField(i));
-        MemberOffset field_offset = field->GetOffset();
-        mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyReads>(field_offset, false);
-        visitor(obj, ref, field_offset, is_static);
-      }
-    }
-  }
-}
-
-template <typename Visitor>
-inline void MarkSweep::VisitObjectArrayReferences(mirror::ObjectArray<mirror::Object>* array,
-                                                  const Visitor& visitor) {
-  const size_t length = static_cast<size_t>(array->GetLength());
-  for (size_t i = 0; i < length; ++i) {
-    mirror::Object* element = array->GetWithoutChecks(static_cast<int32_t>(i));
-    const size_t width = sizeof(mirror::HeapReference<mirror::Object>);
-    MemberOffset offset(i * width + mirror::Array::DataOffset(width).Int32Value());
-    visitor(array, element, offset, false);
   }
 }