Avoid std::string allocations for finding an array class.

Introduce ClassLinker::FindArrayClass which performs an array class lookup
given the element/component class. This has a 16 element cache of recently
looked up arrays.
Pass the current thread to ClassLinker Find .. Class routines to avoid calls
to Thread::Current().
Avoid some uses of FindClass in the debugger where WellKnownClasses is a
faster and more compacting GC friendly alternative.

Change-Id: I60e231820b349543a7edb3ceb9cf1ce92db3c843
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 2180857..715f072 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -18,6 +18,7 @@
 
 #include "class.h"
 #include "class-inl.h"
+#include "class_linker-inl.h"
 #include "common_throws.h"
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
@@ -85,20 +86,22 @@
     }
   }
 
-  // Generate the full name of the array class.
-  std::string descriptor(num_dimensions, '[');
-  descriptor += ClassHelper(element_class.get()).GetDescriptor();
-
   // Find/generate the array class.
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  SirtRef<mirror::ClassLoader> class_loader(self, element_class->GetClassLoader());
   SirtRef<mirror::Class> array_class(self,
-                                     class_linker->FindClass(descriptor.c_str(), class_loader));
+                                     class_linker->FindArrayClass(self, element_class.get()));
   if (UNLIKELY(array_class.get() == nullptr)) {
     CHECK(self->IsExceptionPending());
     return nullptr;
   }
-  // create the array
+  for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
+    array_class.reset(class_linker->FindArrayClass(self, array_class.get()));
+    if (UNLIKELY(array_class.get() == nullptr)) {
+      CHECK(self->IsExceptionPending());
+      return nullptr;
+    }
+  }
+  // Create the array.
   Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions);
   if (UNLIKELY(new_array == nullptr)) {
     CHECK(self->IsExceptionPending());
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 3208de9..6dbb29d 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -72,7 +72,7 @@
             << PrettyClass(this) << " " << old_status << " -> " << new_status;
     }
   }
-  if (new_status == kStatusError) {
+  if (UNLIKELY(new_status == kStatusError)) {
     CHECK_NE(GetStatus(), kStatusError)
         << "Attempt to set as erroneous an already erroneous class " << PrettyClass(this);
 
@@ -95,7 +95,8 @@
     // clear exception to call FindSystemClass
     self->ClearException();
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    Class* eiie_class = class_linker->FindSystemClass("Ljava/lang/ExceptionInInitializerError;");
+    Class* eiie_class = class_linker->FindSystemClass(self,
+                                                      "Ljava/lang/ExceptionInInitializerError;");
     CHECK(!self->IsExceptionPending());
 
     // Only verification errors, not initialization problems, should set a verify error.
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 40c3748..34fb15e 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -123,7 +123,8 @@
   EXPECT_TRUE(oa->Get(0) == oa.get());
   EXPECT_TRUE(oa->Get(1) == oa.get());
 
-  Class* aioobe = class_linker_->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
+  Class* aioobe = class_linker_->FindSystemClass(soa.Self(),
+                                                 "Ljava/lang/ArrayIndexOutOfBoundsException;");
 
   EXPECT_TRUE(oa->Get(-1) == NULL);
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
@@ -138,21 +139,23 @@
   ASSERT_TRUE(oa->GetClass() != NULL);
   ClassHelper oa_ch(oa->GetClass());
   ASSERT_EQ(2U, oa_ch.NumDirectInterfaces());
-  EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Cloneable;"), oa_ch.GetDirectInterface(0));
-  EXPECT_EQ(class_linker_->FindSystemClass("Ljava/io/Serializable;"), oa_ch.GetDirectInterface(1));
+  EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"),
+            oa_ch.GetDirectInterface(0));
+  EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"),
+            oa_ch.GetDirectInterface(1));
 }
 
 TEST_F(ObjectTest, AllocArray) {
   ScopedObjectAccess soa(Thread::Current());
-  Class* c = class_linker_->FindSystemClass("[I");
+  Class* c = class_linker_->FindSystemClass(soa.Self(), "[I");
   SirtRef<Array> a(soa.Self(), Array::Alloc<true>(soa.Self(), c, 1));
   ASSERT_TRUE(c == a->GetClass());
 
-  c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
+  c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;");
   a.reset(Array::Alloc<true>(soa.Self(), c, 1));
   ASSERT_TRUE(c == a->GetClass());
 
-  c = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
+  c = class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;");
   a.reset(Array::Alloc<true>(soa.Self(), c, 1));
   ASSERT_TRUE(c == a->GetClass());
 }
@@ -173,7 +176,7 @@
   EXPECT_EQ(T(123), a->Get(0));
   EXPECT_EQ(T(321), a->Get(1));
 
-  Class* aioobe = cl->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
+  Class* aioobe = cl->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;");
 
   EXPECT_EQ(0, a->Get(-1));
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
@@ -214,7 +217,7 @@
 TEST_F(ObjectTest, CheckAndAllocArrayFromCode) {
   // pretend we are trying to call 'new char[3]' from String.toCharArray
   ScopedObjectAccess soa(Thread::Current());
-  Class* java_util_Arrays = class_linker_->FindSystemClass("Ljava/util/Arrays;");
+  Class* java_util_Arrays = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/Arrays;");
   ArtMethod* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
   const DexFile::StringId* string_id = java_lang_dex_file_->FindStringId("[I");
   ASSERT_TRUE(string_id != NULL);
@@ -233,11 +236,11 @@
 TEST_F(ObjectTest, CreateMultiArray) {
   ScopedObjectAccess soa(Thread::Current());
 
-  SirtRef<Class> c(soa.Self(), class_linker_->FindSystemClass("I"));
+  SirtRef<Class> c(soa.Self(), class_linker_->FindSystemClass(soa.Self(), "I"));
   SirtRef<IntArray> dims(soa.Self(), IntArray::Alloc(soa.Self(), 1));
   dims->Set<false>(0, 1);
   Array* multi = Array::CreateMultiArray(soa.Self(), c, dims);
-  EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass("[I"));
+  EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
   EXPECT_EQ(1, multi->GetLength());
 
   dims->Set<false>(0, -1);
@@ -253,11 +256,11 @@
       dims->Set<false>(0, i);
       dims->Set<false>(1, j);
       multi = Array::CreateMultiArray(soa.Self(), c, dims);
-      EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass("[[I"));
+      EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[[I"));
       EXPECT_EQ(i, multi->GetLength());
       for (int k = 0; k < i; ++k) {
         Array* outer = multi->AsObjectArray<Array>()->Get(k);
-        EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass("[I"));
+        EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
         EXPECT_EQ(j, outer->GetLength());
       }
     }
@@ -272,8 +275,7 @@
   CHECK(dex_file != NULL);
 
   SirtRef<mirror::ClassLoader> loader(soa.Self(), soa.Decode<ClassLoader*>(class_loader));
-  Class* klass =
-      class_linker_->FindClass("LStaticsFromCode;", loader);
+  Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", loader);
   ArtMethod* clinit = klass->FindClassInitializer();
   const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
   ASSERT_TRUE(klass_string_id != NULL);
@@ -404,9 +406,9 @@
   SirtRef<ClassLoader> class_loader_1(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader_1));
   SirtRef<ClassLoader> class_loader_2(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader_2));
 
-  Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
+  Class* klass1 = linker->FindClass(soa.Self(), "LProtoCompare;", class_loader_1);
   ASSERT_TRUE(klass1 != NULL);
-  Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2);
+  Class* klass2 = linker->FindClass(soa.Self(), "LProtoCompare2;", class_loader_2);
   ASSERT_TRUE(klass2 != NULL);
 
   ArtMethod* m1_1 = klass1->GetVirtualMethod(0);
@@ -472,8 +474,8 @@
   jobject jclass_loader = LoadDex("XandY");
   SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
 
-  Class* X = class_linker_->FindClass("LX;", class_loader);
-  Class* Y = class_linker_->FindClass("LY;", class_loader);
+  Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
+  Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
   ASSERT_TRUE(X != NULL);
   ASSERT_TRUE(Y != NULL);
 
@@ -487,16 +489,16 @@
   EXPECT_TRUE(y->InstanceOf(X));
   EXPECT_TRUE(y->InstanceOf(Y));
 
-  Class* java_lang_Class = class_linker_->FindSystemClass("Ljava/lang/Class;");
-  Class* Object_array_class = class_linker_->FindSystemClass("[Ljava/lang/Object;");
+  Class* java_lang_Class = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Class;");
+  Class* Object_array_class = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;");
 
   EXPECT_FALSE(java_lang_Class->InstanceOf(Object_array_class));
   EXPECT_TRUE(Object_array_class->InstanceOf(java_lang_Class));
 
   // All array classes implement Cloneable and Serializable.
   Object* array = ObjectArray<Object>::Alloc(soa.Self(), Object_array_class, 1);
-  Class* java_lang_Cloneable = class_linker_->FindSystemClass("Ljava/lang/Cloneable;");
-  Class* java_io_Serializable = class_linker_->FindSystemClass("Ljava/io/Serializable;");
+  Class* java_lang_Cloneable = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;");
+  Class* java_io_Serializable = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;");
   EXPECT_TRUE(array->InstanceOf(java_lang_Cloneable));
   EXPECT_TRUE(array->InstanceOf(java_io_Serializable));
 }
@@ -505,8 +507,8 @@
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
   SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
-  Class* X = class_linker_->FindClass("LX;", class_loader);
-  Class* Y = class_linker_->FindClass("LY;", class_loader);
+  Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
+  Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
 
   EXPECT_TRUE(X->IsAssignableFrom(X));
   EXPECT_TRUE(X->IsAssignableFrom(Y));
@@ -514,8 +516,8 @@
   EXPECT_TRUE(Y->IsAssignableFrom(Y));
 
   // class final String implements CharSequence, ..
-  Class* string = class_linker_->FindSystemClass("Ljava/lang/String;");
-  Class* charseq = class_linker_->FindSystemClass("Ljava/lang/CharSequence;");
+  Class* string = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;");
+  Class* charseq = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/CharSequence;");
   // Can String be assigned to CharSequence without a cast?
   EXPECT_TRUE(charseq->IsAssignableFrom(string));
   // Can CharSequence be assigned to String without a cast?
@@ -542,36 +544,36 @@
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
   SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
-  Class* X = class_linker_->FindClass("LX;", class_loader);
-  Class* Y = class_linker_->FindClass("LY;", class_loader);
+  Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
+  Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
   ASSERT_TRUE(X != NULL);
   ASSERT_TRUE(Y != NULL);
 
-  Class* YA = class_linker_->FindClass("[LY;", class_loader);
-  Class* YAA = class_linker_->FindClass("[[LY;", class_loader);
+  Class* YA = class_linker_->FindClass(soa.Self(), "[LY;", class_loader);
+  Class* YAA = class_linker_->FindClass(soa.Self(), "[[LY;", class_loader);
   ASSERT_TRUE(YA != NULL);
   ASSERT_TRUE(YAA != NULL);
 
-  Class* XAA = class_linker_->FindClass("[[LX;", class_loader);
+  Class* XAA = class_linker_->FindClass(soa.Self(), "[[LX;", class_loader);
   ASSERT_TRUE(XAA != NULL);
 
-  Class* O = class_linker_->FindSystemClass("Ljava/lang/Object;");
-  Class* OA = class_linker_->FindSystemClass("[Ljava/lang/Object;");
-  Class* OAA = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
-  Class* OAAA = class_linker_->FindSystemClass("[[[Ljava/lang/Object;");
+  Class* O = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
+  Class* OA = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;");
+  Class* OAA = class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;");
+  Class* OAAA = class_linker_->FindSystemClass(soa.Self(), "[[[Ljava/lang/Object;");
   ASSERT_TRUE(O != NULL);
   ASSERT_TRUE(OA != NULL);
   ASSERT_TRUE(OAA != NULL);
   ASSERT_TRUE(OAAA != NULL);
 
-  Class* S = class_linker_->FindSystemClass("Ljava/io/Serializable;");
-  Class* SA = class_linker_->FindSystemClass("[Ljava/io/Serializable;");
-  Class* SAA = class_linker_->FindSystemClass("[[Ljava/io/Serializable;");
+  Class* S = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;");
+  Class* SA = class_linker_->FindSystemClass(soa.Self(), "[Ljava/io/Serializable;");
+  Class* SAA = class_linker_->FindSystemClass(soa.Self(), "[[Ljava/io/Serializable;");
   ASSERT_TRUE(S != NULL);
   ASSERT_TRUE(SA != NULL);
   ASSERT_TRUE(SAA != NULL);
 
-  Class* IA = class_linker_->FindSystemClass("[I");
+  Class* IA = class_linker_->FindSystemClass(soa.Self(), "[I");
   ASSERT_TRUE(IA != NULL);
 
   EXPECT_TRUE(YAA->IsAssignableFrom(YAA));  // identity
@@ -616,7 +618,7 @@
   // TODO: check that s.count == 3.
 
   // Ensure that we handle superclass fields correctly...
-  c = class_linker_->FindSystemClass("Ljava/lang/StringBuilder;");
+  c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/StringBuilder;");
   ASSERT_TRUE(c != NULL);
   // No StringBuilder.count...
   EXPECT_TRUE(c->FindDeclaredInstanceField("count", "I") == NULL);