Move JNI compiler tests to use pure JNI.
Implement JNI upcalls for x86.
Fix off by 1 bug in JNI calling convention for x86.
Fix bugs in ARM JNI upcalls.
Straw man JNI invoke nonvirtual implementations.
Match va_start with va_end in JNI internals.
Change-Id: I64d62eca41ac726ae0d007c1f41d2193db5be82e
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index fd66d73..9fd0e5f 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -20,6 +20,12 @@
namespace art {
+jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args);
+void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args);
+void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue* args);
+
enum JNI_OnLoadState {
kPending = 0, /* initial state, must be zero */
kFailed,
@@ -499,28 +505,36 @@
return arg_array.release();
}
-JValue InvokeWithArgArray(ScopedJniThreadState& ts,
- Object* obj, jmethodID method_id, byte* args) {
+JValue InvokeWithArgArray(ScopedJniThreadState& ts, jobject obj,
+ jmethodID method_id, byte* args) {
// TODO: DecodeReference
Method* method = reinterpret_cast<Method*>(method_id);
+ Object* rcvr = Decode<Object*>(ts, obj);
// Call the invoke stub associated with the method
// Pass everything as arguments
const Method::InvokeStub* stub = method->GetInvokeStub();
CHECK(stub != NULL);
JValue result;
- (*stub)(method, obj, ts.Self(), args, &result);
+ // TODO: we should always have code associated with a method
+ if (method->GetCode()) {
+ (*stub)(method, rcvr, ts.Self(), args, &result);
+ } else {
+ // TODO: pretty print method here
+ LOG(WARNING) << "Not invoking method with no associated code";
+ result.j = 0;
+ }
return result;
}
-JValue InvokeWithJValues(ScopedJniThreadState& ts,
- Object* obj, jmethodID method_id, jvalue* args) {
+JValue InvokeWithJValues(ScopedJniThreadState& ts, jobject obj,
+ jmethodID method_id, jvalue* args) {
Method* method = reinterpret_cast<Method*>(method_id);
scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
return InvokeWithArgArray(ts, obj, method_id, arg_array.get());
}
-JValue InvokeWithVarArgs(ScopedJniThreadState& ts,
- Object* obj, jmethodID method_id, va_list args) {
+JValue InvokeWithVarArgs(ScopedJniThreadState& ts, jobject obj,
+ jmethodID method_id, va_list args) {
Method* method = reinterpret_cast<Method*>(method_id);
scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
return InvokeWithArgArray(ts, obj, method_id, arg_array.get());
@@ -761,8 +775,8 @@
jboolean IsSameObject(JNIEnv* env, jobject obj1, jobject obj2) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return JNI_FALSE;
+ return (Decode<Object*>(ts, obj1) == Decode<Object*>(ts, obj2))
+ ? JNI_TRUE : JNI_FALSE;
}
jint EnsureLocalCapacity(JNIEnv* env, jint) {
@@ -779,22 +793,31 @@
jobject NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ va_list args;
+ va_start(args, methodID);
+ jobject result = NewObjectV(env, clazz, methodID, args);
+ va_end(args);
+ return result;
}
jobject NewObjectV(JNIEnv* env,
jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ Class* klass = Decode<Class*>(ts, clazz);
+ Object* result = klass->NewInstance();
+ jobject local_result = AddLocalReference<jobject>(ts, result);
+ CallNonvirtualVoidMethodV(env, local_result, clazz, methodID, args);
+ return local_result;
}
jobject NewObjectA(JNIEnv* env,
jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ Class* klass = Decode<Class*>(ts, clazz);
+ Object* result = klass->NewInstance();
+ jobject local_result = AddLocalReference<jobjectArray>(ts, result);
+ CallNonvirtualVoidMethodA(env, local_result, clazz, methodID, args);
+ return local_result;
}
jclass GetObjectClass(JNIEnv* env, jobject obj) {
@@ -1056,208 +1079,223 @@
jobject CallNonvirtualObjectMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ jobject local_result = AddLocalReference<jobject>(ts, result.l);
+ va_end(ap);
+ return local_result;
}
jobject CallNonvirtualObjectMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, args);
+ return AddLocalReference<jobject>(ts, result.l);
}
jobject CallNonvirtualObjectMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ JValue result = InvokeWithJValues(ts, obj, methodID, args);
+ return AddLocalReference<jobject>(ts, result.l);
}
jboolean CallNonvirtualBooleanMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return JNI_FALSE;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.z;
}
jboolean CallNonvirtualBooleanMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return JNI_FALSE;
+ return InvokeWithVarArgs(ts, obj, methodID, args).z;
}
jboolean CallNonvirtualBooleanMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return JNI_FALSE;
+ return InvokeWithJValues(ts, obj, methodID, args).z;
}
jbyte CallNonvirtualByteMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.b;
}
jbyte CallNonvirtualByteMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).b;
}
jbyte CallNonvirtualByteMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).b;
}
jchar CallNonvirtualCharMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.c;
}
jchar CallNonvirtualCharMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).c;
}
jchar CallNonvirtualCharMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).c;
}
jshort CallNonvirtualShortMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.s;
}
jshort CallNonvirtualShortMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).s;
}
jshort CallNonvirtualShortMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).s;
}
jint CallNonvirtualIntMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.i;
}
jint CallNonvirtualIntMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).i;
}
jint CallNonvirtualIntMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).i;
}
jlong CallNonvirtualLongMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.j;
}
jlong CallNonvirtualLongMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).j;
}
jlong CallNonvirtualLongMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).j;
}
jfloat CallNonvirtualFloatMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.f;
}
jfloat CallNonvirtualFloatMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).f;
}
jfloat CallNonvirtualFloatMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).f;
}
jdouble CallNonvirtualDoubleMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ va_list ap;
+ va_start(ap, methodID);
+ JValue result = InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
+ return result.d;
}
jdouble CallNonvirtualDoubleMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithVarArgs(ts, obj, methodID, args).d;
}
jdouble CallNonvirtualDoubleMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ return InvokeWithJValues(ts, obj, methodID, args).d;
}
void CallNonvirtualVoidMethod(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, ...) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ va_list ap;
+ va_start(ap, methodID);
+ InvokeWithVarArgs(ts, obj, methodID, ap);
+ va_end(ap);
}
void CallNonvirtualVoidMethodV(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ InvokeWithVarArgs(ts, obj, methodID, args);
}
void CallNonvirtualVoidMethodA(JNIEnv* env,
jobject obj, jclass clazz, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ InvokeWithJValues(ts, obj, methodID, args);
}
jfieldID GetFieldID(JNIEnv* env,
@@ -1409,7 +1447,9 @@
va_list ap;
va_start(ap, methodID);
JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
- return AddLocalReference<jobject>(ts, result.l);
+ jobject local_result = AddLocalReference<jobject>(ts, result.l);
+ va_end(ap);
+ return local_result;
}
jobject CallStaticObjectMethodV(JNIEnv* env,
@@ -1431,7 +1471,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).z;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.z;
}
jboolean CallStaticBooleanMethodV(JNIEnv* env,
@@ -1450,7 +1492,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).b;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.b;
}
jbyte CallStaticByteMethodV(JNIEnv* env,
@@ -1469,7 +1513,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).c;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.c;
}
jchar CallStaticCharMethodV(JNIEnv* env,
@@ -1488,7 +1534,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).s;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.s;
}
jshort CallStaticShortMethodV(JNIEnv* env,
@@ -1507,7 +1555,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).i;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.i;
}
jint CallStaticIntMethodV(JNIEnv* env,
@@ -1526,7 +1576,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).j;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.j;
}
jlong CallStaticLongMethodV(JNIEnv* env,
@@ -1545,7 +1597,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).f;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.f;
}
jfloat CallStaticFloatMethodV(JNIEnv* env,
@@ -1564,7 +1618,9 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, methodID);
- return InvokeWithVarArgs(ts, NULL, methodID, ap).d;
+ JValue result = InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
+ return result.d;
}
jdouble CallStaticDoubleMethodV(JNIEnv* env,
@@ -1584,6 +1640,7 @@
va_list ap;
va_start(ap, methodID);
InvokeWithVarArgs(ts, NULL, methodID, ap);
+ va_end(ap);
}
void CallStaticVoidMethodV(JNIEnv* env,