From 890111968fbd3f5ae528d97e42984c12a3dd27bd Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Mon, 11 Dec 2017 13:45:05 +0000 Subject: Do not pass DexFile to ClassLinker::Lookup/ResolveMethod(). The DexFile can be easily retrieved from the DexCache, so reduce the number of arguments that need to be passed. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Change-Id: I2e47280e7cb8b84595130c4abfb5ece18d7f5c75 --- compiler/optimizing/instruction_builder.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'compiler/optimizing/instruction_builder.cc') diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index bce4de32d5..6fdb616ce2 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -796,7 +796,6 @@ ArtMethod* HInstructionBuilder::ResolveMethod(uint16_t method_idx, InvokeType in ArtMethod* resolved_method = class_linker->ResolveMethod( - *dex_compilation_unit_->GetDexFile(), method_idx, dex_compilation_unit_->GetDexCache(), class_loader, -- cgit v1.2.3-59-g8ed1b From 666ee3d7c6039c80e75287e311895bd6a9b01e9f Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Mon, 11 Dec 2017 18:37:36 +0000 Subject: Do not pass DexFile to ClassLinker::Lookup/ResolveType(). The DexFile can be easily retrieved from the DexCache, so reduce the number of arguments that need to be passed. Also refactor the code to avoid doing the DexCache lookup twice and avoid unnecessary read barriers in the initial DexCache lookup (also for Lookup/ResolveField()). Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Change-Id: Idea9aa42b6a5bade947e93e330b1abdb9d11b2da --- compiler/driver/compiler_driver-inl.h | 16 ++- compiler/driver/compiler_driver.cc | 15 ++- compiler/driver/compiler_driver.h | 24 ++-- compiler/optimizing/inliner.cc | 4 +- compiler/optimizing/instruction_builder.cc | 5 +- compiler/optimizing/reference_type_propagation.cc | 4 +- dex2oat/linker/image_writer.cc | 8 +- dex2oat/linker/oat_writer.cc | 2 +- runtime/art_field-inl.h | 26 ++-- runtime/art_method-inl.h | 25 ++-- runtime/class_linker-inl.h | 116 ++++++++++++++---- runtime/class_linker.cc | 132 +++++++++------------ runtime/class_linker.h | 72 ++++++----- runtime/class_linker_test.cc | 20 ++-- runtime/dex_file_annotations.cc | 8 +- runtime/entrypoints/entrypoint_utils-inl.h | 2 +- .../quick/quick_trampoline_entrypoints.cc | 14 +-- runtime/interpreter/interpreter_common.cc | 3 +- runtime/mirror/class-inl.h | 2 - runtime/mirror/class.cc | 6 +- runtime/native/dalvik_system_VMRuntime.cc | 8 +- runtime/native/java_lang_Class.cc | 4 +- runtime/verifier/method_verifier.cc | 17 ++- 23 files changed, 279 insertions(+), 254 deletions(-) (limited to 'compiler/optimizing/instruction_builder.cc') diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 34c8f22c03..294072d7e7 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -33,13 +33,15 @@ namespace art { inline ObjPtr CompilerDriver::ResolveClass( - const ScopedObjectAccess& soa, Handle dex_cache, - Handle class_loader, dex::TypeIndex cls_index, + const ScopedObjectAccess& soa, + Handle dex_cache, + Handle class_loader, + dex::TypeIndex cls_index, const DexCompilationUnit* mUnit) { DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get()); - ObjPtr cls = mUnit->GetClassLinker()->ResolveType( - *mUnit->GetDexFile(), cls_index, dex_cache, class_loader); + ObjPtr cls = + mUnit->GetClassLinker()->ResolveType(cls_index, dex_cache, class_loader); DCHECK_EQ(cls == nullptr, soa.Self()->IsExceptionPending()); if (UNLIKELY(cls == nullptr)) { // Clean up any exception left by type resolution. @@ -49,8 +51,10 @@ inline ObjPtr CompilerDriver::ResolveClass( } inline ObjPtr CompilerDriver::ResolveCompilingMethodsClass( - const ScopedObjectAccess& soa, Handle dex_cache, - Handle class_loader, const DexCompilationUnit* mUnit) { + const ScopedObjectAccess& soa, + Handle dex_cache, + Handle class_loader, + const DexCompilationUnit* mUnit) { DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile()); DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get()); const DexFile::MethodId& referrer_method_id = diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 8f726895de..0631c0f12c 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1048,22 +1048,21 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { for (const auto& exception_type : unresolved_exception_types) { dex::TypeIndex exception_type_idx = exception_type.first; const DexFile* dex_file = exception_type.second; - StackHandleScope<2> hs2(self); + StackHandleScope<1> hs2(self); Handle dex_cache(hs2.NewHandle(class_linker->RegisterDexFile(*dex_file, nullptr))); - Handle klass(hs2.NewHandle( + ObjPtr klass = (dex_cache != nullptr) - ? class_linker->ResolveType(*dex_file, - exception_type_idx, + ? class_linker->ResolveType(exception_type_idx, dex_cache, ScopedNullHandle()) - : nullptr)); + : nullptr; if (klass == nullptr) { const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx); const char* descriptor = dex_file->GetTypeDescriptor(type_id); LOG(FATAL) << "Failed to resolve class " << descriptor; } - DCHECK(java_lang_Throwable->IsAssignableFrom(klass.Get())); + DCHECK(java_lang_Throwable->IsAssignableFrom(klass)); } // Resolving exceptions may load classes that reference more exceptions, iterate until no // more are found @@ -1638,7 +1637,7 @@ class ResolveClassFieldsAndMethodsVisitor : public CompilationVisitor { soa.Self(), dex_file))); // Resolve the class. ObjPtr klass = - class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache, class_loader); + class_linker->ResolveType(class_def.class_idx_, dex_cache, class_loader); bool resolve_fields_and_methods; if (klass == nullptr) { // Class couldn't be resolved, for example, super-class is in a different dex file. Don't @@ -1729,7 +1728,7 @@ class ResolveTypeVisitor : public CompilationVisitor { dex_file, class_loader.Get()))); ObjPtr klass = (dex_cache != nullptr) - ? class_linker->ResolveType(dex_file, dex::TypeIndex(type_idx), dex_cache, class_loader) + ? class_linker->ResolveType(dex::TypeIndex(type_idx), dex_cache, class_loader) : nullptr; if (klass == nullptr) { diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index ab788e326f..e001726c95 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -219,15 +219,17 @@ class CompilerDriver { REQUIRES_SHARED(Locks::mutator_lock_); // Resolve compiling method's class. Returns null on failure. - ObjPtr ResolveCompilingMethodsClass( - const ScopedObjectAccess& soa, Handle dex_cache, - Handle class_loader, const DexCompilationUnit* mUnit) + ObjPtr ResolveCompilingMethodsClass(const ScopedObjectAccess& soa, + Handle dex_cache, + Handle class_loader, + const DexCompilationUnit* mUnit) REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr ResolveClass( - const ScopedObjectAccess& soa, Handle dex_cache, - Handle class_loader, dex::TypeIndex type_index, - const DexCompilationUnit* mUnit) + ObjPtr ResolveClass(const ScopedObjectAccess& soa, + Handle dex_cache, + Handle class_loader, + dex::TypeIndex type_index, + const DexCompilationUnit* mUnit) REQUIRES_SHARED(Locks::mutator_lock_); // Resolve a field. Returns null on failure, including incompatible class change. @@ -240,10 +242,10 @@ class CompilerDriver { REQUIRES_SHARED(Locks::mutator_lock_); // Can we fast-path an IGET/IPUT access to an instance field? If yes, compute the field offset. - std::pair IsFastInstanceField( - ObjPtr dex_cache, - ObjPtr referrer_class, - ArtField* resolved_field, uint16_t field_idx) + std::pair IsFastInstanceField(ObjPtr dex_cache, + ObjPtr referrer_class, + ArtField* resolved_field, + uint16_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_); // Resolve a method. Returns null on failure, including incompatible class change. diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index a175c21760..8750910fe1 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -294,7 +294,7 @@ static dex::TypeIndex FindClassIndexIn(mirror::Class* cls, // as there may be different class loaders. So only return the index if it's // the right class already resolved with the class loader. if (index.IsValid()) { - ObjPtr resolved = ClassLinker::LookupResolvedType( + ObjPtr resolved = compilation_unit.GetClassLinker()->LookupResolvedType( index, compilation_unit.GetDexCache().Get(), compilation_unit.GetClassLoader().Get()); if (resolved != cls) { index = dex::TypeIndex::Invalid(); @@ -682,7 +682,7 @@ HInliner::InlineCacheType HInliner::ExtractClassesFromOfflineProfile( << "is invalid in location" << dex_cache->GetDexFile()->GetLocation(); return kInlineCacheNoData; } - ObjPtr clazz = ClassLinker::LookupResolvedType( + ObjPtr clazz = caller_compilation_unit_.GetClassLinker()->LookupResolvedType( class_ref.type_index, dex_cache, caller_compilation_unit_.GetClassLoader().Get()); diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 6fdb616ce2..710c2efd5f 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -830,7 +830,6 @@ ArtMethod* HInstructionBuilder::ResolveMethod(uint16_t method_idx, InvokeType in return nullptr; } ObjPtr referenced_class = class_linker->LookupResolvedType( - *dex_compilation_unit_->GetDexFile(), dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx).class_idx_, dex_compilation_unit_->GetDexCache().Get(), class_loader.Get()); @@ -1424,7 +1423,7 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio } static ObjPtr GetClassFrom(CompilerDriver* driver, - const DexCompilationUnit& compilation_unit) { + const DexCompilationUnit& compilation_unit) { ScopedObjectAccess soa(Thread::Current()); Handle class_loader = compilation_unit.GetClassLoader(); Handle dex_cache = compilation_unit.GetDexCache(); @@ -2933,7 +2932,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, ObjPtr HInstructionBuilder::LookupResolvedType( dex::TypeIndex type_index, const DexCompilationUnit& compilation_unit) const { - return ClassLinker::LookupResolvedType( + return compilation_unit.GetClassLinker()->LookupResolvedType( type_index, compilation_unit.GetDexCache().Get(), compilation_unit.GetClassLoader().Get()); } diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 549572ce40..8bb124e066 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -576,8 +576,8 @@ void ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* ScopedObjectAccess soa(Thread::Current()); ObjPtr dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_); - ObjPtr klass = - ClassLinker::LookupResolvedType(type_idx, dex_cache, class_loader_.Get()); + ObjPtr klass = Runtime::Current()->GetClassLinker()->LookupResolvedType( + type_idx, dex_cache, class_loader_.Get()); SetClassAsTypeInfo(instr, klass, is_exact); } diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index f6ceb27b21..738bbf8e9d 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -1050,8 +1050,7 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr dex_cache, const DexFile::MethodId& method_id = dex_file.GetMethodId(i); if (method_id.class_idx_ != last_class_idx) { last_class_idx = method_id.class_idx_; - last_class = class_linker->LookupResolvedType( - dex_file, last_class_idx, dex_cache, class_loader); + last_class = class_linker->LookupResolvedType(last_class_idx, dex_cache, class_loader); if (last_class != nullptr && !KeepClass(last_class)) { last_class = nullptr; } @@ -1096,8 +1095,7 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr dex_cache, const DexFile::FieldId& field_id = dex_file.GetFieldId(i); if (field_id.class_idx_ != last_class_idx) { last_class_idx = field_id.class_idx_; - last_class = class_linker->LookupResolvedType( - dex_file, last_class_idx, dex_cache, class_loader); + last_class = class_linker->LookupResolvedType(last_class_idx, dex_cache, class_loader); if (last_class != nullptr && !KeepClass(last_class)) { last_class = nullptr; } @@ -1130,7 +1128,7 @@ void ImageWriter::PruneAndPreloadDexCache(ObjPtr dex_cache, uint32_t stored_index = pair.index; ObjPtr klass = pair.object.Read(); if (klass == nullptr || i < stored_index) { - klass = class_linker->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader); + klass = class_linker->LookupResolvedType(type_idx, dex_cache, class_loader); if (klass != nullptr) { DCHECK_EQ(dex_cache->GetResolvedType(type_idx), klass); stored_index = i; // For correct clearing below if not keeping the `klass`. diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index c271a6cdf4..786acce8ee 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -1956,7 +1956,7 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor { DCHECK(writer_->HasImage()); ObjPtr dex_cache = GetDexCache(patch.TargetTypeDexFile()); ObjPtr type = - ClassLinker::LookupResolvedType(patch.TargetTypeIndex(), dex_cache, class_loader_); + class_linker_->LookupResolvedType(patch.TargetTypeIndex(), dex_cache, class_loader_); CHECK(type != nullptr); return type; } diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h index 941f9e908c..2b18577ed0 100644 --- a/runtime/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -307,16 +307,10 @@ inline ObjPtr ArtField::LookupResolvedType() { if (UNLIKELY(declaring_class->IsProxyClass())) { return ProxyFindSystemClass(GetTypeDescriptor()); } - ObjPtr dex_cache = declaring_class->GetDexCache(); - const DexFile* const dex_file = dex_cache->GetDexFile(); - dex::TypeIndex type_idx = dex_file->GetFieldId(field_index).type_idx_; - ObjPtr type = dex_cache->GetResolvedType(type_idx); - if (UNLIKELY(type == nullptr)) { - type = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *dex_file, type_idx, dex_cache, declaring_class->GetClassLoader()); - DCHECK(!Thread::Current()->IsExceptionPending()); - } - return type.Ptr(); + ObjPtr type = Runtime::Current()->GetClassLinker()->LookupResolvedType( + declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class); + DCHECK(!Thread::Current()->IsExceptionPending()); + return type; } inline ObjPtr ArtField::ResolveType() { @@ -325,15 +319,9 @@ inline ObjPtr ArtField::ResolveType() { if (UNLIKELY(declaring_class->IsProxyClass())) { return ProxyFindSystemClass(GetTypeDescriptor()); } - auto* dex_cache = declaring_class->GetDexCache(); - const DexFile* const dex_file = dex_cache->GetDexFile(); - dex::TypeIndex type_idx = dex_file->GetFieldId(field_index).type_idx_; - ObjPtr type = dex_cache->GetResolvedType(type_idx); - if (UNLIKELY(type == nullptr)) { - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - type = class_linker->ResolveType(*dex_file, type_idx, declaring_class); - DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending()); - } + ObjPtr type = Runtime::Current()->GetClassLinker()->ResolveType( + declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class); + DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending()); return type; } diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index 327081f67a..869394c388 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -106,23 +106,16 @@ inline uint32_t ArtMethod::GetDexMethodIndex() { inline ObjPtr ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) { ScopedAssertNoThreadSuspension ants(__FUNCTION__); - ObjPtr dex_cache = GetDexCache(); - ObjPtr type = dex_cache->GetResolvedType(type_idx); - if (UNLIKELY(type == nullptr)) { - type = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *dex_cache->GetDexFile(), type_idx, dex_cache, GetClassLoader()); - } - return type.Ptr(); + ObjPtr type = + Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this); + DCHECK(!Thread::Current()->IsExceptionPending()); + return type; } inline ObjPtr ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) { - ObjPtr dex_cache = GetDexCache(); - ObjPtr type = dex_cache->GetResolvedType(type_idx); - if (UNLIKELY(type == nullptr)) { - type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); - CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); - } - return type.Ptr(); + ObjPtr type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); + DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending()); + return type; } inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { @@ -305,9 +298,7 @@ inline const DexFile::ClassDef& ArtMethod::GetClassDef() { inline const char* ArtMethod::GetReturnTypeDescriptor() { DCHECK(!IsProxyMethod()); const DexFile* dex_file = GetDexFile(); - const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex()); - const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); - return dex_file->GetTypeDescriptor(dex_file->GetTypeId(proto_id.return_type_idx_)); + return dex_file->GetTypeDescriptor(dex_file->GetTypeId(GetReturnTypeIndex())); } inline Primitive::Type ArtMethod::GetReturnTypePrimitive() { diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index c086dd2676..4b317f886f 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -61,16 +61,27 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, return array_class.Ptr(); } -inline ObjPtr ClassLinker::LookupResolvedType( - dex::TypeIndex type_idx, - ObjPtr dex_cache, - ObjPtr class_loader) { - ObjPtr type = dex_cache->GetResolvedType(type_idx); - if (type == nullptr) { - type = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *dex_cache->GetDexFile(), type_idx, dex_cache, class_loader); +inline ObjPtr ClassLinker::ResolveType(dex::TypeIndex type_idx, + ObjPtr referrer) { + if (kObjPtrPoisoning) { + StackHandleScope<1> hs(Thread::Current()); + HandleWrapperObjPtr referrer_wrapper = hs.NewHandleWrapper(&referrer); + Thread::Current()->PoisonObjectPointers(); } - return type; + if (kIsDebugBuild) { + Thread::Current()->AssertNoPendingException(); + } + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr resolved_type = + referrer->GetDexCache()->GetResolvedType(type_idx); + if (resolved_type == nullptr) { + StackHandleScope<2> hs(Thread::Current()); + Handle h_dex_cache(hs.NewHandle(referrer->GetDexCache())); + Handle class_loader(hs.NewHandle(referrer->GetClassLoader())); + resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader); + } + return resolved_type; } inline ObjPtr ClassLinker::ResolveType(dex::TypeIndex type_idx, @@ -79,18 +90,67 @@ inline ObjPtr ClassLinker::ResolveType(dex::TypeIndex type_idx, if (kIsDebugBuild) { Thread::Current()->AssertNoPendingException(); } - ObjPtr resolved_type = referrer->GetDexCache()->GetResolvedType(type_idx); + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr resolved_type = + referrer->GetDexCache()->GetResolvedType(type_idx); if (UNLIKELY(resolved_type == nullptr)) { StackHandleScope<2> hs(Thread::Current()); - ObjPtr declaring_class = referrer->GetDeclaringClass(); + ObjPtr referring_class = referrer->GetDeclaringClass(); Handle dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle class_loader(hs.NewHandle(declaring_class->GetClassLoader())); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); + Handle class_loader(hs.NewHandle(referring_class->GetClassLoader())); + resolved_type = DoResolveType(type_idx, dex_cache, class_loader); } return resolved_type; } +inline ObjPtr ClassLinker::ResolveType(dex::TypeIndex type_idx, + Handle dex_cache, + Handle class_loader) { + DCHECK(dex_cache != nullptr); + Thread::PoisonObjectPointersIfDebug(); + ObjPtr resolved = dex_cache->GetResolvedType(type_idx); + if (resolved == nullptr) { + resolved = DoResolveType(type_idx, dex_cache, class_loader); + } + return resolved; +} + +inline ObjPtr ClassLinker::LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr referrer) { + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr type = + referrer->GetDexCache()->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader()); + } + return type; +} + +inline ObjPtr ClassLinker::LookupResolvedType(dex::TypeIndex type_idx, + ArtMethod* referrer) { + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr type = + referrer->GetDexCache()->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader()); + } + return type; +} + +inline ObjPtr ClassLinker::LookupResolvedType( + dex::TypeIndex type_idx, + ObjPtr dex_cache, + ObjPtr class_loader) { + ObjPtr type = dex_cache->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, dex_cache, class_loader); + } + return type; +} + template inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr dex_cache, InvokeType type, @@ -148,10 +208,9 @@ inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr dex_c dex_cache, type, [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = *dex_cache->GetDexFile(); - const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); + const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx); ObjPtr klass = - LookupResolvedType(dex_file, method_id.class_idx_, dex_cache, class_loader); + LookupResolvedType(method_id.class_idx_, dex_cache, class_loader); DCHECK(klass != nullptr); return klass; }); @@ -187,6 +246,8 @@ inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* // lookup in the context of the original method from where it steals the code. // However, we delay the GetInterfaceMethodIfProxy() until needed. DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor()); + // We do not need the read barrier for getting the DexCache for the initial resolved method + // lookup as both from-space and to-space copies point to the same native resolved methods array. ArtMethod* resolved_method = referrer->GetDexCache()->GetResolvedMethod( method_idx, image_pointer_size_); if (resolved_method == nullptr) { @@ -228,6 +289,8 @@ inline ArtMethod* ClassLinker::ResolveMethod(Thread* self, // However, we delay the GetInterfaceMethodIfProxy() until needed. DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor()); Thread::PoisonObjectPointersIfDebug(); + // We do not need the read barrier for getting the DexCache for the initial resolved method + // lookup as both from-space and to-space copies point to the same native resolved methods array. ArtMethod* resolved_method = referrer->GetDexCache()->GetResolvedMethod( method_idx, image_pointer_size_); DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod()); @@ -278,10 +341,13 @@ inline ArtMethod* ClassLinker::ResolveMethod(Thread* self, inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx, ArtMethod* referrer, bool is_static) { - ObjPtr dex_cache = referrer->GetDexCache(); - ArtField* field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); + // We do not need the read barrier for getting the DexCache for the initial resolved field + // lookup as both from-space and to-space copies point to the same native resolved fields array. + ArtField* field = referrer->GetDexCache()->GetResolvedField( + field_idx, image_pointer_size_); if (field == nullptr) { - field = LookupResolvedField(field_idx, dex_cache, referrer->GetClassLoader(), is_static); + ObjPtr class_loader = referrer->GetDeclaringClass()->GetClassLoader(); + field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static); } return field; } @@ -290,13 +356,15 @@ inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, ArtMethod* referrer, bool is_static) { Thread::PoisonObjectPointersIfDebug(); - ObjPtr declaring_class = referrer->GetDeclaringClass(); - ArtField* resolved_field = - referrer->GetDexCache()->GetResolvedField(field_idx, image_pointer_size_); + // We do not need the read barrier for getting the DexCache for the initial resolved field + // lookup as both from-space and to-space copies point to the same native resolved fields array. + ArtField* resolved_field = referrer->GetDexCache()->GetResolvedField( + field_idx, image_pointer_size_); if (UNLIKELY(resolved_field == nullptr)) { StackHandleScope<2> hs(Thread::Current()); + ObjPtr referring_class = referrer->GetDeclaringClass(); Handle dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle class_loader(hs.NewHandle(declaring_class->GetClassLoader())); + Handle class_loader(hs.NewHandle(referring_class->GetClassLoader())); resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static); // Note: We cannot check here to see whether we added the field to the cache. The type // might be an erroneous class, which results in it being hidden from us. diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 892c28d54f..55fa6328f5 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -5466,7 +5466,7 @@ bool ClassLinker::LoadSuperAndInterfaces(Handle klass, const DexF return false; } - ObjPtr super_class = ResolveType(dex_file, super_class_idx, klass.Get()); + ObjPtr super_class = ResolveType(super_class_idx, klass.Get()); if (super_class == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return false; @@ -5485,7 +5485,7 @@ bool ClassLinker::LoadSuperAndInterfaces(Handle klass, const DexF if (interfaces != nullptr) { for (size_t i = 0; i < interfaces->Size(); i++) { dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_; - ObjPtr interface = ResolveType(dex_file, idx, klass.Get()); + ObjPtr interface = ResolveType(idx, klass.Get()); if (interface == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return false; @@ -7762,74 +7762,56 @@ ObjPtr ClassLinker::LookupString(dex::StringIndex string_idx, return string; } -ObjPtr ClassLinker::LookupResolvedType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr dex_cache, - ObjPtr class_loader) { - ObjPtr type = dex_cache->GetResolvedType(type_idx); - if (type == nullptr) { - const char* descriptor = dex_file.StringByTypeIdx(type_idx); - DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; - if (descriptor[1] == '\0') { - // 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 = FindPrimitiveClass(descriptor[0]); +ObjPtr ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx, + ObjPtr dex_cache, + ObjPtr class_loader) { + const DexFile& dex_file = *dex_cache->GetDexFile(); + const char* descriptor = dex_file.StringByTypeIdx(type_idx); + DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; + ObjPtr type = nullptr; + if (descriptor[1] == '\0') { + // 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 = FindPrimitiveClass(descriptor[0]); + } else { + Thread* const self = Thread::Current(); + DCHECK(self != nullptr); + const size_t hash = ComputeModifiedUtf8Hash(descriptor); + // Find the class in the loaded classes table. + type = LookupClass(self, descriptor, hash, class_loader.Ptr()); + } + if (type != nullptr) { + if (type->IsResolved()) { + dex_cache->SetResolvedType(type_idx, type); } else { - Thread* const self = Thread::Current(); - DCHECK(self != nullptr); - const size_t hash = ComputeModifiedUtf8Hash(descriptor); - // Find the class in the loaded classes table. - type = LookupClass(self, descriptor, hash, class_loader.Ptr()); - } - if (type != nullptr) { - if (type->IsResolved()) { - dex_cache->SetResolvedType(type_idx, type); - } else { - type = nullptr; - } + type = nullptr; } } - DCHECK(type == nullptr || type->IsResolved()); return type; } -ObjPtr ClassLinker::ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr referrer) { - StackHandleScope<2> hs(Thread::Current()); - Handle dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle class_loader(hs.NewHandle(referrer->GetClassLoader())); - return ResolveType(dex_file, type_idx, dex_cache, class_loader); -} - -ObjPtr ClassLinker::ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, - Handle dex_cache, - Handle class_loader) { - DCHECK(dex_cache != nullptr); - Thread::PoisonObjectPointersIfDebug(); - ObjPtr resolved = dex_cache->GetResolvedType(type_idx); - if (resolved == nullptr) { - Thread* self = Thread::Current(); - const char* descriptor = dex_file.StringByTypeIdx(type_idx); - resolved = FindClass(self, descriptor, 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 - // same name to be loaded simultaneously by different loaders - dex_cache->SetResolvedType(type_idx, resolved); - } else { - CHECK(self->IsExceptionPending()) - << "Expected pending exception for failed resolution of: " << descriptor; - // Convert a ClassNotFoundException to a NoClassDefFoundError. - StackHandleScope<1> hs(self); - Handle cause(hs.NewHandle(self->GetException())); - if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) { - DCHECK(resolved == nullptr); // No Handle needed to preserve resolved. - self->ClearException(); - ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor); - self->GetException()->SetCause(cause.Get()); - } +ObjPtr ClassLinker::DoResolveType(dex::TypeIndex type_idx, + Handle dex_cache, + Handle class_loader) { + Thread* self = Thread::Current(); + const char* descriptor = dex_cache->GetDexFile()->StringByTypeIdx(type_idx); + ObjPtr resolved = FindClass(self, descriptor, 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 + // same name to be loaded simultaneously by different loaders + dex_cache->SetResolvedType(type_idx, resolved); + } else { + CHECK(self->IsExceptionPending()) + << "Expected pending exception for failed resolution of: " << descriptor; + // Convert a ClassNotFoundException to a NoClassDefFoundError. + StackHandleScope<1> hs(self); + Handle cause(hs.NewHandle(self->GetException())); + if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) { + DCHECK(resolved == nullptr); // No Handle needed to preserve resolved. + self->ClearException(); + ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor); + self->GetException()->SetCause(cause.Get()); } } DCHECK((resolved == nullptr) || resolved->IsResolved()) @@ -7962,7 +7944,7 @@ ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx, if (valid_dex_cache_method) { // We have a valid method from the DexCache but we need to perform ICCE and IAE checks. DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex(); - klass = LookupResolvedType(dex_file, method_id.class_idx_, dex_cache.Get(), class_loader.Get()); + klass = LookupResolvedType(method_id.class_idx_, dex_cache.Get(), class_loader.Get()); if (UNLIKELY(klass == nullptr)) { const char* descriptor = dex_file.StringByTypeIdx(method_id.class_idx_); LOG(FATAL) << "Check failed: klass != nullptr Bug: 64759619 Method: " @@ -7973,7 +7955,7 @@ ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx, } } else { // The method was not in the DexCache, resolve the declaring class. - klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); + klass = ResolveType(method_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; @@ -8059,10 +8041,8 @@ ArtMethod* ClassLinker::ResolveMethodWithoutInvokeType(uint32_t method_idx, return resolved; } // Fail, get the declaring class. - const DexFile& dex_file = *dex_cache->GetDexFile(); - const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); - ObjPtr klass = - ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); + const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx); + ObjPtr klass = ResolveType(method_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { Thread::Current()->AssertPendingException(); return nullptr; @@ -8084,7 +8064,7 @@ ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx, const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); ObjPtr klass = dex_cache->GetResolvedType(field_id.class_idx_); if (klass == nullptr) { - klass = LookupResolvedType(dex_file, field_id.class_idx_, dex_cache, class_loader); + klass = LookupResolvedType(field_id.class_idx_, dex_cache, class_loader); } if (klass == nullptr) { // The class has not been resolved yet, so the field is also unresolved. @@ -8126,7 +8106,7 @@ ArtField* ClassLinker::ResolveField(uint32_t field_idx, const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); Thread* const self = Thread::Current(); - ObjPtr klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); + ObjPtr klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; @@ -8167,7 +8147,7 @@ ArtField* ClassLinker::ResolveFieldJLS(uint32_t field_idx, const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); Thread* self = Thread::Current(); - ObjPtr klass(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)); + ObjPtr klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; @@ -8203,7 +8183,7 @@ ObjPtr ClassLinker::ResolveMethodType( const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::ProtoId& proto_id = dex_file.GetProtoId(proto_idx); Handle return_type(hs.NewHandle( - ResolveType(dex_file, proto_id.return_type_idx_, dex_cache, class_loader))); + ResolveType(proto_id.return_type_idx_, dex_cache, class_loader))); if (return_type == nullptr) { DCHECK(self->IsExceptionPending()); return nullptr; @@ -8229,7 +8209,7 @@ ObjPtr ClassLinker::ResolveMethodType( MutableHandle param_class = hs.NewHandle(nullptr); for (; it.HasNext(); it.Next()) { const dex::TypeIndex type_idx = it.GetTypeIdx(); - param_class.Assign(ResolveType(dex_file, type_idx, dex_cache, class_loader)); + param_class.Assign(ResolveType(type_idx, dex_cache, class_loader)); if (param_class == nullptr) { DCHECK(self->IsExceptionPending()); return nullptr; @@ -8514,7 +8494,7 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod( DexFileParameterIterator it(*dex_file, target_method->GetPrototype()); while (it.HasNext()) { const dex::TypeIndex type_idx = it.GetTypeIdx(); - ObjPtr klass = ResolveType(*dex_file, type_idx, dex_cache, class_loader); + ObjPtr klass = ResolveType(type_idx, dex_cache, class_loader); if (nullptr == klass) { DCHECK(self->IsExceptionPending()); return nullptr; diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 55a4d2db15..10562f0890 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -255,45 +255,50 @@ class ClassLinker { ObjPtr dex_cache) REQUIRES_SHARED(Locks::mutator_lock_); - // Resolve a Type with the given index from the DexFile, storing the - // result in the DexCache. The referrer is used to identify the - // target DexCache and ClassLoader to use for resolution. - ObjPtr ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr referrer) + // Resolve a Type with the given index from the DexFile associated with the given `referrer`, + // storing the result in the DexCache. The `referrer` is used to identify the target DexCache + // and ClassLoader to use for resolution. + ObjPtr ResolveType(dex::TypeIndex type_idx, ObjPtr referrer) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); - // Resolve a Type with the given index from the DexFile, storing the - // result in the DexCache. The referrer is used to identify the - // target DexCache and ClassLoader to use for resolution. + // Resolve a type with the given index from the DexFile associated with the given `referrer`, + // storing the result in the DexCache. The `referrer` is used to identify the target DexCache + // and ClassLoader to use for resolution. ObjPtr ResolveType(dex::TypeIndex type_idx, ArtMethod* referrer) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); - // Look up a resolved type with the given ID from the DexFile. The ClassLoader is used to search - // for the type, since it may be referenced from but not contained within the given DexFile. - ObjPtr LookupResolvedType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr dex_cache, - ObjPtr class_loader) - REQUIRES_SHARED(Locks::mutator_lock_); - static ObjPtr LookupResolvedType(dex::TypeIndex type_idx, - ObjPtr dex_cache, - ObjPtr class_loader) - REQUIRES_SHARED(Locks::mutator_lock_); - - // Resolve a type with the given ID from the DexFile, storing the - // result in DexCache. The ClassLoader is used to search for the - // type, since it may be referenced from but not contained within - // the given DexFile. - ObjPtr ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, + // Resolve a type with the given index from the DexFile associated with the given DexCache + // and ClassLoader, storing the result in DexCache. The ClassLoader is used to search for + // the type, since it may be referenced from but not contained within the DexFile. + ObjPtr ResolveType(dex::TypeIndex type_idx, Handle dex_cache, Handle class_loader) REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); + // Look up a resolved type with the given index from the DexFile associated with the given + // `referrer`, storing the result in the DexCache. The `referrer` is used to identify the + // target DexCache and ClassLoader to use for lookup. + ObjPtr LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr referrer) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Look up a resolved type with the given index from the DexFile associated with the given + // `referrer`, storing the result in the DexCache. The `referrer` is used to identify the + // target DexCache and ClassLoader to use for lookup. + ObjPtr LookupResolvedType(dex::TypeIndex type_idx, ArtMethod* referrer) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Look up a resolved type with the given index from the DexFile associated with the given + // DexCache and ClassLoader. The ClassLoader is used to search for the type, since it may + // be referenced from but not contained within the DexFile. + ObjPtr LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr dex_cache, + ObjPtr class_loader) + REQUIRES_SHARED(Locks::mutator_lock_); + // Determine whether a dex cache result should be trusted, or an IncompatibleClassChangeError // check and IllegalAccessError check should be performed even after a hit. enum class ResolveMode { // private. @@ -876,6 +881,19 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_); + // Implementation of LookupResolvedType() called when the type was not found in the dex cache. + ObjPtr DoLookupResolvedType(dex::TypeIndex type_idx, + ObjPtr dex_cache, + ObjPtr class_loader) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Implementation of ResolveType() called when the type was not found in the dex cache. + ObjPtr DoResolveType(dex::TypeIndex type_idx, + Handle dex_cache, + Handle class_loader) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); + // Finds a class by its descriptor, returning NULL if it isn't wasn't loaded // by the given 'class_loader'. Uses the provided hash for the descriptor. mirror::Class* LookupClass(Thread* self, diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index b625c40fc3..246f89e5cc 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -954,15 +954,14 @@ TEST_F(ClassLinkerTest, LookupResolvedType) { ObjPtr klass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; ObjPtr dex_cache = klass->GetDexCache(); - const DexFile& dex_file = klass->GetDexFile(); EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader.Get()), + class_linker_->LookupResolvedType(type_idx, dex_cache, class_loader.Get()), klass); // Zero out the resolved type and make sure LookupResolvedType still finds it. dex_cache->ClearResolvedType(type_idx); EXPECT_TRUE(dex_cache->GetResolvedType(type_idx) == nullptr); EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader.Get()), + class_linker_->LookupResolvedType(type_idx, dex_cache, class_loader.Get()), klass); } @@ -983,7 +982,7 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeArray) { dex::TypeIndex array_idx = dex_file.GetIndexForTypeId(*array_id); // Check that the array class wasn't resolved yet. EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, array_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(array_idx, dex_cache.Get(), class_loader.Get()), ObjPtr(nullptr)); // Resolve the array class we want to test. ObjPtr array_klass @@ -991,13 +990,13 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeArray) { ASSERT_OBJ_PTR_NE(array_klass, ObjPtr(nullptr)); // Test that LookupResolvedType() finds the array class. EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, array_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(array_idx, dex_cache.Get(), class_loader.Get()), array_klass); // Zero out the resolved type and make sure LookupResolvedType() still finds it. dex_cache->ClearResolvedType(array_idx); EXPECT_TRUE(dex_cache->GetResolvedType(array_idx) == nullptr); EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, array_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(array_idx, dex_cache.Get(), class_loader.Get()), array_klass); } @@ -1012,15 +1011,14 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeErroneousInit) { ASSERT_OBJ_PTR_NE(klass.Get(), ObjPtr(nullptr)); dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; Handle dex_cache = hs.NewHandle(klass->GetDexCache()); - const DexFile& dex_file = klass->GetDexFile(); EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(type_idx, dex_cache.Get(), class_loader.Get()), klass.Get()); // Zero out the resolved type and make sure LookupResolvedType still finds it. dex_cache->ClearResolvedType(type_idx); EXPECT_TRUE(dex_cache->GetResolvedType(type_idx) == nullptr); EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(type_idx, dex_cache.Get(), class_loader.Get()), klass.Get()); // Force initialization to turn the class erroneous. bool initialized = class_linker_->EnsureInitialized(soa.Self(), @@ -1032,13 +1030,13 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeErroneousInit) { soa.Self()->ClearException(); // Check that the LookupResolvedType() can still find the resolved type. EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(type_idx, dex_cache.Get(), class_loader.Get()), klass.Get()); // Zero out the resolved type and make sure LookupResolvedType() still finds it. dex_cache->ClearResolvedType(type_idx); EXPECT_TRUE(dex_cache->GetResolvedType(type_idx) == nullptr); EXPECT_OBJ_PTR_EQ( - class_linker_->LookupResolvedType(dex_file, type_idx, dex_cache.Get(), class_loader.Get()), + class_linker_->LookupResolvedType(type_idx, dex_cache.Get(), class_loader.Get()), klass.Get()); } diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index 43260f733b..bc7b985b41 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -343,8 +343,7 @@ mirror::Object* ProcessEncodedAnnotation(const ClassData& klass, const uint8_t** StackHandleScope<4> hs(self); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); Handle annotation_class(hs.NewHandle( - class_linker->ResolveType(klass.GetDexFile(), - dex::TypeIndex(type_index), + class_linker->ResolveType(dex::TypeIndex(type_index), hs.NewHandle(klass.GetDexCache()), hs.NewHandle(klass.GetClassLoader())))); if (annotation_class == nullptr) { @@ -474,7 +473,6 @@ bool ProcessAnnotationValue(const ClassData& klass, dex::TypeIndex type_index(index); StackHandleScope<2> hs(self); element_object = Runtime::Current()->GetClassLinker()->ResolveType( - klass.GetDexFile(), type_index, hs.NewHandle(klass.GetDexCache()), hs.NewHandle(klass.GetClassLoader())); @@ -782,7 +780,6 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet( Thread* self = Thread::Current(); StackHandleScope<2> hs(self); ObjPtr resolved_class = class_linker->ResolveType( - klass.GetDexFile(), dex::TypeIndex(type_index), hs.NewHandle(klass.GetDexCache()), hs.NewHandle(klass.GetClassLoader())); @@ -1594,8 +1591,7 @@ void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) c break; } case kType: { - ObjPtr resolved = linker_->ResolveType(dex_file_, - dex::TypeIndex(jval_.i), + ObjPtr resolved = linker_->ResolveType(dex::TypeIndex(jval_.i), dex_cache_, class_loader_); field->SetObject(field->GetDeclaringClass(), resolved); diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index fa3c027db8..9e5085067c 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -682,7 +682,7 @@ inline ArtMethod* FindMethodFast(uint32_t method_idx, } else if (type == kSuper) { // TODO This lookup is rather slow. dex::TypeIndex method_type_idx = dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; - ObjPtr method_reference_class = ClassLinker::LookupResolvedType( + ObjPtr method_reference_class = linker->LookupResolvedType( method_type_idx, dex_cache, referrer->GetClassLoader()); if (method_reference_class == nullptr) { // Need to do full type resolution... diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 0a76cddf5e..ca5b79921c 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -1250,17 +1250,8 @@ extern "C" const void* artQuickResolutionTrampoline( } else { DCHECK_EQ(invoke_type, kSuper); CHECK(caller != nullptr) << invoke_type; - StackHandleScope<2> hs(self); - Handle dex_cache( - hs.NewHandle(caller->GetDeclaringClass()->GetDexCache())); - Handle class_loader( - hs.NewHandle(caller->GetDeclaringClass()->GetClassLoader())); - // TODO Maybe put this into a mirror::Class function. ObjPtr ref_class = linker->LookupResolvedType( - *dex_cache->GetDexFile(), - dex_cache->GetDexFile()->GetMethodId(called_method.index).class_idx_, - dex_cache.Get(), - class_loader.Get()); + caller->GetDexFile()->GetMethodId(called_method.index).class_idx_, caller); if (ref_class->IsInterface()) { called = ref_class->FindVirtualMethodForInterfaceSuper(called, kRuntimePointerSize); } else { @@ -2580,9 +2571,8 @@ extern "C" uintptr_t artInvokePolymorphic( const Instruction& inst = code->InstructionAt(dex_pc); DCHECK(inst.Opcode() == Instruction::INVOKE_POLYMORPHIC || inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE); - const DexFile* dex_file = caller_method->GetDexFile(); const uint32_t proto_idx = inst.VRegH(); - const char* shorty = dex_file->GetShorty(proto_idx); + const char* shorty = caller_method->GetDexFile()->GetShorty(proto_idx); const size_t shorty_length = strlen(shorty); static const bool kMethodIsStatic = false; // invoke() and invokeExact() are not static. RememberForGcArgumentVisitor gc_visitor(sp, kMethodIsStatic, shorty, shorty_length, &soa); diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 4d7a576c06..122d1a816b 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -1143,8 +1143,7 @@ static ObjPtr InvokeBootstrapMethod(Thread* self, } case EncodedArrayValueIterator::ValueType::kType: { dex::TypeIndex idx(static_cast(jvalue.i)); - ObjPtr ref = - class_linker->ResolveType(*dex_file, idx, dex_cache, class_loader); + ObjPtr ref = class_linker->ResolveType(idx, dex_cache, class_loader); if (ref.IsNull()) { DCHECK(self->IsExceptionPending()); return nullptr; diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index eb54f7fb1f..b4f5d81067 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -440,7 +440,6 @@ inline bool Class::ResolvedFieldAccessTest(ObjPtr access_to, // cache. Use LookupResolveType here to search the class table if it is not in the dex cache. // should be no thread suspension due to the class being resolved. ObjPtr dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *dex_cache->GetDexFile(), class_idx, dex_cache, access_to->GetClassLoader()); @@ -477,7 +476,6 @@ inline bool Class::ResolvedMethodAccessTest(ObjPtr access_to, // The referenced class has already been resolved with the method, but may not be in the dex // cache. ObjPtr dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *dex_cache->GetDexFile(), class_idx, dex_cache, access_to->GetClassLoader()); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index a0a2f46433..e0a341da67 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -1035,7 +1035,7 @@ ObjPtr Class::GetDirectInterface(Thread* self, ObjPtr klass, uint3 return interfaces->Get(idx); } else { dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx); - ObjPtr interface = ClassLinker::LookupResolvedType( + ObjPtr interface = Runtime::Current()->GetClassLinker()->LookupResolvedType( type_idx, klass->GetDexCache(), klass->GetClassLoader()); return interface; } @@ -1047,9 +1047,7 @@ ObjPtr Class::ResolveDirectInterface(Thread* self, Handle klass, u DCHECK(!klass->IsArrayClass()); DCHECK(!klass->IsProxyClass()); dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx); - interface = Runtime::Current()->GetClassLinker()->ResolveType(klass->GetDexFile(), - type_idx, - klass.Get()); + interface = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, klass.Get()); CHECK(interface != nullptr || self->IsExceptionPending()); } return interface; diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 2d1f886896..1b5c535c87 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -375,8 +375,8 @@ static void PreloadDexCachesResolveField(ObjPtr dex_cache, } const DexFile* dex_file = dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx); - ObjPtr klass = - ClassLinker::LookupResolvedType(field_id.class_idx_, dex_cache, nullptr); + ObjPtr klass = Runtime::Current()->GetClassLinker()->LookupResolvedType( + field_id.class_idx_, dex_cache, /* class_loader */ nullptr); if (klass == nullptr) { return; } @@ -401,8 +401,8 @@ static void PreloadDexCachesResolveMethod(ObjPtr dex_cache, ui } const DexFile* dex_file = dex_cache->GetDexFile(); const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx); - ObjPtr klass = - ClassLinker::LookupResolvedType(method_id.class_idx_, dex_cache, nullptr); + ObjPtr klass = Runtime::Current()->GetClassLinker()->LookupResolvedType( + method_id.class_idx_, dex_cache, /* class_loader */ nullptr); if (klass == nullptr) { return; } diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 9359ffc7fd..da5cee1ddc 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -146,11 +146,11 @@ static jobjectArray Class_getInterfacesInternal(JNIEnv* env, jobject javaThis) { // with kActiveTransaction == false. DCHECK(!Runtime::Current()->IsActiveTransaction()); + ClassLinker* linker = Runtime::Current()->GetClassLinker(); MutableHandle interface(hs.NewHandle(nullptr)); for (uint32_t i = 0; i < num_ifaces; ++i) { const dex::TypeIndex type_idx = iface_list->GetTypeItem(i).type_idx_; - interface.Assign(ClassLinker::LookupResolvedType( - type_idx, klass->GetDexCache(), klass->GetClassLoader())); + interface.Assign(linker->LookupResolvedType(type_idx, klass.Get())); ifaces->SetWithoutChecks(i, interface.Get()); } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index bf02450744..4ff49edb90 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -1077,9 +1077,8 @@ bool MethodVerifier::ScanTryCatchBlocks() { // Ensure exception types are resolved so that they don't need resolution to be delivered, // unresolved exception types will be ignored by exception delivery if (iterator.GetHandlerTypeIndex().IsValid()) { - ObjPtr exception_type = linker->ResolveType(*dex_file_, - iterator.GetHandlerTypeIndex(), - dex_cache_, class_loader_); + ObjPtr exception_type = + linker->ResolveType(iterator.GetHandlerTypeIndex(), dex_cache_, class_loader_); if (exception_type == nullptr) { DCHECK(self_->IsExceptionPending()); self_->ClearException(); @@ -2434,8 +2433,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { const RegType& res_type = ResolveClass(type_idx); if (res_type.IsConflict()) { // If this is a primitive type, fail HARD. - ObjPtr klass = - ClassLinker::LookupResolvedType(type_idx, dex_cache_.Get(), class_loader_.Get()); + ObjPtr klass = Runtime::Current()->GetClassLinker()->LookupResolvedType( + type_idx, dex_cache_.Get(), class_loader_.Get()); if (klass != nullptr && klass->IsPrimitive()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "using primitive type " << dex_file_->StringByTypeIdx(type_idx) << " in instanceof in " @@ -3643,7 +3642,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { } else { // It is also a catch-all if it is java.lang.Throwable. ObjPtr klass = - linker->ResolveType(*dex_file_, handler_type_idx, dex_cache_, class_loader_); + linker->ResolveType(handler_type_idx, dex_cache_, class_loader_); if (klass != nullptr) { if (klass == mirror::Throwable::GetJavaLangThrowable()) { has_catch_all_handler = true; @@ -3767,10 +3766,10 @@ inline bool MethodVerifier::IsInstantiableOrPrimitive(ObjPtr klas template const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) { + ClassLinker* linker = Runtime::Current()->GetClassLinker(); ObjPtr klass = can_load_classes_ - ? Runtime::Current()->GetClassLinker()->ResolveType( - *dex_file_, class_idx, dex_cache_, class_loader_) - : ClassLinker::LookupResolvedType(class_idx, dex_cache_.Get(), class_loader_.Get()); + ? linker->ResolveType(class_idx, dex_cache_, class_loader_) + : linker->LookupResolvedType(class_idx, dex_cache_.Get(), class_loader_.Get()); if (can_load_classes_ && klass == nullptr) { DCHECK(self_->IsExceptionPending()); self_->ClearException(); -- cgit v1.2.3-59-g8ed1b