Always visit object class from VisitReferences

We don't want to unload classes which have instances.

Slight increase in CMS GC time from ~6.5s to ~7.3s on
EvaluateAndApplyChanges.

Bug: 22720414
Change-Id: I467ff9c9d55163d2a90b999aef3bdd7b3f648bac
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index fa4667e..fa25a17 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1109,7 +1109,7 @@
     // If it is not a DexCache, visit all references.
     mirror::Class* klass = object->GetClass();
     if (klass != dex_cache_class_) {
-      object->VisitReferences<false /* visit class */>(*this, *this);
+      object->VisitReferences(*this, *this);
     }
   }
 
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 3a3410c..93897aa 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -1350,7 +1350,7 @@
     }
   }
   FixupClassVisitor visitor(this, copy);
-  static_cast<mirror::Object*>(orig)->VisitReferences<true /*visit class*/>(visitor, visitor);
+  static_cast<mirror::Object*>(orig)->VisitReferences(visitor, visitor);
 }
 
 void ImageWriter::FixupObject(Object* orig, Object* copy) {
@@ -1397,7 +1397,7 @@
       down_cast<mirror::ClassLoader*>(copy)->SetClassTable(nullptr);
     }
     FixupVisitor visitor(this, copy);
-    orig->VisitReferences<true /*visit class*/>(visitor, visitor);
+    orig->VisitReferences(visitor, visitor);
   }
 }
 
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index d601035..a71197a 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -623,7 +623,7 @@
     }
   }
   PatchOat::PatchVisitor visitor(this, copy);
-  object->VisitReferences<true, kVerifyNone>(visitor, visitor);
+  object->VisitReferences<kVerifyNone>(visitor, visitor);
   if (object->IsClass<kVerifyNone>()) {
     auto* klass = object->AsClass();
     auto* copy_klass = down_cast<mirror::Class*>(copy);
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index dd9e2d1..5151819 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -153,7 +153,7 @@
     DCHECK(root != nullptr);
     ModUnionUpdateObjectReferencesVisitor ref_visitor(visitor_, from_space_, immune_space_,
                                                       contains_reference_to_other_space_);
-    root->VisitReferences<kMovingClasses>(ref_visitor, VoidFunctor());
+    root->VisitReferences(ref_visitor, VoidFunctor());
   }
 
  private:
@@ -237,7 +237,7 @@
                                        visitor_,
                                        references_,
                                        has_target_reference_);
-    obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
+    obj->VisitReferences(visitor, VoidFunctor());
   }
 
  private:
@@ -304,7 +304,7 @@
   void operator()(Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
     Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
     CheckReferenceVisitor visitor(mod_union_table_, references_);
-    obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
+    obj->VisitReferences(visitor, VoidFunctor());
   }
 
  private:
diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc
index b9f24f3..277d319 100644
--- a/runtime/gc/accounting/remembered_set.cc
+++ b/runtime/gc/accounting/remembered_set.cc
@@ -120,7 +120,7 @@
       SHARED_REQUIRES(Locks::mutator_lock_) {
     RememberedSetReferenceVisitor visitor(target_space_, contains_reference_to_target_space_,
                                           collector_);
-    obj->VisitReferences<kMovingClasses>(visitor, visitor);
+    obj->VisitReferences(visitor, visitor);
   }
 
  private:
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 220c06e..263e678 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -683,7 +683,7 @@
     space::RegionSpace* region_space = collector->RegionSpace();
     CHECK(!region_space->IsInFromSpace(obj)) << "Scanning object " << obj << " in from space";
     ConcurrentCopyingVerifyNoFromSpaceRefsFieldVisitor visitor(collector);
-    obj->VisitReferences<true>(visitor, visitor);
+    obj->VisitReferences(visitor, visitor);
     if (kUseBakerReadBarrier) {
       if (collector->RegionSpace()->IsInToSpace(obj)) {
         CHECK(obj->GetReadBarrierPointer() == nullptr)
@@ -808,7 +808,7 @@
     CHECK(!region_space->IsInFromSpace(obj)) << "Scanning object " << obj << " in from space";
     collector->AssertToSpaceInvariant(nullptr, MemberOffset(0), obj);
     ConcurrentCopyingAssertToSpaceInvariantFieldVisitor visitor(collector);
-    obj->VisitReferences<true>(visitor, visitor);
+    obj->VisitReferences(visitor, visitor);
   }
 
  private:
@@ -1546,7 +1546,7 @@
 void ConcurrentCopying::Scan(mirror::Object* to_ref) {
   DCHECK(!region_space_->IsInFromSpace(to_ref));
   ConcurrentCopyingRefFieldsVisitor visitor(this);
-  to_ref->VisitReferences<true>(visitor, visitor);
+  to_ref->VisitReferences(visitor, visitor);
 }
 
 // Process a field.
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index 94ffe6e..60f833b 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -457,7 +457,7 @@
 
 void MarkCompact::UpdateObjectReferences(mirror::Object* obj) {
   UpdateReferenceVisitor visitor(this);
-  obj->VisitReferences<kMovingClasses>(visitor, visitor);
+  obj->VisitReferences(visitor, visitor);
 }
 
 inline mirror::Object* MarkCompact::GetMarkedForwardAddress(mirror::Object* obj) {
@@ -608,7 +608,7 @@
 // Visit all of the references of an object and update.
 void MarkCompact::ScanObject(mirror::Object* obj) {
   MarkCompactMarkObjectVisitor visitor(this);
-  obj->VisitReferences<kMovingClasses>(visitor, visitor);
+  obj->VisitReferences(visitor, visitor);
 }
 
 // Scan anything that's on the mark stack.
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 4e3845e..a3cc831 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -32,7 +32,7 @@
 inline void MarkSweep::ScanObjectVisit(mirror::Object* obj, const MarkVisitor& visitor,
                                        const ReferenceVisitor& ref_visitor) {
   DCHECK(IsMarked(obj)) << "Scanning unmarked object " << obj << "\n" << heap_->DumpSpaces();
-  obj->VisitReferences<false>(visitor, ref_visitor);
+  obj->VisitReferences(visitor, ref_visitor);
   if (kCountScannedTypes) {
     mirror::Class* klass = obj->GetClass<kVerifyNone>();
     if (UNLIKELY(klass == mirror::Class::GetJavaLangClass())) {
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index fc2a801..a355d40 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -320,7 +320,7 @@
 void SemiSpace::VerifyNoFromSpaceReferences(Object* obj) {
   DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
   SemiSpaceVerifyNoFromSpaceReferencesVisitor visitor(from_space_);
-  obj->VisitReferences<kMovingClasses>(visitor, VoidFunctor());
+  obj->VisitReferences(visitor, VoidFunctor());
 }
 
 class SemiSpaceVerifyNoFromSpaceReferencesObjectVisitor {
@@ -722,7 +722,7 @@
 void SemiSpace::ScanObject(Object* obj) {
   DCHECK(!from_space_->HasAddress(obj)) << "Scanning object " << obj << " in from space";
   SemiSpaceMarkObjectVisitor visitor(this);
-  obj->VisitReferences<kMovingClasses>(visitor, visitor);
+  obj->VisitReferences(visitor, visitor);
 }
 
 // Scan anything that's on the mark stack.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index e56351f..d7f918b 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1795,7 +1795,7 @@
   // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
   // annotalysis on visitors.
   void operator()(mirror::Object* o) const NO_THREAD_SAFETY_ANALYSIS {
-    o->VisitReferences<true>(*this, VoidFunctor());
+    o->VisitReferences(*this, VoidFunctor());
   }
 
   // For Object::VisitReferences.
@@ -2788,7 +2788,7 @@
     // be live or else how did we find it in the live bitmap?
     VerifyReferenceVisitor visitor(heap_, fail_count_, verify_referent_);
     // The class doesn't count as a reference but we should verify it anyways.
-    obj->VisitReferences<true>(visitor, visitor);
+    obj->VisitReferences(visitor, visitor);
   }
 
   static void VisitCallback(mirror::Object* obj, void* arg)
@@ -2969,7 +2969,7 @@
   void operator()(mirror::Object* obj) const
       SHARED_REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
     VerifyReferenceCardVisitor visitor(heap_, const_cast<bool*>(&failed_));
-    obj->VisitReferences<true>(visitor, VoidFunctor());
+    obj->VisitReferences(visitor, VoidFunctor());
   }
 
   bool Failed() const {
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 713797f..a9a236f 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -1063,7 +1063,7 @@
   }
 
   GcRootVisitor visitor(this);
-  obj->VisitReferences<true>(visitor, VoidFunctor());
+  obj->VisitReferences(visitor, VoidFunctor());
 
   gc::Heap* const heap = Runtime::Current()->GetHeap();
   const gc::space::ContinuousSpace* const space = heap->FindContinuousSpaceFromObject(obj, true);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index ac9cb09..cd678f6 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -669,9 +669,9 @@
   return size;
 }
 
-template <bool kVisitClass, typename Visitor>
+template <typename Visitor>
 inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
-  VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+  VisitInstanceFieldsReferences(klass, visitor);
   // Right after a class is allocated, but not yet loaded
   // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it
   // and scan it. IsTemp() may call Class::GetAccessFlags() but may
@@ -683,7 +683,7 @@
     // Temp classes don't ever populate imt/vtable or static fields and they are not even
     // allocated with the right size for those. Also, unresolved classes don't have fields
     // linked yet.
-    VisitStaticFieldsReferences<kVisitClass>(this, visitor);
+    VisitStaticFieldsReferences(this, visitor);
   }
   // Since this class is reachable, we must also visit the associated roots when we scan it.
   VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index f20cc6e..055b3e5 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -872,8 +872,8 @@
     h_new_class_obj->SetClassSize(new_length_);
     // Visit all of the references to make sure there is no from space references in the native
     // roots.
-    h_new_class_obj->VisitReferences<true>(h_new_class_obj->GetClass(),
-                                           ReadBarrierOnNativeRootsVisitor());
+    static_cast<mirror::Object*>(h_new_class_obj.Get())->VisitReferences(
+        ReadBarrierOnNativeRootsVisitor(), VoidFunctor());
   }
 
  private:
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index dc60a38..3f375be 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1021,10 +1021,6 @@
   void SetPreverifiedFlagOnAllMethods(size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  template <bool kVisitClass, typename Visitor>
-  void VisitReferences(mirror::Class* klass, const Visitor& visitor)
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
   // Get the descriptor of the class. In a few cases a std::string is required, rather than
   // always create one the storage argument is populated and its internal c_str() returned. We do
   // this to avoid memory allocation in the common case.
@@ -1153,6 +1149,10 @@
   static MemberOffset EmbeddedImTableOffset(size_t pointer_size);
   static MemberOffset EmbeddedVTableOffset(size_t pointer_size);
 
+  template <typename Visitor>
+  void VisitReferences(mirror::Class* klass, const Visitor& visitor)
+      SHARED_REQUIRES(Locks::mutator_lock_);
+
   // Defining class loader, or null for the "bootstrap" system loader.
   HeapReference<ClassLoader> class_loader_;
 
@@ -1279,6 +1279,7 @@
   static GcRoot<Class> java_lang_Class_;
 
   friend struct art::ClassOffsets;  // for verifying offset information
+  friend class Object;  // For VisitReferences
   DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
 };
 
diff --git a/runtime/mirror/class_loader-inl.h b/runtime/mirror/class_loader-inl.h
index 35f3664..e22ddd7 100644
--- a/runtime/mirror/class_loader-inl.h
+++ b/runtime/mirror/class_loader-inl.h
@@ -25,10 +25,10 @@
 namespace art {
 namespace mirror {
 
-template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor>
+template <VerifyObjectFlags kVerifyFlags, typename Visitor>
 inline void ClassLoader::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
   // Visit instance fields first.
-  VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+  VisitInstanceFieldsReferences(klass, visitor);
   // Visit classes loaded after.
   ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
   ClassTable* const class_table = GetClassTable();
diff --git a/runtime/mirror/class_loader.h b/runtime/mirror/class_loader.h
index 21c652a..f27b615 100644
--- a/runtime/mirror/class_loader.h
+++ b/runtime/mirror/class_loader.h
@@ -46,14 +46,15 @@
     SetField64<false>(OFFSET_OF_OBJECT_MEMBER(ClassLoader, class_table_),
                       reinterpret_cast<uint64_t>(class_table));
   }
+
+ private:
   // Visit instance fields of the class loader as well as its associated classes.
   // Null class loader is handled by ClassLinker::VisitClassRoots.
-  template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor>
+  template <VerifyObjectFlags kVerifyFlags, typename Visitor>
   void VisitReferences(mirror::Class* klass, const Visitor& visitor)
       SHARED_REQUIRES(Locks::mutator_lock_)
       REQUIRES(!Locks::classlinker_classes_lock_);
 
- private:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   HeapReference<Object> packages_;
   HeapReference<ClassLoader> parent_;
@@ -63,6 +64,7 @@
   uint64_t class_table_;
 
   friend struct art::ClassLoaderOffsets;  // for verifying offset information
+  friend class Object;  // For VisitReferences
   DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader);
 };
 
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 7b1660b..586ae30 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -942,13 +942,10 @@
   return success;
 }
 
-template<bool kVisitClass, bool kIsStatic, typename Visitor>
+template<bool kIsStatic, typename Visitor>
 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
   if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
     // Instance fields and not the slow-path.
-    if (kVisitClass) {
-      visitor(this, ClassOffset(), kIsStatic);
-    }
     uint32_t field_offset = mirror::kObjectHeaderSize;
     while (ref_offsets != 0) {
       if ((ref_offsets & 1) != 0) {
@@ -974,9 +971,9 @@
           ? klass->GetFirstReferenceStaticFieldOffset(
               Runtime::Current()->GetClassLinker()->GetImagePointerSize())
           : klass->GetFirstReferenceInstanceFieldOffset();
-      for (size_t i = 0; i < num_reference_fields; ++i) {
+      for (size_t i = 0u; i < num_reference_fields; ++i) {
         // TODO: Do a simpler check?
-        if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
+        if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
           visitor(this, field_offset, kIsStatic);
         }
         field_offset = MemberOffset(field_offset.Uint32Value() +
@@ -986,19 +983,17 @@
   }
 }
 
-template<bool kVisitClass, typename Visitor>
+template<typename Visitor>
 inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
-  VisitFieldsReferences<kVisitClass, false>(
-      klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
+  VisitFieldsReferences<false>(klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
 }
 
-template<bool kVisitClass, typename Visitor>
+template<typename Visitor>
 inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
   DCHECK(!klass->IsTemp());
-  klass->VisitFieldsReferences<kVisitClass, true>(0, visitor);
+  klass->VisitFieldsReferences<true>(0, visitor);
 }
 
-
 template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsClassLoader() {
   return GetClass<kVerifyFlags>()->IsClassLoaderClass();
@@ -1010,25 +1005,23 @@
   return down_cast<mirror::ClassLoader*>(this);
 }
 
-template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
-    typename JavaLangRefVisitor>
+template <VerifyObjectFlags kVerifyFlags, typename Visitor, typename JavaLangRefVisitor>
 inline void Object::VisitReferences(const Visitor& visitor,
                                     const JavaLangRefVisitor& ref_visitor) {
   mirror::Class* klass = GetClass<kVerifyFlags>();
+  visitor(this, ClassOffset(), false);
   if (klass == Class::GetJavaLangClass()) {
-    AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
+    AsClass<kVerifyNone>()->VisitReferences(klass, visitor);
   } else if (klass->IsArrayClass() || klass->IsStringClass()) {
     if (klass->IsObjectArrayClass<kVerifyNone>()) {
-      AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor);
-    } else if (kVisitClass) {
-      visitor(this, ClassOffset(), false);
+      AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor);
     }
   } else if (klass->IsClassLoaderClass()) {
     mirror::ClassLoader* class_loader = AsClassLoader<kVerifyFlags>();
-    class_loader->VisitReferences<kVisitClass, kVerifyFlags>(klass, visitor);
+    class_loader->VisitReferences<kVerifyFlags>(klass, visitor);
   } else {
     DCHECK(!klass->IsVariableSize());
-    VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
+    VisitInstanceFieldsReferences(klass, visitor);
     if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) {
       ref_visitor(klass, AsReference());
     }
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index df680b5..4d94130 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -85,7 +85,7 @@
     // object above, copy references fields one by one again with a
     // RB. TODO: Optimize this later?
     CopyReferenceFieldsWithReadBarrierVisitor visitor(dest);
-    src->VisitReferences<true>(visitor, visitor);
+    src->VisitReferences(visitor, visitor);
   }
   gc::Heap* heap = Runtime::Current()->GetHeap();
   // Perform write barriers on copied object references.
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 4967a14..3cec29c 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -446,8 +446,9 @@
   }
   // TODO fix thread safety analysis broken by the use of template. This should be
   // SHARED_REQUIRES(Locks::mutator_lock_).
-  template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
-      typename Visitor, typename JavaLangRefVisitor = VoidFunctor>
+  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+            typename Visitor,
+            typename JavaLangRefVisitor = VoidFunctor>
   void VisitReferences(const Visitor& visitor, const JavaLangRefVisitor& ref_visitor)
       NO_THREAD_SAFETY_ANALYSIS;
 
@@ -481,13 +482,13 @@
   }
 
   // TODO: Fixme when anotatalysis works with visitors.
-  template<bool kVisitClass, bool kIsStatic, typename Visitor>
+  template<bool kIsStatic, typename Visitor>
   void VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) HOT_ATTR
       NO_THREAD_SAFETY_ANALYSIS;
-  template<bool kVisitClass, typename Visitor>
+  template<typename Visitor>
   void VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) HOT_ATTR
       SHARED_REQUIRES(Locks::mutator_lock_);
-  template<bool kVisitClass, typename Visitor>
+  template<typename Visitor>
   void VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) HOT_ATTR
       SHARED_REQUIRES(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 4a7e7b3..5b73557 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -269,11 +269,8 @@
                       (i * sizeof(HeapReference<Object>)));
 }
 
-template<class T> template<const bool kVisitClass, typename Visitor>
+template<class T> template<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);
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 607b000..b45cafd 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -83,14 +83,15 @@
   ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  // TODO fix thread safety analysis broken by the use of template. This should be
-  // SHARED_REQUIRES(Locks::mutator_lock_).
-  template<const bool kVisitClass, typename Visitor>
-  void VisitReferences(const Visitor& visitor) NO_THREAD_SAFETY_ANALYSIS;
-
   static MemberOffset OffsetOfElement(int32_t i);
 
  private:
+  // TODO fix thread safety analysis broken by the use of template. This should be
+  // SHARED_REQUIRES(Locks::mutator_lock_).
+  template<typename Visitor>
+  void VisitReferences(const Visitor& visitor) NO_THREAD_SAFETY_ANALYSIS;
+
+  friend class Object;  // For VisitReferences
   DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray);
 };