diff options
author | Ian Rogers <irogers@google.com> | 2014-02-24 16:53:16 -0800 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-02-24 18:47:23 -0800 |
commit | 9837939678bb5dcba178e5fb00ed59b5d14c8d9b (patch) | |
tree | 00f0e6b54d7c4cac78a02752e268724157e50b6e /runtime/mirror | |
parent | 3fcf18e25241253f23efbeebe77b2a4c4a7c54d3 (diff) | |
download | art-9837939678bb5dcba178e5fb00ed59b5d14c8d9b.zip art-9837939678bb5dcba178e5fb00ed59b5d14c8d9b.tar.gz art-9837939678bb5dcba178e5fb00ed59b5d14c8d9b.tar.bz2 |
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
Diffstat (limited to 'runtime/mirror')
-rw-r--r-- | runtime/mirror/array.cc | 17 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 5 | ||||
-rw-r--r-- | runtime/mirror/object_test.cc | 82 |
3 files changed, 55 insertions, 49 deletions
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 @@ Array* Array::CreateMultiArray(Thread* self, const SirtRef<Class>& element_class } } - // 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 @@ void Class::SetStatus(Status new_status, Thread* self) { << 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 @@ void Class::SetStatus(Status new_status, Thread* self) { // 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 @@ TEST_F(ObjectTest, AllocObjectArray) { 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 @@ TEST_F(ObjectTest, AllocObjectArray) { 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 @@ void TestPrimitiveArray(ClassLinker* cl) { 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, PrimitiveArray_Short_Alloc) { 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, CheckAndAllocArrayFromCode) { 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 @@ TEST_F(ObjectTest, CreateMultiArray) { 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 @@ TEST_F(ObjectTest, StaticFieldFromCode) { 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 @@ TEST_F(ObjectTest, DescriptorCompare) { 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 @@ TEST_F(ObjectTest, InstanceOf) { 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 @@ TEST_F(ObjectTest, InstanceOf) { 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 @@ TEST_F(ObjectTest, IsAssignableFrom) { 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 @@ TEST_F(ObjectTest, IsAssignableFrom) { 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 @@ TEST_F(ObjectTest, IsAssignableFromArray) { 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 @@ TEST_F(ObjectTest, FindInstanceField) { // 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); |