Refactor reflective method invocation.
Move invocation code out of JNI internal into reflection, including ArgArray
code. Make reflective invocation use the ArgArray to build arguments rather
than allocating a jvalue[] and unboxing arguments into that.
Move reflection part of jni_internal_test into reflection_test.
Make greater use of fast JNI.
Change-Id: Ib381372df5f9a83679e30e7275de24fa0e6b1057
diff --git a/runtime/thread.cc b/runtime/thread.cc
index f4b9d9a..f5ed082 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -45,7 +45,6 @@
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
#include "gc/space/space.h"
-#include "invoke_arg_array_builder.h"
#include "jni_internal.h"
#include "mirror/art_field-inl.h"
#include "mirror/art_method-inl.h"
@@ -174,12 +173,7 @@
// Invoke the 'run' method of our java.lang.Thread.
mirror::Object* receiver = self->opeer_;
jmethodID mid = WellKnownClasses::java_lang_Thread_run;
- mirror::ArtMethod* m =
- receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(soa.DecodeMethod(mid));
- JValue result;
- ArgArray arg_array(nullptr, 0);
- arg_array.Append(receiver);
- m->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), &result, "V");
+ InvokeVirtualOrInterfaceWithJValues(soa, receiver, mid, nullptr);
}
// Detach and delete self.
Runtime::Current()->GetThreadList()->Unregister(self);
@@ -1413,10 +1407,8 @@
return soa.AddLocalReference<jobjectArray>(trace);
}
-jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, jobject internal,
- jobjectArray output_array, int* stack_depth) {
- // Transition into runnable state to work on Object*/Array*
- ScopedObjectAccess soa(env);
+jobjectArray Thread::InternalStackTraceToStackTraceElementArray(const ScopedObjectAccess& soa,
+ jobject internal, jobjectArray output_array, int* stack_depth) {
// Decode the internal stack trace into the depth, method trace and PC trace
int32_t depth = soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal)->GetLength() - 1;
@@ -1526,11 +1518,12 @@
const char* exception_class_descriptor,
const char* msg) {
DCHECK_EQ(this, Thread::Current());
+ ScopedObjectAccessUnchecked soa(this);
// Ensure we don't forget arguments over object allocation.
SirtRef<mirror::Object> saved_throw_this(this, throw_location.GetThis());
SirtRef<mirror::ArtMethod> saved_throw_method(this, throw_location.GetMethod());
// Ignore the cause throw location. TODO: should we report this as a re-throw?
- SirtRef<mirror::Throwable> cause(this, GetException(nullptr));
+ ScopedLocalRef<jobject> cause(GetJniEnv(), soa.AddLocalReference<jobject>(GetException(nullptr)));
ClearException();
Runtime* runtime = Runtime::Current();
@@ -1567,10 +1560,11 @@
// Choose an appropriate constructor and set up the arguments.
const char* signature;
const char* shorty;
- SirtRef<mirror::String> msg_string(this, nullptr);
+ ScopedLocalRef<jstring> msg_string(GetJniEnv(), nullptr);
if (msg != nullptr) {
// Ensure we remember this and the method over the String allocation.
- msg_string.reset(mirror::String::AllocFromModifiedUtf8(this, msg));
+ msg_string.reset(
+ soa.AddLocalReference<jstring>(mirror::String::AllocFromModifiedUtf8(this, msg)));
if (UNLIKELY(msg_string.get() == nullptr)) {
CHECK(IsExceptionPending()); // OOME.
return;
@@ -1602,25 +1596,27 @@
// case in the compiler. We won't be able to invoke the constructor of the exception, so set
// the exception fields directly.
if (msg != nullptr) {
- exception->SetDetailMessage(msg_string.get());
+ exception->SetDetailMessage(down_cast<mirror::String*>(DecodeJObject(msg_string.get())));
}
if (cause.get() != nullptr) {
- exception->SetCause(cause.get());
+ exception->SetCause(down_cast<mirror::Throwable*>(DecodeJObject(cause.get())));
}
ThrowLocation gc_safe_throw_location(saved_throw_this.get(), saved_throw_method.get(),
throw_location.GetDexPc());
SetException(gc_safe_throw_location, exception.get());
} else {
- ArgArray args(shorty, strlen(shorty));
- args.Append(exception.get());
+ jvalue jv_args[2];
+ size_t i = 0;
+
if (msg != nullptr) {
- args.Append(msg_string.get());
+ jv_args[i].l = msg_string.get();
+ ++i;
}
if (cause.get() != nullptr) {
- args.Append(cause.get());
+ jv_args[i].l = cause.get();
+ ++i;
}
- JValue result;
- exception_init_method->Invoke(this, args.GetArray(), args.GetNumBytes(), &result, shorty);
+ InvokeWithJValues(soa, exception.get(), soa.EncodeMethod(exception_init_method), jv_args);
if (LIKELY(!IsExceptionPending())) {
ThrowLocation gc_safe_throw_location(saved_throw_this.get(), saved_throw_method.get(),
throw_location.GetDexPc());