Compaction cleanup for FindArrayClass.

We now pass double pointer in to signify that it can cause thread
suspension, this double pointer gets wrapped by a handle if don't
find the array class in the cache.

Change-Id: I43436b6c35597c7252b65d1180baddb5ac4caabb
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 84afb2d..9d8888c 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -37,19 +37,19 @@
   return FindClass(self, descriptor, NullHandle<mirror::ClassLoader>());
 }
 
-inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class* element_class) {
+inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class** element_class) {
   for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
     // Read the cached array class once to avoid races with other threads setting it.
     mirror::Class* array_class = find_array_class_cache_[i];
-    if (array_class != nullptr && array_class->GetComponentType() == element_class) {
+    if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
       return array_class;
     }
   }
-  DCHECK(!element_class->IsPrimitiveVoid());
-  std::string descriptor("[");
-  descriptor += element_class->GetDescriptor();
-  StackHandleScope<1> hs(Thread::Current());
-  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
+  DCHECK(!(*element_class)->IsPrimitiveVoid());
+  std::string descriptor = "[" + (*element_class)->GetDescriptor();
+  StackHandleScope<2> hs(Thread::Current());
+  Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
+  HandleWrapper<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
   mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader);
   // Benign races in storing array class and incrementing index.
   size_t victim_index = find_array_class_cache_next_victim_;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index a8271ed..ccf0558 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -84,7 +84,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Finds the array class given for the element class.
-  mirror::Class* FindArrayClass(Thread* self, mirror::Class* element_class)
+  mirror::Class* FindArrayClass(Thread* self, mirror::Class** element_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Reutrns true if the class linker is initialized.
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index c11aecc..e397a5c 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -147,7 +147,8 @@
     EXPECT_STREQ(direct_interface0->GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
     mirror::Class* direct_interface1 = mirror::Class::GetDirectInterface(self, array, 1);
     EXPECT_STREQ(direct_interface1->GetDescriptor().c_str(), "Ljava/io/Serializable;");
-    EXPECT_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
+    mirror::Class* array_ptr = array->GetComponentType();
+    EXPECT_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
   }
 
   void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index f77a0f6..9cfba8d 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -33,7 +33,7 @@
     DCHECK_GE(length, 0);
     mirror::Class* element_class = reinterpret_cast<Object*>(args[0])->AsClass();
     Runtime* runtime = Runtime::Current();
-    mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, element_class);
+    mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
     DCHECK(array_class != nullptr);
     gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
     result->SetL(mirror::Array::Alloc<true>(self, array_class, length,
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index b51e1d5..1351524 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -2058,7 +2058,7 @@
         return nullptr;
       }
       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-      array_class = class_linker->FindArrayClass(soa.Self(), element_class);
+      array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
       if (UNLIKELY(array_class == nullptr)) {
         return nullptr;
       }
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 1076643..f7b5737 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -93,15 +93,17 @@
 
   // Find/generate the array class.
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  mirror::Class* element_class_ptr = element_class.Get();
   StackHandleScope<1> hs(self);
   Handle<mirror::Class> array_class(
-      hs.NewHandle(class_linker->FindArrayClass(self, element_class.Get())));
+      hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr)));
   if (UNLIKELY(array_class.Get() == nullptr)) {
     CHECK(self->IsExceptionPending());
     return nullptr;
   }
   for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
-    array_class.Assign(class_linker->FindArrayClass(self, array_class.Get()));
+    mirror::Class* array_class_ptr = array_class.Get();
+    array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr));
     if (UNLIKELY(array_class.Get() == nullptr)) {
       CHECK(self->IsExceptionPending());
       return nullptr;
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index d55b545..e5cc671 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -67,7 +67,8 @@
     return nullptr;
   }
   Runtime* runtime = Runtime::Current();
-  mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
+  mirror::Class* array_class =
+      runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
   if (UNLIKELY(array_class == nullptr)) {
     return nullptr;
   }
@@ -90,7 +91,7 @@
     return nullptr;
   }
   Runtime* runtime = Runtime::Current();
-  mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
+  mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
   if (UNLIKELY(array_class == nullptr)) {
     return nullptr;
   }
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index db77437..eae4584 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -46,14 +46,14 @@
 static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementClass, jint length) {
   ScopedFastNativeObjectAccess soa(env);
   DCHECK(javaElementClass != NULL);
-  mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
   if (UNLIKELY(length < 0)) {
     ThrowNegativeArraySizeException(length);
     return NULL;
   }
+  mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
-  mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), element_class);
+  mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
   if (UNLIKELY(array_class == NULL)) {
     CHECK(soa.Self()->IsExceptionPending());
     return NULL;
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 8df1e5d..e24c920 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -929,7 +929,7 @@
     }
     mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), common_elem);
+    mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
     DCHECK(array_class != NULL);
     return array_class;
   } else {