From 9837939678bb5dcba178e5fb00ed59b5d14c8d9b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 24 Feb 2014 16:53:16 -0800 Subject: 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 --- runtime/class_linker-inl.h | 30 ++++++ runtime/class_linker.cc | 146 +++++++++++++++--------------- runtime/class_linker.h | 26 ++++-- runtime/class_linker_test.cc | 96 +++++++++++--------- runtime/common_test.h | 16 ++-- runtime/debugger.cc | 97 ++++++++++++-------- runtime/entrypoints/entrypoint_utils.h | 2 +- runtime/exception_test.cc | 2 +- runtime/gc/heap_test.cc | 3 +- runtime/gc/space/space_test.h | 5 +- runtime/indirect_reference_table_test.cc | 2 +- runtime/interpreter/interpreter_common.cc | 4 +- runtime/jni_internal.cc | 15 +-- runtime/jni_internal_test.cc | 5 +- runtime/mirror/array.cc | 17 ++-- runtime/mirror/class.cc | 5 +- runtime/mirror/object_test.cc | 82 +++++++++-------- runtime/native/dalvik_system_VMRuntime.cc | 26 +++--- runtime/native/java_lang_Class.cc | 6 +- runtime/native/java_lang_reflect_Array.cc | 8 +- runtime/object_utils.h | 8 +- runtime/scoped_thread_state_change.h | 5 +- runtime/thread.cc | 2 +- runtime/transaction_test.cc | 60 ++++++++---- runtime/utils_test.cc | 11 ++- runtime/verifier/method_verifier.cc | 11 ++- runtime/verifier/method_verifier_test.cc | 2 +- runtime/verifier/reg_type.cc | 7 +- runtime/verifier/reg_type_cache.cc | 9 +- 29 files changed, 403 insertions(+), 305 deletions(-) (limited to 'runtime') diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 66c24b51d2..6ef0082a7b 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -23,10 +23,40 @@ #include "mirror/dex_cache.h" #include "mirror/iftable.h" #include "mirror/object_array.h" +#include "object_utils.h" #include "sirt_ref.h" namespace art { +inline bool ClassLinker::IsInBootClassPath(const char* descriptor) { + DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_); + return pair.second != nullptr; +} + +inline mirror::Class* ClassLinker::FindSystemClass(Thread* self, const char* descriptor) { + SirtRef class_loader(self, nullptr); + return FindClass(self, descriptor, class_loader); +} + +inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class* element_class) { + for (size_t i = 0; i < kFindArrayCacheSize; ++i) { + // Read the cached the 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) { + return array_class; + } + } + std::string descriptor("["); + descriptor += ClassHelper(element_class).GetDescriptor(); + SirtRef class_loader(self, element_class->GetClassLoader()); + 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_; + find_array_class_cache_[victim_index] = array_class; + find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize; + return array_class; +} + inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx, mirror::ArtMethod* referrer) { mirror::String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 48ec5abc7a..a165a68d38 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -176,17 +176,19 @@ ClassLinker::ClassLinker(InternTable* intern_table) : dex_lock_("ClassLinker dex lock", kDefaultMutexLevel), dex_cache_image_class_lookup_required_(false), failed_dex_cache_class_lookups_(0), - class_roots_(NULL), - array_iftable_(NULL), + class_roots_(nullptr), + array_iftable_(nullptr), + find_array_class_cache_next_victim_(0), init_done_(false), dex_caches_dirty_(false), class_table_dirty_(false), intern_table_(intern_table), - portable_resolution_trampoline_(NULL), - quick_resolution_trampoline_(NULL), - portable_imt_conflict_trampoline_(NULL), - quick_imt_conflict_trampoline_(NULL) { + portable_resolution_trampoline_(nullptr), + quick_resolution_trampoline_(nullptr), + portable_imt_conflict_trampoline_(nullptr), + quick_imt_conflict_trampoline_(nullptr) { CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax)); + memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*)); } void ClassLinker::InitFromCompiler(const std::vector& boot_class_path) { @@ -335,54 +337,54 @@ void ClassLinker::InitFromCompiler(const std::vector& boot_class // Object, String and DexCache need to be rerun through FindSystemClass to finish init java_lang_Object->SetStatus(mirror::Class::kStatusNotReady, self); - mirror::Class* Object_class = FindSystemClass("Ljava/lang/Object;"); + mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;"); CHECK_EQ(java_lang_Object.get(), Object_class); CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(mirror::Object)); java_lang_String->SetStatus(mirror::Class::kStatusNotReady, self); - mirror::Class* String_class = FindSystemClass("Ljava/lang/String;"); + mirror::Class* String_class = FindSystemClass(self, "Ljava/lang/String;"); CHECK_EQ(java_lang_String.get(), String_class); CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(mirror::String)); java_lang_DexCache->SetStatus(mirror::Class::kStatusNotReady, self); - mirror::Class* DexCache_class = FindSystemClass("Ljava/lang/DexCache;"); + mirror::Class* DexCache_class = FindSystemClass(self, "Ljava/lang/DexCache;"); CHECK_EQ(java_lang_String.get(), String_class); CHECK_EQ(java_lang_DexCache.get(), DexCache_class); CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(mirror::DexCache)); // Setup the primitive array type classes - can't be done until Object has a vtable. - SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z")); + SetClassRoot(kBooleanArrayClass, FindSystemClass(self, "[Z")); mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); - SetClassRoot(kByteArrayClass, FindSystemClass("[B")); + SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B")); mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); - mirror::Class* found_char_array_class = FindSystemClass("[C"); + mirror::Class* found_char_array_class = FindSystemClass(self, "[C"); CHECK_EQ(char_array_class.get(), found_char_array_class); - SetClassRoot(kShortArrayClass, FindSystemClass("[S")); + SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S")); mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); - mirror::Class* found_int_array_class = FindSystemClass("[I"); + mirror::Class* found_int_array_class = FindSystemClass(self, "[I"); CHECK_EQ(int_array_class.get(), found_int_array_class); - SetClassRoot(kLongArrayClass, FindSystemClass("[J")); + SetClassRoot(kLongArrayClass, FindSystemClass(self, "[J")); mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); - SetClassRoot(kFloatArrayClass, FindSystemClass("[F")); + SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F")); mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); - SetClassRoot(kDoubleArrayClass, FindSystemClass("[D")); + SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D")); mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); - mirror::Class* found_class_array_class = FindSystemClass("[Ljava/lang/Class;"); + mirror::Class* found_class_array_class = FindSystemClass(self, "[Ljava/lang/Class;"); CHECK_EQ(class_array_class.get(), found_class_array_class); - mirror::Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;"); + mirror::Class* found_object_array_class = FindSystemClass(self, "[Ljava/lang/Object;"); CHECK_EQ(object_array_class.get(), found_object_array_class); // Setup the single, global copy of "iftable". - mirror::Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;"); + mirror::Class* java_lang_Cloneable = FindSystemClass(self, "Ljava/lang/Cloneable;"); CHECK(java_lang_Cloneable != NULL); - mirror::Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;"); + mirror::Class* java_io_Serializable = FindSystemClass(self, "Ljava/io/Serializable;"); CHECK(java_io_Serializable != NULL); // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to // crawl up and explicitly list all of the supers as well. @@ -398,73 +400,73 @@ void ClassLinker::InitFromCompiler(const std::vector& boot_class CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1)); // Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their // dex_cache_ fields and register them in class_table_. - mirror::Class* Class_class = FindSystemClass("Ljava/lang/Class;"); + mirror::Class* Class_class = FindSystemClass(self, "Ljava/lang/Class;"); CHECK_EQ(java_lang_Class.get(), Class_class); java_lang_reflect_ArtMethod->SetStatus(mirror::Class::kStatusNotReady, self); - mirror::Class* Art_method_class = FindSystemClass("Ljava/lang/reflect/ArtMethod;"); + mirror::Class* Art_method_class = FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;"); CHECK_EQ(java_lang_reflect_ArtMethod.get(), Art_method_class); java_lang_reflect_ArtField->SetStatus(mirror::Class::kStatusNotReady, self); - mirror::Class* Art_field_class = FindSystemClass("Ljava/lang/reflect/ArtField;"); + mirror::Class* Art_field_class = FindSystemClass(self, "Ljava/lang/reflect/ArtField;"); CHECK_EQ(java_lang_reflect_ArtField.get(), Art_field_class); - mirror::Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]); + mirror::Class* String_array_class = FindSystemClass(self, class_roots_descriptors_[kJavaLangStringArrayClass]); CHECK_EQ(object_array_string.get(), String_array_class); mirror::Class* Art_method_array_class = - FindSystemClass(class_roots_descriptors_[kJavaLangReflectArtMethodArrayClass]); + FindSystemClass(self, class_roots_descriptors_[kJavaLangReflectArtMethodArrayClass]); CHECK_EQ(object_array_art_method.get(), Art_method_array_class); mirror::Class* Art_field_array_class = - FindSystemClass(class_roots_descriptors_[kJavaLangReflectArtFieldArrayClass]); + FindSystemClass(self, class_roots_descriptors_[kJavaLangReflectArtFieldArrayClass]); CHECK_EQ(object_array_art_field.get(), Art_field_array_class); // End of special init trickery, subsequent classes may be loaded via FindSystemClass. // Create java.lang.reflect.Proxy root. - mirror::Class* java_lang_reflect_Proxy = FindSystemClass("Ljava/lang/reflect/Proxy;"); + mirror::Class* java_lang_reflect_Proxy = FindSystemClass(self, "Ljava/lang/reflect/Proxy;"); SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy); // java.lang.ref classes need to be specially flagged, but otherwise are normal classes - mirror::Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;"); + mirror::Class* java_lang_ref_Reference = FindSystemClass(self, "Ljava/lang/ref/Reference;"); SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference); - mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;"); + mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); java_lang_ref_FinalizerReference->SetAccessFlags( java_lang_ref_FinalizerReference->GetAccessFlags() | kAccClassIsReference | kAccClassIsFinalizerReference); - mirror::Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;"); + mirror::Class* java_lang_ref_PhantomReference = FindSystemClass(self, "Ljava/lang/ref/PhantomReference;"); java_lang_ref_PhantomReference->SetAccessFlags( java_lang_ref_PhantomReference->GetAccessFlags() | kAccClassIsReference | kAccClassIsPhantomReference); - mirror::Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;"); + mirror::Class* java_lang_ref_SoftReference = FindSystemClass(self, "Ljava/lang/ref/SoftReference;"); java_lang_ref_SoftReference->SetAccessFlags( java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference); - mirror::Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;"); + mirror::Class* java_lang_ref_WeakReference = FindSystemClass(self, "Ljava/lang/ref/WeakReference;"); java_lang_ref_WeakReference->SetAccessFlags( java_lang_ref_WeakReference->GetAccessFlags() | kAccClassIsReference | kAccClassIsWeakReference); // Setup the ClassLoader, verifying the object_size_. - mirror::Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;"); + mirror::Class* java_lang_ClassLoader = FindSystemClass(self, "Ljava/lang/ClassLoader;"); CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), sizeof(mirror::ClassLoader)); SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader); // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and // java.lang.StackTraceElement as a convenience. - SetClassRoot(kJavaLangThrowable, FindSystemClass("Ljava/lang/Throwable;")); + SetClassRoot(kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;")); mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); - SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass("Ljava/lang/ClassNotFoundException;")); - SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;")); - SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;")); + SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass(self, "Ljava/lang/ClassNotFoundException;")); + SetClassRoot(kJavaLangStackTraceElement, FindSystemClass(self, "Ljava/lang/StackTraceElement;")); + SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass(self, "[Ljava/lang/StackTraceElement;")); mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); - FinishInit(); + FinishInit(self); VLOG(startup) << "ClassLinker::InitFromCompiler exiting"; } -void ClassLinker::FinishInit() { +void ClassLinker::FinishInit(Thread* self) { VLOG(startup) << "ClassLinker::FinishInit entering"; // Let the heap know some key offsets into java.lang.ref instances @@ -473,7 +475,7 @@ void ClassLinker::FinishInit() { // fully initialized mirror::Class* java_lang_ref_Reference = GetClassRoot(kJavaLangRefReference); mirror::Class* java_lang_ref_FinalizerReference = - FindSystemClass("Ljava/lang/ref/FinalizerReference;"); + FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); mirror::ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0); FieldHelper fh(pendingNext); @@ -1111,7 +1113,7 @@ void ClassLinker::InitFromImage() { mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); - FinishInit(); + FinishInit(self); VLOG(startup) << "ClassLinker::InitFromImage exiting"; } @@ -1150,6 +1152,13 @@ void ClassLinker::VisitRoots(RootCallback* callback, void* arg, bool only_dirty, } callback(reinterpret_cast(&array_iftable_), arg, 0, kRootVMInternal); DCHECK(array_iftable_ != nullptr); + for (size_t i = 0; i < kFindArrayCacheSize; ++i) { + if (find_array_class_cache_[i] != nullptr) { + callback(reinterpret_cast(&find_array_class_cache_[i]), arg, 0, + kRootVMInternal); + DCHECK(find_array_class_cache_[i] != nullptr); + } + } } void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) { @@ -1307,21 +1316,10 @@ static mirror::Class* EnsureResolved(Thread* self, mirror::Class* klass) return klass; } -bool ClassLinker::IsInBootClassPath(const char* descriptor) { - DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_); - return pair.second != NULL; -} - -mirror::Class* ClassLinker::FindSystemClass(const char* descriptor) { - SirtRef class_loader(Thread::Current(), nullptr); - return FindClass(descriptor, class_loader); -} - -mirror::Class* ClassLinker::FindClass(const char* descriptor, +mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor, const SirtRef& class_loader) { DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; - Thread* self = Thread::Current(); - DCHECK(self != NULL); + DCHECK(self != nullptr); self->AssertNoPendingException(); if (descriptor[1] == '\0') { // only the descriptors of primitive types should be 1 character long, also avoid class lookup @@ -1335,7 +1333,7 @@ mirror::Class* ClassLinker::FindClass(const char* descriptor, } // Class is not yet loaded. if (descriptor[0] == '[') { - return CreateArrayClass(descriptor, class_loader); + return CreateArrayClass(self, descriptor, class_loader); } else if (class_loader.get() == nullptr) { DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_); if (pair.second != NULL) { @@ -1346,7 +1344,7 @@ mirror::Class* ClassLinker::FindClass(const char* descriptor, // First try the boot class path, we check the descriptor first to avoid an unnecessary // throw of a NoClassDefFoundError. if (IsInBootClassPath(descriptor)) { - mirror::Class* system_class = FindSystemClass(descriptor); + mirror::Class* system_class = FindSystemClass(self, descriptor); CHECK(system_class != NULL); return system_class; } @@ -1365,7 +1363,7 @@ mirror::Class* ClassLinker::FindClass(const char* descriptor, } } else { - ScopedObjectAccessUnchecked soa(self->GetJniEnv()); + ScopedObjectAccessUnchecked soa(self); ScopedLocalRef class_loader_object(soa.Env(), soa.AddLocalReference(class_loader.get())); std::string class_name_string(DescriptorToDot(descriptor)); @@ -1382,7 +1380,7 @@ mirror::Class* ClassLinker::FindClass(const char* descriptor, WellKnownClasses::java_lang_ClassLoader_loadClass, class_name_object.get())); } - if (soa.Self()->IsExceptionPending()) { + if (self->IsExceptionPending()) { // If the ClassLoader threw, pass that exception up. return NULL; } else if (result.get() == NULL) { @@ -2133,12 +2131,11 @@ mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_cl // array class; that always comes from the base element class. // // Returns NULL with an exception raised on failure. -mirror::Class* ClassLinker::CreateArrayClass(const char* descriptor, +mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descriptor, const SirtRef& class_loader) { // Identify the underlying component type CHECK_EQ('[', descriptor[0]); - Thread* self = Thread::Current(); - SirtRef component_type(self, FindClass(descriptor + 1, class_loader)); + SirtRef component_type(self, FindClass(self, descriptor + 1, class_loader)); if (component_type.get() == nullptr) { DCHECK(self->IsExceptionPending()); return nullptr; @@ -3242,7 +3239,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef& kl for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) { mirror::ArtMethod* method = klass->GetVTable()->Get(i); if (method != super->GetVTable()->Get(i) && - !IsSameMethodSignatureInDifferentClassContexts(method, super.get(), klass.get())) { + !IsSameMethodSignatureInDifferentClassContexts(self, method, super.get(), klass.get())) { ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in superclass %s", PrettyDescriptor(klass.get()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(super.get()).c_str()); @@ -3255,7 +3252,7 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef& kl if (klass->GetClassLoader() != interface->GetClassLoader()) { for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j); - if (!IsSameMethodSignatureInDifferentClassContexts(method, interface.get(), + if (!IsSameMethodSignatureInDifferentClassContexts(self, method, interface.get(), method->GetDeclaringClass())) { ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in interface %s", PrettyDescriptor(method->GetDeclaringClass()).c_str(), @@ -3271,13 +3268,13 @@ bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef& kl // Returns true if classes referenced by the signature of the method are the // same classes in klass1 as they are in klass2. -bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method, +bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(Thread* self, + mirror::ArtMethod* method, mirror::Class* klass1, mirror::Class* klass2) { if (klass1 == klass2) { return true; } - Thread* self = Thread::Current(); CHECK(klass1 != nullptr); CHECK(klass2 != nullptr); SirtRef loader1(self, klass1->GetClassLoader()); @@ -3292,7 +3289,7 @@ bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMetho } if (descriptor[0] == 'L' || descriptor[0] == '[') { // Found a non-primitive type. - if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) { + if (!IsSameDescriptorInDifferentClassContexts(self, descriptor, loader1, loader2)) { return false; } } @@ -3300,7 +3297,7 @@ bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMetho // Check the return type const char* descriptor = dex_file.GetReturnTypeDescriptor(proto_id); if (descriptor[0] == 'L' || descriptor[0] == '[') { - if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) { + if (!IsSameDescriptorInDifferentClassContexts(self, descriptor, loader1, loader2)) { return false; } } @@ -3308,16 +3305,15 @@ bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMetho } // Returns true if the descriptor resolves to the same class in the context of loader1 and loader2. -bool ClassLinker::IsSameDescriptorInDifferentClassContexts(const char* descriptor, +bool ClassLinker::IsSameDescriptorInDifferentClassContexts(Thread* self, const char* descriptor, SirtRef& loader1, SirtRef& loader2) { CHECK(descriptor != nullptr); - Thread* self = Thread::Current(); - SirtRef found1(self, FindClass(descriptor, loader1)); + SirtRef found1(self, FindClass(self, descriptor, loader1)); if (found1.get() == nullptr) { self->ClearException(); } - mirror::Class* found2 = FindClass(descriptor, loader2); + mirror::Class* found2 = FindClass(self, descriptor, loader2); if (found2 == nullptr) { self->ClearException(); } @@ -4117,22 +4113,22 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_i DCHECK(dex_cache.get() != NULL); mirror::Class* resolved = dex_cache->GetResolvedType(type_idx); if (resolved == NULL) { + Thread* self = Thread::Current(); const char* descriptor = dex_file.StringByTypeIdx(type_idx); - resolved = FindClass(descriptor, class_loader); + resolved = FindClass(self, descriptor, class_loader); if (resolved != NULL) { // TODO: we used to throw here if resolved's class loader was not the // boot class loader. This was to permit different classes with the // same name to be loaded simultaneously by different loaders dex_cache->SetResolvedType(type_idx, resolved); } else { - Thread* self = Thread::Current(); CHECK(self->IsExceptionPending()) << "Expected pending exception for failed resolution of: " << descriptor; // Convert a ClassNotFoundException to a NoClassDefFoundError. SirtRef cause(self, self->GetException(NULL)); if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) { DCHECK(resolved == NULL); // No SirtRef needed to preserve resolved. - Thread::Current()->ClearException(); + self->ClearException(); ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor); self->GetException(NULL)->SetCause(cause.get()); } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 0745ee2b09..f346102f97 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -72,10 +72,17 @@ class ClassLinker { // Finds a class by its descriptor, loading it if necessary. // If class_loader is null, searches boot_class_path_. - mirror::Class* FindClass(const char* descriptor, const SirtRef& class_loader) + mirror::Class* FindClass(Thread* self, const char* descriptor, + const SirtRef& class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::Class* FindSystemClass(const char* descriptor) + // Finds a class by its descriptor using the "system" class loader, ie by searching the + // boot_class_path_. + mirror::Class* FindSystemClass(Thread* self, const char* descriptor) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Finds the array class given for the 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. @@ -378,7 +385,7 @@ class ClassLinker { LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void FinishInit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FinishInit(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // For early bootstrapping by Init mirror::Class* AllocClass(Thread* self, mirror::Class* java_lang_Class, size_t class_size) @@ -399,7 +406,7 @@ class ClassLinker { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::Class* CreateArrayClass(const char* descriptor, + mirror::Class* CreateArrayClass(Thread* self, const char* descriptor, const SirtRef& class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -449,12 +456,12 @@ class ClassLinker { bool ValidateSuperClassDescriptors(const SirtRef& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsSameDescriptorInDifferentClassContexts(const char* descriptor, + bool IsSameDescriptorInDifferentClassContexts(Thread* self, const char* descriptor, SirtRef& class_loader1, SirtRef& class_loader2) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method, + bool IsSameMethodSignatureInDifferentClassContexts(Thread* self, mirror::ArtMethod* method, mirror::Class* klass1, mirror::Class* klass2) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -617,8 +624,15 @@ class ClassLinker { return descriptor; } + // The interface table used by all arrays. mirror::IfTable* array_iftable_; + // A cache of the last FindArrayClass results. The cache serves to avoid creating array class + // descriptors for the sake of performing FindClass. + static constexpr size_t kFindArrayCacheSize = 16; + mirror::Class* find_array_class_cache_[kFindArrayCacheSize]; + size_t find_array_class_cache_next_victim_; + bool init_done_; bool dex_caches_dirty_ GUARDED_BY(dex_lock_); bool class_table_dirty_ GUARDED_BY(Locks::classlinker_classes_lock_); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index ebf02fe888..d6a67ccc7a 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -41,18 +41,20 @@ class ClassLinkerTest : public CommonTest { protected: void AssertNonExistentClass(const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - EXPECT_TRUE(class_linker_->FindSystemClass(descriptor.c_str()) == NULL); Thread* self = Thread::Current(); + EXPECT_TRUE(class_linker_->FindSystemClass(self, descriptor.c_str()) == NULL); EXPECT_TRUE(self->IsExceptionPending()); mirror::Object* exception = self->GetException(NULL); self->ClearException(); - mirror::Class* exception_class = class_linker_->FindSystemClass("Ljava/lang/NoClassDefFoundError;"); + mirror::Class* exception_class = + class_linker_->FindSystemClass(self, "Ljava/lang/NoClassDefFoundError;"); EXPECT_TRUE(exception->InstanceOf(exception_class)); } void AssertPrimitiveClass(const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(descriptor.c_str())); + Thread* self = Thread::Current(); + AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(self, descriptor.c_str())); } void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive) @@ -98,7 +100,7 @@ class ClassLinkerTest : public CommonTest { Thread* self = Thread::Current(); SirtRef loader(self, class_loader); SirtRef array(self, - class_linker_->FindClass(array_descriptor.c_str(), loader)); + class_linker_->FindClass(self, array_descriptor.c_str(), loader)); ClassHelper array_component_ch(array->GetComponentType()); EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor()); EXPECT_EQ(class_loader, array->GetClassLoader()); @@ -115,7 +117,8 @@ class ClassLinkerTest : public CommonTest { EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL); ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor()); EXPECT_TRUE(array->GetSuperClass() != NULL); - EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass()); + Thread* self = Thread::Current(); + EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass()); EXPECT_TRUE(array->HasSuperClass()); ASSERT_TRUE(array->GetComponentType() != NULL); kh.ChangeClass(array->GetComponentType()); @@ -147,6 +150,7 @@ class ClassLinkerTest : public CommonTest { kh.ChangeClass(array.get()); kh.ChangeClass(kh.GetDirectInterface(1)); EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;"); + EXPECT_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.get()); } void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -300,8 +304,8 @@ class ClassLinkerTest : public CommonTest { void AssertDexFileClass(mirror::ClassLoader* class_loader, const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ASSERT_TRUE(descriptor != NULL); - SirtRef klass(Thread::Current(), - class_linker_->FindSystemClass(descriptor.c_str())); + Thread* self = Thread::Current(); + SirtRef klass(self, class_linker_->FindSystemClass(self, descriptor.c_str())); ASSERT_TRUE(klass.get() != nullptr); EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass.get()).GetDescriptor()); EXPECT_EQ(class_loader, klass->GetClassLoader()); @@ -359,7 +363,9 @@ struct CheckOffsets { std::vector offsets; bool Check() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Class* klass = Runtime::Current()->GetClassLinker()->FindSystemClass(class_descriptor.c_str()); + Thread* self = Thread::Current(); + mirror::Class* klass = + Runtime::Current()->GetClassLinker()->FindSystemClass(self, class_descriptor.c_str()); CHECK(klass != NULL) << class_descriptor; bool error = false; @@ -646,12 +652,12 @@ TEST_F(ClassLinkerTest, FindClassNested) { ScopedObjectAccess soa(Thread::Current()); SirtRef class_loader(soa.Self(), soa.Decode(LoadDex("Nested"))); - mirror::Class* outer = class_linker_->FindClass("LNested;", class_loader); + mirror::Class* outer = class_linker_->FindClass(soa.Self(), "LNested;", class_loader); ASSERT_TRUE(outer != NULL); EXPECT_EQ(0U, outer->NumVirtualMethods()); EXPECT_EQ(1U, outer->NumDirectMethods()); - mirror::Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader); + mirror::Class* inner = class_linker_->FindClass(soa.Self(), "LNested$Inner;", class_loader); ASSERT_TRUE(inner != NULL); EXPECT_EQ(0U, inner->NumVirtualMethods()); EXPECT_EQ(1U, inner->NumDirectMethods()); @@ -673,7 +679,7 @@ TEST_F(ClassLinkerTest, FindClass_Primitives) { TEST_F(ClassLinkerTest, FindClass) { ScopedObjectAccess soa(Thread::Current()); - mirror::Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;"); + mirror::Class* JavaLangObject = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); ClassHelper kh(JavaLangObject); ASSERT_TRUE(JavaLangObject != NULL); ASSERT_TRUE(JavaLangObject->GetClass() != NULL); @@ -710,7 +716,7 @@ TEST_F(ClassLinkerTest, FindClass) { SirtRef class_loader(soa.Self(), soa.Decode(LoadDex("MyClass"))); AssertNonExistentClass("LMyClass;"); - mirror::Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader); + mirror::Class* MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); kh.ChangeClass(MyClass); ASSERT_TRUE(MyClass != NULL); ASSERT_TRUE(MyClass->GetClass() != NULL); @@ -761,7 +767,7 @@ TEST_F(ClassLinkerTest, LibCore) { // start of the object TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) { ScopedObjectAccess soa(Thread::Current()); - mirror::Class* array_class = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* array_class = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;"); mirror::ObjectArray* array = mirror::ObjectArray::Alloc(soa.Self(), array_class, 0); uintptr_t data_offset = @@ -777,27 +783,27 @@ TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) { TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) { ScopedObjectAccess soa(Thread::Current()); SirtRef long_array(soa.Self(), mirror::LongArray::Alloc(soa.Self(), 0)); - EXPECT_EQ(class_linker_->FindSystemClass("[J"), long_array->GetClass()); + EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[J"), long_array->GetClass()); uintptr_t data_offset = reinterpret_cast(long_array->GetData()); EXPECT_TRUE(IsAligned<8>(data_offset)); // Longs require 8 byte alignment SirtRef double_array(soa.Self(), mirror::DoubleArray::Alloc(soa.Self(), 0)); - EXPECT_EQ(class_linker_->FindSystemClass("[D"), double_array->GetClass()); + EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[D"), double_array->GetClass()); data_offset = reinterpret_cast(double_array->GetData()); EXPECT_TRUE(IsAligned<8>(data_offset)); // Doubles require 8 byte alignment SirtRef int_array(soa.Self(), mirror::IntArray::Alloc(soa.Self(), 0)); - EXPECT_EQ(class_linker_->FindSystemClass("[I"), int_array->GetClass()); + EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[I"), int_array->GetClass()); data_offset = reinterpret_cast(int_array->GetData()); EXPECT_TRUE(IsAligned<4>(data_offset)); // Ints require 4 byte alignment SirtRef char_array(soa.Self(), mirror::CharArray::Alloc(soa.Self(), 0)); - EXPECT_EQ(class_linker_->FindSystemClass("[C"), char_array->GetClass()); + EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[C"), char_array->GetClass()); data_offset = reinterpret_cast(char_array->GetData()); EXPECT_TRUE(IsAligned<2>(data_offset)); // Chars require 2 byte alignment SirtRef short_array(soa.Self(), mirror::ShortArray::Alloc(soa.Self(), 0)); - EXPECT_EQ(class_linker_->FindSystemClass("[S"), short_array->GetClass()); + EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[S"), short_array->GetClass()); data_offset = reinterpret_cast(short_array->GetData()); EXPECT_TRUE(IsAligned<2>(data_offset)); // Shorts require 2 byte alignment @@ -810,28 +816,28 @@ TEST_F(ClassLinkerTest, ValidateBoxedTypes) { ScopedObjectAccess soa(Thread::Current()); SirtRef class_loader(soa.Self(), nullptr); mirror::Class* c; - c = class_linker_->FindClass("Ljava/lang/Boolean;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader); FieldHelper fh(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Byte;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Byte;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Character;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Character;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Double;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Double;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Float;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Float;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Integer;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Integer;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Long;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Long;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); - c = class_linker_->FindClass("Ljava/lang/Short;", class_loader); + c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Short;", class_loader); fh.ChangeField(c->GetIFields()->Get(0)); EXPECT_STREQ("value", fh.GetName()); } @@ -840,8 +846,8 @@ TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { ScopedObjectAccess soa(Thread::Current()); SirtRef class_loader_1(soa.Self(), soa.Decode(LoadDex("MyClass"))); SirtRef class_loader_2(soa.Self(), soa.Decode(LoadDex("MyClass"))); - mirror::Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1); - mirror::Class* MyClass_2 = class_linker_->FindClass("LMyClass;", class_loader_2); + mirror::Class* MyClass_1 = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_1); + mirror::Class* MyClass_2 = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_2); EXPECT_TRUE(MyClass_1 != NULL); EXPECT_TRUE(MyClass_2 != NULL); EXPECT_NE(MyClass_1, MyClass_2); @@ -849,8 +855,10 @@ TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { TEST_F(ClassLinkerTest, StaticFields) { ScopedObjectAccess soa(Thread::Current()); - SirtRef class_loader(soa.Self(), soa.Decode(LoadDex("Statics"))); - SirtRef statics(soa.Self(), class_linker_->FindClass("LStatics;", class_loader)); + SirtRef class_loader(soa.Self(), + soa.Decode(LoadDex("Statics"))); + SirtRef statics(soa.Self(), class_linker_->FindClass(soa.Self(), "LStatics;", + class_loader)); class_linker_->EnsureInitialized(statics, true, true); // Static final primitives that are initialized by a compile-time constant @@ -933,11 +941,11 @@ TEST_F(ClassLinkerTest, StaticFields) { TEST_F(ClassLinkerTest, Interfaces) { ScopedObjectAccess soa(Thread::Current()); SirtRef class_loader(soa.Self(), soa.Decode(LoadDex("Interfaces"))); - mirror::Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader); - mirror::Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader); - mirror::Class* K = class_linker_->FindClass("LInterfaces$K;", class_loader); - mirror::Class* A = class_linker_->FindClass("LInterfaces$A;", class_loader); - mirror::Class* B = class_linker_->FindClass("LInterfaces$B;", class_loader); + mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader); + mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader); + mirror::Class* K = class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader); + mirror::Class* A = class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader); + mirror::Class* B = class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader); EXPECT_TRUE(I->IsAssignableFrom(A)); EXPECT_TRUE(J->IsAssignableFrom(A)); EXPECT_TRUE(J->IsAssignableFrom(K)); @@ -996,7 +1004,7 @@ TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) { SirtRef class_loader(soa.Self(), soa.Decode(jclass_loader)); const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(jclass_loader)[0]; CHECK(dex_file != NULL); - mirror::Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader); + mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader); mirror::ArtMethod* clinit = klass->FindClassInitializer(); mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;"); const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;"); @@ -1017,32 +1025,32 @@ TEST_F(ClassLinkerTest, FinalizableBit) { mirror::Class* c; // Object has a finalize method, but we know it's empty. - c = class_linker_->FindSystemClass("Ljava/lang/Object;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); EXPECT_FALSE(c->IsFinalizable()); // Enum has a finalize method to prevent its subclasses from implementing one. - c = class_linker_->FindSystemClass("Ljava/lang/Enum;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Enum;"); EXPECT_FALSE(c->IsFinalizable()); // RoundingMode is an enum. - c = class_linker_->FindSystemClass("Ljava/math/RoundingMode;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/math/RoundingMode;"); EXPECT_FALSE(c->IsFinalizable()); // RandomAccessFile extends Object and overrides finalize. - c = class_linker_->FindSystemClass("Ljava/io/RandomAccessFile;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/RandomAccessFile;"); EXPECT_TRUE(c->IsFinalizable()); // FileInputStream is finalizable and extends InputStream which isn't. - c = class_linker_->FindSystemClass("Ljava/io/InputStream;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/InputStream;"); EXPECT_FALSE(c->IsFinalizable()); - c = class_linker_->FindSystemClass("Ljava/io/FileInputStream;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/FileInputStream;"); EXPECT_TRUE(c->IsFinalizable()); // ScheduledThreadPoolExecutor doesn't have a finalize method but // extends ThreadPoolExecutor which does. - c = class_linker_->FindSystemClass("Ljava/util/concurrent/ThreadPoolExecutor;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/concurrent/ThreadPoolExecutor;"); EXPECT_TRUE(c->IsFinalizable()); - c = class_linker_->FindSystemClass("Ljava/util/concurrent/ScheduledThreadPoolExecutor;"); + c = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/concurrent/ScheduledThreadPoolExecutor;"); EXPECT_TRUE(c->IsFinalizable()); } diff --git a/runtime/common_test.h b/runtime/common_test.h index 7f9b6b192b..215b6428bb 100644 --- a/runtime/common_test.h +++ b/runtime/common_test.h @@ -418,8 +418,9 @@ class CommonTest : public testing::Test { void MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string class_descriptor(DotToDescriptor(class_name)); - SirtRef loader(Thread::Current(), class_loader); - mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader); + Thread* self = Thread::Current(); + SirtRef loader(self, class_loader); + mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader); CHECK(klass != NULL) << "Class not found " << class_name; for (size_t i = 0; i < klass->NumDirectMethods(); i++) { MakeExecutable(klass->GetDirectMethod(i)); @@ -632,8 +633,9 @@ class CommonTest : public testing::Test { void CompileClass(mirror::ClassLoader* class_loader, const char* class_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string class_descriptor(DotToDescriptor(class_name)); - SirtRef loader(Thread::Current(), class_loader); - mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader); + Thread* self = Thread::Current(); + SirtRef loader(self, class_loader); + mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader); CHECK(klass != NULL) << "Class not found " << class_name; for (size_t i = 0; i < klass->NumDirectMethods(); i++) { CompileMethod(klass->GetDirectMethod(i)); @@ -656,7 +658,8 @@ class CommonTest : public testing::Test { const char* method_name, const char* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string class_descriptor(DotToDescriptor(class_name)); - mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); + Thread* self = Thread::Current(); + mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader); CHECK(klass != NULL) << "Class not found " << class_name; mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature); CHECK(method != NULL) << "Direct method not found: " @@ -668,7 +671,8 @@ class CommonTest : public testing::Test { const char* method_name, const char* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::string class_descriptor(DotToDescriptor(class_name)); - mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); + Thread* self = Thread::Current(); + mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader); CHECK(klass != NULL) << "Class not found " << class_name; mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature); CHECK(method != NULL) << "Virtual method not found: " diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 89f841eb3d..d3f684dc0c 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -289,27 +289,39 @@ static JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) { return static_cast(descriptor[0]); } -static JDWP::JdwpTag TagFromClass(mirror::Class* c) +static JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(c != NULL); if (c->IsArrayClass()) { return JDWP::JT_ARRAY; } - - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (c->IsStringClass()) { return JDWP::JT_STRING; - } else if (c->IsClassClass()) { + } + if (c->IsClassClass()) { return JDWP::JT_CLASS_OBJECT; - } else if (class_linker->FindSystemClass("Ljava/lang/Thread;")->IsAssignableFrom(c)) { - return JDWP::JT_THREAD; - } else if (class_linker->FindSystemClass("Ljava/lang/ThreadGroup;")->IsAssignableFrom(c)) { - return JDWP::JT_THREAD_GROUP; - } else if (class_linker->FindSystemClass("Ljava/lang/ClassLoader;")->IsAssignableFrom(c)) { - return JDWP::JT_CLASS_LOADER; - } else { - return JDWP::JT_OBJECT; } + { + mirror::Class* thread_class = soa.Decode(WellKnownClasses::java_lang_Thread); + if (thread_class->IsAssignableFrom(c)) { + return JDWP::JT_THREAD; + } + } + { + mirror::Class* thread_group_class = + soa.Decode(WellKnownClasses::java_lang_ThreadGroup); + if (thread_group_class->IsAssignableFrom(c)) { + return JDWP::JT_THREAD_GROUP; + } + } + { + mirror::Class* class_loader_class = + soa.Decode(WellKnownClasses::java_lang_ClassLoader); + if (class_loader_class->IsAssignableFrom(c)) { + return JDWP::JT_CLASS_LOADER; + } + } + return JDWP::JT_OBJECT; } /* @@ -320,9 +332,9 @@ static JDWP::JdwpTag TagFromClass(mirror::Class* c) * * Null objects are tagged JT_OBJECT. */ -static JDWP::JdwpTag TagFromObject(mirror::Object* o) +static JDWP::JdwpTag TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(o->GetClass()); + return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass()); } static bool IsPrimitiveTag(JDWP::JdwpTag tag) { @@ -1011,11 +1023,12 @@ JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string& result } JDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) { + ScopedObjectAccessUnchecked soa(Thread::Current()); mirror::Object* o = gRegistry->Get(object_id); if (o == ObjectRegistry::kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - tag = TagFromObject(o); + tag = TagFromObject(soa, o); return JDWP::ERR_NONE; } @@ -1062,7 +1075,7 @@ JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int& length) { JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) { JDWP::JdwpError status; mirror::Array* a = DecodeArray(array_id, status); - if (a == NULL) { + if (a == nullptr) { return status; } @@ -1093,10 +1106,12 @@ JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, memcpy(dst, &src[offset * width], count * width); } } else { + ScopedObjectAccessUnchecked soa(Thread::Current()); mirror::ObjectArray* oa = a->AsObjectArray(); for (int i = 0; i < count; ++i) { mirror::Object* element = oa->Get(offset + i); - JDWP::JdwpTag specific_tag = (element != NULL) ? TagFromObject(element) : tag; + JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element) + : tag; expandBufAdd1(pReply, specific_tag); expandBufAddObjectId(pReply, gRegistry->Add(element)); } @@ -1639,8 +1654,9 @@ void Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::Expa CHECK_EQ(tag, JDWP::JT_VOID); } } else { + ScopedObjectAccessUnchecked soa(Thread::Current()); mirror::Object* value = return_value->GetL(); - expandBufAdd1(pReply, TagFromObject(value)); + expandBufAdd1(pReply, TagFromObject(soa, value)); expandBufAddObjectId(pReply, gRegistry->Add(value)); } } @@ -1672,7 +1688,7 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p if (thread_object == ObjectRegistry::kInvalidObject) { return JDWP::ERR_INVALID_OBJECT; } - + const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroup"); // Okay, so it's an object, but is it actually a thread? MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread; @@ -1685,14 +1701,14 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p if (error != JDWP::ERR_NONE) { return error; } - - mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Thread;"); - CHECK(c != NULL); + mirror::Class* c = soa.Decode(WellKnownClasses::java_lang_Thread); + CHECK(c != nullptr); mirror::ArtField* f = c->FindInstanceField("group", "Ljava/lang/ThreadGroup;"); CHECK(f != NULL); mirror::Object* group = f->GetObject(thread_object); CHECK(group != NULL); JDWP::ObjectId thread_group_id = gRegistry->Add(group); + soa.Self()->EndAssertNoThreadSuspension(old_cause); expandBufAddObjectId(pReply, thread_group_id); return JDWP::ERR_NONE; @@ -1701,25 +1717,28 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p std::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) { ScopedObjectAccess soa(Thread::Current()); mirror::Object* thread_group = gRegistry->Get(thread_group_id); - CHECK(thread_group != NULL); - - mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;"); - CHECK(c != NULL); + CHECK(thread_group != nullptr); + const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupName"); + mirror::Class* c = soa.Decode(WellKnownClasses::java_lang_ThreadGroup); + CHECK(c != nullptr); mirror::ArtField* f = c->FindInstanceField("name", "Ljava/lang/String;"); CHECK(f != NULL); mirror::String* s = reinterpret_cast(f->GetObject(thread_group)); + soa.Self()->EndAssertNoThreadSuspension(old_cause); return s->ToModifiedUtf8(); } JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) { + ScopedObjectAccessUnchecked soa(Thread::Current()); mirror::Object* thread_group = gRegistry->Get(thread_group_id); - CHECK(thread_group != NULL); - - mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;"); - CHECK(c != NULL); + CHECK(thread_group != nullptr); + const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupParent"); + mirror::Class* c = soa.Decode(WellKnownClasses::java_lang_ThreadGroup); + CHECK(c != nullptr); mirror::ArtField* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;"); CHECK(f != NULL); mirror::Object* parent = f->GetObject(thread_group); + soa.Self()->EndAssertNoThreadSuspension(old_cause); return gRegistry->Add(parent); } @@ -2090,13 +2109,13 @@ JDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame return JDWP::ERR_NONE; } -void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, - uint8_t* buf, size_t width) { +void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, + JDWP::JdwpTag tag, uint8_t* buf, size_t width) { struct GetLocalVisitor : public StackVisitor { - GetLocalVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id, int slot, - JDWP::JdwpTag tag, uint8_t* buf, size_t width) + GetLocalVisitor(const ScopedObjectAccessUnchecked& soa, Thread* thread, Context* context, + JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : StackVisitor(thread, context), frame_id_(frame_id), slot_(slot), tag_(tag), + : StackVisitor(thread, context), soa_(soa), frame_id_(frame_id), slot_(slot), tag_(tag), buf_(buf), width_(width) {} // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses @@ -2175,7 +2194,7 @@ void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { LOG(FATAL) << "Register " << reg << " expected to hold object: " << o; } - tag_ = TagFromObject(o); + tag_ = TagFromObject(soa_, o); JDWP::SetObjectId(buf_+1, gRegistry->Add(o)); } break; @@ -2208,7 +2227,7 @@ void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl JDWP::Set1(buf_, tag_); return false; } - + const ScopedObjectAccessUnchecked& soa_; const JDWP::FrameId frame_id_; const int slot_; JDWP::JdwpTag tag_; @@ -2224,7 +2243,7 @@ void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int sl return; } UniquePtr context(Context::Create()); - GetLocalVisitor visitor(thread, context.get(), frame_id, slot, tag, buf, width); + GetLocalVisitor visitor(soa, thread, context.get(), frame_id, slot, tag, buf, width); visitor.WalkStack(); } @@ -3037,7 +3056,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { pReq->result_value.SetJ(0); } else if (pReq->result_tag == JDWP::JT_OBJECT) { /* if no exception thrown, examine object result more closely */ - JDWP::JdwpTag new_tag = TagFromObject(pReq->result_value.GetL()); + JDWP::JdwpTag new_tag = TagFromObject(soa, pReq->result_value.GetL()); if (new_tag != pReq->result_tag) { VLOG(jdwp) << " JDWP promoted result from " << pReq->result_tag << " to " << new_tag; pReq->result_tag = new_tag; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 8b94b5abe1..2c083518a3 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -18,7 +18,7 @@ #define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ #include "base/macros.h" -#include "class_linker.h" +#include "class_linker-inl.h" #include "common_throws.h" #include "dex_file.h" #include "indirect_reference_table.h" diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc index f7b621fb7e..c7f537a785 100644 --- a/runtime/exception_test.cc +++ b/runtime/exception_test.cc @@ -39,7 +39,7 @@ class ExceptionTest : public CommonTest { ScopedObjectAccess soa(Thread::Current()); SirtRef class_loader( soa.Self(), soa.Decode(LoadDex("ExceptionHandle"))); - my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader); + my_klass_ = class_linker_->FindClass(soa.Self(), "LExceptionHandle;", class_loader); ASSERT_TRUE(my_klass_ != NULL); SirtRef sirt_klass(soa.Self(), my_klass_); class_linker_->EnsureInitialized(sirt_klass, true, true); diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc index b02b8bb022..4b863397c4 100644 --- a/runtime/gc/heap_test.cc +++ b/runtime/gc/heap_test.cc @@ -43,7 +43,8 @@ TEST_F(HeapTest, GarbageCollectClassLinkerInit) { ScopedObjectAccess soa(Thread::Current()); // garbage is created during ClassLinker::Init - SirtRef c(soa.Self(), class_linker_->FindSystemClass("[Ljava/lang/Object;")); + SirtRef c(soa.Self(), class_linker_->FindSystemClass(soa.Self(), + "[Ljava/lang/Object;")); for (size_t i = 0; i < 1024; ++i) { SirtRef > array(soa.Self(), mirror::ObjectArray::Alloc(soa.Self(), c.get(), 2048)); diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h index d01bf2c33b..093967ead0 100644 --- a/runtime/gc/space/space_test.h +++ b/runtime/gc/space/space_test.h @@ -43,8 +43,9 @@ class SpaceTest : public CommonTest { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Note the minimum size, which is the size of a zero-length byte array. EXPECT_GE(size, SizeOfZeroLengthByteArray()); - SirtRef null_loader(Thread::Current(), nullptr); - mirror::Class* byte_array_class = Runtime::Current()->GetClassLinker()->FindClass("[B", + Thread* self = Thread::Current(); + SirtRef null_loader(self, nullptr); + mirror::Class* byte_array_class = Runtime::Current()->GetClassLinker()->FindClass(self, "[B", null_loader); EXPECT_TRUE(byte_array_class != nullptr); o->SetClass(byte_array_class); diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc index b6c6cb4be3..78e1992391 100644 --- a/runtime/indirect_reference_table_test.cc +++ b/runtime/indirect_reference_table_test.cc @@ -48,7 +48,7 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { static const size_t kTableMax = 20; IndirectReferenceTable irt(kTableInitial, kTableMax, kGlobal); - mirror::Class* c = class_linker_->FindSystemClass("Ljava/lang/Object;"); + mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"); ASSERT_TRUE(c != NULL); mirror::Object* obj0 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj0 != NULL); diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 9e1d915a0f..83a1fbc6e2 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -280,7 +280,7 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh, std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str())); SirtRef class_loader(self, nullptr); // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader(); - Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(), + Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(), class_loader); CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: " << PrettyDescriptor(descriptor); @@ -289,7 +289,7 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh, SirtRef class_loader(self, down_cast(shadow_frame->GetVRegReference(arg_offset))); std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset + 1)->AsString()->ToModifiedUtf8().c_str())); - Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(), + Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(), class_loader); result->SetL(found); } else if (name == "java.lang.Object java.lang.Class.newInstance()") { diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index a0665b57a8..76aa734220 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -27,7 +27,7 @@ #include "base/mutex.h" #include "base/stl_util.h" #include "base/stringpiece.h" -#include "class_linker.h" +#include "class_linker-inl.h" #include "dex_file-inl.h" #include "gc/accounting/card_table-inl.h" #include "interpreter/interpreter.h" @@ -284,7 +284,7 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (sig[1] != '\0') { SirtRef class_loader(soa.Self(), c->GetClassLoader()); - field_type = class_linker->FindClass(sig, class_loader); + field_type = class_linker->FindClass(soa.Self(), sig, class_loader); } else { field_type = class_linker->FindPrimitiveClass(*sig); } @@ -651,9 +651,9 @@ class JNI { mirror::Class* c = nullptr; if (runtime->IsStarted()) { SirtRef class_loader(soa.Self(), GetClassLoader(soa)); - c = class_linker->FindClass(descriptor.c_str(), class_loader); + c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader); } else { - c = class_linker->FindSystemClass(descriptor.c_str()); + c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str()); } return soa.AddLocalReference(c); } @@ -2140,13 +2140,8 @@ class JNI { PrettyDescriptor(element_class).c_str()); return nullptr; } - std::string descriptor("["); - descriptor += ClassHelper(element_class).GetDescriptor(); - - // Find the class. ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - SirtRef class_loader(soa.Self(), element_class->GetClassLoader()); - array_class = class_linker->FindClass(descriptor.c_str(), class_loader); + array_class = class_linker->FindArrayClass(soa.Self(), element_class); if (UNLIKELY(array_class == nullptr)) { return nullptr; } diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index 2dd7d96c05..63bc45cbd2 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -107,7 +107,8 @@ class JniInternalTest : public CommonTest { class_name); } - mirror::Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(), class_loader); + mirror::Class* c = class_linker_->FindClass(self, DotToDescriptor(class_name).c_str(), + class_loader); CHECK(c != NULL); *method = is_static ? c->FindDirectMethod(method_name, method_signature) @@ -1778,7 +1779,7 @@ TEST_F(JniInternalTest, StaticMainMethod) { class_loader(soa.Self(), soa.Decode(jclass_loader)); CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V"); - mirror::Class* klass = class_linker_->FindClass("LMain;", class_loader); + mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader); ASSERT_TRUE(klass != NULL); mirror::ArtMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V"); diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc index 2180857019..715f072c4a 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& 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 class_loader(self, element_class->GetClassLoader()); SirtRef 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 3208de9566..6dbb29dae3 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 40c37489cc..34fb15e98d 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 a(soa.Self(), Array::Alloc(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(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(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 c(soa.Self(), class_linker_->FindSystemClass("I")); + SirtRef c(soa.Self(), class_linker_->FindSystemClass(soa.Self(), "I")); SirtRef dims(soa.Self(), IntArray::Alloc(soa.Self(), 1)); dims->Set(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(0, -1); @@ -253,11 +256,11 @@ TEST_F(ObjectTest, CreateMultiArray) { dims->Set(0, i); dims->Set(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()->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 loader(soa.Self(), soa.Decode(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 class_loader_1(soa.Self(), soa.Decode(jclass_loader_1)); SirtRef class_loader_2(soa.Self(), soa.Decode(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 class_loader(soa.Self(), soa.Decode(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::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 class_loader(soa.Self(), soa.Decode(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 class_loader(soa.Self(), soa.Decode(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); diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index def32924c5..5779442271 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -16,7 +16,7 @@ #include -#include "class_linker.h" +#include "class_linker-inl.h" #include "common_throws.h" #include "debugger.h" #include "dex_file-inl.h" @@ -57,22 +57,22 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle jint length) { ScopedFastNativeObjectAccess soa(env); mirror::Class* element_class = soa.Decode(javaElementClass); - if (element_class == NULL) { + if (UNLIKELY(element_class == nullptr)) { ThrowNullPointerException(NULL, "element class == null"); - return NULL; + return nullptr; } - if (length < 0) { + if (UNLIKELY(length < 0)) { ThrowNegativeArraySizeException(length); - return NULL; - } - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - std::string descriptor; - descriptor += "["; - descriptor += ClassHelper(element_class).GetDescriptor(); - SirtRef class_loader(soa.Self(), nullptr); - mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader); + return nullptr; + } + Runtime* runtime = Runtime::Current(); + mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class); + if (UNLIKELY(array_class == nullptr)) { + return nullptr; + } + gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentNonMovingAllocator(); mirror::Array* result = mirror::Array::Alloc(soa.Self(), array_class, length, - Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator()); + allocator); return soa.AddLocalReference(result); } diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 3e3f608c89..8bf36e7e37 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -43,7 +43,8 @@ static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobje } // "name" is in "binary name" format, e.g. "dalvik.system.Debug$1". -static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) { +static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, + jobject javaLoader) { ScopedObjectAccess soa(env); ScopedUtfChars name(env, javaName); if (name.c_str() == nullptr) { @@ -64,7 +65,8 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean SirtRef class_loader(soa.Self(), soa.Decode(javaLoader)); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - SirtRef c(soa.Self(), class_linker->FindClass(descriptor.c_str(), class_loader)); + SirtRef c(soa.Self(), class_linker->FindClass(soa.Self(), descriptor.c_str(), + class_loader)); if (c.get() == nullptr) { ScopedLocalRef cause(env, env->ExceptionOccurred()); env->ExceptionClear(); diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc index 21975974e4..fc30aa6a1b 100644 --- a/runtime/native/java_lang_reflect_Array.cc +++ b/runtime/native/java_lang_reflect_Array.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "class_linker.h" +#include "class_linker-inl.h" #include "common_throws.h" #include "dex_file-inl.h" #include "jni_internal.h" @@ -50,12 +50,8 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl ThrowNegativeArraySizeException(length); return NULL; } - std::string descriptor("["); - descriptor += ClassHelper(element_class).GetDescriptor(); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - SirtRef class_loader(soa.Self(), element_class->GetClassLoader()); - mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader); + 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/object_utils.h b/runtime/object_utils.h index a981fabf3d..4eac29164e 100644 --- a/runtime/object_utils.h +++ b/runtime/object_utils.h @@ -17,7 +17,7 @@ #ifndef ART_RUNTIME_OBJECT_UTILS_H_ #define ART_RUNTIME_OBJECT_UTILS_H_ -#include "class_linker-inl.h" +#include "class_linker.h" #include "dex_file.h" #include "monitor.h" #include "mirror/art_field.h" @@ -158,10 +158,10 @@ class ClassHelper { DCHECK(!klass_->IsPrimitive()); if (klass_->IsArrayClass()) { if (idx == 0) { - return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;"); + return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/lang/Cloneable;"); } else { DCHECK_EQ(1U, idx); - return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;"); + return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/io/Serializable;"); } } else if (klass_->IsProxyClass()) { return klass_->GetIfTable()->GetInterface(idx); @@ -251,7 +251,7 @@ class FieldHelper { mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t field_index = field_->GetDexFieldIndex(); if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { - return GetClassLinker()->FindSystemClass(GetTypeDescriptor()); + return GetClassLinker()->FindSystemClass(Thread::Current(), GetTypeDescriptor()); } const DexFile& dex_file = GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h index 2f959dbcb7..f0f5ed263d 100644 --- a/runtime/scoped_thread_state_change.h +++ b/runtime/scoped_thread_state_change.h @@ -122,6 +122,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { : ScopedThreadStateChange(ThreadForEnv(env), kRunnable), env_(down_cast(env)), vm_(env_->vm) { self_->VerifyStack(); + Locks::mutator_lock_->AssertSharedHeld(self_); } explicit ScopedObjectAccessUnchecked(Thread* self) @@ -130,6 +131,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { env_(down_cast(self->GetJniEnv())), vm_(env_ != NULL ? env_->vm : NULL) { self_->VerifyStack(); + Locks::mutator_lock_->AssertSharedHeld(self_); } // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't @@ -139,6 +141,7 @@ class ScopedObjectAccessUnchecked : public ScopedThreadStateChange { // Here purely to force inlining. ~ScopedObjectAccessUnchecked() ALWAYS_INLINE { + Locks::mutator_lock_->AssertSharedHeld(self_); } JNIEnvExt* Env() const { @@ -250,14 +253,12 @@ class ScopedObjectAccess : public ScopedObjectAccessUnchecked { LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE : ScopedObjectAccessUnchecked(env) { - Locks::mutator_lock_->AssertSharedHeld(Self()); } explicit ScopedObjectAccess(Thread* self) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) : ScopedObjectAccessUnchecked(self) { - Locks::mutator_lock_->AssertSharedHeld(Self()); } ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE { diff --git a/runtime/thread.cc b/runtime/thread.cc index 8949a5b513..8b93b915f0 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -1529,7 +1529,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location, } SirtRef class_loader(this, cl); SirtRef - exception_class(this, runtime->GetClassLinker()->FindClass(exception_class_descriptor, + exception_class(this, runtime->GetClassLinker()->FindClass(this, exception_class_descriptor, class_loader)); if (UNLIKELY(exception_class.get() == nullptr)) { CHECK(IsExceptionPending()); diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc index dcfa24bea1..9dc7b44247 100644 --- a/runtime/transaction_test.cc +++ b/runtime/transaction_test.cc @@ -29,7 +29,7 @@ class TransactionTest : public CommonTest { TEST_F(TransactionTest, Object_class) { ScopedObjectAccess soa(Thread::Current()); SirtRef sirt_klass(soa.Self(), - class_linker_->FindSystemClass("Ljava/lang/Object;")); + class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")); ASSERT_TRUE(sirt_klass.get() != nullptr); Transaction transaction; @@ -47,7 +47,8 @@ TEST_F(TransactionTest, Object_class) { TEST_F(TransactionTest, Object_monitor) { ScopedObjectAccess soa(Thread::Current()); SirtRef sirt_klass(soa.Self(), - class_linker_->FindSystemClass("Ljava/lang/Object;")); + class_linker_->FindSystemClass(soa.Self(), + "Ljava/lang/Object;")); ASSERT_TRUE(sirt_klass.get() != nullptr); SirtRef sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self())); ASSERT_TRUE(sirt_obj.get() != nullptr); @@ -74,7 +75,8 @@ TEST_F(TransactionTest, Object_monitor) { TEST_F(TransactionTest, Array_length) { ScopedObjectAccess soa(Thread::Current()); SirtRef sirt_klass(soa.Self(), - class_linker_->FindSystemClass("[Ljava/lang/Object;")); + class_linker_->FindSystemClass(soa.Self(), + "[Ljava/lang/Object;")); ASSERT_TRUE(sirt_klass.get() != nullptr); constexpr int32_t kArraySize = 2; @@ -101,7 +103,8 @@ TEST_F(TransactionTest, StaticFieldsTest) { ASSERT_TRUE(class_loader.get() != nullptr); SirtRef sirt_klass(soa.Self(), - class_linker_->FindClass("LStaticFieldsTest;", class_loader)); + class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->EnsureInitialized(sirt_klass, true, true); ASSERT_TRUE(sirt_klass->IsInitialized()); @@ -147,13 +150,16 @@ TEST_F(TransactionTest, StaticFieldsTest) { ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble); ASSERT_EQ(doubleField->GetDouble(sirt_klass.get()), static_cast(0.0)); - mirror::ArtField* objectField = sirt_klass->FindDeclaredStaticField("objectField", "Ljava/lang/Object;"); + mirror::ArtField* objectField = sirt_klass->FindDeclaredStaticField("objectField", + "Ljava/lang/Object;"); ASSERT_TRUE(objectField != nullptr); ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot); ASSERT_EQ(objectField->GetObject(sirt_klass.get()), nullptr); // Create a java.lang.Object instance to set objectField. - SirtRef object_klass(soa.Self(), class_linker_->FindSystemClass("Ljava/lang/Object;")); + SirtRef object_klass(soa.Self(), + class_linker_->FindSystemClass(soa.Self(), + "Ljava/lang/Object;")); ASSERT_TRUE(object_klass.get() != nullptr); SirtRef sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self())); ASSERT_TRUE(sirt_obj.get() != nullptr); @@ -193,7 +199,8 @@ TEST_F(TransactionTest, InstanceFieldsTest) { ASSERT_TRUE(class_loader.get() != nullptr); SirtRef sirt_klass(soa.Self(), - class_linker_->FindClass("LInstanceFieldsTest;", class_loader)); + class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->EnsureInitialized(sirt_klass, true, true); ASSERT_TRUE(sirt_klass->IsInitialized()); @@ -243,13 +250,16 @@ TEST_F(TransactionTest, InstanceFieldsTest) { ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble); ASSERT_EQ(doubleField->GetDouble(sirt_instance.get()), static_cast(0.0)); - mirror::ArtField* objectField = sirt_klass->FindDeclaredInstanceField("objectField", "Ljava/lang/Object;"); + mirror::ArtField* objectField = sirt_klass->FindDeclaredInstanceField("objectField", + "Ljava/lang/Object;"); ASSERT_TRUE(objectField != nullptr); ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot); ASSERT_EQ(objectField->GetObject(sirt_instance.get()), nullptr); // Create a java.lang.Object instance to set objectField. - SirtRef object_klass(soa.Self(), class_linker_->FindSystemClass("Ljava/lang/Object;")); + SirtRef object_klass(soa.Self(), + class_linker_->FindSystemClass(soa.Self(), + "Ljava/lang/Object;")); ASSERT_TRUE(object_klass.get() != nullptr); SirtRef sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self())); ASSERT_TRUE(sirt_obj.get() != nullptr); @@ -290,7 +300,8 @@ TEST_F(TransactionTest, StaticArrayFieldsTest) { ASSERT_TRUE(class_loader.get() != nullptr); SirtRef sirt_klass(soa.Self(), - class_linker_->FindClass("LStaticArrayFieldsTest;", class_loader)); + class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->EnsureInitialized(sirt_klass, true, true); ASSERT_TRUE(sirt_klass->IsInitialized()); @@ -352,15 +363,19 @@ TEST_F(TransactionTest, StaticArrayFieldsTest) { ASSERT_EQ(doubleArray->GetLength(), 1); ASSERT_EQ(doubleArray->GetWithoutChecks(0), static_cast(0.0f)); - mirror::ArtField* objectArrayField = sirt_klass->FindDeclaredStaticField("objectArrayField", "[Ljava/lang/Object;"); + mirror::ArtField* objectArrayField = sirt_klass->FindDeclaredStaticField("objectArrayField", + "[Ljava/lang/Object;"); ASSERT_TRUE(objectArrayField != nullptr); - mirror::ObjectArray* objectArray = objectArrayField->GetObject(sirt_klass.get())->AsObjectArray(); + mirror::ObjectArray* objectArray = + objectArrayField->GetObject(sirt_klass.get())->AsObjectArray(); ASSERT_TRUE(objectArray != nullptr); ASSERT_EQ(objectArray->GetLength(), 1); ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr); // Create a java.lang.Object instance to set objectField. - SirtRef object_klass(soa.Self(), class_linker_->FindSystemClass("Ljava/lang/Object;")); + SirtRef object_klass(soa.Self(), + class_linker_->FindSystemClass(soa.Self(), + "Ljava/lang/Object;")); ASSERT_TRUE(object_klass.get() != nullptr); SirtRef sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self())); ASSERT_TRUE(sirt_obj.get() != nullptr); @@ -400,7 +415,9 @@ TEST_F(TransactionTest, EmptyClass) { ASSERT_TRUE(class_loader.get() != nullptr); SirtRef sirt_klass(soa.Self(), - class_linker_->FindClass("LTransaction$EmptyStatic;", class_loader)); + class_linker_->FindClass(soa.Self(), + "LTransaction$EmptyStatic;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->VerifyClass(sirt_klass); ASSERT_TRUE(sirt_klass->IsVerified()); @@ -419,7 +436,9 @@ TEST_F(TransactionTest, StaticFieldClass) { ASSERT_TRUE(class_loader.get() != nullptr); SirtRef sirt_klass(soa.Self(), - class_linker_->FindClass("LTransaction$StaticFieldClass;", class_loader)); + class_linker_->FindClass(soa.Self(), + "LTransaction$StaticFieldClass;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->VerifyClass(sirt_klass); ASSERT_TRUE(sirt_klass->IsVerified()); @@ -441,22 +460,25 @@ TEST_F(TransactionTest, BlacklistedClass) { // Load and verify java.lang.ExceptionInInitializerError and java.lang.InternalError which will // be thrown by class initialization due to native call. SirtRef sirt_klass(soa.Self(), - class_linker_->FindSystemClass("Ljava/lang/ExceptionInInitializerError;")); + class_linker_->FindSystemClass(soa.Self(), + "Ljava/lang/ExceptionInInitializerError;")); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->VerifyClass(sirt_klass); ASSERT_TRUE(sirt_klass->IsVerified()); - sirt_klass.reset(class_linker_->FindSystemClass("Ljava/lang/InternalError;")); + sirt_klass.reset(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/InternalError;")); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->VerifyClass(sirt_klass); ASSERT_TRUE(sirt_klass->IsVerified()); // Load and verify Transaction$NativeSupport used in class initialization. - sirt_klass.reset(class_linker_->FindClass("LTransaction$NativeSupport;", class_loader)); + sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$NativeSupport;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->VerifyClass(sirt_klass); ASSERT_TRUE(sirt_klass->IsVerified()); - sirt_klass.reset(class_linker_->FindClass("LTransaction$BlacklistedClass;", class_loader)); + sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$BlacklistedClass;", + class_loader)); ASSERT_TRUE(sirt_klass.get() != nullptr); class_linker_->VerifyClass(sirt_klass); ASSERT_TRUE(sirt_klass->IsVerified()); diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index b43177b4fd..150695bb02 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -99,7 +99,7 @@ TEST_F(UtilsTest, PrettyTypeOf) { SirtRef a(soa.Self(), mirror::ShortArray::Alloc(soa.Self(), 2)); EXPECT_EQ("short[]", PrettyTypeOf(a.get())); - mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); mirror::Object* o = mirror::ObjectArray::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.String[]", PrettyTypeOf(o)); @@ -109,7 +109,7 @@ TEST_F(UtilsTest, PrettyTypeOf) { TEST_F(UtilsTest, PrettyClass) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyClass(NULL)); - mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); mirror::Object* o = mirror::ObjectArray::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.Class", PrettyClass(o->GetClass())); @@ -118,7 +118,7 @@ TEST_F(UtilsTest, PrettyClass) { TEST_F(UtilsTest, PrettyClassAndClassLoader) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyClassAndClassLoader(NULL)); - mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); mirror::Object* o = mirror::ObjectArray::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.Class", PrettyClassAndClassLoader(o->GetClass())); @@ -128,7 +128,8 @@ TEST_F(UtilsTest, PrettyField) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyField(NULL)); - mirror::Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;"); + mirror::Class* java_lang_String = class_linker_->FindSystemClass(soa.Self(), + "Ljava/lang/String;"); mirror::ArtField* f; f = java_lang_String->FindDeclaredInstanceField("count", "I"); @@ -197,7 +198,7 @@ TEST_F(UtilsTest, MangleForJni) { TEST_F(UtilsTest, JniShortName_JniLongName) { ScopedObjectAccess soa(Thread::Current()); - mirror::Class* c = class_linker_->FindSystemClass("Ljava/lang/String;"); + mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;"); ASSERT_TRUE(c != NULL); mirror::ArtMethod* m; diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index ab943a629e..ffa8b9e14c 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -3129,14 +3129,15 @@ mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst this_class = actual_arg_type.GetClass(); } else { const std::string& descriptor(actual_arg_type.GetDescriptor()); + Thread* self = Thread::Current(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - this_class = class_linker->FindClass(descriptor.c_str(), *class_loader_); + this_class = class_linker->FindClass(self, descriptor.c_str(), *class_loader_); if (this_class == NULL) { Thread* self = Thread::Current(); self->ClearException(); // Look for a system class SirtRef null_class_loader(self, nullptr); - this_class = class_linker->FindClass(descriptor.c_str(), null_class_loader); + this_class = class_linker->FindClass(self, descriptor.c_str(), null_class_loader); } } if (this_class == NULL) { @@ -3638,7 +3639,7 @@ static mirror::ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint3 // Returns the access field of a quick field access (iget/iput-quick) or NULL // if it cannot be found. mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst, - RegisterLine* reg_line) { + RegisterLine* reg_line) { DCHECK(inst->Opcode() == Instruction::IGET_QUICK || inst->Opcode() == Instruction::IGET_WIDE_QUICK || inst->Opcode() == Instruction::IGET_OBJECT_QUICK || @@ -3654,12 +3655,12 @@ mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst, const std::string& descriptor(object_type.GetDescriptor()); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Thread* self = Thread::Current(); - object_class = class_linker->FindClass(descriptor.c_str(), *class_loader_); + object_class = class_linker->FindClass(self, descriptor.c_str(), *class_loader_); if (object_class == NULL) { self->ClearException(); // Look for a system class SirtRef null_class_loader(self, nullptr); - object_class = class_linker->FindClass(descriptor.c_str(), null_class_loader); + object_class = class_linker->FindClass(self, descriptor.c_str(), null_class_loader); } } if (object_class == NULL) { diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc index a56abba3cf..ffa245583d 100644 --- a/runtime/verifier/method_verifier_test.cc +++ b/runtime/verifier/method_verifier_test.cc @@ -30,7 +30,7 @@ class MethodVerifierTest : public CommonTest { void VerifyClass(const std::string& descriptor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ASSERT_TRUE(descriptor != NULL); - mirror::Class* klass = class_linker_->FindSystemClass(descriptor.c_str()); + mirror::Class* klass = class_linker_->FindSystemClass(Thread::Current(), descriptor.c_str()); // Verify the class std::string error_msg; diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 630ef8a3c4..63f0ff49a3 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -18,6 +18,7 @@ #include "base/casts.h" +#include "class_linker-inl.h" #include "dex_file-inl.h" #include "mirror/class.h" #include "mirror/class-inl.h" @@ -928,11 +929,7 @@ mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) { } mirror::Class* common_elem = ClassJoin(s_ct, t_ct); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Thread* self = Thread::Current(); - SirtRef class_loader(self, s->GetClassLoader()); - std::string descriptor("["); - descriptor += ClassHelper(common_elem).GetDescriptor(); - mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader); + mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), common_elem); DCHECK(array_class != NULL); return array_class; } else { diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index 5e894edecc..9dd57b880b 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -17,6 +17,7 @@ #include "reg_type_cache-inl.h" #include "base/casts.h" +#include "class_linker-inl.h" #include "dex_file-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -140,10 +141,11 @@ mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassL // Class was not found, must create new type. // Try resolving class ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - SirtRef class_loader(Thread::Current(), loader); + Thread* self = Thread::Current(); + SirtRef class_loader(self, loader); mirror::Class* klass = NULL; if (can_load_classes_) { - klass = class_linker->FindClass(descriptor, class_loader); + klass = class_linker->FindClass(self, descriptor, class_loader); } else { klass = class_linker->LookupClass(descriptor, loader); if (klass != NULL && !klass->IsLoaded()) { @@ -277,7 +279,8 @@ Type* RegTypeCache::CreatePrimitiveTypeInstance(const std::string& descriptor) { mirror::Class* klass = NULL; // Try loading the class from linker. if (!descriptor.empty()) { - klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor.c_str()); + klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), + descriptor.c_str()); } Type* entry = Type::CreateInstance(klass, descriptor, RegTypeCache::primitive_count_); RegTypeCache::primitive_count_++; -- cgit v1.2.3