diff options
author | 2017-12-11 18:37:36 +0000 | |
---|---|---|
committer | 2017-12-12 13:48:02 +0000 | |
commit | 666ee3d7c6039c80e75287e311895bd6a9b01e9f (patch) | |
tree | 5e65f39ff7cc83af4be3b691c247d7348052f854 | |
parent | 890111968fbd3f5ae528d97e42984c12a3dd27bd (diff) |
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
23 files changed, 279 insertions, 254 deletions
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<mirror::Class> CompilerDriver::ResolveClass( - const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, dex::TypeIndex cls_index, + const ScopedObjectAccess& soa, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> 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<mirror::Class> cls = mUnit->GetClassLinker()->ResolveType( - *mUnit->GetDexFile(), cls_index, dex_cache, class_loader); + ObjPtr<mirror::Class> 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<mirror::Class> CompilerDriver::ResolveClass( } inline ObjPtr<mirror::Class> CompilerDriver::ResolveCompilingMethodsClass( - const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit) { + const ScopedObjectAccess& soa, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> 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<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->RegisterDexFile(*dex_file, nullptr))); - Handle<mirror::Class> klass(hs2.NewHandle( + ObjPtr<mirror::Class> klass = (dex_cache != nullptr) - ? class_linker->ResolveType(*dex_file, - exception_type_idx, + ? class_linker->ResolveType(exception_type_idx, dex_cache, ScopedNullHandle<mirror::ClassLoader>()) - : 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<mirror::Class> 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<mirror::Class> 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<mirror::Class> ResolveCompilingMethodsClass( - const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit) + ObjPtr<mirror::Class> ResolveCompilingMethodsClass(const ScopedObjectAccess& soa, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader, + const DexCompilationUnit* mUnit) REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<mirror::Class> ResolveClass( - const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, dex::TypeIndex type_index, - const DexCompilationUnit* mUnit) + ObjPtr<mirror::Class> ResolveClass(const ScopedObjectAccess& soa, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> 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<bool, bool> IsFastInstanceField( - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::Class> referrer_class, - ArtField* resolved_field, uint16_t field_idx) + std::pair<bool, bool> IsFastInstanceField(ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::Class> 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<mirror::Class> resolved = ClassLinker::LookupResolvedType( + ObjPtr<mirror::Class> 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<mirror::Class> clazz = ClassLinker::LookupResolvedType( + ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> GetClassFrom(CompilerDriver* driver, - const DexCompilationUnit& compilation_unit) { + const DexCompilationUnit& compilation_unit) { ScopedObjectAccess soa(Thread::Current()); Handle<mirror::ClassLoader> class_loader = compilation_unit.GetClassLoader(); Handle<mirror::DexCache> dex_cache = compilation_unit.GetDexCache(); @@ -2933,7 +2932,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, ObjPtr<mirror::Class> 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<mirror::DexCache> dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_); - ObjPtr<mirror::Class> klass = - ClassLinker::LookupResolvedType(type_idx, dex_cache, class_loader_.Get()); + ObjPtr<mirror::Class> 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<mirror::DexCache> 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<mirror::DexCache> 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<mirror::DexCache> dex_cache, uint32_t stored_index = pair.index; ObjPtr<mirror::Class> 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<mirror::DexCache> dex_cache = GetDexCache(patch.TargetTypeDexFile()); ObjPtr<mirror::Class> 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<mirror::Class> ArtField::LookupResolvedType() { if (UNLIKELY(declaring_class->IsProxyClass())) { return ProxyFindSystemClass(GetTypeDescriptor()); } - ObjPtr<mirror::DexCache> 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<mirror::Class> 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<mirror::Class> type = Runtime::Current()->GetClassLinker()->LookupResolvedType( + declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class); + DCHECK(!Thread::Current()->IsExceptionPending()); + return type; } inline ObjPtr<mirror::Class> ArtField::ResolveType() { @@ -325,15 +319,9 @@ inline ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> 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<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) { ScopedAssertNoThreadSuspension ants(__FUNCTION__); - ObjPtr<mirror::DexCache> dex_cache = GetDexCache(); - ObjPtr<mirror::Class> 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<mirror::Class> type = + Runtime::Current()->GetClassLinker()->LookupResolvedType(type_idx, this); + DCHECK(!Thread::Current()->IsExceptionPending()); + return type; } inline ObjPtr<mirror::Class> ArtMethod::ResolveClassFromTypeIndex(dex::TypeIndex type_idx) { - ObjPtr<mirror::DexCache> dex_cache = GetDexCache(); - ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> ClassLinker::LookupResolvedType( - dex::TypeIndex type_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> class_loader) { - ObjPtr<mirror::Class> 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<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, + ObjPtr<mirror::Class> referrer) { + if (kObjPtrPoisoning) { + StackHandleScope<1> hs(Thread::Current()); + HandleWrapperObjPtr<mirror::Class> 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<mirror::Class> resolved_type = + referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx); + if (resolved_type == nullptr) { + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader())); + resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader); + } + return resolved_type; } inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, @@ -79,18 +90,67 @@ inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, if (kIsDebugBuild) { Thread::Current()->AssertNoPendingException(); } - ObjPtr<mirror::Class> 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<mirror::Class> resolved_type = + referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx); if (UNLIKELY(resolved_type == nullptr)) { StackHandleScope<2> hs(Thread::Current()); - ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); + ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle<mirror::ClassLoader> 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<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader())); + resolved_type = DoResolveType(type_idx, dex_cache, class_loader); } return resolved_type; } +inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) { + DCHECK(dex_cache != nullptr); + Thread::PoisonObjectPointersIfDebug(); + ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx); + if (resolved == nullptr) { + resolved = DoResolveType(type_idx, dex_cache, class_loader); + } + return resolved; +} + +inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr<mirror::Class> 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<mirror::Class> type = + referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader()); + } + return type; +} + +inline ObjPtr<mirror::Class> 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<mirror::Class> type = + referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader()); + } + return type; +} + +inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType( + dex::TypeIndex type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader) { + ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, dex_cache, class_loader); + } + return type; +} + template <bool kThrowOnError, typename ClassGetter> inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache, InvokeType type, @@ -148,10 +208,9 @@ inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> 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<mirror::Class> 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<kWithoutReadBarrier>()->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<kWithoutReadBarrier>()->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<mirror::DexCache> 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<kWithoutReadBarrier>()->GetResolvedField( + field_idx, image_pointer_size_); if (field == nullptr) { - field = LookupResolvedField(field_idx, dex_cache, referrer->GetClassLoader(), is_static); + ObjPtr<mirror::ClassLoader> 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<mirror::Class> 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<kWithoutReadBarrier>()->GetResolvedField( + field_idx, image_pointer_size_); if (UNLIKELY(resolved_field == nullptr)) { StackHandleScope<2> hs(Thread::Current()); + ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader())); + Handle<mirror::ClassLoader> 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<mirror::Class> klass, const DexF return false; } - ObjPtr<mirror::Class> super_class = ResolveType(dex_file, super_class_idx, klass.Get()); + ObjPtr<mirror::Class> 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<mirror::Class> klass, const DexF if (interfaces != nullptr) { for (size_t i = 0; i < interfaces->Size(); i++) { dex::TypeIndex idx = interfaces->GetTypeItem(i).type_idx_; - ObjPtr<mirror::Class> interface = ResolveType(dex_file, idx, klass.Get()); + ObjPtr<mirror::Class> interface = ResolveType(idx, klass.Get()); if (interface == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return false; @@ -7762,74 +7762,56 @@ ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx, return string; } -ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> class_loader) { - ObjPtr<mirror::Class> 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<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> 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<mirror::Class> 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<mirror::Class> ClassLinker::ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr<mirror::Class> referrer) { - StackHandleScope<2> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader())); - return ResolveType(dex_file, type_idx, dex_cache, class_loader); -} - -ObjPtr<mirror::Class> ClassLinker::ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, - Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader) { - DCHECK(dex_cache != nullptr); - Thread::PoisonObjectPointersIfDebug(); - ObjPtr<mirror::Class> 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<mirror::Throwable> 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<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) { + Thread* self = Thread::Current(); + const char* descriptor = dex_cache->GetDexFile()->StringByTypeIdx(type_idx); + ObjPtr<mirror::Class> 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<mirror::Throwable> 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<mirror::Class> klass = - ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); + const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx); + ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> klass = ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader); + ObjPtr<mirror::Class> 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<mirror::Class> klass(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader)); + ObjPtr<mirror::Class> klass = ResolveType(field_id.class_idx_, dex_cache, class_loader); if (klass == nullptr) { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; @@ -8203,7 +8183,7 @@ ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType( const DexFile& dex_file = *dex_cache->GetDexFile(); const DexFile::ProtoId& proto_id = dex_file.GetProtoId(proto_idx); Handle<mirror::Class> 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<mirror::MethodType> ClassLinker::ResolveMethodType( MutableHandle<mirror::Class> param_class = hs.NewHandle<mirror::Class>(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<mirror::Class> klass = ResolveType(*dex_file, type_idx, dex_cache, class_loader); + ObjPtr<mirror::Class> 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<mirror::DexCache> 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<mirror::Class> ResolveType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr<mirror::Class> 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<mirror::Class> ResolveType(dex::TypeIndex type_idx, ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> LookupResolvedType(const DexFile& dex_file, - dex::TypeIndex type_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> class_loader) - REQUIRES_SHARED(Locks::mutator_lock_); - static ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> 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<mirror::Class> 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<mirror::Class> ResolveType(dex::TypeIndex type_idx, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> 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<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> 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<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Implementation of ResolveType() called when the type was not found in the dex cache. + ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> 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<mirror::Class> klass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader); dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; ObjPtr<mirror::DexCache> 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<mirror::Class>(nullptr)); // Resolve the array class we want to test. ObjPtr<mirror::Class> array_klass @@ -991,13 +990,13 @@ TEST_F(ClassLinkerTest, LookupResolvedTypeArray) { ASSERT_OBJ_PTR_NE(array_klass, ObjPtr<mirror::Class>(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<mirror::Class>(nullptr)); dex::TypeIndex type_idx = klass->GetClassDef()->class_idx_; Handle<mirror::DexCache> 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<mirror::Class> 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<mirror::Class> 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<mirror::Class> resolved = linker_->ResolveType(dex_file_, - dex::TypeIndex(jval_.i), + ObjPtr<mirror::Class> resolved = linker_->ResolveType(dex::TypeIndex(jval_.i), dex_cache_, class_loader_); field->SetObject<kTransactionActive>(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<mirror::Class> method_reference_class = ClassLinker::LookupResolvedType( + ObjPtr<mirror::Class> 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<mirror::DexCache> dex_cache( - hs.NewHandle(caller->GetDeclaringClass()->GetDexCache())); - Handle<mirror::ClassLoader> class_loader( - hs.NewHandle(caller->GetDeclaringClass()->GetClassLoader())); - // TODO Maybe put this into a mirror::Class function. ObjPtr<mirror::Class> 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<mirror::CallSite> InvokeBootstrapMethod(Thread* self, } case EncodedArrayValueIterator::ValueType::kType: { dex::TypeIndex idx(static_cast<uint32_t>(jvalue.i)); - ObjPtr<mirror::Class> ref = - class_linker->ResolveType(*dex_file, idx, dex_cache, class_loader); + ObjPtr<mirror::Class> 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<Class> 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<Class> 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<Class> access_to, // The referenced class has already been resolved with the method, but may not be in the dex // cache. ObjPtr<Class> 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> Class::GetDirectInterface(Thread* self, ObjPtr<Class> klass, uint3 return interfaces->Get(idx); } else { dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx); - ObjPtr<Class> interface = ClassLinker::LookupResolvedType( + ObjPtr<Class> interface = Runtime::Current()->GetClassLinker()->LookupResolvedType( type_idx, klass->GetDexCache(), klass->GetClassLoader()); return interface; } @@ -1047,9 +1047,7 @@ ObjPtr<Class> Class::ResolveDirectInterface(Thread* self, Handle<Class> 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<mirror::DexCache> dex_cache, } const DexFile* dex_file = dex_cache->GetDexFile(); const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx); - ObjPtr<mirror::Class> klass = - ClassLinker::LookupResolvedType(field_id.class_idx_, dex_cache, nullptr); + ObjPtr<mirror::Class> 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<mirror::DexCache> dex_cache, ui } const DexFile* dex_file = dex_cache->GetDexFile(); const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx); - ObjPtr<mirror::Class> klass = - ClassLinker::LookupResolvedType(method_id.class_idx_, dex_cache, nullptr); + ObjPtr<mirror::Class> 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<mirror::Class> interface(hs.NewHandle<mirror::Class>(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<false>(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<mirror::Class> exception_type = linker->ResolveType(*dex_file_, - iterator.GetHandlerTypeIndex(), - dex_cache_, class_loader_); + ObjPtr<mirror::Class> 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<CheckAccess::kYes>(type_idx); if (res_type.IsConflict()) { // If this is a primitive type, fail HARD. - ObjPtr<mirror::Class> klass = - ClassLinker::LookupResolvedType(type_idx, dex_cache_.Get(), class_loader_.Get()); + ObjPtr<mirror::Class> 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<mirror::Class> 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<mirror::Class> klas template <MethodVerifier::CheckAccess C> const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) { + ClassLinker* linker = Runtime::Current()->GetClassLinker(); ObjPtr<mirror::Class> 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(); |