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/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index 8bc1ced..314f3c5 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -70,37 +70,29 @@
 
 class ModUnionUpdateObjectReferencesVisitor {
  public:
-  ModUnionUpdateObjectReferencesVisitor(MarkObjectCallback* callback, void* arg)
+  ModUnionUpdateObjectReferencesVisitor(MarkHeapReferenceCallback* callback, void* arg)
     : callback_(callback),
       arg_(arg) {
   }
 
   // Extra parameters are required since we use this same visitor signature for checking objects.
-  void operator()(Object* obj, Object* ref, const MemberOffset& offset,
-                  bool /* is_static */) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void operator()(Object* obj, MemberOffset offset, bool /* static */) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Only add the reference if it is non null and fits our criteria.
-    if (ref != nullptr) {
-      Object* new_ref = callback_(ref, arg_);
-      if (new_ref != ref) {
-        // Use SetFieldObjectWithoutWriteBarrier to avoid card mark as an optimization which
-        // reduces dirtied pages and improves performance.
-        if (Runtime::Current()->IsActiveTransaction()) {
-          obj->SetFieldObjectWithoutWriteBarrier<true>(offset, new_ref, true);
-        } else {
-          obj->SetFieldObjectWithoutWriteBarrier<false>(offset, new_ref, true);
-        }
-      }
+    mirror::HeapReference<Object>* obj_ptr = obj->GetFieldObjectReferenceAddr(offset);
+    if (obj_ptr->AsMirrorPtr() != nullptr) {
+      callback_(obj_ptr, arg_);
     }
   }
 
  private:
-  MarkObjectCallback* const callback_;
+  MarkHeapReferenceCallback* const callback_;
   void* arg_;
 };
 
 class ModUnionScanImageRootVisitor {
  public:
-  ModUnionScanImageRootVisitor(MarkObjectCallback* callback, void* arg)
+  ModUnionScanImageRootVisitor(MarkHeapReferenceCallback* callback, void* arg)
       : callback_(callback), arg_(arg) {}
 
   void operator()(Object* root) const
@@ -108,11 +100,11 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(root != NULL);
     ModUnionUpdateObjectReferencesVisitor ref_visitor(callback_, arg_);
-    collector::MarkSweep::VisitObjectReferences<kMovingClasses>(root, ref_visitor);
+    root->VisitReferences<kMovingClasses>(ref_visitor);
   }
 
  private:
-  MarkObjectCallback* const callback_;
+  MarkHeapReferenceCallback* const callback_;
   void* const arg_;
 };
 
@@ -131,12 +123,14 @@
   }
 
   // Extra parameters are required since we use this same visitor signature for checking objects.
-  void operator()(Object* obj, Object* ref, const MemberOffset& offset,
-                  bool /* is_static */) const {
+  void operator()(Object* obj, MemberOffset offset, bool /* static */) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    mirror::HeapReference<Object>* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
+    mirror::Object* ref = ref_ptr->AsMirrorPtr();
     // Only add the reference if it is non null and fits our criteria.
-    if (ref != nullptr && mod_union_table_->AddReference(obj, ref)) {
+    if (ref  != nullptr && mod_union_table_->AddReference(obj, ref)) {
       // Push the adddress of the reference.
-      references_->push_back(obj->GetFieldObjectReferenceAddr(offset));
+      references_->push_back(ref_ptr);
     }
   }
 
@@ -155,11 +149,10 @@
 
   void operator()(Object* obj) const
       SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-    DCHECK(obj != NULL);
     // We don't have an early exit since we use the visitor pattern, an early
     // exit should significantly speed this up.
     AddToReferenceArrayVisitor visitor(mod_union_table_, references_);
-    collector::MarkSweep::VisitObjectReferences<kMovingClasses>(obj, visitor);
+    obj->VisitReferences<kMovingClasses>(visitor);
   }
  private:
   ModUnionTableReferenceCache* const mod_union_table_;
@@ -175,20 +168,22 @@
   }
 
   // Extra parameters are required since we use this same visitor signature for checking objects.
-  void operator()(Object* obj, Object* ref,
-                  const MemberOffset& /* offset */, bool /* is_static */) const
+  void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const
       SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
-    Heap* heap = mod_union_table_->GetHeap();
-    if (ref != NULL && mod_union_table_->AddReference(obj, ref) &&
+    mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset, false);
+    if (ref != nullptr && mod_union_table_->AddReference(obj, ref) &&
         references_.find(ref) == references_.end()) {
+      Heap* heap = mod_union_table_->GetHeap();
       space::ContinuousSpace* from_space = heap->FindContinuousSpaceFromObject(obj, false);
       space::ContinuousSpace* to_space = heap->FindContinuousSpaceFromObject(ref, false);
-      LOG(INFO) << "Object " << reinterpret_cast<const void*>(obj) << "(" << PrettyTypeOf(obj) << ")"
-                << "References " << reinterpret_cast<const void*>(ref)
-                << "(" << PrettyTypeOf(ref) << ") without being in mod-union table";
-      LOG(INFO) << "FromSpace " << from_space->GetName() << " type " << from_space->GetGcRetentionPolicy();
-      LOG(INFO) << "ToSpace " << to_space->GetName() << " type " << to_space->GetGcRetentionPolicy();
-      mod_union_table_->GetHeap()->DumpSpaces();
+      LOG(INFO) << "Object " << reinterpret_cast<const void*>(obj) << "(" << PrettyTypeOf(obj)
+          << ")" << "References " << reinterpret_cast<const void*>(ref) << "(" << PrettyTypeOf(ref)
+          << ") without being in mod-union table";
+      LOG(INFO) << "FromSpace " << from_space->GetName() << " type "
+          << from_space->GetGcRetentionPolicy();
+      LOG(INFO) << "ToSpace " << to_space->GetName() << " type "
+          << to_space->GetGcRetentionPolicy();
+      heap->DumpSpaces();
       LOG(FATAL) << "FATAL ERROR";
     }
   }
@@ -208,9 +203,8 @@
 
   void operator()(Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
     Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
-    DCHECK(obj != NULL);
     CheckReferenceVisitor visitor(mod_union_table_, references_);
-    collector::MarkSweep::VisitObjectReferences<kMovingClasses>(obj, visitor);
+    obj->VisitReferences<kMovingClasses>(visitor);
   }
 
  private:
@@ -264,7 +258,7 @@
   }
 }
 
-void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkObjectCallback* callback,
+void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
                                                           void* arg) {
   Heap* heap = GetHeap();
   CardTable* card_table = heap->GetCardTable();
@@ -298,14 +292,7 @@
   size_t count = 0;
   for (const auto& ref : references_) {
     for (mirror::HeapReference<Object>* obj_ptr : ref.second) {
-      Object* obj = obj_ptr->AsMirrorPtr();
-      if (obj != nullptr) {
-        Object* new_obj = callback(obj, arg);
-        // Avoid dirtying pages in the image unless necessary.
-        if (new_obj != obj) {
-          obj_ptr->Assign(new_obj);
-        }
-      }
+      callback(obj_ptr, arg);
     }
     count += ref.second.size();
   }
@@ -322,7 +309,8 @@
 }
 
 // Mark all references to the alloc space(s).
-void ModUnionTableCardCache::UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg) {
+void ModUnionTableCardCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
+                                                     void* arg) {
   CardTable* card_table = heap_->GetCardTable();
   ModUnionScanImageRootVisitor scan_visitor(callback, arg);
   SpaceBitmap* bitmap = space_->GetLiveBitmap();
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index 2e22a11..c4b020b 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -69,7 +69,7 @@
   // Update the mod-union table using data stored by ClearCards. There may be multiple ClearCards
   // before a call to update, for example, back-to-back sticky GCs. Also mark references to other
   // spaces which are stored in the mod-union table.
-  virtual void UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg) = 0;
+  virtual void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback, void* arg) = 0;
 
   // Verification, sanity checks that we don't have clean cards which conflict with out cached data
   // for said cards. Exclusive lock is required since verify sometimes uses
@@ -106,7 +106,7 @@
   void ClearCards();
 
   // Update table based on cleared cards and mark all references to the other spaces.
-  void UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg)
+  void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
 
@@ -142,7 +142,7 @@
   void ClearCards();
 
   // Mark all references to the alloc space(s).
-  void UpdateAndMarkReferences(MarkObjectCallback* callback, void* arg)
+  void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback, void* arg)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index a832615..afa5054 100644
--- a/runtime/gc/accounting/remembered_set.cc
+++ b/runtime/gc/accounting/remembered_set.cc
@@ -60,28 +60,24 @@
 
 class RememberedSetReferenceVisitor {
  public:
-  RememberedSetReferenceVisitor(MarkObjectCallback* callback, space::ContinuousSpace* target_space,
+  RememberedSetReferenceVisitor(MarkHeapReferenceCallback* callback,
+                                space::ContinuousSpace* target_space,
                                 bool* const contains_reference_to_target_space, void* arg)
       : callback_(callback), target_space_(target_space), arg_(arg),
         contains_reference_to_target_space_(contains_reference_to_target_space) {}
 
-  void operator()(mirror::Object* obj, mirror::Object* ref,
-                  const MemberOffset& offset, bool /* is_static */) const
+  void operator()(mirror::Object* obj, MemberOffset offset, bool /* is_static */) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (ref != nullptr) {
-      if (target_space_->HasAddress(ref)) {
-        *contains_reference_to_target_space_ = true;
-        mirror::Object* new_ref = callback_(ref, arg_);
-        DCHECK(!target_space_->HasAddress(new_ref));
-        if (new_ref != ref) {
-          obj->SetFieldObjectWithoutWriteBarrier<false>(offset, new_ref, false);
-        }
-      }
+    mirror::HeapReference<mirror::Object>* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
+    if (target_space_->HasAddress(ref_ptr->AsMirrorPtr())) {
+      *contains_reference_to_target_space_ = true;
+      callback_(ref_ptr, arg_);
+      DCHECK(!target_space_->HasAddress(ref_ptr->AsMirrorPtr()));
     }
   }
 
  private:
-  MarkObjectCallback* const callback_;
+  MarkHeapReferenceCallback* const callback_;
   space::ContinuousSpace* const target_space_;
   void* const arg_;
   bool* const contains_reference_to_target_space_;
@@ -89,27 +85,27 @@
 
 class RememberedSetObjectVisitor {
  public:
-  RememberedSetObjectVisitor(MarkObjectCallback* callback, space::ContinuousSpace* target_space,
+  RememberedSetObjectVisitor(MarkHeapReferenceCallback* callback,
+                             space::ContinuousSpace* target_space,
                              bool* const contains_reference_to_target_space, void* arg)
       : callback_(callback), target_space_(target_space), arg_(arg),
         contains_reference_to_target_space_(contains_reference_to_target_space) {}
 
   void operator()(mirror::Object* obj) const EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(obj != NULL);
     RememberedSetReferenceVisitor ref_visitor(callback_, target_space_,
                                               contains_reference_to_target_space_, arg_);
-    collector::MarkSweep::VisitObjectReferences<kMovingClasses>(obj, ref_visitor);
+    obj->VisitReferences<kMovingClasses>(ref_visitor);
   }
 
  private:
-  MarkObjectCallback* const callback_;
+  MarkHeapReferenceCallback* const callback_;
   space::ContinuousSpace* const target_space_;
   void* const arg_;
   bool* const contains_reference_to_target_space_;
 };
 
-void RememberedSet::UpdateAndMarkReferences(MarkObjectCallback* callback,
+void RememberedSet::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
                                             space::ContinuousSpace* target_space, void* arg) {
   CardTable* card_table = heap_->GetCardTable();
   bool contains_reference_to_target_space = false;
diff --git a/runtime/gc/accounting/remembered_set.h b/runtime/gc/accounting/remembered_set.h
index 92feeb1..4ed20dd 100644
--- a/runtime/gc/accounting/remembered_set.h
+++ b/runtime/gc/accounting/remembered_set.h
@@ -52,7 +52,7 @@
   void ClearCards();
 
   // Mark through all references to the target space.
-  void UpdateAndMarkReferences(MarkObjectCallback* callback,
+  void UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
                                space::ContinuousSpace* target_space, void* arg)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);