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/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);
 };