ART: Refactor retrieval of types through ArtMethod.
Split Get*() functions that take a "bool resolve"
argument into Lookup*() and Resolve*() functions.
Test: m test-art-host-gtest
Test: testrunner.py --host
Change-Id: I0b7eaa1fadc2ffa8c0168203790467f91a126963
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 9a9f125..fad9278 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -154,20 +154,22 @@
return GetDexCacheResolvedMethods(pointer_size) == other_cache;
}
-inline mirror::Class* ArtMethod::GetClassFromTypeIndex(dex::TypeIndex type_idx, bool resolve) {
- // TODO: Refactor this function into two functions, Resolve...() and Lookup...()
- // so that we can properly annotate it with no-suspension possible / suspension possible.
+inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) {
ObjPtr<mirror::DexCache> dex_cache = GetDexCache();
ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
if (UNLIKELY(type == nullptr)) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (resolve) {
- type = class_linker->ResolveType(type_idx, this);
- CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
- } else {
- type = class_linker->LookupResolvedType(
- *dex_cache->GetDexFile(), type_idx, dex_cache, GetClassLoader());
- }
+ type = Runtime::Current()->GetClassLinker()->LookupResolvedType(
+ *dex_cache->GetDexFile(), type_idx, dex_cache, GetClassLoader());
+ }
+ return type.Ptr();
+}
+
+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();
}
@@ -294,7 +296,7 @@
inline bool ArtMethod::IsResolvedTypeIdx(dex::TypeIndex type_idx) {
DCHECK(!IsProxyMethod());
- return GetClassFromTypeIndex(type_idx, /* resolve */ false) != nullptr;
+ return LookupResolvedClassFromTypeIndex(type_idx) != nullptr;
}
inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
@@ -403,13 +405,20 @@
pointer_size);
}
-inline mirror::Class* ArtMethod::GetReturnType(bool resolve) {
+inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() {
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);
- dex::TypeIndex return_type_idx = proto_id.return_type_idx_;
- return GetClassFromTypeIndex(return_type_idx, resolve);
+ return proto_id.return_type_idx_;
+}
+
+inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedReturnType() {
+ return LookupResolvedClassFromTypeIndex(GetReturnTypeIndex());
+}
+
+inline ObjPtr<mirror::Class> ArtMethod::ResolveReturnType() {
+ return ResolveClassFromTypeIndex(GetReturnTypeIndex());
}
inline bool ArtMethod::HasSingleImplementation() {
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 631f5e7..7d8deda 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -280,7 +280,7 @@
break;
}
// Does this catch exception type apply?
- mirror::Class* iter_exception_type = GetClassFromTypeIndex(iter_type_idx, true /* resolve */);
+ ObjPtr<mirror::Class> iter_exception_type = ResolveClassFromTypeIndex(iter_type_idx);
if (UNLIKELY(iter_exception_type == nullptr)) {
// Now have a NoClassDefFoundError as exception. Ignore in case the exception class was
// removed by a pro-guard like tool.
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 511ac83..cac40e0 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -376,8 +376,11 @@
PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Get the Class* from the type index into this method's dex cache.
- mirror::Class* GetClassFromTypeIndex(dex::TypeIndex type_idx, bool resolve)
+ // Lookup the Class* from the type index into this method's dex cache.
+ ObjPtr<mirror::Class> LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ // Resolve the Class* from the type index into this method's dex cache.
+ ObjPtr<mirror::Class> ResolveClassFromTypeIndex(dex::TypeIndex type_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if this method has the same name and signature of the other method.
@@ -592,9 +595,11 @@
const char* GetTypeDescriptorFromTypeIdx(dex::TypeIndex type_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
- // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large
- // number of bugs at call sites.
- mirror::Class* GetReturnType(bool resolve) REQUIRES_SHARED(Locks::mutator_lock_);
+ // Lookup return type.
+ ObjPtr<mirror::Class> LookupResolvedReturnType() REQUIRES_SHARED(Locks::mutator_lock_);
+ // Resolve return type. May cause thread suspension due to GetClassFromTypeIdx
+ // calling ResolveType this caused a large number of bugs at call sites.
+ ObjPtr<mirror::Class> ResolveReturnType() REQUIRES_SHARED(Locks::mutator_lock_);
mirror::ClassLoader* GetClassLoader() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -748,6 +753,8 @@
// Compare given pointer size to the image pointer size.
static bool IsImagePointerSize(PointerSize pointer_size);
+ dex::TypeIndex GetReturnTypeIndex() REQUIRES_SHARED(Locks::mutator_lock_);
+
template<typename T>
ALWAYS_INLINE T GetNativePointer(MemberOffset offset, PointerSize pointer_size) const {
static_assert(std::is_pointer<T>::value, "T must be a pointer type");
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d06ba78..3f19375 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4710,7 +4710,7 @@
CHECK_STREQ(np->GetName(), prototype->GetName());
CHECK_STREQ(np->GetShorty(), prototype->GetShorty());
// More complex sanity - via dex cache
- CHECK_EQ(np->GetReturnType(true /* resolve */), prototype->GetReturnType(true /* resolve */));
+ CHECK_EQ(np->ResolveReturnType(), prototype->ResolveReturnType());
}
bool ClassLinker::CanWeInitializeClass(ObjPtr<mirror::Class> klass, bool can_init_statics,
@@ -5186,12 +5186,12 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
{
StackHandleScope<1> hs(self);
- Handle<mirror::Class> return_type(hs.NewHandle(method1->GetReturnType(true /* resolve */)));
+ Handle<mirror::Class> return_type(hs.NewHandle(method1->ResolveReturnType()));
if (UNLIKELY(return_type == nullptr)) {
ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method1);
return false;
}
- ObjPtr<mirror::Class> other_return_type = method2->GetReturnType(true /* resolve */);
+ ObjPtr<mirror::Class> other_return_type = method2->ResolveReturnType();
if (UNLIKELY(other_return_type == nullptr)) {
ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method2);
return false;
@@ -5236,7 +5236,7 @@
StackHandleScope<1> hs(self);
dex::TypeIndex param_type_idx = types1->GetTypeItem(i).type_idx_;
Handle<mirror::Class> param_type(hs.NewHandle(
- method1->GetClassFromTypeIndex(param_type_idx, true /* resolve */)));
+ method1->ResolveClassFromTypeIndex(param_type_idx)));
if (UNLIKELY(param_type == nullptr)) {
ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
method1, i, param_type_idx);
@@ -5244,7 +5244,7 @@
}
dex::TypeIndex other_param_type_idx = types2->GetTypeItem(i).type_idx_;
ObjPtr<mirror::Class> other_param_type =
- method2->GetClassFromTypeIndex(other_param_type_idx, true /* resolve */);
+ method2->ResolveClassFromTypeIndex(other_param_type_idx);
if (UNLIKELY(other_param_type == nullptr)) {
ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
method2, i, other_param_type_idx);
@@ -8508,7 +8508,7 @@
it.Next();
}
- Handle<mirror::Class> return_type = hs.NewHandle(target_method->GetReturnType(true));
+ Handle<mirror::Class> return_type = hs.NewHandle(target_method->ResolveReturnType());
if (UNLIKELY(return_type.IsNull())) {
DCHECK(self->IsExceptionPending());
return nullptr;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 5a87ae8..0b7af4e 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -4008,8 +4008,8 @@
if (shorty[i + 1] == 'L') {
// Did we really get an argument of an appropriate reference type?
- mirror::Class* parameter_type =
- m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true /* resolve */);
+ ObjPtr<mirror::Class> parameter_type =
+ m->ResolveClassFromTypeIndex(types->GetTypeItem(i).type_idx_);
mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error);
if (error != JDWP::ERR_NONE) {
return JDWP::ERR_INVALID_OBJECT;
diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc
index 2b81f0a..b556745 100644
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -695,8 +695,7 @@
if (annotation_method == nullptr) {
return nullptr;
}
- Handle<mirror::Class> method_return(hs.NewHandle(
- annotation_method->GetReturnType(true /* resolve */)));
+ Handle<mirror::Class> method_return(hs.NewHandle(annotation_method->ResolveReturnType()));
DexFile::AnnotationValue annotation_value;
if (!ProcessAnnotationValue<false>(klass,
@@ -1073,7 +1072,7 @@
}
DexFile::AnnotationValue annotation_value;
StackHandleScope<1> hs(Thread::Current());
- Handle<mirror::Class> return_type(hs.NewHandle(method->GetReturnType(true /* resolve */)));
+ Handle<mirror::Class> return_type(hs.NewHandle(method->ResolveReturnType()));
if (!ProcessAnnotationValue<false>(klass,
&annotation,
&annotation_value,
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 01fc9ce..2bf4372 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -45,7 +45,7 @@
}
// Make sure that the result is an instance of the type this method was expected to return.
ArtMethod* method = self->GetCurrentMethod(nullptr);
- mirror::Class* return_type = method->GetReturnType(true /* resolve */);
+ ObjPtr<mirror::Class> return_type = method->ResolveReturnType();
if (!o->InstanceOf(return_type)) {
Runtime::Current()->GetJavaVM()->JniAbortF(nullptr,
@@ -108,7 +108,7 @@
ArtMethod* interface_method =
soa.Decode<mirror::Method>(interface_method_jobj)->GetArtMethod();
// This can cause thread suspension.
- mirror::Class* result_type = interface_method->GetReturnType(true /* resolve */);
+ ObjPtr<mirror::Class> result_type = interface_method->ResolveReturnType();
ObjPtr<mirror::Object> result_ref = soa.Decode<mirror::Object>(result);
JValue result_unboxed;
if (!UnboxPrimitiveForResult(result_ref.Ptr(), result_type, &result_unboxed)) {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 85904ee..136d0c6 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -1070,7 +1070,7 @@
// Preserve o since it is used below and GetClassFromTypeIndex may cause thread
// suspension.
HandleWrapperObjPtr<mirror::Object> h = hs.NewHandleWrapper(&o);
- arg_type = method->GetClassFromTypeIndex(type_idx, true /* resolve */);
+ arg_type = method->ResolveClassFromTypeIndex(type_idx);
if (arg_type == nullptr) {
CHECK(self->IsExceptionPending());
return false;
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 0a2705d..bdb8332 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -349,7 +349,7 @@
const size_t ref_idx = inst->VRegA_11x(inst_data);
ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
if (do_assignability_check && obj_result != nullptr) {
- ObjPtr<mirror::Class> return_type = method->GetReturnType(true /* resolve */);
+ ObjPtr<mirror::Class> return_type = method->ResolveReturnType();
// Re-load since it might have moved.
obj_result = shadow_frame.GetVRegReference(ref_idx);
if (return_type == nullptr) {
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index 2aad12d..f209f1d 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -260,7 +260,7 @@
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
- ObjPtr<mirror::Class> return_type(method->GetReturnType(true /* resolve */));
+ ObjPtr<mirror::Class> return_type(method->ResolveReturnType());
if (return_type.IsNull()) {
CHECK(soa.Self()->IsExceptionPending());
return nullptr;
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 6f1d15c..f28f0ca 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -238,8 +238,7 @@
// TODO: The method's parameter's type must have been previously resolved, yet
// we've seen cases where it's not b/34440020.
ObjPtr<mirror::Class> dst_class(
- m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_,
- true /* resolve */));
+ m->ResolveClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_));
if (dst_class.Ptr() == nullptr) {
CHECK(self->IsExceptionPending());
return false;
@@ -378,7 +377,7 @@
Thread* const self = Thread::Current();
for (uint32_t i = 0; i < num_params; i++) {
dex::TypeIndex type_idx = params->GetTypeItem(i).type_idx_;
- ObjPtr<mirror::Class> param_type(m->GetClassFromTypeIndex(type_idx, true /* resolve */));
+ ObjPtr<mirror::Class> param_type(m->ResolveClassFromTypeIndex(type_idx));
if (param_type == nullptr) {
CHECK(self->IsExceptionPending());
LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 6149f0d..0c460db 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2899,10 +2899,12 @@
ArtMethod* called_method = VerifyInvocationArgs(inst, type, is_range);
const RegType* return_type = nullptr;
if (called_method != nullptr) {
- mirror::Class* return_type_class = called_method->GetReturnType(can_load_classes_);
+ ObjPtr<mirror::Class> return_type_class = can_load_classes_
+ ? called_method->ResolveReturnType()
+ : called_method->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type = &FromClass(called_method->GetReturnTypeDescriptor(),
- return_type_class,
+ return_type_class.Ptr(),
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -2942,10 +2944,12 @@
} else {
is_constructor = called_method->IsConstructor();
return_type_descriptor = called_method->GetReturnTypeDescriptor();
- mirror::Class* return_type_class = called_method->GetReturnType(can_load_classes_);
+ ObjPtr<mirror::Class> return_type_class = can_load_classes_
+ ? called_method->ResolveReturnType()
+ : called_method->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type = &FromClass(return_type_descriptor,
- return_type_class,
+ return_type_class.Ptr(),
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -5261,10 +5265,12 @@
const RegType& MethodVerifier::GetMethodReturnType() {
if (return_type_ == nullptr) {
if (mirror_method_ != nullptr) {
- mirror::Class* return_type_class = mirror_method_->GetReturnType(can_load_classes_);
+ ObjPtr<mirror::Class> return_type_class = can_load_classes_
+ ? mirror_method_->ResolveReturnType()
+ : mirror_method_->LookupResolvedReturnType();
if (return_type_class != nullptr) {
return_type_ = &FromClass(mirror_method_->GetReturnTypeDescriptor(),
- return_type_class,
+ return_type_class.Ptr(),
return_type_class->CannotBeAssignedFromOtherTypes());
} else {
DCHECK(!can_load_classes_ || self_->IsExceptionPending());