Change MethodHelper to use a Handle.
Added ConstHandle to help prevent errors where you modify the value
stored in the handle of the caller. Also fixed compaction bugs
related to not knowing MethodHelper::GetReturnType can resolve types.
This bug was present in interpreter RETURN_OBJECT.
Bug: 13077697
Change-Id: I71f964d4d810ab4debda1a09bc968af8f3c874a3
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index c08cc30..89cdb4d 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -222,7 +222,7 @@
mirror::Object* receiver,
mirror::ObjectArray<mirror::Object>* args, MethodHelper& mh)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile::TypeList* classes = mh.GetParameterTypeList();
+ const DexFile::TypeList* classes = mh.GetMethod()->GetParameterTypeList();
// Set receiver if non-null (method is not static)
if (receiver != nullptr) {
Append(receiver);
@@ -349,7 +349,7 @@
static void CheckMethodArguments(mirror::ArtMethod* m, uint32_t* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- const DexFile::TypeList* params = MethodHelper(m).GetParameterTypeList();
+ const DexFile::TypeList* params = m->GetParameterTypeList();
if (params == nullptr) {
return; // No arguments so nothing to check.
}
@@ -359,24 +359,31 @@
if (!m->IsStatic()) {
offset = 1;
}
+ // TODO: If args contain object references, it may cause problems
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ArtMethod> h_m(hs.NewHandle(m));
+ MethodHelper mh(h_m);
for (uint32_t i = 0; i < num_params; i++) {
uint16_t type_idx = params->GetTypeItem(i).type_idx_;
- mirror::Class* param_type = MethodHelper(m).GetClassFromTypeIdx(type_idx);
+ mirror::Class* param_type = mh.GetClassFromTypeIdx(type_idx);
if (param_type == nullptr) {
- Thread* self = Thread::Current();
CHECK(self->IsExceptionPending());
LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
- << MethodHelper(m).GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
+ << h_m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
<< self->GetException(nullptr)->Dump();
self->ClearException();
++error_count;
} else if (!param_type->IsPrimitive()) {
// TODO: check primitives are in range.
+ // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension,
+ // this is a hard to fix problem since the args can contain Object*, we need to save and
+ // restore them by using a visitor similar to the ones used in the trampoline entrypoints.
mirror::Object* argument = reinterpret_cast<mirror::Object*>(args[i + offset]);
if (argument != nullptr && !argument->InstanceOf(param_type)) {
LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
<< PrettyTypeOf(argument) << " as argument " << (i + 1)
- << " to " << PrettyMethod(m);
+ << " to " << PrettyMethod(h_m.Get());
++error_count;
}
} else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) {
@@ -387,7 +394,7 @@
// TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort
// with an argument.
JniAbortF(nullptr, "bad arguments passed to %s (see above for details)",
- PrettyMethod(m).c_str());
+ PrettyMethod(h_m.Get()).c_str());
}
}
@@ -414,33 +421,36 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* method = soa.DecodeMethod(mid);
mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
- MethodHelper mh(method);
+ uint32_t shorty_len = 0;
+ const char* shorty = method->GetShorty(&shorty_len);
JValue result;
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ ArgArray arg_array(shorty, shorty_len);
arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
+ InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
return result;
}
JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* receiver,
jmethodID mid, jvalue* args) {
mirror::ArtMethod* method = soa.DecodeMethod(mid);
- MethodHelper mh(method);
+ uint32_t shorty_len = 0;
+ const char* shorty = method->GetShorty(&shorty_len);
JValue result;
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ ArgArray arg_array(shorty, shorty_len);
arg_array.BuildArgArrayFromJValues(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
+ InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
return result;
}
JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
mirror::Object* receiver, jmethodID mid, jvalue* args) {
mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
- MethodHelper mh(method);
+ uint32_t shorty_len = 0;
+ const char* shorty = method->GetShorty(&shorty_len);
JValue result;
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ ArgArray arg_array(shorty, shorty_len);
arg_array.BuildArgArrayFromJValues(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
+ InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
return result;
}
@@ -448,11 +458,12 @@
jobject obj, jmethodID mid, va_list args) {
mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
- MethodHelper mh(method);
+ uint32_t shorty_len = 0;
+ const char* shorty = method->GetShorty(&shorty_len);
JValue result;
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ ArgArray arg_array(shorty, shorty_len);
arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
+ InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
return result;
}
@@ -493,8 +504,7 @@
// Get our arrays of arguments and their types, and check they're the same size.
mirror::ObjectArray<mirror::Object>* objects =
soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
- MethodHelper mh(m);
- const DexFile::TypeList* classes = mh.GetParameterTypeList();
+ const DexFile::TypeList* classes = m->GetParameterTypeList();
uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
if (arg_count != classes_size) {
@@ -513,13 +523,17 @@
// Invoke the method.
JValue result;
- ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
+ uint32_t shorty_len = 0;
+ const char* shorty = m->GetShorty(&shorty_len);
+ ArgArray arg_array(shorty, shorty_len);
+ StackHandleScope<1> hs(soa.Self());
+ MethodHelper mh(hs.NewHandle(m));
if (!arg_array.BuildArgArrayFromObjectArray(soa, receiver, objects, mh)) {
CHECK(soa.Self()->IsExceptionPending());
return nullptr;
}
- InvokeWithArgArray(soa, m, &arg_array, &result, mh.GetShorty());
+ InvokeWithArgArray(soa, m, &arg_array, &result, shorty);
// Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
if (soa.Self()->IsExceptionPending()) {