Partial revert of "Reduce using ArtMethod's dex_cache_resolved_types_."
Change Ic45a5ff8c66b79429e440cbc08d67bf22a083682 made the resolution
from true to false, assuming we could only enter that specific code
with a resolved type. Unfortunately b/34440020 shows we still
need to resolve.
Also move arg to a Handle, now that we are resolving, which could
lead to thread suspension.
bug:34440020
bug:34452336
Test: test-art-host test-art-target
Change-Id: I98c834158733a46cf896e7dfa7ce226c53e2d949
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 75176f9..a2b4cb3 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -216,43 +216,54 @@
}
bool BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver,
- ObjPtr<mirror::ObjectArray<mirror::Object>> args,
- ArtMethod* m)
+ ObjPtr<mirror::ObjectArray<mirror::Object>> raw_args,
+ ArtMethod* m,
+ Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile::TypeList* classes = m->GetParameterTypeList();
// Set receiver if non-null (method is not static)
if (receiver != nullptr) {
Append(receiver);
}
+ StackHandleScope<2> hs(self);
+ MutableHandle<mirror::Object> arg(hs.NewHandle<mirror::Object>(nullptr));
+ Handle<mirror::ObjectArray<mirror::Object>> args(
+ hs.NewHandle<mirror::ObjectArray<mirror::Object>>(raw_args));
for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
- ObjPtr<mirror::Object> arg(args->Get(args_offset));
- if (((shorty_[i] == 'L') && (arg != nullptr)) || ((arg == nullptr && shorty_[i] != 'L'))) {
- // Note: The method's parameter's type must have been previously resolved.
+ arg.Assign(args->Get(args_offset));
+ if (((shorty_[i] == 'L') && (arg.Get() != nullptr)) ||
+ ((arg.Get() == nullptr && shorty_[i] != 'L'))) {
+ // 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_,
- false /* resolve */));
- DCHECK(dst_class != nullptr) << m->PrettyMethod() << " arg #" << i;
- if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) {
+ true /* resolve */));
+ if (dst_class.Ptr() == nullptr) {
+ CHECK(self->IsExceptionPending());
+ return false;
+ }
+ if (UNLIKELY(arg.Get() == nullptr || !arg->InstanceOf(dst_class))) {
ThrowIllegalArgumentException(
StringPrintf("method %s argument %zd has type %s, got %s",
m->PrettyMethod(false).c_str(),
args_offset + 1, // Humans don't count from 0.
mirror::Class::PrettyDescriptor(dst_class).c_str(),
- mirror::Object::PrettyTypeOf(arg).c_str()).c_str());
+ mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str());
return false;
}
}
#define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
- if (LIKELY(arg != nullptr && arg->GetClass()->DescriptorEquals(match_descriptor))) { \
+ if (LIKELY(arg.Get() != nullptr && \
+ arg->GetClass()->DescriptorEquals(match_descriptor))) { \
ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
- append(primitive_field-> get_fn(arg));
+ append(primitive_field-> get_fn(arg.Get()));
#define DO_ARG(match_descriptor, get_fn, append) \
- } else if (LIKELY(arg != nullptr && \
+ } else if (LIKELY(arg.Get() != nullptr && \
arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
- append(primitive_field-> get_fn(arg));
+ append(primitive_field-> get_fn(arg.Get()));
#define DO_FAIL(expected) \
} else { \
@@ -266,14 +277,14 @@
ArtMethod::PrettyMethod(m, false).c_str(), \
args_offset + 1, \
expected, \
- mirror::Object::PrettyTypeOf(arg).c_str()).c_str()); \
+ mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str()); \
} \
return false; \
} }
switch (shorty_[i]) {
case 'L':
- Append(arg);
+ Append(arg.Get());
break;
case 'Z':
DO_FIRST_ARG("Ljava/lang/Boolean;", GetBoolean, Append)
@@ -646,7 +657,7 @@
uint32_t shorty_len = 0;
const char* shorty = np_method->GetShorty(&shorty_len);
ArgArray arg_array(shorty, shorty_len);
- if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method)) {
+ if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method, soa.Self())) {
CHECK(soa.Self()->IsExceptionPending());
return nullptr;
}