diff options
author | 2024-11-05 14:33:29 +0000 | |
---|---|---|
committer | 2024-11-11 08:33:23 +0000 | |
commit | 01df4b3a9bb31f21f451452f0ce47632dd8916ad (patch) | |
tree | 2414f41e33f7c1ec468ea7c6f141267a6387d537 | |
parent | 8a2ca0019489d3e1c5a79789af68fb05822af9cb (diff) |
Avoid `strlen()` for `ClassLinker::FindClass()`...
... and related functions in most cases.
Note that the `CompilerDriver` previously resolved the
`ClassLoader` and `TransactionAbortError` using the provided
class loaders. We're now using the `ClassLoader` from the
class roots and resolving the `TransactionAbortError` in the
BCP class loader.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 181943478
Bug: 338123769
Change-Id: I38e480cdcdb8bf02c958e4d0773437f5766f6be0
61 files changed, 450 insertions, 417 deletions
diff --git a/compiler/compiler_reflection_test.cc b/compiler/compiler_reflection_test.cc index f3c07db136..f9cc02f16e 100644 --- a/compiler/compiler_reflection_test.cc +++ b/compiler/compiler_reflection_test.cc @@ -35,7 +35,7 @@ TEST_F(CompilerReflectionTest, StaticMainMethod) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader); + ObjPtr<mirror::Class> klass = FindClass("LMain;", class_loader); ASSERT_TRUE(klass != nullptr); ArtMethod* method = klass->FindClassMethod("main", diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc index 0e289353c7..4eae96158e 100644 --- a/compiler/exception_test.cc +++ b/compiler/exception_test.cc @@ -61,7 +61,7 @@ class ExceptionTest : public CommonRuntimeTest { StackHandleScope<2> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("ExceptionHandle")))); - my_klass_ = class_linker_->FindClass(soa.Self(), "LExceptionHandle;", class_loader); + my_klass_ = FindClass("LExceptionHandle;", class_loader); ASSERT_TRUE(my_klass_ != nullptr); Handle<mirror::Class> klass(hs.NewHandle(my_klass_)); class_linker_->EnsureInitialized(soa.Self(), klass, true, true); diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc index 2f4a1b5f44..35ee1edafd 100644 --- a/compiler/jni/jni_compiler_test.cc +++ b/compiler/jni/jni_compiler_test.cc @@ -243,8 +243,7 @@ class JniCompilerTest : public CommonCompilerTest { Handle<mirror::ClassLoader> loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); // Compile the native method before starting the runtime - Handle<mirror::Class> c = - hs.NewHandle(class_linker_->FindClass(self, "LMyClassNatives;", loader)); + Handle<mirror::Class> c = hs.NewHandle(FindClass("LMyClassNatives;", loader)); const auto pointer_size = class_linker_->GetImagePointerSize(); ArtMethod* method = c->FindClassMethod(method_name, method_sig, pointer_size); ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig; diff --git a/compiler/oat/jni_stub_hash_map_test.cc b/compiler/oat/jni_stub_hash_map_test.cc index 2a26bcfae6..170381d988 100644 --- a/compiler/oat/jni_stub_hash_map_test.cc +++ b/compiler/oat/jni_stub_hash_map_test.cc @@ -88,8 +88,7 @@ class JniStubHashMapTest : public CommonCompilerTest { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); pointer_size_ = class_linker_->GetImagePointerSize(); - ObjPtr<mirror::Class> klass = - class_linker_->FindClass(soa.Self(), "LMyClassNatives;", class_loader); + ObjPtr<mirror::Class> klass = FindClass("LMyClassNatives;", class_loader); ASSERT_TRUE(klass != nullptr); jklass_ = soa.AddLocalReference<jclass>(klass); } diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 1375c36643..44af0d6b66 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -782,9 +782,10 @@ HInliner::InlineCacheType HInliner::GetInlineCacheAOT( Thread* self = Thread::Current(); for (const dex::TypeIndex& type_index : dex_pc_data.classes) { const DexFile* dex_file = caller_compilation_unit_.GetDexFile(); - const char* descriptor = pci->GetTypeDescriptor(dex_file, type_index); - ObjPtr<mirror::Class> clazz = - class_linker->FindClass(self, descriptor, caller_compilation_unit_.GetClassLoader()); + size_t descriptor_length; + const char* descriptor = pci->GetTypeDescriptor(dex_file, type_index, &descriptor_length); + ObjPtr<mirror::Class> clazz = class_linker->FindClass( + self, descriptor, descriptor_length, caller_compilation_unit_.GetClassLoader()); if (clazz == nullptr) { self->ClearException(); // Clean up the exception left by type resolution. VLOG(compiler) << "Could not find class from inline cache in AOT mode " diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc index 0491b2b797..bbb70e4ef1 100644 --- a/dex2oat/driver/compiler_driver.cc +++ b/dex2oat/driver/compiler_driver.cc @@ -750,7 +750,8 @@ static void EnsureVerifiedOrVerifyAtRuntime(jobject jclass_loader, for (const DexFile* dex_file : dex_files) { for (ClassAccessor accessor : dex_file->GetClasses()) { - cls.Assign(class_linker->FindClass(soa.Self(), accessor.GetDescriptor(), class_loader)); + cls.Assign( + class_linker->FindClass(soa.Self(), *dex_file, accessor.GetClassIdx(), class_loader)); if (cls == nullptr) { soa.Self()->ClearException(); } else if (&cls->GetDexFile() == dex_file) { @@ -1253,7 +1254,8 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings, CHECK(image_classes != nullptr); for (auto it = image_classes->begin(), end = image_classes->end(); it != end;) { const std::string& descriptor(*it); - ObjPtr<mirror::Class> klass = class_linker->FindClass(self, descriptor.c_str(), loader); + ObjPtr<mirror::Class> klass = + class_linker->FindClass(self, descriptor.c_str(), descriptor.length(), loader); if (klass == nullptr) { VLOG(compiler) << "Failed to find class " << descriptor; it = image_classes->erase(it); // May cause some descriptors to be revisited. @@ -1739,9 +1741,7 @@ class ResolveTypeVisitor : public CompilationVisitor { } // Check that the current class is not a subclass of java.lang.ClassLoader. if (!hklass->IsInterface() && - hklass->IsSubClass(class_linker->FindClass(soa.Self(), - "Ljava/lang/ClassLoader;", - defining_class_loader))) { + hklass->IsSubClass(GetClassRoot<mirror::ClassLoader>(class_linker))) { // Subclassing of java.lang.ClassLoader. // This OptStat stuff is to enable logging from the APK scanner. if (is_fatal) { @@ -1806,16 +1806,15 @@ static void LoadAndUpdateStatus(const ClassAccessor& accessor, Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { StackHandleScope<1> hs(self); - const char* descriptor = accessor.GetDescriptor(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Handle<mirror::Class> cls(hs.NewHandle<mirror::Class>( - class_linker->FindClass(self, descriptor, class_loader))); + class_linker->FindClass(self, accessor.GetDexFile(), accessor.GetClassIdx(), class_loader))); if (cls != nullptr) { // Check that the class is resolved with the current dex file. We might get // a boot image class, or a class in a different dex file for multidex, and // we should not update the status in that case. if (&cls->GetDexFile() == &accessor.GetDexFile()) { - VLOG(compiler) << "Updating class status of " << std::string(descriptor) << " to " << status; + VLOG(compiler) << "Updating class status of " << accessor.GetDescriptor() << " to " << status; ObjectLock<mirror::Class> lock(self, cls); mirror::Class::SetStatus(cls, status, self); } @@ -1971,14 +1970,13 @@ class VerifyClassVisitor : public CompilationVisitor { ScopedObjectAccess soa(Thread::Current()); const DexFile& dex_file = *manager_->GetDexFile(); const dex::ClassDef& class_def = dex_file.GetClassDef(class_def_index); - const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = manager_->GetClassLinker(); jobject jclass_loader = manager_->GetClassLoader(); StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> klass( - hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader))); + Handle<mirror::Class> klass = hs.NewHandle( + class_linker->FindClass(soa.Self(), dex_file, class_def.class_idx_, class_loader)); ClassReference ref(manager_->GetDexFile(), class_def_index); verifier::FailureKind failure_kind; if (klass == nullptr) { @@ -2135,14 +2133,13 @@ class SetVerifiedClassVisitor : public CompilationVisitor { ScopedObjectAccess soa(Thread::Current()); const DexFile& dex_file = *manager_->GetDexFile(); const dex::ClassDef& class_def = dex_file.GetClassDef(class_def_index); - const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = manager_->GetClassLinker(); jobject jclass_loader = manager_->GetClassLoader(); StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> klass( - hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader))); + Handle<mirror::Class> klass = hs.NewHandle( + class_linker->FindClass(soa.Self(), dex_file, class_def.class_idx_, class_loader)); // Class might have failed resolution. Then don't set it to verified. if (klass != nullptr) { // Only do this if the class is resolved. If even resolution fails, quickening will go very, @@ -2197,15 +2194,13 @@ class InitializeClassVisitor : public CompilationVisitor { jobject jclass_loader = manager_->GetClassLoader(); const DexFile& dex_file = *manager_->GetDexFile(); const dex::ClassDef& class_def = dex_file.GetClassDef(class_def_index); - const dex::TypeId& class_type_id = dex_file.GetTypeId(class_def.class_idx_); - const char* descriptor = dex_file.GetStringData(class_type_id.descriptor_idx_); ScopedObjectAccess soa(Thread::Current()); StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> klass( - hs.NewHandle(manager_->GetClassLinker()->FindClass(soa.Self(), descriptor, class_loader))); + Handle<mirror::Class> klass = hs.NewHandle(manager_->GetClassLinker()->FindClass( + soa.Self(), dex_file, class_def.class_idx_, class_loader)); if (klass != nullptr) { if (!SkipClass(manager_->GetClassLoader(), dex_file, klass.Get())) { @@ -2329,8 +2324,8 @@ class InitializeClassVisitor : public CompilationVisitor { // the transaction aborts and cannot resolve the type. // TransactionAbortError is not initialized ant not in boot image, needed only by // compiler and will be pruned by ImageWriter. - Handle<mirror::Class> exception_class = hs.NewHandle( - class_linker->FindClass(self, kTransactionAbortErrorDescriptor, class_loader)); + Handle<mirror::Class> exception_class = + hs.NewHandle(class_linker->FindSystemClass(self, kTransactionAbortErrorDescriptor)); bool exception_initialized = class_linker->EnsureInitialized(self, exception_class, true, true); DCHECK(exception_initialized); @@ -2695,8 +2690,8 @@ static void CompileDexFile(CompilerDriver* driver, StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> klass( - hs.NewHandle(class_linker->FindClass(soa.Self(), accessor.GetDescriptor(), class_loader))); + Handle<mirror::Class> klass = hs.NewHandle( + class_linker->FindClass(soa.Self(), dex_file, class_def.class_idx_, class_loader)); Handle<mirror::DexCache> dex_cache; if (klass == nullptr) { soa.Self()->AssertPendingException(); diff --git a/dex2oat/driver/compiler_driver_test.cc b/dex2oat/driver/compiler_driver_test.cc index 759426a1d3..7d4c32b25c 100644 --- a/dex2oat/driver/compiler_driver_test.cc +++ b/dex2oat/driver/compiler_driver_test.cc @@ -105,7 +105,7 @@ class CompilerDriverTest : public CommonCompilerDriverTest { StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> c = class_linker->FindClass(soa.Self(), descriptor, loader); + ObjPtr<mirror::Class> c = FindClass(descriptor, loader); CHECK(c != nullptr); const auto pointer_size = class_linker->GetImagePointerSize(); for (auto& m : c->GetMethods(pointer_size)) { @@ -237,7 +237,7 @@ class CompilerDriverProfileTest : public CompilerDriverTest { StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader); + ObjPtr<mirror::Class> klass = FindClass(clazz.c_str(), h_loader); ASSERT_NE(klass, nullptr); const auto pointer_size = class_linker->GetImagePointerSize(); @@ -298,7 +298,7 @@ class CompilerDriverVerifyTest : public CompilerDriverTest { StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader); + ObjPtr<mirror::Class> klass = FindClass(clazz.c_str(), h_loader); ASSERT_NE(klass, nullptr); EXPECT_TRUE(klass->IsVerified()); diff --git a/dex2oat/interpreter/unstarted_runtime_transaction_test.cc b/dex2oat/interpreter/unstarted_runtime_transaction_test.cc index ec308c2c18..a60da0657f 100644 --- a/dex2oat/interpreter/unstarted_runtime_transaction_test.cc +++ b/dex2oat/interpreter/unstarted_runtime_transaction_test.cc @@ -32,10 +32,8 @@ class UnstartedRuntimeTransactionTest : public CommonTransactionTestBase<Unstart // Prepare for aborts. Aborts assume that the exception class is already resolved, as the // loading code doesn't work under transactions. void PrepareForAborts() REQUIRES_SHARED(Locks::mutator_lock_) { - ObjPtr<mirror::Object> result = Runtime::Current()->GetClassLinker()->FindClass( - Thread::Current(), - kTransactionAbortErrorDescriptor, - ScopedNullHandle<mirror::ClassLoader>()); + ObjPtr<mirror::Object> result = + FindClass(kTransactionAbortErrorDescriptor, ScopedNullHandle<mirror::ClassLoader>()); CHECK(result != nullptr); } }; @@ -152,9 +150,7 @@ class UnstartedClassForNameTransactionTest : public UnstartedRuntimeTransactionT // For transaction mode, we cannot load any classes, as the pre-fence initialization of // classes isn't transactional. Load them ahead of time. for (const char* name : kTestCases) { - class_linker_->FindClass(self, - DotToDescriptor(name).c_str(), - ScopedNullHandle<mirror::ClassLoader>()); + FindClass(DotToDescriptor(name).c_str(), ScopedNullHandle<mirror::ClassLoader>()); CHECK(!self->IsExceptionPending()) << self->GetException()->Dump(); } diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index a905294360..0a585edb53 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -460,9 +460,7 @@ TEST_F(OatTest, WriteRead) { size_t num_virtual_methods = accessor.NumVirtualMethods(); const char* descriptor = accessor.GetDescriptor(); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), - descriptor, - ScopedNullHandle<mirror::ClassLoader>()); + ObjPtr<mirror::Class> klass = FindClass(descriptor, ScopedNullHandle<mirror::ClassLoader>()); const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(accessor.GetClassDefIndex()); CHECK_EQ(ClassStatus::kNotReady, oat_class.GetStatus()) << descriptor; diff --git a/dex2oat/transaction_test.cc b/dex2oat/transaction_test.cc index 17a78ad6af..03ee7e98fa 100644 --- a/dex2oat/transaction_test.cc +++ b/dex2oat/transaction_test.cc @@ -59,14 +59,13 @@ class TransactionTest : public CommonTransactionTest { ASSERT_TRUE(h_klass->IsInitialized()); // Load and verify utility class. - h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;", - class_loader)); + h_klass.Assign(FindClass("LTransaction$AbortHelperClass;", class_loader)); ASSERT_TRUE(h_klass != nullptr); class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); // Load and verify tested class. - h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader)); + h_klass.Assign(FindClass(tested_class_signature, class_loader)); ASSERT_TRUE(h_klass != nullptr); class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); @@ -171,8 +170,7 @@ TEST_F(TransactionTest, StaticFieldsTest) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); ASSERT_TRUE(class_loader != nullptr); - Handle<mirror::Class> h_klass( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader))); + Handle<mirror::Class> h_klass = hs.NewHandle(FindClass("LStaticFieldsTest;", class_loader)); ASSERT_TRUE(h_klass != nullptr); bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); ASSERT_TRUE(success); @@ -267,8 +265,7 @@ TEST_F(TransactionTest, InstanceFieldsTest) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); ASSERT_TRUE(class_loader != nullptr); - Handle<mirror::Class> h_klass( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader))); + Handle<mirror::Class> h_klass = hs.NewHandle(FindClass("LInstanceFieldsTest;", class_loader)); ASSERT_TRUE(h_klass != nullptr); bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); ASSERT_TRUE(success); @@ -419,8 +416,7 @@ TEST_F(TransactionTest, StaticArrayFieldsTest) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); ASSERT_TRUE(class_loader != nullptr); - Handle<mirror::Class> h_klass( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;", class_loader))); + Handle<mirror::Class> h_klass = hs.NewHandle(FindClass("LStaticArrayFieldsTest;", class_loader)); ASSERT_TRUE(h_klass != nullptr); bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); ASSERT_TRUE(success); @@ -542,9 +538,8 @@ TEST_F(TransactionTest, ResolveString) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); ASSERT_TRUE(class_loader != nullptr); - Handle<mirror::Class> h_klass( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$ResolveString;", - class_loader))); + Handle<mirror::Class> h_klass = + hs.NewHandle(FindClass("LTransaction$ResolveString;", class_loader)); ASSERT_TRUE(h_klass != nullptr); Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache())); @@ -608,7 +603,7 @@ TEST_F(MethodTypeTransactionTest, ResolveMethodType) { class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true); ASSERT_TRUE(h_klass->IsInitialized()); - h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction;", class_loader)); + h_klass.Assign(FindClass("LTransaction;", class_loader)); ASSERT_TRUE(h_klass != nullptr); Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache())); @@ -640,9 +635,8 @@ TEST_F(TransactionTest, EmptyClass) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); ASSERT_TRUE(class_loader != nullptr); - Handle<mirror::Class> h_klass( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;", - class_loader))); + Handle<mirror::Class> h_klass = + hs.NewHandle(FindClass("LTransaction$EmptyStatic;", class_loader)); ASSERT_TRUE(h_klass != nullptr); class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); @@ -663,9 +657,8 @@ TEST_F(TransactionTest, StaticFieldClass) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); ASSERT_TRUE(class_loader != nullptr); - Handle<mirror::Class> h_klass( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;", - class_loader))); + Handle<mirror::Class> h_klass = + hs.NewHandle(FindClass("LTransaction$StaticFieldClass;", class_loader)); ASSERT_TRUE(h_klass != nullptr); class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); @@ -724,8 +717,8 @@ TEST_F(TransactionTest, Constraints) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction")))); gc::Heap* heap = Runtime::Current()->GetHeap(); - Handle<mirror::Class> boolean_class = hs.NewHandle( - class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader)); + Handle<mirror::Class> boolean_class = + hs.NewHandle(FindClass("Ljava/lang/Boolean;", class_loader)); ASSERT_TRUE(boolean_class != nullptr); ASSERT_TRUE(heap->ObjectIsInBootImageSpace(boolean_class.Get())); ArtField* true_field = boolean_class->FindDeclaredStaticField("TRUE", "Ljava/lang/Boolean;"); @@ -738,23 +731,23 @@ TEST_F(TransactionTest, Constraints) { ASSERT_TRUE(value_field != nullptr); ASSERT_FALSE(value_field->IsStatic()); - Handle<mirror::Class> static_field_class(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;", class_loader))); + Handle<mirror::Class> static_field_class = + hs.NewHandle(FindClass("LTransaction$StaticFieldClass;", class_loader)); ASSERT_TRUE(static_field_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_field_class.Get())); ArtField* int_field = static_field_class->FindDeclaredStaticField("intField", "I"); ASSERT_TRUE(int_field != nullptr); - Handle<mirror::Class> static_fields_test_class(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader))); + Handle<mirror::Class> static_fields_test_class = + hs.NewHandle(FindClass("LStaticFieldsTest;", class_loader)); ASSERT_TRUE(static_fields_test_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(static_fields_test_class.Get())); ArtField* static_fields_test_int_field = static_fields_test_class->FindDeclaredStaticField("intField", "I"); ASSERT_TRUE(static_fields_test_int_field != nullptr); - Handle<mirror::Class> instance_fields_test_class(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader))); + Handle<mirror::Class> instance_fields_test_class = + hs.NewHandle(FindClass("LInstanceFieldsTest;", class_loader)); ASSERT_TRUE(instance_fields_test_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(instance_fields_test_class.Get())); ArtField* instance_fields_test_int_field = @@ -768,8 +761,7 @@ TEST_F(TransactionTest, Constraints) { // The `long[].class` should be in the boot image but `long[][][].class` should not. // (We have seen `long[][].class` both present and missing from the boot image, // depending on the libcore code, so we do not use it for this test.) - Handle<mirror::Class> long_array_dim3_class = hs.NewHandle( - class_linker_->FindClass(soa.Self(), "[[[J", class_loader)); + Handle<mirror::Class> long_array_dim3_class = hs.NewHandle(FindClass("[[[J", class_loader)); ASSERT_TRUE(long_array_dim3_class != nullptr); ASSERT_FALSE(heap->ObjectIsInBootImageSpace(long_array_dim3_class.Get())); ASSERT_TRUE(heap->ObjectIsInBootImageSpace( diff --git a/dex2oat/verifier_deps_test.cc b/dex2oat/verifier_deps_test.cc index a79bad2944..828691d3e2 100644 --- a/dex2oat/verifier_deps_test.cc +++ b/dex2oat/verifier_deps_test.cc @@ -80,7 +80,7 @@ class VerifierDepsTest : public CommonCompilerDriverTest { Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_))); ObjPtr<mirror::Class> klass = - class_linker_->FindClass(soa.Self(), name.c_str(), class_loader_handle); + class_linker_->FindClass(soa.Self(), name.c_str(), name.length(), class_loader_handle); if (klass == nullptr) { DCHECK(soa.Self()->IsExceptionPending()); soa.Self()->ClearException(); @@ -220,9 +220,8 @@ class VerifierDepsTest : public CommonCompilerDriverTest { const std::vector<bool>& verified_classes = deps.GetVerifiedClasses(*dex_file); ASSERT_EQ(verified_classes.size(), dex_file->NumClassDefs()); for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { - const dex::ClassDef& class_def = dex_file->GetClassDef(i); - const char* descriptor = dex_file->GetClassDescriptor(class_def); - cls.Assign(class_linker_->FindClass(soa.Self(), descriptor, class_loader_handle)); + cls.Assign(class_linker_->FindClass( + soa.Self(), *dex_file, dex_file->GetClassDef(i).class_idx_, class_loader_handle)); if (cls == nullptr) { CHECK(soa.Self()->IsExceptionPending()); soa.Self()->ClearException(); @@ -273,8 +272,9 @@ class VerifierDepsTest : public CommonCompilerDriverTest { for (auto& set : storage) { for (auto& entry : set) { std::string actual_destination = - verifier_deps_->GetStringFromId(dex_file, entry.GetDestination()); - std::string actual_source = verifier_deps_->GetStringFromId(dex_file, entry.GetSource()); + verifier_deps_->GetStringFromIndex(dex_file, entry.GetDestination()); + std::string actual_source = + verifier_deps_->GetStringFromIndex(dex_file, entry.GetSource()); if ((expected_destination == actual_destination) && (expected_source == actual_source)) { return true; } @@ -351,19 +351,19 @@ TEST_F(VerifierDepsTest, StringToId) { dex::StringIndex id_Main1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;"); ASSERT_LT(id_Main1.index_, primary_dex_file_->NumStringIds()); - ASSERT_EQ("LMain;", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Main1)); + ASSERT_STREQ("LMain;", verifier_deps_->GetStringFromIndex(*primary_dex_file_, id_Main1)); dex::StringIndex id_Main2 = verifier_deps_->GetIdFromString(*primary_dex_file_, "LMain;"); ASSERT_LT(id_Main2.index_, primary_dex_file_->NumStringIds()); - ASSERT_EQ("LMain;", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Main2)); + ASSERT_STREQ("LMain;", verifier_deps_->GetStringFromIndex(*primary_dex_file_, id_Main2)); dex::StringIndex id_Lorem1 = verifier_deps_->GetIdFromString(*primary_dex_file_, "Lorem ipsum"); ASSERT_GE(id_Lorem1.index_, primary_dex_file_->NumStringIds()); - ASSERT_EQ("Lorem ipsum", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Lorem1)); + ASSERT_STREQ("Lorem ipsum", verifier_deps_->GetStringFromIndex(*primary_dex_file_, id_Lorem1)); dex::StringIndex id_Lorem2 = verifier_deps_->GetIdFromString(*primary_dex_file_, "Lorem ipsum"); ASSERT_GE(id_Lorem2.index_, primary_dex_file_->NumStringIds()); - ASSERT_EQ("Lorem ipsum", verifier_deps_->GetStringFromId(*primary_dex_file_, id_Lorem2)); + ASSERT_STREQ("Lorem ipsum", verifier_deps_->GetStringFromIndex(*primary_dex_file_, id_Lorem2)); ASSERT_EQ(id_Main1, id_Main2); ASSERT_EQ(id_Lorem1, id_Lorem2); diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h index ad6c8c31ba..a6ea97d705 100644 --- a/libdexfile/dex/dex_file-inl.h +++ b/libdexfile/dex/dex_file-inl.h @@ -46,12 +46,15 @@ inline int DexFile::CompareMemberNames(std::string_view lhs, std::string_view rh return lhs.compare(rhs); } +inline size_t DexFile::Utf8Length(const char* utf8_data, size_t utf16_length) { + return LIKELY(utf8_data[utf16_length] == 0) // Is ASCII? + ? utf16_length + : utf16_length + strlen(utf8_data + utf16_length); +} + inline std::string_view DexFile::StringViewFromUtf16Length(const char* utf8_data, size_t utf16_length) { - size_t utf8_length = LIKELY(utf8_data[utf16_length] == 0) // Is ASCII? - ? utf16_length - : utf16_length + strlen(utf8_data + utf16_length); - return std::string_view(utf8_data, utf8_length); + return std::string_view(utf8_data, Utf8Length(utf8_data, utf16_length)); } ALWAYS_INLINE diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h index 6c41849616..619ee0d4f5 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -911,6 +911,7 @@ class DexFile { static int CompareDescriptors(std::string_view lhs, std::string_view rhs); static int CompareMemberNames(std::string_view lhs, std::string_view rhs); + static size_t Utf8Length(const char* utf8_data, size_t utf16_length); static std::string_view StringViewFromUtf16Length(const char* utf8_data, size_t utf16_length); protected: diff --git a/libprofile/profile/profile_compilation_info.h b/libprofile/profile/profile_compilation_info.h index f6b0105ff6..c8c325939c 100644 --- a/libprofile/profile/profile_compilation_info.h +++ b/libprofile/profile/profile_compilation_info.h @@ -33,7 +33,7 @@ #include "base/malloc_arena_pool.h" #include "base/mem_map.h" #include "base/safe_map.h" -#include "dex/dex_file.h" +#include "dex/dex_file-inl.h" #include "dex/dex_file_types.h" #include "dex/method_reference.h" #include "dex/type_reference.h" @@ -674,13 +674,25 @@ class ProfileCompilationInfo { // Get type descriptor for a valid type index, whether a normal type index // referencing a `dex::TypeId` in the dex file, or an artificial type index // referencing an "extra descriptor". - const char* GetTypeDescriptor(const DexFile* dex_file, dex::TypeIndex type_index) const { + const char* GetTypeDescriptor(const DexFile* dex_file, + dex::TypeIndex type_index, + /*out*/ size_t* utf8_length = nullptr) const { DCHECK(type_index.IsValid()); uint32_t num_type_ids = dex_file->NumTypeIds(); if (type_index.index_ < num_type_ids) { - return dex_file->GetTypeDescriptor(type_index); + uint32_t utf16_length; + const char* descriptor = dex_file->GetStringDataAndUtf16Length( + dex_file->GetTypeId(type_index).descriptor_idx_, &utf16_length); + if (utf8_length != nullptr) { + *utf8_length = DexFile::Utf8Length(descriptor, utf16_length); + } + return descriptor; } else { - return extra_descriptors_[type_index.index_ - num_type_ids].c_str(); + const std::string& descriptor = extra_descriptors_[type_index.index_ - num_type_ids]; + if (utf8_length != nullptr) { + *utf8_length = descriptor.length(); + } + return descriptor.c_str(); } } diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 2c97f92636..feba70ff3a 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -2803,10 +2803,11 @@ class IMTDumper { class_def_index != dex_file->NumClassDefs(); ++class_def_index) { const dex::ClassDef& class_def = dex_file->GetClassDef(class_def_index); - const char* descriptor = dex_file->GetClassDescriptor(class_def); - h_klass.Assign(class_linker->FindClass(self, descriptor, h_class_loader)); + h_klass.Assign( + class_linker->FindClass(self, *dex_file, class_def.class_idx_, h_class_loader)); if (h_klass == nullptr) { - std::cerr << "Warning: could not load " << descriptor << std::endl; + std::cerr << "Warning: could not load " + << dex_file->GetTypeDescriptor(class_def.class_idx_) << std::endl; continue; } @@ -2929,8 +2930,8 @@ class IMTDumper { descriptor = DotToDescriptor(class_name.c_str()); } - ObjPtr<mirror::Class> klass = - runtime->GetClassLinker()->FindClass(self, descriptor.c_str(), h_loader); + ObjPtr<mirror::Class> klass = runtime->GetClassLinker()->FindClass( + self, descriptor.c_str(), descriptor.length(), h_loader); if (klass == nullptr) { self->ClearException(); diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc index bf89b6e476..f9f043dbe5 100644 --- a/openjdkjvmti/ti_method.cc +++ b/openjdkjvmti/ti_method.cc @@ -1066,8 +1066,7 @@ class SetLocalVariableClosure : public CommonLocalVariableClosure { art::ObjPtr<art::mirror::Class> set_class = caller_->DecodeJObject(val_.l)->GetClass(); art::ObjPtr<art::mirror::ClassLoader> loader = method->GetDeclaringClass()->GetClassLoader(); - art::ObjPtr<art::mirror::Class> slot_class = - cl->LookupClass(caller_, descriptor.c_str(), loader); + art::ObjPtr<art::mirror::Class> slot_class = cl->LookupClass(caller_, descriptor, loader); DCHECK(!slot_class.IsNull()) << descriptor << " slot: " << slot_type; return slot_class->IsAssignableFrom(set_class) ? OK : ERR(TYPE_MISMATCH); } diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc index 1e056f119d..8699a021f6 100644 --- a/profman/profile_assistant_test.cc +++ b/profman/profile_assistant_test.cc @@ -285,7 +285,7 @@ class ProfileAssistantTest : public CommonRuntimeTest, public ProfileTestHelper StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> h_loader(hs.NewHandle( ObjPtr<mirror::ClassLoader>::DownCast(soa.Self()->DecodeJObject(class_loader)))); - return class_linker->FindClass(soa.Self(), clazz.c_str(), h_loader); + return FindClass(clazz.c_str(), h_loader); } ArtMethod* GetVirtualMethod(jobject class_loader, diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h index cbe38db80e..dd86e68164 100644 --- a/runtime/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -371,7 +371,7 @@ inline bool ArtField::IsPrimitiveType() { inline ObjPtr<mirror::Class> ArtField::LookupResolvedType() { ScopedAssertNoThreadSuspension ants(__FUNCTION__); if (UNLIKELY(IsProxyField())) { - return ProxyFindSystemClass(GetTypeDescriptor()); + return ProxyFindSystemClass(GetTypeDescriptorView()); } ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->LookupResolvedType( GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this); @@ -381,7 +381,7 @@ inline ObjPtr<mirror::Class> ArtField::LookupResolvedType() { inline ObjPtr<mirror::Class> ArtField::ResolveType() { if (UNLIKELY(IsProxyField())) { - return ProxyFindSystemClass(GetTypeDescriptor()); + return ProxyFindSystemClass(GetTypeDescriptorView()); } ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType( GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this); diff --git a/runtime/art_field.cc b/runtime/art_field.cc index 70d6d2ba94..b7b2a779fe 100644 --- a/runtime/art_field.cc +++ b/runtime/art_field.cc @@ -39,7 +39,7 @@ void ArtField::SetOffset(MemberOffset num_bytes) { offset_ = num_bytes.Uint32Value(); } -ObjPtr<mirror::Class> ArtField::ProxyFindSystemClass(const char* descriptor) { +ObjPtr<mirror::Class> ArtField::ProxyFindSystemClass(std::string_view descriptor) { DCHECK(IsProxyField()); ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupClass( Thread::Current(), descriptor, /* class_loader= */ nullptr); diff --git a/runtime/art_field.h b/runtime/art_field.h index 141de5650d..fd991cd53a 100644 --- a/runtime/art_field.h +++ b/runtime/art_field.h @@ -256,7 +256,7 @@ class EXPORT ArtField final { private: bool IsProxyField() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor) + ObjPtr<mirror::Class> ProxyFindSystemClass(std::string_view descriptor) REQUIRES_SHARED(Locks::mutator_lock_); GcRoot<mirror::Class> declaring_class_; diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 6461f54f5f..7d84fc1c09 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -25,7 +25,7 @@ #include "base/mutex.h" #include "class_linker.h" #include "class_table-inl.h" -#include "dex/dex_file.h" +#include "dex/dex_file-inl.h" #include "dex/dex_file_structs.h" #include "gc_root-inl.h" #include "handle_scope-inl.h" @@ -54,7 +54,8 @@ inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self, descriptor += element_class->GetDescriptor(&temp); StackHandleScope<1> hs(Thread::Current()); Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader())); - ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader); + ObjPtr<mirror::Class> array_class = + FindClass(self, descriptor.c_str(), descriptor.length(), class_loader); if (array_class != nullptr) { // Benign races in storing array class and incrementing index. size_t victim_index = find_array_class_cache_next_victim_; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 2d3217be2e..b4c2e4a54d 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2878,8 +2878,9 @@ void ClassLinker::FinishCoreArrayClassSetup(ClassRoot array_root) { ObjPtr<mirror::Class> array_class = GetClassRoot(array_root, this); FinishArrayClassSetup(array_class); - std::string temp; - const char* descriptor = array_class->GetDescriptor(&temp); + std::string descriptor; + const char* raw_descriptor = array_class->GetDescriptor(&descriptor); + DCHECK(raw_descriptor == descriptor.c_str()); size_t hash = ComputeModifiedUtf8Hash(descriptor); ObjPtr<mirror::Class> existing = InsertClass(descriptor, array_class, hash); CHECK(existing == nullptr); @@ -3243,18 +3244,31 @@ bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( } ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, + const DexFile& dex_file, + dex::TypeIndex type_index, + Handle<mirror::ClassLoader> class_loader) { + dex::StringIndex descriptor_idx = dex_file.GetTypeId(type_index).descriptor_idx_; + uint32_t utf16_length; + const char* descriptor = dex_file.GetStringDataAndUtf16Length(descriptor_idx, &utf16_length); + size_t descriptor_length = DexFile::Utf8Length(descriptor, utf16_length); + return FindClass(self, descriptor, descriptor_length, class_loader); +} + +ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, const char* descriptor, + size_t descriptor_length, Handle<mirror::ClassLoader> class_loader) { - DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; + DCHECK_EQ(strlen(descriptor), descriptor_length); + DCHECK_NE(descriptor_length, 0u) << "descriptor is empty string"; DCHECK(self != nullptr); self->AssertNoPendingException(); self->PoisonObjectPointers(); // For DefineClass, CreateArrayClass, etc... - if (descriptor[1] == '\0') { + if (descriptor_length == 1u) { // only the descriptors of primitive types should be 1 character long, also avoid class lookup // for primitive classes that aren't backed by dex files. return FindPrimitiveClass(descriptor[0]); } - const std::string_view sv_descriptor(descriptor); + const std::string_view sv_descriptor(descriptor, descriptor_length); const size_t hash = ComputeModifiedUtf8Hash(sv_descriptor); // Find the class in the loaded classes table. ObjPtr<mirror::Class> klass = LookupClass(self, sv_descriptor, hash, class_loader.Get()); @@ -3264,11 +3278,11 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, // Class is not yet loaded. if (descriptor[0] != '[' && class_loader == nullptr) { // Non-array class and the boot class loader, search the boot class path. - ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); + ClassPathEntry pair = FindInClassPath(sv_descriptor, hash, boot_class_path_); if (pair.second != nullptr) { return DefineClass(self, descriptor, - sv_descriptor.length(), + descriptor_length, hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, @@ -3286,14 +3300,14 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, ObjPtr<mirror::Class> result_ptr; bool descriptor_equals; if (descriptor[0] == '[') { - result_ptr = CreateArrayClass(self, descriptor, hash, class_loader); + result_ptr = CreateArrayClass(self, descriptor, descriptor_length, hash, class_loader); DCHECK_EQ(result_ptr == nullptr, self->IsExceptionPending()); DCHECK(result_ptr == nullptr || result_ptr->DescriptorEquals(sv_descriptor)); descriptor_equals = true; } else { ScopedObjectAccessUnchecked soa(self); bool known_hierarchy = FindClassInBaseDexClassLoader( - self, descriptor, sv_descriptor.length(), hash, class_loader, &result_ptr); + self, descriptor, 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 @@ -3329,13 +3343,13 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, // 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". if (UNLIKELY(descriptor[0] != 'L') || - UNLIKELY(descriptor[sv_descriptor.length() - 1] != ';') || - UNLIKELY(memchr(descriptor + 1, '.', sv_descriptor.length() - 2) != nullptr)) { + UNLIKELY(descriptor[descriptor_length - 1] != ';') || + UNLIKELY(memchr(descriptor + 1, '.', descriptor_length - 2) != nullptr)) { ThrowNoClassDefFoundError("Invalid descriptor: %s.", descriptor); return nullptr; } - std::string class_name_string(sv_descriptor.substr(1u, sv_descriptor.length() - 2u)); + std::string class_name_string(sv_descriptor.substr(1u, descriptor_length - 2u)); std::replace(class_name_string.begin(), class_name_string.end(), '/', '.'); if (known_hierarchy && fast_class_not_found_exceptions_ && @@ -3580,11 +3594,11 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, klass->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable()); // Add the newly loaded class to the loaded classes table. - ObjPtr<mirror::Class> existing = InsertClass(descriptor, klass.Get(), hash); + ObjPtr<mirror::Class> existing = InsertClass(sv_descriptor, klass.Get(), hash); if (existing != nullptr) { // We failed to insert because we raced with another thread. Calling EnsureResolved may cause // this thread to block. - return sdc.Finish(EnsureResolved(self, descriptor, existing)); + return sdc.Finish(EnsureResolved(self, sv_descriptor, existing)); } // Load the fields and other things after we are inserted in the table. This is so that we don't @@ -4585,7 +4599,7 @@ void ClassLinker::CreatePrimitiveClass(Thread* self, DCHECK_EQ(primitive_class->NumMethods(), 0u); // Primitive classes are initialized during single threaded startup, so visibly initialized. primitive_class->SetStatusForPrimitiveOrArray(ClassStatus::kVisiblyInitialized); - const char* descriptor = Primitive::Descriptor(type); + std::string_view descriptor(Primitive::Descriptor(type)); ObjPtr<mirror::Class> existing = InsertClass(descriptor, primitive_class, ComputeModifiedUtf8Hash(descriptor)); @@ -4612,10 +4626,12 @@ inline ObjPtr<mirror::IfTable> ClassLinker::GetArrayIfTable() { // Returns null with an exception raised on failure. ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader) { // Identify the underlying component type CHECK_EQ('[', descriptor[0]); + std::string_view sv_descriptor(descriptor, descriptor_length); StackHandleScope<2> hs(self); // This is to prevent the calls to ClassLoad and ClassPrepare which can cause java/user-supplied @@ -4629,14 +4645,16 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, return nullptr; } - MutableHandle<mirror::Class> component_type(hs.NewHandle(FindClass(self, descriptor + 1, - class_loader))); + MutableHandle<mirror::Class> component_type = + hs.NewHandle(FindClass(self, descriptor + 1, descriptor_length - 1, class_loader)); if (component_type == nullptr) { DCHECK(self->IsExceptionPending()); // We need to accept erroneous classes as component types. Under AOT, we // don't accept them as we cannot encode the erroneous class in an image. - const size_t component_hash = ComputeModifiedUtf8Hash(descriptor + 1); - component_type.Assign(LookupClass(self, descriptor + 1, component_hash, class_loader.Get())); + std::string_view component_descriptor = sv_descriptor.substr(1u); + const size_t component_hash = ComputeModifiedUtf8Hash(component_descriptor); + component_type.Assign( + LookupClass(self, component_descriptor, component_hash, class_loader.Get())); if (component_type == nullptr || Runtime::Current()->IsAotCompiler()) { DCHECK(self->IsExceptionPending()); return nullptr; @@ -4667,7 +4685,7 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, // other threads.) if (class_loader.Get() != component_type->GetClassLoader()) { ObjPtr<mirror::Class> new_class = - LookupClass(self, descriptor, hash, component_type->GetClassLoader()); + LookupClass(self, sv_descriptor, hash, component_type->GetClassLoader()); if (new_class != nullptr) { return new_class; } @@ -4711,7 +4729,7 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, return nullptr; } - ObjPtr<mirror::Class> existing = InsertClass(descriptor, new_class.Get(), hash); + ObjPtr<mirror::Class> existing = InsertClass(sv_descriptor, new_class.Get(), hash); if (existing == nullptr) { // We postpone ClassLoad and ClassPrepare events to this point in time to avoid // duplicate events in case of races. Array classes don't really follow dedicated @@ -5271,8 +5289,9 @@ ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRun // Object has an empty iftable, copy it for that reason. temp_klass->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable()); mirror::Class::SetStatus(temp_klass, ClassStatus::kIdx, self); - std::string storage; - const char* descriptor = temp_klass->GetDescriptor(&storage); + std::string descriptor; + const char* raw_descriptor = temp_klass->GetDescriptor(&descriptor); + DCHECK(raw_descriptor == descriptor.c_str()); const size_t hash = ComputeModifiedUtf8Hash(descriptor); // Needs to be before we insert the class so that the allocator field is set. @@ -5396,7 +5415,7 @@ ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRun // The new class will replace the old one in the class table. Handle<mirror::ObjectArray<mirror::Class>> h_interfaces( hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces))); - if (!LinkClass(self, descriptor, temp_klass, h_interfaces, &klass)) { + if (!LinkClass(self, descriptor.c_str(), temp_klass, h_interfaces, &klass)) { if (!temp_klass->IsErroneous()) { mirror::Class::SetStatus(temp_klass, ClassStatus::kErrorUnresolved, self); } @@ -9910,7 +9929,7 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx, ObjPtr<mirror::ClassLoader> class_loader) { DCHECK(dex_cache->GetClassLoader() == class_loader); const DexFile& dex_file = *dex_cache->GetDexFile(); - const char* descriptor = dex_file.GetTypeDescriptor(type_idx); + std::string_view descriptor = dex_file.GetTypeDescriptorView(type_idx); ObjPtr<mirror::Class> type = LookupResolvedType(descriptor, class_loader); if (type != nullptr) { DCHECK(type->IsResolved()); @@ -9919,11 +9938,11 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx, return type; } -ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(const char* descriptor, +ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(std::string_view descriptor, ObjPtr<mirror::ClassLoader> class_loader) { - DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; + DCHECK(!descriptor.empty()) << "descriptor is empty string"; ObjPtr<mirror::Class> type = nullptr; - if (descriptor[1] == '\0') { + if (descriptor.length() == 1u) { // only the descriptors of primitive types should be 1 character long, also avoid class lookup // for primitive classes that aren't backed by dex files. type = LookupPrimitiveClass(descriptor[0]); @@ -9958,8 +9977,8 @@ ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx, Handle<mirror::ClassLoader> class_loader) { DCHECK(dex_cache->GetClassLoader() == class_loader.Get()); Thread* self = Thread::Current(); - const char* descriptor = dex_cache->GetDexFile()->GetTypeDescriptor(type_idx); - ObjPtr<mirror::Class> resolved = FindClass(self, descriptor, class_loader); + const DexFile* dex_file = dex_cache->GetDexFile(); + ObjPtr<mirror::Class> resolved = FindClass(self, *dex_file, type_idx, class_loader); if (resolved != nullptr) { // 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 @@ -9967,14 +9986,15 @@ ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx, dex_cache->SetResolvedType(type_idx, resolved); } else { CHECK(self->IsExceptionPending()) - << "Expected pending exception for failed resolution of: " << descriptor; + << "Expected pending exception for failed resolution of: " + << dex_file->GetTypeDescriptor(type_idx); // Convert a ClassNotFoundException to a NoClassDefFoundError. StackHandleScope<1> hs(self); Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException())); if (cause->InstanceOf(GetClassRoot(ClassRoot::kJavaLangClassNotFoundException, this))) { DCHECK(resolved == nullptr); // No Handle needed to preserve resolved. self->ClearException(); - ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor); + ThrowNoClassDefFoundError("Failed resolution of: %s", dex_file->GetTypeDescriptor(type_idx)); self->GetException()->SetCause(cause.Get()); } } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index ef8241ad2f..d1c82776cc 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -207,6 +207,15 @@ class ClassLinker { // If class_loader is null, searches boot_class_path_. EXPORT ObjPtr<mirror::Class> FindClass(Thread* self, const char* descriptor, + size_t descriptor_length, + Handle<mirror::ClassLoader> class_loader) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Locks::dex_lock_); + + // Helper overload that retrieves the descriptor and its length from the `dex_file`. + EXPORT ObjPtr<mirror::Class> FindClass(Thread* self, + const DexFile& dex_file, + dex::TypeIndex type_index, Handle<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_); @@ -216,7 +225,7 @@ class ClassLinker { ObjPtr<mirror::Class> FindSystemClass(Thread* self, const char* descriptor) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_) { - return FindClass(self, descriptor, ScopedNullHandle<mirror::ClassLoader>()); + return FindClass(self, descriptor, strlen(descriptor), ScopedNullHandle<mirror::ClassLoader>()); } // Finds the array class given for the element class. @@ -321,7 +330,7 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_); // Look up a resolved type with the given descriptor associated with the given ClassLoader. - ObjPtr<mirror::Class> LookupResolvedType(const char* descriptor, + ObjPtr<mirror::Class> LookupResolvedType(std::string_view descriptor, ObjPtr<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); @@ -1102,6 +1111,7 @@ class ClassLinker { ObjPtr<mirror::Class> CreateArrayClass(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 9c4e0289ae..d4fcefef27 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -181,8 +181,7 @@ class ClassLinkerTest : public CommonRuntimeTest { Thread* self = Thread::Current(); StackHandleScope<2> hs(self); Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader)); - Handle<mirror::Class> array( - hs.NewHandle(class_linker_->FindClass(self, array_descriptor.c_str(), loader))); + Handle<mirror::Class> array = hs.NewHandle(FindClass(array_descriptor.c_str(), loader)); std::string temp; EXPECT_STREQ(component_type.c_str(), array->GetComponentType()->GetDescriptor(&temp)); EXPECT_OBJ_PTR_EQ(loader.Get(), array->GetClassLoader()); @@ -912,13 +911,12 @@ TEST_F(ClassLinkerTest, FindClassNested) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Nested")))); - ObjPtr<mirror::Class> outer = class_linker_->FindClass(soa.Self(), "LNested;", class_loader); + ObjPtr<mirror::Class> outer = FindClass("LNested;", class_loader); ASSERT_TRUE(outer != nullptr); EXPECT_EQ(0U, outer->NumVirtualMethods()); EXPECT_EQ(1U, outer->NumDirectMethods()); - ObjPtr<mirror::Class> inner = - class_linker_->FindClass(soa.Self(), "LNested$Inner;", class_loader); + ObjPtr<mirror::Class> inner = FindClass("LNested$Inner;", class_loader); ASSERT_TRUE(inner != nullptr); EXPECT_EQ(0U, inner->NumVirtualMethods()); EXPECT_EQ(1U, inner->NumDirectMethods()); @@ -948,7 +946,7 @@ TEST_F(ClassLinkerTest, FindClass) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass")))); AssertNonExistentClass("LMyClass;"); - ObjPtr<mirror::Class> MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); + ObjPtr<mirror::Class> MyClass = FindClass("LMyClass;", class_loader); ASSERT_TRUE(MyClass != nullptr); ASSERT_TRUE(MyClass->GetClass() != nullptr); ASSERT_OBJ_PTR_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass()); @@ -997,7 +995,7 @@ TEST_F(ClassLinkerTest, LookupResolvedType) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass")))); AssertNonExistentClass("LMyClass;"); - ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); + ObjPtr<mirror::Class> klass = FindClass("LMyClass;", class_loader); dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache(); EXPECT_OBJ_PTR_EQ( @@ -1017,8 +1015,7 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeArray) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("AllFields")))); // Get the AllFields class for the dex cache and dex file. - ObjPtr<mirror::Class> all_fields_klass - = class_linker_->FindClass(soa.Self(), "LAllFields;", class_loader); + ObjPtr<mirror::Class> all_fields_klass = FindClass("LAllFields;", class_loader); ASSERT_TRUE(all_fields_klass != nullptr); Handle<mirror::DexCache> dex_cache = hs.NewHandle(all_fields_klass->GetDexCache()); const DexFile& dex_file = *dex_cache->GetDexFile(); @@ -1030,8 +1027,7 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeArray) { EXPECT_TRUE( class_linker_->LookupResolvedType(array_idx, dex_cache.Get(), class_loader.Get()) == nullptr); // Resolve the array class we want to test. - ObjPtr<mirror::Class> array_klass - = class_linker_->FindClass(soa.Self(), "[Ljava/lang/Object;", class_loader); + ObjPtr<mirror::Class> array_klass = FindClass("[Ljava/lang/Object;", class_loader); ASSERT_TRUE(array_klass != nullptr); // Test that LookupResolvedType() finds the array class. EXPECT_OBJ_PTR_EQ( @@ -1051,8 +1047,7 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeErroneousInit) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("ErroneousInit")))); AssertNonExistentClass("LErroneousInit;"); - Handle<mirror::Class> klass = - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LErroneousInit;", class_loader)); + Handle<mirror::Class> klass = hs.NewHandle(FindClass("LErroneousInit;", class_loader)); ASSERT_TRUE(klass != nullptr); dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; Handle<mirror::DexCache> dex_cache = hs.NewHandle(klass->GetDexCache()); @@ -1146,21 +1141,21 @@ TEST_F(ClassLinkerTest, ValidateBoxedTypes) { ScopedObjectAccess soa(Thread::Current()); ScopedNullHandle<mirror::ClassLoader> class_loader; ObjPtr<mirror::Class> c; - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader); + c = FindClass("Ljava/lang/Boolean;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Byte;", class_loader); + c = FindClass("Ljava/lang/Byte;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Character;", class_loader); + c = FindClass("Ljava/lang/Character;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Double;", class_loader); + c = FindClass("Ljava/lang/Double;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Float;", class_loader); + c = FindClass("Ljava/lang/Float;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Integer;", class_loader); + c = FindClass("Ljava/lang/Integer;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Long;", class_loader); + c = FindClass("Ljava/lang/Long;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Short;", class_loader); + c = FindClass("Ljava/lang/Short;", class_loader); EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName()); } @@ -1171,10 +1166,8 @@ TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass")))); Handle<mirror::ClassLoader> class_loader_2( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MyClass")))); - Handle<mirror::Class> MyClass_1 = hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_1)); - ObjPtr<mirror::Class> MyClass_2 = - class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_2); + Handle<mirror::Class> MyClass_1 = hs.NewHandle(FindClass("LMyClass;", class_loader_1)); + ObjPtr<mirror::Class> MyClass_2 = FindClass("LMyClass;", class_loader_2); EXPECT_TRUE(MyClass_1 != nullptr); EXPECT_TRUE(MyClass_2 != nullptr); EXPECT_OBJ_PTR_NE(MyClass_1.Get(), MyClass_2); @@ -1185,8 +1178,7 @@ TEST_F(ClassLinkerTest, StaticFields) { StackHandleScope<2> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Statics")))); - Handle<mirror::Class> statics( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStatics;", class_loader))); + Handle<mirror::Class> statics = hs.NewHandle(FindClass("LStatics;", class_loader)); class_linker_->EnsureInitialized(soa.Self(), statics, true, true); // Static final primitives that are initialized by a compile-time constant @@ -1261,16 +1253,11 @@ TEST_F(ClassLinkerTest, Interfaces) { StackHandleScope<6> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Interfaces")))); - Handle<mirror::Class> I( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader))); - Handle<mirror::Class> J( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader))); - Handle<mirror::Class> K( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader))); - Handle<mirror::Class> A( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader))); - Handle<mirror::Class> B( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader))); + Handle<mirror::Class> I = hs.NewHandle(FindClass("LInterfaces$I;", class_loader)); + Handle<mirror::Class> J = hs.NewHandle(FindClass("LInterfaces$J;", class_loader)); + Handle<mirror::Class> K = hs.NewHandle(FindClass("LInterfaces$K;", class_loader)); + Handle<mirror::Class> A = hs.NewHandle(FindClass("LInterfaces$A;", class_loader)); + Handle<mirror::Class> B = hs.NewHandle(FindClass("LInterfaces$B;", class_loader)); EXPECT_TRUE(I->IsAssignableFrom(A.Get())); EXPECT_TRUE(J->IsAssignableFrom(A.Get())); EXPECT_TRUE(J->IsAssignableFrom(K.Get())); @@ -1336,8 +1323,7 @@ TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) { StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - ObjPtr<mirror::Class> klass = - class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader); + ObjPtr<mirror::Class> klass = FindClass("LStaticsFromCode;", class_loader); ArtMethod* clinit = klass->FindClassInitializer(kRuntimePointerSize); ArtMethod* getS0 = klass->FindClassMethod("getS0", "()Ljava/lang/Object;", kRuntimePointerSize); @@ -1370,7 +1356,7 @@ TEST_F(ClassLinkerTest, ErroneousClass) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); hs.Self()->AssertNoPendingException(); const char* descriptor = "LErroneous;"; - ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), descriptor, class_loader); + ObjPtr<mirror::Class> klass = FindClass(descriptor, class_loader); // Erronenous since we are extending final class. hs.Self()->AssertPendingException(); EXPECT_TRUE(klass == nullptr); @@ -1429,19 +1415,19 @@ TEST_F(ClassLinkerTest, ValidatePredefinedClassSizes) { ScopedNullHandle<mirror::ClassLoader> class_loader; ObjPtr<mirror::Class> c; - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Class;", class_loader); + c = FindClass("Ljava/lang/Class;", class_loader); ASSERT_TRUE(c != nullptr); EXPECT_EQ(c->GetClassSize(), mirror::Class::ClassClassSize(kRuntimePointerSize)); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Object;", class_loader); + c = FindClass("Ljava/lang/Object;", class_loader); ASSERT_TRUE(c != nullptr); EXPECT_EQ(c->GetClassSize(), mirror::Object::ClassSize(kRuntimePointerSize)); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/String;", class_loader); + c = FindClass("Ljava/lang/String;", class_loader); ASSERT_TRUE(c != nullptr); EXPECT_EQ(c->GetClassSize(), mirror::String::ClassSize(kRuntimePointerSize)); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/DexCache;", class_loader); + c = FindClass("Ljava/lang/DexCache;", class_loader); ASSERT_TRUE(c != nullptr); EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize(kRuntimePointerSize)); } @@ -1494,8 +1480,7 @@ TEST_F(ClassLinkerTest, Preverified_App) { StackHandleScope<2> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Statics")))); - Handle<mirror::Class> statics( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStatics;", class_loader))); + Handle<mirror::Class> statics = hs.NewHandle(FindClass("LStatics;", class_loader)); CheckVerificationAttempted(statics.Get(), false); @@ -1517,8 +1502,7 @@ TEST_F(ClassLinkerTest, IsBootStrapClassLoaded) { EXPECT_TRUE(jlo_class->IsBootStrapClassLoaded()); // Statics is not a bootstrap class. - Handle<mirror::Class> statics( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStatics;", class_loader))); + Handle<mirror::Class> statics = hs.NewHandle(FindClass("LStatics;", class_loader)); ASSERT_TRUE(statics != nullptr); EXPECT_FALSE(statics->IsBootStrapClassLoaded()); } @@ -1568,8 +1552,7 @@ TEST_F(ClassLinkerMethodHandlesTest, TestResolveMethodTypes) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("MethodTypes")))); - Handle<mirror::Class> method_types( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LMethodTypes;", class_loader))); + Handle<mirror::Class> method_types = hs.NewHandle(FindClass("LMethodTypes;", class_loader)); class_linker_->EnsureInitialized(soa.Self(), method_types, true, true); ArtMethod* method1 = method_types->FindClassMethod( @@ -1596,9 +1579,7 @@ TEST_F(ClassLinkerMethodHandlesTest, TestResolveMethodTypes) { ASSERT_TRUE(method1_type != nullptr); // Assert that the return type and the method arguments are as we expect. - Handle<mirror::Class> string_class(hs.NewHandle(class_linker_->FindClass(soa.Self(), - "Ljava/lang/String;", - class_loader))); + Handle<mirror::Class> string_class = hs.NewHandle(FindClass("Ljava/lang/String;", class_loader)); ASSERT_OBJ_PTR_EQ(string_class.Get(), method1_type->GetRType()); ASSERT_OBJ_PTR_EQ(string_class.Get(), method1_type->GetPTypes()->Get(0)); @@ -1704,8 +1685,8 @@ class ClassLinkerClassLoaderTest : public ClassLinkerTest { Handle<mirror::ClassLoader> class_loader_to_search( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_to_search_obj))); - Handle<mirror::Class> klass = hs.NewHandle( - class_linker_->FindClass(soa.Self(), descriptor.c_str(), class_loader_to_search)); + Handle<mirror::Class> klass = + hs.NewHandle(FindClass(descriptor.c_str(), class_loader_to_search)); if (!should_find) { if (self->IsExceptionPending()) { diff --git a/runtime/class_table_test.cc b/runtime/class_table_test.cc index 15cca6dda9..88530bcec8 100644 --- a/runtime/class_table_test.cc +++ b/runtime/class_table_test.cc @@ -80,10 +80,8 @@ TEST_F(ClassTableTest, ClassTable) { Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); const char* descriptor_x = "LX;"; const char* descriptor_y = "LY;"; - Handle<mirror::Class> h_X( - hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_x, class_loader))); - Handle<mirror::Class> h_Y( - hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader))); + Handle<mirror::Class> h_X = hs.NewHandle(FindClass(descriptor_x, class_loader)); + Handle<mirror::Class> h_Y = hs.NewHandle(FindClass(descriptor_y, class_loader)); Handle<mirror::Object> obj_X = hs.NewHandle(h_X->AllocObject(soa.Self())); ASSERT_TRUE(obj_X != nullptr); ClassTable table; diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 165b3a9c8a..ab7ddbcb25 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -601,6 +601,12 @@ void CommonRuntimeTestImpl::GenerateProfile(ArrayRef<const std::string> dexes, EXPECT_EQ(out_file->Flush(), 0); } +ObjPtr<mirror::Class> CommonRuntimeTestImpl::FindClass( + const char* descriptor, + Handle<mirror::ClassLoader> class_loader) const { + return class_linker_->FindClass(Thread::Current(), descriptor, strlen(descriptor), class_loader); +} + CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) { vm_->SetCheckJniAbortHook(Hook, &actual_); } diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index 5416cb493c..7c20de30fd 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -190,6 +190,10 @@ class CommonRuntimeTestImpl : public CommonArtTestImpl { dexes, out_file, method_frequency, type_frequency, /*for_boot_image=*/ true); } + ObjPtr<mirror::Class> FindClass(const char* descriptor, + Handle<mirror::ClassLoader> class_loader) const + REQUIRES_SHARED(Locks::mutator_lock_); + std::unique_ptr<Runtime> runtime_; // The class_linker_, java_lang_dex_file_, and boot_class_path_ are all @@ -202,7 +206,7 @@ class CommonRuntimeTestImpl : public CommonArtTestImpl { // This only looks into the current class loader and does not recurse into the parents. std::vector<const DexFile*> GetDexFiles(jobject jclass_loader); std::vector<const DexFile*> GetDexFiles(Thread* self, Handle<mirror::ClassLoader> class_loader) - REQUIRES_SHARED(Locks::mutator_lock_); + REQUIRES_SHARED(Locks::mutator_lock_); // Get the first dex file from a PathClassLoader. Will abort if it is null. const DexFile* GetFirstDexFile(jobject jclass_loader); diff --git a/runtime/fuzzer_corpus_test.cc b/runtime/fuzzer_corpus_test.cc index 24edebcc20..6b312d5973 100644 --- a/runtime/fuzzer_corpus_test.cc +++ b/runtime/fuzzer_corpus_test.cc @@ -124,8 +124,8 @@ class FuzzerCorpusTest : public CommonRuntimeTest { scope.NewHandle<art::mirror::DexCache>(nullptr)); for (art::ClassAccessor accessor : dex_file.GetClasses()) { - const char* descriptor = accessor.GetDescriptor(); - h_klass.Assign(class_linker->FindClass(soa.Self(), descriptor, h_loader)); + h_klass.Assign( + class_linker->FindClass(soa.Self(), dex_file, accessor.GetClassIdx(), h_loader)); // Ignore classes that couldn't be loaded since we are looking for crashes during // class/method verification. if (h_klass == nullptr || h_klass->IsErroneous()) { diff --git a/runtime/gc/reference_queue_test.cc b/runtime/gc/reference_queue_test.cc index 2b5c3fdea7..ce4f8d93b0 100644 --- a/runtime/gc/reference_queue_test.cc +++ b/runtime/gc/reference_queue_test.cc @@ -42,8 +42,7 @@ TEST_F(ReferenceQueueTest, EnqueueDequeue) { ASSERT_TRUE(queue.IsEmpty()); ASSERT_EQ(queue.GetLength(), 0U); auto ref_class = hs.NewHandle( - Runtime::Current()->GetClassLinker()->FindClass(self, "Ljava/lang/ref/WeakReference;", - ScopedNullHandle<mirror::ClassLoader>())); + FindClass("Ljava/lang/ref/WeakReference;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(ref_class != nullptr); auto ref1(hs.NewHandle(ref_class->AllocObject(self)->AsReference())); ASSERT_TRUE(ref1 != nullptr); @@ -77,12 +76,10 @@ TEST_F(ReferenceQueueTest, Dump) { queue.Dump(oss); LOG(INFO) << oss.str(); auto weak_ref_class = hs.NewHandle( - Runtime::Current()->GetClassLinker()->FindClass(self, "Ljava/lang/ref/WeakReference;", - ScopedNullHandle<mirror::ClassLoader>())); + FindClass("Ljava/lang/ref/WeakReference;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(weak_ref_class != nullptr); auto finalizer_ref_class = hs.NewHandle( - Runtime::Current()->GetClassLinker()->FindClass(self, "Ljava/lang/ref/FinalizerReference;", - ScopedNullHandle<mirror::ClassLoader>())); + FindClass("Ljava/lang/ref/FinalizerReference;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(finalizer_ref_class != nullptr); auto ref1(hs.NewHandle(weak_ref_class->AllocObject(self)->AsReference())); ASSERT_TRUE(ref1 != nullptr); diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc index eff54bd861..b16c42f1a7 100644 --- a/runtime/hidden_api_test.cc +++ b/runtime/hidden_api_test.cc @@ -626,8 +626,8 @@ TEST_F(HiddenApiTest, CheckMemberSignatureForProxyClass) { hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader_))); // Find interface we will create a proxy for. - Handle<mirror::Class> h_iface(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "Lmypackage/packagea/Interface;", class_loader))); + Handle<mirror::Class> h_iface = + hs.NewHandle(FindClass("Lmypackage/packagea/Interface;", class_loader)); ASSERT_TRUE(h_iface != nullptr); // Create the proxy class. diff --git a/runtime/imtable_test.cc b/runtime/imtable_test.cc index 9fed220f44..30c5c0b611 100644 --- a/runtime/imtable_test.cc +++ b/runtime/imtable_test.cc @@ -51,8 +51,7 @@ class ImTableTest : public CommonRuntimeTest { // A. h_class_loader.Assign( ObjPtr<mirror::ClassLoader>::DownCast(self->DecodeJObject(jclass_loader_a))); - Handle<mirror::Class> h_class_a( - hs.NewHandle(class_linker->FindClass(self, class_name.c_str(), h_class_loader))); + Handle<mirror::Class> h_class_a = hs.NewHandle(FindClass(class_name.c_str(), h_class_loader)); if (h_class_a == nullptr) { LOG(ERROR) << self->GetException()->Dump(); CHECK(false) << "h_class_a == nullptr"; @@ -61,8 +60,7 @@ class ImTableTest : public CommonRuntimeTest { // B. h_class_loader.Assign( ObjPtr<mirror::ClassLoader>::DownCast(self->DecodeJObject(jclass_loader_b))); - Handle<mirror::Class> h_class_b( - hs.NewHandle(class_linker->FindClass(self, class_name.c_str(), h_class_loader))); + Handle<mirror::Class> h_class_b = hs.NewHandle(FindClass(class_name.c_str(), h_class_loader)); if (h_class_b == nullptr) { LOG(ERROR) << self->GetException()->Dump(); CHECK(false) << "h_class_b == nullptr"; diff --git a/runtime/instrumentation_test.cc b/runtime/instrumentation_test.cc index 664d3577be..e9fb0eafd2 100644 --- a/runtime/instrumentation_test.cc +++ b/runtime/instrumentation_test.cc @@ -491,7 +491,7 @@ TEST_F(InstrumentationTest, MethodEntryEvent) { ClassLinker* class_linker = runtime->GetClassLinker(); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtMethod* method = klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize); @@ -512,7 +512,7 @@ TEST_F(InstrumentationTest, MethodExitObjectEvent) { StackHandleScope<1> hs(soa.Self()); MutableHandle<mirror::ClassLoader> loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtMethod* method = klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize); @@ -532,7 +532,7 @@ TEST_F(InstrumentationTest, MethodExitPrimEvent) { ClassLinker* class_linker = runtime->GetClassLinker(); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtMethod* method = klass->FindClassMethod("returnPrimitive", "()I", kRuntimePointerSize); ASSERT_TRUE(method != nullptr); @@ -567,7 +567,7 @@ TEST_F(InstrumentationTest, FieldWriteObjectEvent) { ClassLinker* class_linker = runtime->GetClassLinker(); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtField* field = klass->FindDeclaredStaticField("referenceField", "Ljava/lang/Object;"); ASSERT_TRUE(field != nullptr); @@ -585,7 +585,7 @@ TEST_F(InstrumentationTest, FieldWritePrimEvent) { ClassLinker* class_linker = runtime->GetClassLinker(); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtField* field = klass->FindDeclaredStaticField("primitiveField", "I"); ASSERT_TRUE(field != nullptr); @@ -616,7 +616,7 @@ TEST_F(InstrumentationTest, DeoptimizeDirectMethod) { ClassLinker* class_linker = runtime->GetClassLinker(); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtMethod* method_to_deoptimize = klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize); @@ -666,7 +666,7 @@ TEST_F(InstrumentationTest, MixedDeoptimization) { ClassLinker* class_linker = runtime->GetClassLinker(); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); + ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader); ASSERT_TRUE(klass != nullptr); ArtMethod* method_to_deoptimize = klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize); diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index db4ff095ef..9149f3a6c2 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -142,7 +142,8 @@ static void UnstartedRuntimeFindClass(Thread* self, std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str())); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ObjPtr<mirror::Class> found = class_linker->FindClass(self, descriptor.c_str(), class_loader); + ObjPtr<mirror::Class> found = + class_linker->FindClass(self, descriptor.c_str(), descriptor.length(), class_loader); if (found != nullptr && !found->CheckIsVisibleWithTargetSdk(self)) { CHECK(self->IsExceptionPending()); return; @@ -626,9 +627,7 @@ static void GetResourceAsStream(Thread* self, // Create a ByteArrayInputStream. Handle<mirror::Class> h_class(hs.NewHandle( - runtime->GetClassLinker()->FindClass(self, - "Ljava/io/ByteArrayInputStream;", - ScopedNullHandle<mirror::ClassLoader>()))); + runtime->GetClassLinker()->FindSystemClass(self, "Ljava/io/ByteArrayInputStream;"))); if (h_class == nullptr) { AbortTransactionOrFail(self, "Could not find ByteArrayInputStream class"); return; @@ -1015,9 +1014,7 @@ static void GetSystemProperty(Thread* self, // Get the storage class. ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Handle<mirror::Class> h_props_class(hs.NewHandle( - class_linker->FindClass(self, - "Ljava/lang/AndroidHardcodedSystemProperties;", - ScopedNullHandle<mirror::ClassLoader>()))); + class_linker->FindSystemClass(self, "Ljava/lang/AndroidHardcodedSystemProperties;"))); if (h_props_class == nullptr) { AbortTransactionOrFail(self, "Could not find AndroidHardcodedSystemProperties"); return; @@ -1124,8 +1121,7 @@ static ObjPtr<mirror::Object> CreateInstanceOf(Thread* self, const char* class_d REQUIRES_SHARED(Locks::mutator_lock_) { // Find the requested class. ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ObjPtr<mirror::Class> klass = - class_linker->FindClass(self, class_descriptor, ScopedNullHandle<mirror::ClassLoader>()); + ObjPtr<mirror::Class> klass = class_linker->FindSystemClass(self, class_descriptor); if (klass == nullptr) { AbortTransactionOrFail(self, "Could not load class %s", class_descriptor); return nullptr; @@ -1156,8 +1152,9 @@ void UnstartedRuntime::UnstartedThreadLocalGet(Thread* self, ShadowFrame* shadow_frame, JValue* result, [[maybe_unused]] size_t arg_offset) { - if (CheckCallers(shadow_frame, { "jdk.internal.math.FloatingDecimal$BinaryToASCIIBuffer " - "jdk.internal.math.FloatingDecimal.getBinaryToASCIIBuffer()" })) { + if (CheckCallers(shadow_frame, + { "jdk.internal.math.FloatingDecimal$BinaryToASCIIBuffer " + "jdk.internal.math.FloatingDecimal.getBinaryToASCIIBuffer()" })) { result->SetL(CreateInstanceOf(self, "Ljdk/internal/math/FloatingDecimal$BinaryToASCIIBuffer;")); } else { AbortTransactionOrFail(self, diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index cf7782dcdc..1f5f111c59 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -784,7 +784,7 @@ TEST_F(UnstartedRuntimeTest, IsAnonymousClass) { StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - ObjPtr<mirror::Class> c = class_linker_->FindClass(soa.Self(), "LNested$1;", loader); + ObjPtr<mirror::Class> c = FindClass("LNested$1;", loader); ASSERT_TRUE(c != nullptr); shadow_frame->SetVRegReference(0, c); UnstartedClassIsAnonymousClass(self, shadow_frame.get(), &result, 0); @@ -803,12 +803,9 @@ TEST_F(UnstartedRuntimeTest, GetDeclaringClass) { Handle<mirror::ClassLoader> loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); - Handle<mirror::Class> nested_klass(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LNested;", loader))); - Handle<mirror::Class> inner_klass(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LNested$Inner;", loader))); - Handle<mirror::Class> anon_klass(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LNested$1;", loader))); + Handle<mirror::Class> nested_klass = hs.NewHandle(FindClass("LNested;", loader)); + Handle<mirror::Class> inner_klass = hs.NewHandle(FindClass("LNested$Inner;", loader)); + Handle<mirror::Class> anon_klass = hs.NewHandle(FindClass("LNested$1;", loader)); shadow_frame->SetVRegReference(0, nested_klass.Get()); UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0); @@ -835,9 +832,7 @@ TEST_F(UnstartedRuntimeTest, ThreadLocalGet) { // Positive test. See that We get something for float conversion. { Handle<mirror::Class> floating_decimal = hs.NewHandle( - class_linker_->FindClass(self, - "Ljdk/internal/math/FloatingDecimal;", - ScopedNullHandle<mirror::ClassLoader>())); + FindClass("Ljdk/internal/math/FloatingDecimal;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(floating_decimal != nullptr); ASSERT_TRUE(class_linker_->EnsureInitialized(self, floating_decimal, true, true)); @@ -865,10 +860,8 @@ TEST_F(UnstartedRuntimeTest, FloatConversion) { ScopedObjectAccess soa(self); StackHandleScope<1> hs(self); - Handle<mirror::Class> double_class = hs.NewHandle( - class_linker_->FindClass(self, - "Ljava/lang/Double;", - ScopedNullHandle<mirror::ClassLoader>())); + Handle<mirror::Class> double_class = + hs.NewHandle(FindClass("Ljava/lang/Double;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(double_class != nullptr); ASSERT_TRUE(class_linker_->EnsureInitialized(self, double_class, true, true)); @@ -905,8 +898,8 @@ TEST_F(UnstartedRuntimeTest, LogManager) { ScopedObjectAccess soa(self); StackHandleScope<1> hs(self); - Handle<mirror::Class> log_manager_class = hs.NewHandle(class_linker_->FindClass( - self, "Ljava/util/logging/LogManager;", ScopedNullHandle<mirror::ClassLoader>())); + Handle<mirror::Class> log_manager_class = hs.NewHandle( + FindClass("Ljava/util/logging/LogManager;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(log_manager_class.Get() != nullptr); ASSERT_TRUE(class_linker_->EnsureInitialized(self, log_manager_class, true, true)); } @@ -991,10 +984,8 @@ TEST_F(UnstartedRuntimeTest, ClassGetSignatureAnnotation) { ScopedObjectAccess soa(self); StackHandleScope<1> hs(self); - Handle<mirror::Class> list_class = hs.NewHandle( - class_linker_->FindClass(self, - "Ljava/util/List;", - ScopedNullHandle<mirror::ClassLoader>())); + Handle<mirror::Class> list_class = + hs.NewHandle(FindClass("Ljava/util/List;", ScopedNullHandle<mirror::ClassLoader>())); ASSERT_TRUE(list_class.Get() != nullptr); ASSERT_TRUE(class_linker_->EnsureInitialized(self, list_class, true, true)); diff --git a/runtime/interpreter/unstarted_runtime_test.h b/runtime/interpreter/unstarted_runtime_test.h index 465a4268ea..eb0a28aaec 100644 --- a/runtime/interpreter/unstarted_runtime_test.h +++ b/runtime/interpreter/unstarted_runtime_test.h @@ -85,8 +85,8 @@ class UnstartedRuntimeTestBase : public CommonRuntimeTest { StackHandleScope<2> hs(self); // Create the fake boot classloader. Any instance is fine, they are technically interchangeable. - Handle<mirror::Class> boot_cp_class = hs.NewHandle(class_linker_->FindClass( - self, "Ljava/lang/BootClassLoader;", ScopedNullHandle<mirror::ClassLoader>())); + Handle<mirror::Class> boot_cp_class = hs.NewHandle( + FindClass("Ljava/lang/BootClassLoader;", ScopedNullHandle<mirror::ClassLoader>())); CHECK(boot_cp_class != nullptr); CHECK(class_linker_->EnsureInitialized( self, boot_cp_class, /*can_init_fields=*/ true, /*can_init_parents=*/ true)); diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index 66fc1e639a..c8e274a846 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -803,15 +803,17 @@ class ZygoteVerificationTask final : public Task { const std::vector<const DexFile*>& boot_class_path = runtime->GetClassLinker()->GetBootClassPath(); ScopedObjectAccess soa(self); - StackHandleScope<1> hs(self); + StackHandleScope<2> hs(self); + MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle<mirror::DexCache>(nullptr); MutableHandle<mirror::Class> klass = hs.NewHandle<mirror::Class>(nullptr); uint64_t start_ns = ThreadCpuNanoTime(); uint64_t number_of_classes = 0; for (const DexFile* dex_file : boot_class_path) { + dex_cache.Assign(linker->FindDexCache(self, *dex_file)); for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { const dex::ClassDef& class_def = dex_file->GetClassDef(i); - const char* descriptor = dex_file->GetClassDescriptor(class_def); - klass.Assign(linker->LookupResolvedType(descriptor, /* class_loader= */ nullptr)); + klass.Assign(linker->LookupResolvedType( + class_def.class_idx_, dex_cache.Get(), /* class_loader= */ nullptr)); if (klass == nullptr) { // Class not loaded yet. DCHECK(!self->IsExceptionPending()); diff --git a/runtime/jit/profiling_info_test.cc b/runtime/jit/profiling_info_test.cc index 9b91c28ac5..41f75b87fc 100644 --- a/runtime/jit/profiling_info_test.cc +++ b/runtime/jit/profiling_info_test.cc @@ -46,15 +46,14 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { } protected: - std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader, - const std::string& clazz) { + std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader, const char* clazz) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Thread* self = Thread::Current(); ScopedObjectAccess soa(self); StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_loader( hs.NewHandle(self->DecodeJObject(class_loader)->AsClassLoader())); - ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader); + ObjPtr<mirror::Class> klass = FindClass(clazz, h_loader); const auto pointer_size = class_linker->GetImagePointerSize(); std::vector<ArtMethod*> methods; diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc index 51350dc713..f1ea88da4e 100644 --- a/runtime/jni/jni_internal.cc +++ b/runtime/jni/jni_internal.cc @@ -535,7 +535,7 @@ ArtField* FindFieldJNI(const ScopedObjectAccess& soa, DCHECK(field == nullptr); } else if (sig[1] != '\0') { Handle<mirror::ClassLoader> class_loader(hs.NewHandle(c->GetClassLoader())); - field_type = class_linker->FindClass(soa.Self(), sig, class_loader); + field_type = class_linker->FindClass(soa.Self(), sig, strlen(sig), class_loader); } else { field_type = class_linker->FindPrimitiveClass(*sig); } @@ -675,14 +675,11 @@ class JNI { ClassLinker* class_linker = runtime->GetClassLinker(); std::string descriptor(NormalizeJniClassDescriptor(name)); ScopedObjectAccess soa(env); - ObjPtr<mirror::Class> c = nullptr; - if (runtime->IsStarted()) { - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader<kEnableIndexIds>(soa))); - c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader); - } else { - c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str()); - } + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader = hs.NewHandle( + runtime->IsStarted() ? GetClassLoader<kEnableIndexIds>(soa) : nullptr); + ObjPtr<mirror::Class> c = class_linker->FindClass( + soa.Self(), descriptor.c_str(), descriptor.length(), class_loader); return soa.AddLocalReference<jclass>(c); } diff --git a/runtime/jni/jni_internal_test.cc b/runtime/jni/jni_internal_test.cc index ed97e4d4c8..6115556940 100644 --- a/runtime/jni/jni_internal_test.cc +++ b/runtime/jni/jni_internal_test.cc @@ -624,7 +624,7 @@ class JniInternalTest : public CommonRuntimeTest { StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader_))); - ObjPtr<mirror::Class> c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader); + ObjPtr<mirror::Class> c = FindClass("LMyClassNatives;", loader); const auto pointer_size = class_linker_->GetImagePointerSize(); ArtMethod* method = c->FindClassMethod(method_name, method_sig, pointer_size); ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig; diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc index 49177aca02..b4ab2dc26a 100644 --- a/runtime/mirror/class_ext.cc +++ b/runtime/mirror/class_ext.cc @@ -84,9 +84,7 @@ bool ClassExt::ExtendObsoleteArrays(Handle<ClassExt> h_this, Thread* self, uint3 } Handle<ObjectArray<DexCache>> new_dex_caches(hs.NewHandle<ObjectArray<DexCache>>( ObjectArray<DexCache>::Alloc(self, - cl->FindClass(self, - "[Ljava/lang/DexCache;", - ScopedNullHandle<ClassLoader>()), + cl->FindSystemClass(self, "[Ljava/lang/DexCache;"), new_len))); if (new_dex_caches.IsNull()) { // Fail. diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index 9ca8d307ba..1429bb3e04 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -79,11 +79,9 @@ TEST_F(DexCacheTest, TestResolvedFieldAccess) { StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader(hs.NewHandle( soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> klass1 = - hs.NewHandle(class_linker_->FindClass(soa.Self(), "Lpackage1/Package1;", class_loader)); + Handle<mirror::Class> klass1 = hs.NewHandle(FindClass("Lpackage1/Package1;", class_loader)); ASSERT_TRUE(klass1 != nullptr); - Handle<mirror::Class> klass2 = - hs.NewHandle(class_linker_->FindClass(soa.Self(), "Lpackage2/Package2;", class_loader)); + Handle<mirror::Class> klass2 = hs.NewHandle(FindClass("Lpackage2/Package2;", class_loader)); ASSERT_TRUE(klass2 != nullptr); EXPECT_OBJ_PTR_EQ(klass1->GetDexCache(), klass2->GetDexCache()); @@ -107,8 +105,7 @@ TEST_F(DexCacheMethodHandlesTest, TestResolvedMethodTypes) { Handle<mirror::ClassLoader> class_loader(hs.NewHandle( soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> method_types( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LMethodTypes;", class_loader))); + Handle<mirror::Class> method_types = hs.NewHandle(FindClass("LMethodTypes;", class_loader)); class_linker_->EnsureInitialized(soa.Self(), method_types, true, true); ArtMethod* method1 = method_types->FindClassMethod( diff --git a/runtime/mirror/method_type_test.cc b/runtime/mirror/method_type_test.cc index 9d23f8f23d..c5ab7dd522 100644 --- a/runtime/mirror/method_type_test.cc +++ b/runtime/mirror/method_type_test.cc @@ -32,43 +32,48 @@ namespace art HIDDEN { namespace mirror { -class MethodTypeTest : public CommonRuntimeTest {}; +class MethodTypeTest : public CommonRuntimeTest { + protected: + ObjPtr<mirror::MethodType> CreateMethodType(const std::string& return_type, + const std::vector<std::string>& param_types); +}; static std::string FullyQualifiedType(const std::string& shorthand) { return "Ljava/lang/" + shorthand + ";"; } -ObjPtr<mirror::Class> FindClass(Thread* self, ClassLinker* const cl, const std::string& shorthand) - REQUIRES_SHARED(Locks::mutator_lock_) { - StackHandleScope<1> hs(self); - Handle<mirror::ClassLoader> boot_class_loader = hs.NewHandle<mirror::ClassLoader>(nullptr); +std::string ExpandShortHand(const std::string& shorthand) { if (shorthand.size() == 1) { - return cl->FindSystemClass(self, shorthand.c_str()); + return shorthand; } else if (shorthand.find('/') == std::string::npos) { - return cl->FindClass(self, FullyQualifiedType(shorthand).c_str(), boot_class_loader); + return FullyQualifiedType(shorthand); } else { - return cl->FindClass(self, shorthand.c_str(), boot_class_loader); + return shorthand; } } -static ObjPtr<mirror::MethodType> CreateMethodType(const std::string& return_type, - const std::vector<std::string>& param_types) { +ObjPtr<mirror::MethodType> MethodTypeTest::CreateMethodType( + const std::string& return_type, + const std::vector<std::string>& param_types) { Runtime* const runtime = Runtime::Current(); - ClassLinker* const class_linker = runtime->GetClassLinker(); Thread* const self = Thread::Current(); ScopedObjectAccess soa(self); StackHandleScope<2> hs(soa.Self()); - Handle<mirror::Class> return_clazz = hs.NewHandle(FindClass(self, class_linker, return_type)); + ScopedNullHandle<mirror::ClassLoader> boot_class_loader; + Handle<mirror::Class> return_clazz = + hs.NewHandle(FindClass(ExpandShortHand(return_type).c_str(), boot_class_loader)); CHECK(return_clazz != nullptr); ObjPtr<mirror::Class> class_array_type = - GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker); + GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker_); Handle<mirror::ObjectArray<mirror::Class>> param_classes = hs.NewHandle( mirror::ObjectArray<mirror::Class>::Alloc(self, class_array_type, param_types.size())); + CHECK(param_classes != nullptr); for (uint32_t i = 0; i < param_types.size(); ++i) { - ObjPtr<mirror::Class> param = FindClass(self, class_linker, param_types[i]); + ObjPtr<mirror::Class> param = + FindClass(ExpandShortHand(param_types[i]).c_str(), boot_class_loader); CHECK(!param.IsNull()); param_classes->Set(i, param); } diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index f879b805a9..579ccdce01 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -407,8 +407,7 @@ TEST_F(ObjectTest, StaticFieldFromCode) { StackHandleScope<3> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader>(class_loader))); - Handle<Class> klass = - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", loader)); + Handle<Class> klass = hs.NewHandle(FindClass("LStaticsFromCode;", loader)); ArtMethod* clinit = klass->FindClassInitializer(kRuntimePointerSize); const dex::TypeId* klass_type_id = dex_file->FindTypeId("LStaticsFromCode;"); ASSERT_TRUE(klass_type_id != nullptr); @@ -534,7 +533,6 @@ TEST_F(ObjectTest, StringLength) { TEST_F(ObjectTest, DescriptorCompare) { // Two classloaders conflicts in compile_time_class_paths_. ScopedObjectAccess soa(Thread::Current()); - ClassLinker* linker = class_linker_; jobject jclass_loader_1 = LoadDex("ProtoCompare"); jobject jclass_loader_2 = LoadDex("ProtoCompare2"); @@ -542,11 +540,9 @@ TEST_F(ObjectTest, DescriptorCompare) { Handle<ClassLoader> class_loader_1(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader_1))); Handle<ClassLoader> class_loader_2(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader_2))); - Handle<Class> klass1 = - hs.NewHandle(linker->FindClass(soa.Self(), "LProtoCompare;", class_loader_1)); + Handle<Class> klass1 = hs.NewHandle(FindClass("LProtoCompare;", class_loader_1)); ASSERT_TRUE(klass1 != nullptr); - Handle<Class> klass2 = - hs.NewHandle(linker->FindClass(soa.Self(), "LProtoCompare2;", class_loader_2)); + Handle<Class> klass2 = hs.NewHandle(FindClass("LProtoCompare2;", class_loader_2)); ASSERT_TRUE(klass2 != nullptr); ArtMethod* m1_1 = klass1->GetVirtualMethod(0, kRuntimePointerSize); @@ -586,8 +582,8 @@ TEST_F(ObjectTest, InstanceOf) { StackHandleScope<10> hs(soa.Self()); Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); - Handle<Class> X = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)); - Handle<Class> Y = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); + Handle<Class> X = hs.NewHandle(FindClass("LX;", class_loader)); + Handle<Class> Y = hs.NewHandle(FindClass("LY;", class_loader)); ASSERT_TRUE(X != nullptr); ASSERT_TRUE(Y != nullptr); @@ -625,8 +621,8 @@ TEST_F(ObjectTest, IsAssignableFrom) { jobject jclass_loader = LoadDex("XandY"); StackHandleScope<5> hs(soa.Self()); Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); - Handle<Class> X = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)); - Handle<Class> Y = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); + Handle<Class> X = hs.NewHandle(FindClass("LX;", class_loader)); + Handle<Class> Y = hs.NewHandle(FindClass("LY;", class_loader)); EXPECT_TRUE(X->IsAssignableFrom(X.Get())); EXPECT_TRUE(X->IsAssignableFrom(Y.Get())); @@ -665,17 +661,17 @@ TEST_F(ObjectTest, IsAssignableFromArray) { jobject jclass_loader = LoadDex("XandY"); StackHandleScope<14> hs(soa.Self()); Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); - Handle<Class> X = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)); - Handle<Class> Y = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); + Handle<Class> X = hs.NewHandle(FindClass("LX;", class_loader)); + Handle<Class> Y = hs.NewHandle(FindClass("LY;", class_loader)); ASSERT_TRUE(X != nullptr); ASSERT_TRUE(Y != nullptr); - Handle<Class> YA = hs.NewHandle(class_linker_->FindClass(soa.Self(), "[LY;", class_loader)); - Handle<Class> YAA = hs.NewHandle(class_linker_->FindClass(soa.Self(), "[[LY;", class_loader)); + Handle<Class> YA = hs.NewHandle(FindClass("[LY;", class_loader)); + Handle<Class> YAA = hs.NewHandle(FindClass("[[LY;", class_loader)); ASSERT_TRUE(YA != nullptr); ASSERT_TRUE(YAA != nullptr); - Handle<Class> XAA = hs.NewHandle(class_linker_->FindClass(soa.Self(), "[[LX;", class_loader)); + Handle<Class> XAA = hs.NewHandle(FindClass("[[LX;", class_loader)); ASSERT_TRUE(XAA != nullptr); Handle<Class> O = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")); @@ -797,8 +793,7 @@ TEST_F(ObjectTest, ObjectPointer) { jobject jclass_loader = LoadDex("XandY"); StackHandleScope<2> hs(soa.Self()); Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); - Handle<mirror::Class> h_X( - hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader))); + Handle<mirror::Class> h_X = hs.NewHandle(FindClass("LX;", class_loader)); if (kObjPtrPoisoning) { ObjPtr<mirror::Object> null_ptr; @@ -816,7 +811,7 @@ TEST_F(ObjectTest, ObjectPointer) { EXPECT_TRUE(X.Ptr() != nullptr); EXPECT_OBJ_PTR_EQ(h_X.Get(), X); // FindClass may cause thread suspension, it should invalidate X. - ObjPtr<Class> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); + ObjPtr<Class> Y = FindClass("LY;", class_loader); EXPECT_TRUE(!Y.IsNull()); EXPECT_TRUE(Y.IsValid()); EXPECT_TRUE(Y.Ptr() != nullptr); diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc index 22d1e4a6d4..bb7753c42a 100644 --- a/runtime/mirror/var_handle_test.cc +++ b/runtime/mirror/var_handle_test.cc @@ -137,6 +137,26 @@ class VarHandleTest : public CommonRuntimeTest { return AccessModesBitMask(first) | AccessModesBitMask(args...); } + ObjPtr<MethodType> MethodTypeOf(const std::string& method_descriptor); + + template <typename VH> + bool AccessModeExactMatch(Handle<VH> vh, + VarHandle::AccessMode access_mode, + const char* descriptor) + REQUIRES_SHARED(Locks::mutator_lock_); + + template <typename VH> + bool AccessModeWithConversionsMatch(Handle<VH> vh, + VarHandle::AccessMode access_mode, + const char* descriptor) + REQUIRES_SHARED(Locks::mutator_lock_); + + template <typename VH> + bool AccessModeNoMatch(Handle<VH> vh, + VarHandle::AccessMode access_mode, + const char* descriptor) + REQUIRES_SHARED(Locks::mutator_lock_); + private: static void InitializeVarHandle(ObjPtr<VarHandle> vh, Handle<Class> var_type, @@ -169,7 +189,7 @@ class VarHandleTest : public CommonRuntimeTest { // Convenience method for constructing MethodType instances from // well-formed method descriptors. -static ObjPtr<MethodType> MethodTypeOf(const std::string& method_descriptor) { +ObjPtr<MethodType> VarHandleTest::MethodTypeOf(const std::string& method_descriptor) { std::vector<std::string> descriptors; auto it = method_descriptor.cbegin(); @@ -226,10 +246,9 @@ static ObjPtr<MethodType> MethodTypeOf(const std::string& method_descriptor) { ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count)); Handle<mirror::ClassLoader> boot_class_loader = hs.NewHandle<mirror::ClassLoader>(nullptr); for (int i = 0; i < ptypes_count; ++i) { - ptypes->Set(i, class_linker->FindClass(self, descriptors[i].c_str(), boot_class_loader)); + ptypes->Set(i, FindClass(descriptors[i].c_str(), boot_class_loader)); } - Handle<Class> rtype = - hs.NewHandle(class_linker->FindClass(self, descriptors.back().c_str(), boot_class_loader)); + Handle<Class> rtype = hs.NewHandle(FindClass(descriptors.back().c_str(), boot_class_loader)); return MethodType::Create(self, rtype, ptypes); } @@ -242,10 +261,9 @@ static bool AccessModeMatch(ObjPtr<VarHandle> vh, } template <typename VH> -static bool AccessModeExactMatch(Handle<VH> vh, - VarHandle::AccessMode access_mode, - const char* descriptor) - REQUIRES_SHARED(Locks::mutator_lock_) { +bool VarHandleTest::AccessModeExactMatch(Handle<VH> vh, + VarHandle::AccessMode access_mode, + const char* descriptor) { ObjPtr<MethodType> method_type = MethodTypeOf(descriptor); return AccessModeMatch(vh.Get(), access_mode, @@ -254,10 +272,9 @@ static bool AccessModeExactMatch(Handle<VH> vh, } template <typename VH> -static bool AccessModeWithConversionsMatch(Handle<VH> vh, - VarHandle::AccessMode access_mode, - const char* descriptor) - REQUIRES_SHARED(Locks::mutator_lock_) { +bool VarHandleTest::AccessModeWithConversionsMatch(Handle<VH> vh, + VarHandle::AccessMode access_mode, + const char* descriptor) { ObjPtr<MethodType> method_type = MethodTypeOf(descriptor); return AccessModeMatch(vh.Get(), access_mode, @@ -266,10 +283,9 @@ static bool AccessModeWithConversionsMatch(Handle<VH> vh, } template <typename VH> -static bool AccessModeNoMatch(Handle<VH> vh, - VarHandle::AccessMode access_mode, - const char* descriptor) - REQUIRES_SHARED(Locks::mutator_lock_) { +bool VarHandleTest::AccessModeNoMatch(Handle<VH> vh, + VarHandle::AccessMode access_mode, + const char* descriptor) { ObjPtr<MethodType> method_type = MethodTypeOf(descriptor); return AccessModeMatch(vh.Get(), access_mode, diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 79c8176027..c31c9790bd 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -111,8 +111,8 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader))); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - Handle<mirror::Class> c( - hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader))); + Handle<mirror::Class> c = hs.NewHandle( + class_linker->FindClass(soa.Self(), descriptor.c_str(), descriptor.length(), class_loader)); if (UNLIKELY(c == nullptr)) { StackHandleScope<2> hs2(soa.Self()); Handle<mirror::Object> cause = hs2.NewHandle(soa.Self()->GetException()); diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index a735765bdd..eeae51c5e7 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -45,7 +45,7 @@ class VMClassLoader { public: static ObjPtr<mirror::Class> LookupClass(ClassLinker* cl, Thread* self, - const char* descriptor, + std::string_view descriptor, size_t hash, ObjPtr<mirror::ClassLoader> class_loader) REQUIRES(!Locks::classlinker_classes_lock_) @@ -89,7 +89,7 @@ static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoa ObjPtr<mirror::Class> c = VMClassLoader::LookupClass(cl, soa.Self(), - descriptor.c_str(), + descriptor, descriptor_hash, loader); if (c != nullptr && c->IsResolved()) { diff --git a/runtime/oat/oat_file_manager.cc b/runtime/oat/oat_file_manager.cc index f10ba673df..320961755f 100644 --- a/runtime/oat/oat_file_manager.cc +++ b/runtime/oat/oat_file_manager.cc @@ -724,10 +724,8 @@ class BackgroundVerificationTask final : public Task { StackHandleScope<2> hs(self); Handle<mirror::ClassLoader> h_loader(hs.NewHandle( soa.Decode<mirror::ClassLoader>(class_loader_))); - Handle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(class_linker->FindClass( - self, - dex_file->GetClassDescriptor(class_def), - h_loader))); + Handle<mirror::Class> h_class = + hs.NewHandle(class_linker->FindClass(self, *dex_file, class_def.class_idx_, h_loader)); if (h_class == nullptr) { DCHECK(self->IsExceptionPending()); diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc index fb877d3ec5..f9bf31bedd 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -43,10 +43,8 @@ TEST_F(ProxyTest, ProxyClassHelper) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> I(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader))); - Handle<mirror::Class> J(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader))); + Handle<mirror::Class> I = hs.NewHandle(FindClass("LInterfaces$I;", class_loader)); + Handle<mirror::Class> J = hs.NewHandle(FindClass("LInterfaces$J;", class_loader)); ASSERT_TRUE(I != nullptr); ASSERT_TRUE(J != nullptr); @@ -77,10 +75,8 @@ TEST_F(ProxyTest, ProxyFieldHelper) { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> I(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader))); - Handle<mirror::Class> J(hs.NewHandle( - class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader))); + Handle<mirror::Class> I = hs.NewHandle(FindClass("LInterfaces$I;", class_loader)); + Handle<mirror::Class> J = hs.NewHandle(FindClass("LInterfaces$J;", class_loader)); ASSERT_TRUE(I != nullptr); ASSERT_TRUE(J != nullptr); diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc index af8f4e50bc..40c22c8a3e 100644 --- a/runtime/reference_table_test.cc +++ b/runtime/reference_table_test.cc @@ -45,10 +45,12 @@ class ReferenceTableTest : public CommonRuntimeTest { ReferenceTableTest() { use_boot_image_ = true; // Make the Runtime creation cheaper. } + + ObjPtr<mirror::Object> CreateWeakReference(ObjPtr<mirror::Object> referent) + REQUIRES_SHARED(Locks::mutator_lock_); }; -static ObjPtr<mirror::Object> CreateWeakReference(ObjPtr<mirror::Object> referent) - REQUIRES_SHARED(Locks::mutator_lock_) { +ObjPtr<mirror::Object> ReferenceTableTest::CreateWeakReference(ObjPtr<mirror::Object> referent) { Thread* self = Thread::Current(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); @@ -56,9 +58,7 @@ static ObjPtr<mirror::Object> CreateWeakReference(ObjPtr<mirror::Object> referen Handle<mirror::Object> h_referent(scope.NewHandle<mirror::Object>(referent)); Handle<mirror::Class> h_ref_class(scope.NewHandle<mirror::Class>( - class_linker->FindClass(self, - "Ljava/lang/ref/WeakReference;", - ScopedNullHandle<mirror::ClassLoader>()))); + FindClass("Ljava/lang/ref/WeakReference;", ScopedNullHandle<mirror::ClassLoader>()))); CHECK(h_ref_class != nullptr); CHECK(class_linker->EnsureInitialized(self, h_ref_class, true, true)); diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc index d307ba0cca..f65a244fef 100644 --- a/runtime/reflection_test.cc +++ b/runtime/reflection_test.cc @@ -103,9 +103,7 @@ class ReflectionTest : public CommonRuntimeTest { MakeInterpreted(class_linker_->FindSystemClass(self, "Ljava/lang/Object;")); } - ObjPtr<mirror::Class> c = class_linker_->FindClass(self, - DotToDescriptor(class_name).c_str(), - class_loader); + ObjPtr<mirror::Class> c = FindClass(DotToDescriptor(class_name).c_str(), class_loader); CHECK(c != nullptr); MakeInterpreted(c); diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc index 719cae5e3c..053d4eaaf5 100644 --- a/runtime/runtime_callbacks_test.cc +++ b/runtime/runtime_callbacks_test.cc @@ -303,8 +303,7 @@ TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) { soa.Decode<mirror::ClassLoader>(jclass_loader))); const char* descriptor_y = "LY;"; - Handle<mirror::Class> h_Y( - hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader))); + Handle<mirror::Class> h_Y = hs.NewHandle(FindClass(descriptor_y, class_loader)); ASSERT_TRUE(h_Y != nullptr); bool expect1 = Expect({ "PreDefine:LY; <art-gtest-jars-XandY.jar>", diff --git a/runtime/thread.cc b/runtime/thread.cc index 319782b351..5bd97eb59a 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -3642,7 +3642,8 @@ void Thread::ThrowNewWrappedException(const char* exception_class_descriptor, Runtime* runtime = Runtime::Current(); auto* cl = runtime->GetClassLinker(); Handle<mirror::Class> exception_class( - hs.NewHandle(cl->FindClass(this, exception_class_descriptor, class_loader))); + hs.NewHandle(cl->FindClass( + this, exception_class_descriptor, strlen(exception_class_descriptor), class_loader))); if (UNLIKELY(exception_class == nullptr)) { CHECK(IsExceptionPending()); LOG(ERROR) << "No exception class " << PrettyDescriptor(exception_class_descriptor); diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index 6702970c68..db2a976c22 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -392,10 +392,12 @@ bool VdexFile::HasOnlyStandardDexFiles() const { static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker, Thread* self, - const char* name, + const char* descriptor, + size_t descriptor_length, Handle<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) { - ObjPtr<mirror::Class> result = class_linker->FindClass(self, name, class_loader); + ObjPtr<mirror::Class> result = + class_linker->FindClass(self, descriptor, descriptor_length, class_loader); if (result == nullptr) { DCHECK(self->IsExceptionPending()); self->ClearException(); @@ -403,18 +405,24 @@ static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linke return result; } -static const char* GetStringFromId(const DexFile& dex_file, - dex::StringIndex string_id, - uint32_t number_of_extra_strings, - const uint32_t* extra_strings_offsets, - const uint8_t* verifier_deps) { +static const char* GetStringFromIndex(const DexFile& dex_file, + dex::StringIndex string_id, + uint32_t number_of_extra_strings, + const uint32_t* extra_strings_offsets, + const uint8_t* verifier_deps, + /*out*/ size_t* utf8_length) { uint32_t num_ids_in_dex = dex_file.NumStringIds(); if (string_id.index_ < num_ids_in_dex) { - return dex_file.GetStringData(string_id); + uint32_t utf16_length; + const char* str = dex_file.GetStringDataAndUtf16Length(string_id, &utf16_length); + *utf8_length = DexFile::Utf8Length(str, utf16_length); + return str; } else { CHECK_LT(string_id.index_ - num_ids_in_dex, number_of_extra_strings); uint32_t offset = extra_strings_offsets[string_id.index_ - num_ids_in_dex]; - return reinterpret_cast<const char*>(verifier_deps) + offset; + const char* str = reinterpret_cast<const char*>(verifier_deps) + offset; + *utf8_length = strlen(str); + return str; } } @@ -499,20 +507,25 @@ ClassStatus VdexFile::ComputeClassStatus(Thread* self, Handle<mirror::Class> cls // Error parsing the data, just return that we are not verified. return ClassStatus::kResolved; } - const char* destination_desc = GetStringFromId(dex_file, - dex::StringIndex(destination_index), - number_of_extra_strings, - extra_strings_offsets, - verifier_deps); - destination.Assign( - FindClassAndClearException(class_linker, self, destination_desc, class_loader)); - - const char* source_desc = GetStringFromId(dex_file, - dex::StringIndex(source_index), - number_of_extra_strings, - extra_strings_offsets, - verifier_deps); - source.Assign(FindClassAndClearException(class_linker, self, source_desc, class_loader)); + size_t destination_desc_length; + const char* destination_desc = GetStringFromIndex(dex_file, + dex::StringIndex(destination_index), + number_of_extra_strings, + extra_strings_offsets, + verifier_deps, + &destination_desc_length); + destination.Assign(FindClassAndClearException( + class_linker, self, destination_desc, destination_desc_length, class_loader)); + + size_t source_desc_length; + const char* source_desc = GetStringFromIndex(dex_file, + dex::StringIndex(source_index), + number_of_extra_strings, + extra_strings_offsets, + verifier_deps, + &source_desc_length); + source.Assign(FindClassAndClearException( + class_linker, self, source_desc, source_desc_length, class_loader)); if (destination == nullptr || source == nullptr) { // The interpreter / compiler can handle a missing class. diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index 3a88458a42..47bb35cec9 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -140,15 +140,16 @@ bool RegTypeCache::MatchDescriptor(size_t idx, const std::string_view& descripto return true; } -ObjPtr<mirror::Class> RegTypeCache::ResolveClass(const char* descriptor) { +ObjPtr<mirror::Class> RegTypeCache::ResolveClass(const char* descriptor, size_t descriptor_length) { // Class was not found, must create new type. // Try resolving class Thread* self = Thread::Current(); ObjPtr<mirror::Class> klass = nullptr; if (can_load_classes_) { - klass = class_linker_->FindClass(self, descriptor, class_loader_); + klass = class_linker_->FindClass(self, descriptor, descriptor_length, class_loader_); } else { - klass = class_linker_->LookupClass(self, descriptor, class_loader_.Get()); + std::string_view sv_descriptor(descriptor, descriptor_length); + klass = class_linker_->LookupClass(self, sv_descriptor, class_loader_.Get()); if (klass != nullptr && !klass->IsResolved()) { // We found the class but without it being loaded its not safe for use. klass = nullptr; @@ -164,6 +165,7 @@ std::string_view RegTypeCache::AddString(const std::string_view& str) { } const RegType& RegTypeCache::From(const char* descriptor) { + // TODO: Avoid the implicit `strlen()` call for ASCII descriptors from the dex file. std::string_view sv_descriptor(descriptor); // Try looking up the class in the cache first. We use a std::string_view to avoid // repeated strlen operations on the descriptor. @@ -174,7 +176,7 @@ const RegType& RegTypeCache::From(const char* descriptor) { } // Class not found in the cache, will create a new type for that. // Try resolving class. - ObjPtr<mirror::Class> klass = ResolveClass(descriptor); + ObjPtr<mirror::Class> klass = ResolveClass(descriptor, sv_descriptor.length()); // TODO: Avoid copying the `descriptor` with `AddString()` below if the `descriptor` // comes from the dex file, for example through `FromTypeIndex()`. if (klass != nullptr) { diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h index db7f4291e1..023f7bce32 100644 --- a/runtime/verifier/reg_type_cache.h +++ b/runtime/verifier/reg_type_cache.h @@ -189,7 +189,7 @@ class RegTypeCache { private: void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<mirror::Class> ResolveClass(const char* descriptor) + ObjPtr<mirror::Class> ResolveClass(const char* descriptor, size_t descriptor_length) REQUIRES_SHARED(Locks::mutator_lock_); bool MatchDescriptor(size_t idx, const std::string_view& descriptor) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc index 8841c9f62e..736b51ed1e 100644 --- a/runtime/verifier/reg_type_test.cc +++ b/runtime/verifier/reg_type_test.cc @@ -1115,10 +1115,8 @@ class RegTypeClassJoinTest : public RegTypeTest { Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); - Handle<mirror::Class> c1(hs.NewHandle( - class_linker_->FindClass(soa.Self(), in1, class_loader))); - Handle<mirror::Class> c2(hs.NewHandle( - class_linker_->FindClass(soa.Self(), in2, class_loader))); + Handle<mirror::Class> c1 = hs.NewHandle(FindClass(in1, class_loader)); + Handle<mirror::Class> c2 = hs.NewHandle(FindClass(in2, class_loader)); ASSERT_TRUE(c1 != nullptr); ASSERT_TRUE(c2 != nullptr); const DexFile* dex_file = &c1->GetDexFile(); diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 81f0a9cd2e..98d9e27c97 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -167,22 +167,32 @@ dex::StringIndex VerifierDeps::GetIdFromString(const DexFile& dex_file, const st deps->strings_.push_back(str); dex::StringIndex new_id(num_ids_in_dex + deps->strings_.size() - 1); CHECK_GE(new_id.index_, num_ids_in_dex); // check for overflows - DCHECK_EQ(str, singleton->GetStringFromId(dex_file, new_id)); + DCHECK_EQ(str, singleton->GetStringFromIndex(dex_file, new_id)); return new_id; } } -std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, - dex::StringIndex string_id) const { +const char* VerifierDeps::GetStringFromIndex(const DexFile& dex_file, + dex::StringIndex string_idx, + /*out*/ size_t* utf8_length) const { uint32_t num_ids_in_dex = dex_file.NumStringIds(); - if (string_id.index_ < num_ids_in_dex) { - return std::string(dex_file.GetStringView(string_id)); + if (string_idx.index_ < num_ids_in_dex) { + uint32_t utf16_length; + const char* str = dex_file.GetStringDataAndUtf16Length(string_idx, &utf16_length); + if (utf8_length != nullptr) { + *utf8_length = DexFile::Utf8Length(str, utf16_length); + } + return str; } else { const DexFileDeps* deps = GetDexFileDeps(dex_file); DCHECK(deps != nullptr); - string_id.index_ -= num_ids_in_dex; - CHECK_LT(string_id.index_, deps->strings_.size()); - return deps->strings_[string_id.index_]; + size_t index = string_idx.index_ - num_ids_in_dex; + CHECK_LT(index, deps->strings_.size()); + const std::string& str = deps->strings_[index]; + if (utf8_length != nullptr) { + *utf8_length = str.length(); + } + return str.c_str(); } } @@ -660,8 +670,9 @@ void VerifierDeps::Dump(VariableIndentationOutputStream* vios) const { vios->Stream() << "Dependencies of " << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx)) << ":\n"; for (const TypeAssignability& entry : dep.second->assignable_types_[idx]) { - vios->Stream() << GetStringFromId(dex_file, entry.GetSource()) << " must be assignable to " - << GetStringFromId(dex_file, entry.GetDestination()) << "\n"; + vios->Stream() << GetStringFromIndex(dex_file, entry.GetSource()) + << " must be assignable to " + << GetStringFromIndex(dex_file, entry.GetDestination()) << "\n"; } } @@ -692,10 +703,12 @@ bool VerifierDeps::ValidateDependenciesAndUpdateStatus( // the same lookup pattern. static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker, Thread* self, - const std::string& name, + const char* descriptor, + size_t descriptor_length, Handle<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) { - ObjPtr<mirror::Class> result = class_linker->FindClass(self, name.c_str(), class_loader); + ObjPtr<mirror::Class> result = + class_linker->FindClass(self, descriptor, descriptor_length, class_loader); if (result == nullptr) { DCHECK(self->IsExceptionPending()); self->ClearException(); @@ -720,11 +733,16 @@ bool VerifierDeps::VerifyDexFileAndUpdateStatus( static constexpr uint32_t kMaxWarnings = 5; for (const auto& vec : assignables) { for (const auto& entry : vec) { - const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination()); - destination.Assign( - FindClassAndClearException(class_linker, self, destination_desc, class_loader)); - const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource()); - source.Assign(FindClassAndClearException(class_linker, self, source_desc, class_loader)); + size_t destination_desc_length; + const char* destination_desc = + GetStringFromIndex(dex_file, entry.GetDestination(), &destination_desc_length); + destination.Assign(FindClassAndClearException( + class_linker, self, destination_desc, destination_desc_length, class_loader)); + size_t source_desc_length; + const char* source_desc = + GetStringFromIndex(dex_file, entry.GetSource(), &source_desc_length); + source.Assign(FindClassAndClearException( + class_linker, self, source_desc, source_desc_length, class_loader)); if (destination == nullptr || source == nullptr) { // We currently don't use assignability information for unresolved diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 5e3fb63c2d..293a6d99b3 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -207,8 +207,10 @@ class VerifierDeps { dex::StringIndex GetIdFromString(const DexFile& dex_file, const std::string& str) REQUIRES(!Locks::verifier_deps_lock_); - // Returns the string represented by `id`. - std::string GetStringFromId(const DexFile& dex_file, dex::StringIndex string_id) const; + // Returns the string represented by `string_idx`. + const char* GetStringFromIndex(const DexFile& dex_file, + dex::StringIndex string_idx, + /*out*/ size_t* utf8_length = nullptr) const; // Returns a string ID of the descriptor of the class. dex::StringIndex GetClassDescriptorStringId(const DexFile& dex_file, ObjPtr<mirror::Class> klass) diff --git a/test/692-vdex-inmem-loader/vdex_inmem_loader.cc b/test/692-vdex-inmem-loader/vdex_inmem_loader.cc index e1278becbd..919107eb63 100644 --- a/test/692-vdex-inmem-loader/vdex_inmem_loader.cc +++ b/test/692-vdex-inmem-loader/vdex_inmem_loader.cc @@ -59,9 +59,9 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesVerified(JNIEnv*, bool all_verified = false; for (const DexFile* dex_file : dex_files) { for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) { - const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx)); - h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader)); - CHECK(h_class != nullptr) << "Could not find class " << desc; + dex::TypeIndex type_idx = dex_file->GetClassDef(cdef_idx).class_idx_; + h_class.Assign(class_linker->FindClass(soa.Self(), *dex_file, type_idx, h_loader)); + CHECK(h_class != nullptr) << "Could not find class " << dex_file->GetTypeDescriptor(type_idx); bool is_verified = h_class->IsVerified(); if (is_first) { all_verified = is_verified; @@ -155,9 +155,9 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesPreverified(JNIEnv*, bool all_preverified = false; for (const DexFile* dex_file : dex_files) { for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) { - const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx)); - h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader)); - CHECK(h_class != nullptr) << "Could not find class " << desc; + dex::TypeIndex type_idx = dex_file->GetClassDef(cdef_idx).class_idx_; + h_class.Assign(class_linker->FindClass(soa.Self(), *dex_file, type_idx, h_loader)); + CHECK(h_class != nullptr) << "Could not find class " << dex_file->GetTypeDescriptor(type_idx); ClassStatus oat_file_class_status(ClassStatus::kNotReady); bool is_preverified = class_linker->VerifyClassUsingOatFile( diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc index f5d957683a..66cb326dbb 100644 --- a/tools/art_verifier/art_verifier.cc +++ b/tools/art_verifier/art_verifier.cc @@ -234,11 +234,11 @@ struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> { } for (const DexFile* dex_file : dex_files) { for (ClassAccessor accessor : dex_file->GetClasses()) { - const char* descriptor = accessor.GetDescriptor(); - h_klass.Assign(class_linker->FindClass(soa.Self(), descriptor, h_loader)); + h_klass.Assign( + class_linker->FindClass(soa.Self(), *dex_file, accessor.GetClassIdx(), h_loader)); if (h_klass == nullptr || h_klass->IsErroneous()) { if (args_->repetitions_ == 0) { - LOG(ERROR) << "Warning: could not load " << descriptor; + LOG(ERROR) << "Warning: could not load " << accessor.GetDescriptor(); } soa.Self()->ClearException(); continue; @@ -258,7 +258,7 @@ struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> { args_->api_level_, &error_msg); if (args_->repetitions_ == 0) { - LOG(INFO) << descriptor << ": " << res << " " << error_msg; + LOG(INFO) << accessor.GetDescriptor() << ": " << res << " " << error_msg; } } } diff --git a/tools/fuzzer/libart_verify_classes_fuzzer.cc b/tools/fuzzer/libart_verify_classes_fuzzer.cc index d066ef4b6e..13abd7c613 100644 --- a/tools/fuzzer/libart_verify_classes_fuzzer.cc +++ b/tools/fuzzer/libart_verify_classes_fuzzer.cc @@ -186,8 +186,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { scope.NewHandle<art::mirror::DexCache>(nullptr)); for (art::ClassAccessor accessor : dex_file.GetClasses()) { - const char* descriptor = accessor.GetDescriptor(); - h_klass.Assign(class_linker->FindClass(soa.Self(), descriptor, h_loader)); + h_klass.Assign( + class_linker->FindClass(soa.Self(), dex_file, accessor.GetClassIdx(), h_loader)); // Ignore classes that couldn't be loaded since we are looking for crashes during // class/method verification. if (h_klass == nullptr || h_klass->IsErroneous()) { |