diff options
author | 2022-04-06 09:30:50 +0000 | |
---|---|---|
committer | 2024-11-05 15:24:05 +0000 | |
commit | 29ec7aef84f4b47d89edee274562b22a177b00b8 (patch) | |
tree | f958dafda289458ce7dac0ad86f7596636ee7ecf /runtime/class_linker.cc | |
parent | 96dc77238e2b5a962911a6da06d5e1b869dc92f8 (diff) |
Use `std::string_view` for `ClassTable` operations.
Use `std::string_view` instead of `const char*` descriptor.
This uses faster `memcmp` instead of the slower`strcmp` for
descriptor comparison.
Note that the `ScopedTrace` passes `const char*` across the
`libartpalette` boundary, so we cannot easily replace the
`const char* descriptor` with `std::string_view descriptor`
in certain `ClassLinker` functions because we actually need
to pass a null-terminated string and the `string_view` API
does not technically guarantee null-terminated data.
Therefore we resort to explicitly passing around the
descriptor and its length as separate arguments.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 181943478
Bug: 338123769
Change-Id: Ie3fa251390acc582c54b4686d18696eb89b32361
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 119 |
1 files changed, 72 insertions, 47 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 991673f966..2d3217be2e 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2893,7 +2893,7 @@ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTr } ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self, - const char* descriptor, + std::string_view descriptor, ObjPtr<mirror::Class> klass) { DCHECK(klass != nullptr); if (kIsDebugBuild) { @@ -2972,8 +2972,9 @@ ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self, using ClassPathEntry = std::pair<const DexFile*, const dex::ClassDef*>; // Search a collection of DexFiles for a descriptor -ClassPathEntry FindInClassPath(const char* descriptor, - size_t hash, const std::vector<const DexFile*>& class_path) { +ClassPathEntry FindInClassPath(std::string_view descriptor, + size_t hash, + const std::vector<const DexFile*>& class_path) { for (const DexFile* dex_file : class_path) { DCHECK(dex_file != nullptr); const dex::ClassDef* dex_class_def = OatDexFile::FindClassDef(*dex_file, descriptor, hash); @@ -3006,15 +3007,18 @@ do { \ bool ClassLinker::FindClassInSharedLibraries(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { ArtField* field = WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders; - return FindClassInSharedLibrariesHelper(self, descriptor, hash, class_loader, field, result); + return FindClassInSharedLibrariesHelper( + self, descriptor, descriptor_length, hash, class_loader, field, result); } bool ClassLinker::FindClassInSharedLibrariesHelper(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, ArtField* field, @@ -3031,7 +3035,8 @@ bool ClassLinker::FindClassInSharedLibrariesHelper(Thread* self, for (auto loader : shared_libraries.Iterate<mirror::ClassLoader>()) { temp_loader.Assign(loader); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoader(self, descriptor, hash, temp_loader, result), + FindClassInBaseDexClassLoader( + self, descriptor, descriptor_length, hash, temp_loader, result), *result, self); } @@ -3040,22 +3045,27 @@ bool ClassLinker::FindClassInSharedLibrariesHelper(Thread* self, bool ClassLinker::FindClassInSharedLibrariesAfter(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { ArtField* field = WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter; - return FindClassInSharedLibrariesHelper(self, descriptor, hash, class_loader, field, result); + return FindClassInSharedLibrariesHelper( + self, descriptor, descriptor_length, hash, class_loader, field, result); } bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { // Termination case: boot class loader. if (IsBootClassLoader(class_loader.Get())) { RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBootClassLoaderClassPath(self, descriptor, hash, result), *result, self); + FindClassInBootClassLoaderClassPath(self, descriptor, descriptor_length, hash, result), + *result, + self); return true; } @@ -3069,19 +3079,21 @@ bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent())); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoader(self, descriptor, hash, h_parent, result), + FindClassInBaseDexClassLoader(self, descriptor, descriptor_length, hash, h_parent, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibraries(self, descriptor, hash, class_loader, result), + FindClassInSharedLibraries(self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoaderClassPath(self, descriptor, hash, class_loader, result), + FindClassInBaseDexClassLoaderClassPath( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibrariesAfter(self, descriptor, hash, class_loader, result), + FindClassInSharedLibrariesAfter( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); // We did not find a class, but the class loader chain was recognized, so we @@ -3096,17 +3108,21 @@ bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, // - class loader dex files // - parent RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBootClassLoaderClassPath(self, descriptor, hash, result), *result, self); + FindClassInBootClassLoaderClassPath(self, descriptor, descriptor_length, hash, result), + *result, + self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibraries(self, descriptor, hash, class_loader, result), + FindClassInSharedLibraries(self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoaderClassPath(self, descriptor, hash, class_loader, result), + FindClassInBaseDexClassLoaderClassPath( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibrariesAfter(self, descriptor, hash, class_loader, result), + FindClassInSharedLibrariesAfter( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); @@ -3114,7 +3130,7 @@ bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent())); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoader(self, descriptor, hash, h_parent, result), + FindClassInBaseDexClassLoader(self, descriptor, descriptor_length, hash, h_parent, result), *result, self); // We did not find a class, but the class loader chain was recognized, so we @@ -3158,16 +3174,19 @@ ALWAYS_INLINE void FilterDexFileCaughtExceptions(Thread* self, ClassLinker* clas // If the class is found the method returns the resolved class. Otherwise it returns null. bool ClassLinker::FindClassInBootClassLoaderClassPath(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, /*out*/ ObjPtr<mirror::Class>* result) { - ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); + std::string_view sv_descriptor(descriptor, descriptor_length); + ClassPathEntry pair = FindInClassPath(sv_descriptor, hash, boot_class_path_); if (pair.second != nullptr) { - ObjPtr<mirror::Class> klass = LookupClass(self, descriptor, hash, nullptr); + ObjPtr<mirror::Class> klass = LookupClass(self, sv_descriptor, hash, nullptr); if (klass != nullptr) { - *result = EnsureResolved(self, descriptor, klass); + *result = EnsureResolved(self, sv_descriptor, klass); } else { *result = DefineClass(self, descriptor, + descriptor_length, hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, @@ -3185,6 +3204,7 @@ bool ClassLinker::FindClassInBootClassLoaderClassPath(Thread* self, bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { @@ -3193,11 +3213,12 @@ bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( IsDelegateLastClassLoader(class_loader)) << "Unexpected class loader for descriptor " << descriptor; + std::string_view sv_descriptor(descriptor, descriptor_length); const DexFile* dex_file = nullptr; const dex::ClassDef* class_def = nullptr; ObjPtr<mirror::Class> ret; auto find_class_def = [&](const DexFile* cp_dex_file) REQUIRES_SHARED(Locks::mutator_lock_) { - const dex::ClassDef* cp_class_def = OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash); + const dex::ClassDef* cp_class_def = OatDexFile::FindClassDef(*cp_dex_file, sv_descriptor, hash); if (cp_class_def != nullptr) { dex_file = cp_dex_file; class_def = cp_class_def; @@ -3208,7 +3229,8 @@ bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( VisitClassLoaderDexFiles(self, class_loader, find_class_def); if (class_def != nullptr) { - *result = DefineClass(self, descriptor, hash, class_loader, *dex_file, *class_def); + *result = + DefineClass(self, descriptor, descriptor_length, hash, class_loader, *dex_file, *class_def); if (UNLIKELY(*result == nullptr)) { CHECK(self->IsExceptionPending()) << descriptor; FilterDexFileCaughtExceptions(self, this); @@ -3232,11 +3254,12 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, // for primitive classes that aren't backed by dex files. return FindPrimitiveClass(descriptor[0]); } - const size_t hash = ComputeModifiedUtf8Hash(descriptor); + const std::string_view sv_descriptor(descriptor); + const size_t hash = ComputeModifiedUtf8Hash(sv_descriptor); // Find the class in the loaded classes table. - ObjPtr<mirror::Class> klass = LookupClass(self, descriptor, hash, class_loader.Get()); + ObjPtr<mirror::Class> klass = LookupClass(self, sv_descriptor, hash, class_loader.Get()); if (klass != nullptr) { - return EnsureResolved(self, descriptor, klass); + return EnsureResolved(self, sv_descriptor, klass); } // Class is not yet loaded. if (descriptor[0] != '[' && class_loader == nullptr) { @@ -3245,6 +3268,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, if (pair.second != nullptr) { return DefineClass(self, descriptor, + sv_descriptor.length(), hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, @@ -3264,18 +3288,18 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, if (descriptor[0] == '[') { result_ptr = CreateArrayClass(self, descriptor, hash, class_loader); DCHECK_EQ(result_ptr == nullptr, self->IsExceptionPending()); - DCHECK(result_ptr == nullptr || result_ptr->DescriptorEquals(descriptor)); + DCHECK(result_ptr == nullptr || result_ptr->DescriptorEquals(sv_descriptor)); descriptor_equals = true; } else { ScopedObjectAccessUnchecked soa(self); - bool known_hierarchy = - FindClassInBaseDexClassLoader(self, descriptor, hash, class_loader, &result_ptr); + bool known_hierarchy = FindClassInBaseDexClassLoader( + self, descriptor, sv_descriptor.length(), hash, class_loader, &result_ptr); if (result_ptr != nullptr) { // The chain was understood and we found the class. We still need to add the class to // the class table to protect from racy programs that can try and redefine the path list // which would change the Class<?> returned for subsequent evaluation of const-class. DCHECK(known_hierarchy); - DCHECK(result_ptr->DescriptorEquals(descriptor)); + DCHECK(result_ptr->DescriptorEquals(sv_descriptor)); descriptor_equals = true; } else if (!self->IsExceptionPending()) { // Either the chain wasn't understood or the class wasn't found. @@ -3304,15 +3328,14 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, // when native code erroneously calls JNI GetFieldId() with signature "java/lang/String" // instead of "Ljava/lang/String;", the message below using the "dot" names would be // "class loader [...] returned class java.lang.String instead of java.lang.String". - size_t descriptor_length = strlen(descriptor); if (UNLIKELY(descriptor[0] != 'L') || - UNLIKELY(descriptor[descriptor_length - 1] != ';') || - UNLIKELY(memchr(descriptor + 1, '.', descriptor_length - 2) != nullptr)) { + UNLIKELY(descriptor[sv_descriptor.length() - 1] != ';') || + UNLIKELY(memchr(descriptor + 1, '.', sv_descriptor.length() - 2) != nullptr)) { ThrowNoClassDefFoundError("Invalid descriptor: %s.", descriptor); return nullptr; } - std::string class_name_string(descriptor + 1, descriptor_length - 2); + std::string class_name_string(sv_descriptor.substr(1u, sv_descriptor.length() - 2u)); std::replace(class_name_string.begin(), class_name_string.end(), '/', '.'); if (known_hierarchy && fast_class_not_found_exceptions_ && @@ -3342,7 +3365,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, return nullptr; } // Check the name of the returned class. - descriptor_equals = (result_ptr != nullptr) && result_ptr->DescriptorEquals(descriptor); + descriptor_equals = (result_ptr != nullptr) && result_ptr->DescriptorEquals(sv_descriptor); } } else { DCHECK(!MatchesDexFileCaughtExceptions(self->GetException(), this)); @@ -3352,10 +3375,10 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, if (self->IsExceptionPending()) { // If the ClassLoader threw or array class allocation failed, pass that exception up. // However, to comply with the RI behavior, first check if another thread succeeded. - result_ptr = LookupClass(self, descriptor, hash, class_loader.Get()); + result_ptr = LookupClass(self, sv_descriptor, hash, class_loader.Get()); if (result_ptr != nullptr && !result_ptr->IsErroneous()) { self->ClearException(); - return EnsureResolved(self, descriptor, result_ptr); + return EnsureResolved(self, sv_descriptor, result_ptr); } return nullptr; } @@ -3365,7 +3388,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, { WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); ClassTable* const class_table = InsertClassTableForClassLoader(class_loader.Get()); - old = class_table->Lookup(descriptor, hash); + old = class_table->Lookup(sv_descriptor, hash); if (old == nullptr) { old = result_ptr; // For the comparison below, after releasing the lock. if (descriptor_equals) { @@ -3383,7 +3406,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, LOG(WARNING) << "Initiating class loader of type " << DescriptorToDot(loader_class_name) << " is not well-behaved; it returned a different Class for racing loadClass(\"" << DescriptorToDot(descriptor) << "\")."; - return EnsureResolved(self, descriptor, old); + return EnsureResolved(self, sv_descriptor, old); } if (UNLIKELY(!descriptor_equals)) { std::string result_storage; @@ -3447,10 +3470,12 @@ struct ScopedDefiningClass { ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, const dex::ClassDef& dex_class_def) { + std::string_view sv_descriptor(descriptor, descriptor_length); ScopedDefiningClass sdc(self); StackHandleScope<3> hs(self); metrics::AutoTimer timer{GetMetrics()->ClassLoadingTotalTime()}; @@ -3460,17 +3485,17 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, // Load the class from the dex file. if (UNLIKELY(!init_done_)) { // finish up init of hand crafted class_roots_ - if (strcmp(descriptor, "Ljava/lang/Object;") == 0) { + if (sv_descriptor == "Ljava/lang/Object;") { klass.Assign(GetClassRoot<mirror::Object>(this)); - } else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) { + } else if (sv_descriptor == "Ljava/lang/Class;") { klass.Assign(GetClassRoot<mirror::Class>(this)); - } else if (strcmp(descriptor, "Ljava/lang/String;") == 0) { + } else if (sv_descriptor == "Ljava/lang/String;") { klass.Assign(GetClassRoot<mirror::String>(this)); - } else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) { + } else if (sv_descriptor == "Ljava/lang/ref/Reference;") { klass.Assign(GetClassRoot<mirror::Reference>(this)); - } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) { + } else if (sv_descriptor == "Ljava/lang/DexCache;") { klass.Assign(GetClassRoot<mirror::DexCache>(this)); - } else if (strcmp(descriptor, "Ldalvik/system/ClassExt;") == 0) { + } else if (sv_descriptor == "Ldalvik/system/ClassExt;") { klass.Assign(GetClassRoot<mirror::ClassExt>(this)); } } @@ -3544,7 +3569,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, // Mark the string class by setting its access flag. if (UNLIKELY(!init_done_)) { - if (strcmp(descriptor, "Ljava/lang/String;") == 0) { + if (sv_descriptor == "Ljava/lang/String;") { klass->SetStringClass(); } } @@ -4733,7 +4758,7 @@ ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) { return result; } -ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor, +ObjPtr<mirror::Class> ClassLinker::InsertClass(std::string_view descriptor, ObjPtr<mirror::Class> klass, size_t hash) { DCHECK(Thread::Current()->CanLoadClasses()); @@ -4786,13 +4811,13 @@ void ClassLinker::UpdateClassMethods(ObjPtr<mirror::Class> klass, } ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self, - const char* descriptor, + std::string_view descriptor, ObjPtr<mirror::ClassLoader> class_loader) { return LookupClass(self, descriptor, ComputeModifiedUtf8Hash(descriptor), class_loader); } ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self, - const char* descriptor, + std::string_view descriptor, size_t hash, ObjPtr<mirror::ClassLoader> class_loader) { ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); |