Changes to remove need for compiled invoke stubs for quick.
ARM, x86, and MIPS implementation complete, though MIPS is untested.
The ArgArray is changed to be a uint32_t array instead of a JValue array.
Also, a separate result for float/double was needed for x86/MIPS. The invoke
stubs are currently still there, but only used for portable.
Change-Id: I0647f8d5d420cea61370e662e85bdc0c13b5e378
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 887fcb4..eabce2c 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -85,20 +85,19 @@
return reinterpret_cast<jweak>(ref);
}
-static bool IsBadJniVersion(int version) {
- // We don't support JNI_VERSION_1_1. These are the only other valid versions.
- return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
-}
-
-static void CheckMethodArguments(AbstractMethod* m, JValue* args)
+static void CheckMethodArguments(AbstractMethod* m, uint32_t* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
MethodHelper mh(m);
const DexFile::TypeList* params = mh.GetParameterTypeList();
if (params == NULL) {
return; // No arguments so nothing to check.
}
+ uint32_t offset = 0;
uint32_t num_params = params->Size();
size_t error_count = 0;
+ if (!m->IsStatic()) {
+ offset = 1;
+ }
for (uint32_t i = 0; i < num_params; i++) {
uint16_t type_idx = params->GetTypeItem(i).type_idx_;
Class* param_type = mh.GetClassFromTypeIdx(type_idx);
@@ -112,12 +111,14 @@
++error_count;
} else if (!param_type->IsPrimitive()) {
// TODO: check primitives are in range.
- Object* argument = args[i].GetL();
+ Object* argument = reinterpret_cast<Object*>(args[i + offset]);
if (argument != NULL && !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);
++error_count;
}
+ } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) {
+ offset++;
}
}
if (error_count > 0) {
@@ -127,15 +128,13 @@
}
}
-static JValue InvokeWithArgArray(const ScopedObjectAccess& soa, Object* receiver,
- AbstractMethod* method, JValue* args)
+void InvokeWithArgArray(const ScopedObjectAccess& soa, AbstractMethod* method,
+ ArgArray* arg_array, JValue* result, JValue* float_result)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (UNLIKELY(soa.Env()->check_jni)) {
- CheckMethodArguments(method, args);
+ CheckMethodArguments(method, arg_array->GetArray());
}
- JValue result;
- method->Invoke(soa.Self(), receiver, args, &result);
- return result;
+ method->Invoke(soa.Self(), arg_array->GetArray(), arg_array->GetNumBytes(), result, float_result);
}
static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,
@@ -144,9 +143,16 @@
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = soa.DecodeMethod(mid);
MethodHelper mh(method);
+ JValue result;
+ JValue float_result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArray(soa, args);
- return InvokeWithArgArray(soa, receiver, method, arg_array.get());
+ arg_array.BuildArgArray(soa, receiver, args);
+ InvokeWithArgArray(soa, method, &arg_array, &result, &float_result);
+ if (mh.IsReturnFloatOrDouble()) {
+ return float_result;
+ } else {
+ return result;
+ }
}
static AbstractMethod* FindVirtualMethod(Object* receiver, AbstractMethod* method)
@@ -160,9 +166,16 @@
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
MethodHelper mh(method);
+ JValue result;
+ JValue float_result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArray(soa, args);
- return InvokeWithArgArray(soa, receiver, method, arg_array.get());
+ arg_array.BuildArgArray(soa, receiver, args);
+ InvokeWithArgArray(soa, method, &arg_array, &result, &float_result);
+ if (mh.IsReturnFloatOrDouble()) {
+ return float_result;
+ } else {
+ return result;
+ }
}
static JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccess& soa,
@@ -171,9 +184,16 @@
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
MethodHelper mh(method);
+ JValue result;
+ JValue float_result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArray(soa, args);
- return InvokeWithArgArray(soa, receiver, method, arg_array.get());
+ arg_array.BuildArgArray(soa, receiver, args);
+ InvokeWithArgArray(soa, method, &arg_array, &result, &float_result);
+ if (mh.IsReturnFloatOrDouble()) {
+ return float_result;
+ } else {
+ return result;
+ }
}
// Section 12.3.2 of the JNI spec describes JNI class descriptors. They're
@@ -570,15 +590,16 @@
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = soa.DecodeMethod(mid);
MethodHelper mh(method);
+ JValue result;
+ JValue float_result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
- arg_array.BuildArgArray(soa, args);
- return InvokeWithArgArray(soa, receiver, method, arg_array.get());
-}
-
-JValue InvokeWithJValues(const ScopedObjectAccess& soa, Object* receiver, AbstractMethod* m,
- JValue* args)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return InvokeWithArgArray(soa, receiver, m, args);
+ arg_array.BuildArgArray(soa, receiver, args);
+ InvokeWithArgArray(soa, method, &arg_array, &result, &float_result);
+ if (mh.IsReturnFloatOrDouble()) {
+ return float_result;
+ } else {
+ return result;
+ }
}
class JNI {