summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/driver/compiler_driver-inl.h16
-rw-r--r--compiler/driver/compiler_driver.cc15
-rw-r--r--compiler/driver/compiler_driver.h24
-rw-r--r--compiler/optimizing/inliner.cc4
-rw-r--r--compiler/optimizing/instruction_builder.cc5
-rw-r--r--compiler/optimizing/reference_type_propagation.cc4
-rw-r--r--dex2oat/linker/image_writer.cc8
-rw-r--r--dex2oat/linker/oat_writer.cc2
-rw-r--r--runtime/art_field-inl.h26
-rw-r--r--runtime/art_method-inl.h25
-rw-r--r--runtime/class_linker-inl.h116
-rw-r--r--runtime/class_linker.cc132
-rw-r--r--runtime/class_linker.h72
-rw-r--r--runtime/class_linker_test.cc20
-rw-r--r--runtime/dex_file_annotations.cc8
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc14
-rw-r--r--runtime/interpreter/interpreter_common.cc3
-rw-r--r--runtime/mirror/class-inl.h2
-rw-r--r--runtime/mirror/class.cc6
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc8
-rw-r--r--runtime/native/java_lang_Class.cc4
-rw-r--r--runtime/verifier/method_verifier.cc17
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();