Clean up ArtField/ArtMethod relocation for app image.

Remove specialized code and use the same code as for
boot image relocation.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: I5d7cad217165ea0a6afefdc58981e0a1f7bffdcc
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 4aeb055..41808dd 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -348,15 +348,6 @@
   return Runtime::Current()->GetClassLinker()->ResolveString(field_id.name_idx_, this);
 }
 
-template <typename Visitor>
-inline void ArtField::UpdateObjects(const Visitor& visitor) {
-  ObjPtr<mirror::Class> old_class = DeclaringClassRoot().Read<kWithoutReadBarrier>();
-  ObjPtr<mirror::Class> new_class = visitor(old_class.Ptr());
-  if (old_class != new_class) {
-    SetDeclaringClass(new_class);
-  }
-}
-
 // If kExactOffset is true then we only find the matching offset, not the field containing the
 // offset.
 template <bool kExactOffset>
diff --git a/runtime/art_field.h b/runtime/art_field.h
index 6967e49..e44517e 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -225,11 +225,6 @@
   std::string PrettyField(bool with_type = true)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Update the declaring class with the passed in visitor. Does not use read barrier.
-  template <typename Visitor>
-  ALWAYS_INLINE void UpdateObjects(const Visitor& visitor)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   bool IsProxyField() REQUIRES_SHARED(Locks::mutator_lock_);
 
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 2670f91..c25bd00 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -382,15 +382,6 @@
 }
 
 template <typename Visitor>
-inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor) {
-  ObjPtr<mirror::Class> old_class = GetDeclaringClassUnchecked<kWithoutReadBarrier>();
-  ObjPtr<mirror::Class> new_class = visitor(old_class.Ptr());
-  if (old_class != new_class) {
-    SetDeclaringClass(new_class);
-  }
-}
-
-template <typename Visitor>
 inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size) {
   if (IsNative()) {
     const void* old_native_code = GetEntryPointFromJniPtrSize(pointer_size);
diff --git a/runtime/art_method.h b/runtime/art_method.h
index c865433..e4c21f0 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -692,12 +692,6 @@
   std::string JniLongName()
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Update heap objects and non-entrypoint pointers by the passed in visitor for image relocation.
-  // Does not use read barrier.
-  template <typename Visitor>
-  ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Update entry points by passing them through the visitor.
   template <typename Visitor>
   ALWAYS_INLINE void UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 1cc7b53..689c9ab 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1309,7 +1309,7 @@
             method.SetEntryPointFromQuickCompiledCodePtrSize(new_code, kPointerSize);
           }
         } else {
-          method.UpdateObjectsForImageRelocation(forward_object);
+          patch_object_visitor.PatchGcRoot(&method.DeclaringClassRoot());
           method.UpdateEntrypoints(forward_code, kPointerSize);
         }
       }, target_base, kPointerSize);
@@ -1319,7 +1319,8 @@
         // Only touches objects in the app image, no need for mutator lock.
         TimingLogger::ScopedTiming timing("Fixup fields", &logger);
         image_header.VisitPackedArtFields([&](ArtField& field) NO_THREAD_SAFETY_ANALYSIS {
-          field.UpdateObjects(forward_object);
+          patch_object_visitor.template PatchGcRoot</*kMayBeNull=*/ false>(
+              &field.DeclaringClassRoot());
         }, target_base);
       }
       {