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/mirror/class-inl.h b/runtime/mirror/class-inl.h
index e3f4eed..89d9241 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -465,6 +465,12 @@
   return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator());
 }
 
+template <bool kVisitClass, typename Visitor>
+inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
+  VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+  VisitStaticFieldsReferences<kVisitClass>(this, visitor);
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 76ab94c..ddc07ff 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -861,6 +861,10 @@
   // When class is verified, set the kAccPreverified flag on each method.
   void SetPreverifiedFlagOnAllMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template <bool kVisitClass, typename Visitor>
+  void VisitReferences(mirror::Class* klass, const Visitor& visitor)
+      NO_THREAD_SAFETY_ANALYSIS;
+
  private:
   void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index cad1017..281d4ec 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -557,6 +557,77 @@
   return success;
 }
 
+template<bool kVisitClass, bool kIsStatic, typename Visitor>
+inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
+  if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
+    if (!kVisitClass) {
+     // Mask out the class from the reference offsets.
+      ref_offsets ^= kWordHighBitMask;
+    }
+    DCHECK_EQ(ClassOffset().Uint32Value(), 0U);
+    // Found a reference offset bitmap. Visit the specified offsets.
+    while (ref_offsets != 0) {
+      size_t right_shift = CLZ(ref_offsets);
+      MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
+      visitor(this, field_offset, kIsStatic);
+      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 = kIsStatic ? AsClass() : GetClass(); klass != nullptr;
+        klass = kIsStatic ? nullptr : klass->GetSuperClass()) {
+      size_t num_reference_fields =
+          kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
+      for (size_t i = 0; i < num_reference_fields; ++i) {
+        mirror::ArtField* field = kIsStatic ? klass->GetStaticField(i)
+            : klass->GetInstanceField(i);
+        MemberOffset field_offset = field->GetOffset();
+        // TODO: Do a simpler check?
+        if (!kVisitClass && UNLIKELY(field_offset.Uint32Value() == ClassOffset().Uint32Value())) {
+          continue;
+        }
+        visitor(this, field_offset, kIsStatic);
+      }
+    }
+  }
+}
+
+template<bool kVisitClass, typename Visitor>
+inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
+  VisitFieldsReferences<kVisitClass, false>(
+      klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
+}
+
+template<bool kVisitClass, typename Visitor>
+inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
+  klass->VisitFieldsReferences<kVisitClass, true>(
+      klass->GetReferenceStaticOffsets<kVerifyNone>(), visitor);
+}
+
+template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
+    typename JavaLangRefVisitor>
+inline void Object::VisitReferences(const Visitor& visitor,
+                                    const JavaLangRefVisitor& ref_visitor) {
+  mirror::Class* klass = GetClass<kVerifyFlags>();
+  if (UNLIKELY(klass == Class::GetJavaLangClass())) {
+    DCHECK_EQ(klass->GetClass(), Class::GetJavaLangClass());
+    AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
+  } else if (UNLIKELY(klass->IsArrayClass<kVerifyFlags>())) {
+    if (klass->IsObjectArrayClass<kVerifyNone>()) {
+      AsObjectArray<mirror::Object>()->VisitReferences<kVisitClass>(visitor);
+    } else if (kVisitClass) {
+      visitor(this, ClassOffset(), false);
+    }
+  } else {
+    VisitFieldsReferences<kVisitClass, false>(klass->GetReferenceInstanceOffsets(), visitor);
+    if (UNLIKELY(klass->IsReferenceClass())) {
+      ref_visitor(klass, AsReference());
+    }
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 476259f..0a77828 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -240,6 +240,14 @@
 #endif
   }
 
+  // TODO fix thread safety analysis broken by the use of template. This should be
+  // SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
+  template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+      typename Visitor, typename JavaLangRefVisitor = VoidFunctor>
+  void VisitReferences(const Visitor& visitor,
+                       const JavaLangRefVisitor& ref_visitor = VoidFunctor())
+      NO_THREAD_SAFETY_ANALYSIS;
+
  protected:
   // Accessors for non-Java type fields
   template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -251,6 +259,17 @@
 #endif
   }
 
+  // TODO: Fixme when anotatalysis works with visitors.
+  template<bool kVisitClass, bool kIsStatic, typename Visitor>
+  void VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor)
+      NO_THREAD_SAFETY_ANALYSIS;
+  template<bool kVisitClass, typename Visitor>
+  void VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<bool kVisitClass, typename Visitor>
+  void VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   // Verify the type correctness of stores to fields.
   void CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value)
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index a427957..8032cc3 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -233,6 +233,17 @@
                       (i * sizeof(HeapReference<Object>)));
 }
 
+template<class T> template<const bool kVisitClass, typename Visitor>
+void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
+  if (kVisitClass) {
+    visitor(this, ClassOffset(), false);
+  }
+  const size_t length = static_cast<size_t>(GetLength());
+  for (size_t i = 0; i < length; ++i) {
+    visitor(this, OffsetOfElement(i), false);
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 7f9e716..5ff0490 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -78,6 +78,11 @@
   ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // TODO fix thread safety analysis broken by the use of template. This should be
+  // SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
+  template<const bool kVisitClass, typename Visitor>
+  void VisitReferences(const Visitor& visitor) NO_THREAD_SAFETY_ANALYSIS;
+
  private:
   static MemberOffset OffsetOfElement(int32_t i);