Remove PrimitiveArray<T>::array_class_.

And ObjPtr<>-ify jni_internal.cc while we're touching it.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 31113334
Change-Id: I15a8ade772e3e4337371c6f3c472f9efea9f4636
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e2449f9..1c75fba 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -499,7 +499,6 @@
   Handle<mirror::Class> char_array_class(hs.NewHandle(
       AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
   char_array_class->SetComponentType(char_class.Get());
-  mirror::CharArray::SetArrayClass(char_array_class.Get());
 
   // Setup String.
   Handle<mirror::Class> java_lang_String(hs.NewHandle(
@@ -549,14 +548,12 @@
   Handle<mirror::Class> int_array_class(hs.NewHandle(
       AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
   int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this));
-  mirror::IntArray::SetArrayClass(int_array_class.Get());
   SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get());
 
   // Create long array type for AllocDexCache (done in AppendToBootClassPath).
   Handle<mirror::Class> long_array_class(hs.NewHandle(
       AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
   long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this));
-  mirror::LongArray::SetArrayClass(long_array_class.Get());
   SetClassRoot(ClassRoot::kLongArrayClass, long_array_class.Get());
 
   // now that these are registered, we can use AllocClass() and AllocObjectArray
@@ -637,24 +634,19 @@
 
   // Setup the primitive array type classes - can't be done until Object has a vtable.
   SetClassRoot(ClassRoot::kBooleanArrayClass, FindSystemClass(self, "[Z"));
-  mirror::BooleanArray::SetArrayClass(GetClassRoot(ClassRoot::kBooleanArrayClass, this));
 
   SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B"));
-  mirror::ByteArray::SetArrayClass(GetClassRoot(ClassRoot::kByteArrayClass, this));
 
   CheckSystemClass(self, char_array_class, "[C");
 
   SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S"));
-  mirror::ShortArray::SetArrayClass(GetClassRoot(ClassRoot::kShortArrayClass, this));
 
   CheckSystemClass(self, int_array_class, "[I");
   CheckSystemClass(self, long_array_class, "[J");
 
   SetClassRoot(ClassRoot::kFloatArrayClass, FindSystemClass(self, "[F"));
-  mirror::FloatArray::SetArrayClass(GetClassRoot(ClassRoot::kFloatArrayClass, this));
 
   SetClassRoot(ClassRoot::kDoubleArrayClass, FindSystemClass(self, "[D"));
-  mirror::DoubleArray::SetArrayClass(GetClassRoot(ClassRoot::kDoubleArrayClass, this));
 
   // Run Class through FindSystemClass. This initializes the dex_cache_ fields and register it
   // in class_table_.
@@ -1081,14 +1073,6 @@
   mirror::ByteBufferViewVarHandle::SetClass(
       GetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, this).Ptr());
   mirror::Reference::SetClass(GetClassRoot(ClassRoot::kJavaLangRefReference, this));
-  mirror::BooleanArray::SetArrayClass(GetClassRoot(ClassRoot::kBooleanArrayClass, this));
-  mirror::ByteArray::SetArrayClass(GetClassRoot(ClassRoot::kByteArrayClass, this));
-  mirror::CharArray::SetArrayClass(GetClassRoot(ClassRoot::kCharArrayClass, this));
-  mirror::DoubleArray::SetArrayClass(GetClassRoot(ClassRoot::kDoubleArrayClass, this));
-  mirror::FloatArray::SetArrayClass(GetClassRoot(ClassRoot::kFloatArrayClass, this));
-  mirror::IntArray::SetArrayClass(GetClassRoot(ClassRoot::kIntArrayClass, this));
-  mirror::LongArray::SetArrayClass(GetClassRoot(ClassRoot::kLongArrayClass, this));
-  mirror::ShortArray::SetArrayClass(GetClassRoot(ClassRoot::kShortArrayClass, this));
   mirror::Throwable::SetClass(GetClassRoot(ClassRoot::kJavaLangThrowable, this));
   mirror::StackTraceElement::SetClass(GetClassRoot(ClassRoot::kJavaLangStackTraceElement, this));
   mirror::EmulatedStackFrame::SetClass(
@@ -2179,17 +2163,9 @@
   mirror::StackTraceElement::ResetClass();
   mirror::String::ResetClass();
   mirror::Throwable::ResetClass();
-  mirror::BooleanArray::ResetArrayClass();
-  mirror::ByteArray::ResetArrayClass();
-  mirror::CharArray::ResetArrayClass();
   mirror::Constructor::ResetArrayClass();
-  mirror::DoubleArray::ResetArrayClass();
   mirror::Field::ResetArrayClass();
-  mirror::FloatArray::ResetArrayClass();
   mirror::Method::ResetArrayClass();
-  mirror::IntArray::ResetArrayClass();
-  mirror::LongArray::ResetArrayClass();
-  mirror::ShortArray::ResetArrayClass();
   mirror::CallSite::ResetClass();
   mirror::MethodType::ResetClass();
   mirror::MethodHandleImpl::ResetClass();
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 95b42d2..ffa0a90 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -23,6 +23,7 @@
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "class_linker-inl.h"
+#include "class_root.h"
 #include "dex/dex_file-inl.h"
 #include "jni/jni_internal.h"
 #include "jvalue-inl.h"
@@ -1211,7 +1212,7 @@
   }
 
   // Extract the parameters' access flags int[].
-  Handle<mirror::Class> int_array_class(hs.NewHandle(mirror::IntArray::GetArrayClass()));
+  Handle<mirror::Class> int_array_class(hs.NewHandle(GetClassRoot<mirror::IntArray>()));
   if (UNLIKELY(int_array_class == nullptr)) {
     return false;
   }
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index cd66a60..cf67517 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -33,6 +33,7 @@
 #include "base/safe_map.h"
 #include "base/stl_util.h"
 #include "class_linker-inl.h"
+#include "class_root.h"
 #include "dex/dex_file-inl.h"
 #include "dex/utf.h"
 #include "fault_handler.h"
@@ -305,7 +306,7 @@
     return nullptr;
   }
   ArtField* field = nullptr;
-  mirror::Class* field_type;
+  ObjPtr<mirror::Class> field_type;
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   if (sig[1] != '\0') {
     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(c->GetClassLoader()));
@@ -346,8 +347,11 @@
   return jni::EncodeArtField(field);
 }
 
-static void ThrowAIOOBE(ScopedObjectAccess& soa, mirror::Array* array, jsize start,
-                        jsize length, const char* identifier)
+static void ThrowAIOOBE(ScopedObjectAccess& soa,
+                        ObjPtr<mirror::Array> array,
+                        jsize start,
+                        jsize length,
+                        const char* identifier)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   std::string type(array->PrettyTypeOf());
   soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
@@ -434,7 +438,9 @@
   }
 
 template <bool kNative>
-static ArtMethod* FindMethod(mirror::Class* c, const StringPiece& name, const StringPiece& sig)
+static ArtMethod* FindMethod(ObjPtr<mirror::Class> c,
+                             const StringPiece& name,
+                             const StringPiece& sig)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   for (auto& method : c->GetMethods(pointer_size)) {
@@ -462,7 +468,7 @@
     ClassLinker* class_linker = runtime->GetClassLinker();
     std::string descriptor(NormalizeJniClassDescriptor(name));
     ScopedObjectAccess soa(env);
-    mirror::Class* c = nullptr;
+    ObjPtr<mirror::Class> c = nullptr;
     if (runtime->IsStarted()) {
       StackHandleScope<1> hs(soa.Self());
       Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa)));
@@ -608,7 +614,7 @@
 
   static jthrowable ExceptionOccurred(JNIEnv* env) {
     ScopedObjectAccess soa(env);
-    mirror::Object* exception = soa.Self()->GetException();
+    ObjPtr<mirror::Object> exception = soa.Self()->GetException();
     return soa.AddLocalReference<jthrowable>(exception);
   }
 
@@ -1979,7 +1985,7 @@
     ObjPtr<mirror::ObjectArray<mirror::Object>> array =
         soa.Decode<mirror::ObjectArray<mirror::Object>>(java_array);
     ObjPtr<mirror::Object> value = soa.Decode<mirror::Object>(java_value);
-    array->Set<false>(index, value.Ptr());
+    array->Set<false>(index, value);
   }
 
   static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
@@ -2022,7 +2028,7 @@
     ScopedObjectAccess soa(env);
     ObjPtr<mirror::Class> array_class;
     {
-      ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(element_jclass).Ptr();
+      ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(element_jclass);
       if (UNLIKELY(element_class->IsPrimitive())) {
         soa.Vm()->JniAbortF("NewObjectArray",
                             "not an object type: %s",
@@ -2042,7 +2048,7 @@
     if (result != nullptr && initial_element != nullptr) {
       ObjPtr<mirror::Object> initial_object = soa.Decode<mirror::Object>(initial_element);
       if (initial_object != nullptr) {
-        mirror::Class* element_class = result->GetClass()->GetComponentType();
+        ObjPtr<mirror::Class> element_class = result->GetClass()->GetComponentType();
         if (UNLIKELY(!element_class->IsAssignableFrom(initial_object->GetClass()))) {
           soa.Vm()->JniAbortF("NewObjectArray", "cannot assign object of type '%s' to array with "
                               "element type of '%s'",
@@ -2051,7 +2057,7 @@
           return nullptr;
         } else {
           for (jsize i = 0; i < length; ++i) {
-            result->SetWithoutChecks<false>(i, initial_object.Ptr());
+            result->SetWithoutChecks<false>(i, initial_object);
           }
         }
       }
@@ -2101,7 +2107,7 @@
       return;
     }
     const size_t component_size = array->GetClass()->GetComponentSize();
-    ReleasePrimitiveArray(soa, array.Ptr(), component_size, elements, mode);
+    ReleasePrimitiveArray(soa, array, component_size, elements, mode);
   }
 
   static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
@@ -2338,13 +2344,13 @@
            current_class != nullptr;
            current_class = current_class->GetSuperClass()) {
         // Search first only comparing methods which are native.
-        m = FindMethod<true>(current_class.Ptr(), name, sig);
+        m = FindMethod<true>(current_class, name, sig);
         if (m != nullptr) {
           break;
         }
 
         // Search again comparing to all methods, to find non-native methods that match.
-        m = FindMethod<false>(current_class.Ptr(), name, sig);
+        m = FindMethod<false>(current_class, name, sig);
         if (m != nullptr) {
           break;
         }
@@ -2547,30 +2553,32 @@
   }
 
   template <typename JArrayT, typename ElementT, typename ArtArrayT>
-  static ArtArrayT* DecodeAndCheckArrayType(ScopedObjectAccess& soa, JArrayT java_array,
-                                           const char* fn_name, const char* operation)
+  static ObjPtr<ArtArrayT> DecodeAndCheckArrayType(ScopedObjectAccess& soa,
+                                                   JArrayT java_array,
+                                                   const char* fn_name,
+                                                   const char* operation)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     ObjPtr<ArtArrayT> array = soa.Decode<ArtArrayT>(java_array);
-    if (UNLIKELY(ArtArrayT::GetArrayClass() != array->GetClass())) {
+    ObjPtr<mirror::Class> expected_array_class = GetClassRoot<ArtArrayT>();
+    if (UNLIKELY(expected_array_class != array->GetClass())) {
       soa.Vm()->JniAbortF(fn_name,
                           "attempt to %s %s primitive array elements with an object of type %s",
                           operation,
                           mirror::Class::PrettyDescriptor(
-                              ArtArrayT::GetArrayClass()->GetComponentType()).c_str(),
+                              expected_array_class->GetComponentType()).c_str(),
                           mirror::Class::PrettyDescriptor(array->GetClass()).c_str());
       return nullptr;
     }
     DCHECK_EQ(sizeof(ElementT), array->GetClass()->GetComponentSize());
-    return array.Ptr();
+    return array;
   }
 
   template <typename ArrayT, typename ElementT, typename ArtArrayT>
   static ElementT* GetPrimitiveArray(JNIEnv* env, ArrayT java_array, jboolean* is_copy) {
     CHECK_NON_NULL_ARGUMENT(java_array);
     ScopedObjectAccess soa(env);
-    ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
-                                                                            "GetArrayElements",
-                                                                            "get");
+    ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(
+        soa, java_array, "GetArrayElements", "get");
     if (UNLIKELY(array == nullptr)) {
       return nullptr;
     }
@@ -2596,17 +2604,19 @@
   static void ReleasePrimitiveArray(JNIEnv* env, ArrayT java_array, ElementT* elements, jint mode) {
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
     ScopedObjectAccess soa(env);
-    ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
-                                                                            "ReleaseArrayElements",
-                                                                            "release");
+    ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(
+        soa, java_array, "ReleaseArrayElements", "release");
     if (array == nullptr) {
       return;
     }
     ReleasePrimitiveArray(soa, array, sizeof(ElementT), elements, mode);
   }
 
-  static void ReleasePrimitiveArray(ScopedObjectAccess& soa, mirror::Array* array,
-                                    size_t component_size, void* elements, jint mode)
+  static void ReleasePrimitiveArray(ScopedObjectAccess& soa,
+                                    ObjPtr<mirror::Array> array,
+                                    size_t component_size,
+                                    void* elements,
+                                    jint mode)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     void* array_data = array->GetRawData(component_size, 0);
     gc::Heap* heap = Runtime::Current()->GetHeap();
@@ -2649,10 +2659,8 @@
                                       jsize start, jsize length, ElementT* buf) {
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
     ScopedObjectAccess soa(env);
-    ArtArrayT* array =
-        DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
-                                                              "GetPrimitiveArrayRegion",
-                                                              "get region of");
+    ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(
+        soa, java_array, "GetPrimitiveArrayRegion", "get region of");
     if (array != nullptr) {
       if (start < 0 || length < 0 || length > array->GetLength() - start) {
         ThrowAIOOBE(soa, array, start, length, "src");
@@ -2669,10 +2677,8 @@
                                       jsize start, jsize length, const ElementT* buf) {
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
     ScopedObjectAccess soa(env);
-    ArtArrayT* array =
-        DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
-                                                              "SetPrimitiveArrayRegion",
-                                                              "set region of");
+    ObjPtr<ArtArrayT> array = DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(
+        soa, java_array, "SetPrimitiveArrayRegion", "set region of");
     if (array != nullptr) {
       if (start < 0 || length < 0 || length > array->GetLength() - start) {
         ThrowAIOOBE(soa, array, start, length, "dst");
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 636c84c..d2adcb4 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -201,11 +201,6 @@
   return result;
 }
 
-template<class T>
-inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor) {
-  array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
 template<typename T>
 inline PrimitiveArray<T>* PrimitiveArray<T>::AllocateAndFill(Thread* self,
                                                              const T* data,
@@ -220,16 +215,6 @@
 }
 
 template<typename T>
-inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
-  Array* raw_array = Array::Alloc<true>(self,
-                                        GetArrayClass(),
-                                        length,
-                                        ComponentSizeShiftWidth(sizeof(T)),
-                                        Runtime::Current()->GetHeap()->GetCurrentAllocator());
-  return down_cast<PrimitiveArray<T>*>(raw_array);
-}
-
-template<typename T>
 inline T PrimitiveArray<T>::Get(int32_t i) {
   if (!CheckIsValidIndex(i)) {
     DCHECK(Thread::Current()->IsExceptionPending());
@@ -461,13 +446,6 @@
   }
 }
 
-template<typename T>
-inline void PrimitiveArray<T>::SetArrayClass(ObjPtr<Class> array_class) {
-  CHECK(array_class_.IsNull());
-  CHECK(array_class != nullptr);
-  array_class_ = GcRoot<Class>(array_class);
-}
-
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index ea202e7..06ce0bb 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -20,6 +20,7 @@
 #include "class-inl.h"
 #include "class.h"
 #include "class_linker-inl.h"
+#include "class_root.h"
 #include "common_throws.h"
 #include "dex/dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
@@ -118,6 +119,16 @@
   return new_array.Ptr();
 }
 
+template<typename T>
+PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
+  Array* raw_array = Array::Alloc<true>(self,
+                                        GetClassRoot<PrimitiveArray<T>>(),
+                                        length,
+                                        ComponentSizeShiftWidth(sizeof(T)),
+                                        Runtime::Current()->GetHeap()->GetCurrentAllocator());
+  return down_cast<PrimitiveArray<T>*>(raw_array);
+}
+
 void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
   art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
 }
@@ -146,9 +157,6 @@
   return new_array.Ptr();
 }
 
-
-template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_;
-
 // Explicitly instantiate all the primitive array types.
 template class PrimitiveArray<uint8_t>;   // BooleanArray
 template class PrimitiveArray<int8_t>;    // ByteArray
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 11128bb..c9c99e8 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -167,24 +167,7 @@
   void Memcpy(int32_t dst_pos, ObjPtr<PrimitiveArray<T>> src, int32_t src_pos, int32_t count)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static void SetArrayClass(ObjPtr<Class> array_class);
-
-  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  static Class* GetArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-    DCHECK(!array_class_.IsNull());
-    return array_class_.Read<kReadBarrierOption>();
-  }
-
-  static void ResetArrayClass() {
-    CHECK(!array_class_.IsNull());
-    array_class_ = GcRoot<Class>(nullptr);
-  }
-
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
-  static GcRoot<Class> array_class_;
-
   DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
 };
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1402749..621eec5 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1995,15 +1995,6 @@
   mirror::ArrayElementVarHandle::VisitRoots(visitor);
   mirror::ByteArrayViewVarHandle::VisitRoots(visitor);
   mirror::ByteBufferViewVarHandle::VisitRoots(visitor);
-  // Visit all the primitive array types classes.
-  mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor);   // BooleanArray
-  mirror::PrimitiveArray<int8_t>::VisitRoots(visitor);    // ByteArray
-  mirror::PrimitiveArray<uint16_t>::VisitRoots(visitor);  // CharArray
-  mirror::PrimitiveArray<double>::VisitRoots(visitor);    // DoubleArray
-  mirror::PrimitiveArray<float>::VisitRoots(visitor);     // FloatArray
-  mirror::PrimitiveArray<int32_t>::VisitRoots(visitor);   // IntArray
-  mirror::PrimitiveArray<int64_t>::VisitRoots(visitor);   // LongArray
-  mirror::PrimitiveArray<int16_t>::VisitRoots(visitor);   // ShortArray
   // Visiting the roots of these ArtMethods is not currently required since all the GcRoots are
   // null.
   BufferedRootVisitor<16> buffered_visitor(visitor, RootInfo(kRootVMInternal));