diff --git a/src/constants.h b/src/constants.h index 4f571d0ec1..7e5896d4e6 100644 --- a/src/constants.h +++ b/src/constants.h @@ -249,6 +249,9 @@ const unsigned ACC_INTERFACE = 1 << 9; const unsigned ACC_ABSTRACT = 1 << 10; const unsigned ACC_STRICT = 1 << 11; +const int JNI_COMMIT = 1; +const int JNI_ABORT = 2; + } // namespace vm #endif//CONSTANTS_H diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 345997ef8c..7c7de36d4e 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -1,10 +1,14 @@ #include "jnienv.h" #include "machine.h" +#include "constants.h" using namespace vm; namespace { +const uintptr_t InterfaceMethodID += (static_cast(1) << (BitsPerWord - 1)); + jsize JNICALL GetStringUTFLength(Thread* t, jstring s) { @@ -40,24 +44,6 @@ NewStringUTF(Thread* t, const char* chars) return pushReference(t, makeString(t, "%s", chars)); } -void JNICALL -GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, - jbyte* dst) -{ - ENTER(t, Thread::ActiveState); - - memcpy(dst, &byteArrayBody(t, *array, offset), length); -} - -void JNICALL -SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, - const jbyte* src) -{ - ENTER(t, Thread::ActiveState); - - memcpy(&byteArrayBody(t, *array, offset), src, length); -} - jclass JNICALL FindClass(Thread* t, const char* name) { @@ -110,18 +96,24 @@ ExceptionCheck(Thread* t) jclass JNICALL GetObjectClass(Thread* t, jobject o) { + ENTER(t, Thread::ActiveState); + return pushReference(t, objectClass(t, *o)); } jboolean JNICALL IsInstanceOf(Thread* t, jobject o, jclass c) { + ENTER(t, Thread::ActiveState); + return instanceOf(t, *c, *o); } object findMethod(Thread* t, object class_, const char* name, const char* spec) { + ENTER(t, Thread::ActiveState); + object n = makeString(t, "%s", name); PROTECT(t, n); @@ -129,40 +121,476 @@ findMethod(Thread* t, object class_, const char* name, const char* spec) return vm::findMethod(t, class_, n, s); } -// jmethodID JNICALL -// GetMethodID(Thread* t, jclass c, const char* name, const char* spec) -// { -// object method = findMethod(t, *c, name, spec); -// if (UNLIKELY(t->exception)) return 0; +jmethodID JNICALL +GetMethodID(Thread* t, jclass c, const char* name, const char* spec) +{ + ENTER(t, Thread::ActiveState); -// if (classFlags(t, *c) & ACC_INTERFACE) { -// PROTECT(t, method); + object method = findMethod(t, *c, name, spec); + if (UNLIKELY(t->exception)) return 0; -// ACQUIRE(t, t->vm->referenceLock); + if (classFlags(t, *c) & ACC_INTERFACE) { + PROTECT(t, method); + + ACQUIRE(t, t->vm->referenceLock); -// for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) { -// if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) { -// return i; -// } -// } + for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) { + if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) { + return i; + } + } -// t->vm->jniInterfaceTable -// = vectorAppend(t, t->vm->jniInterfaceTable, method); + t->vm->jniInterfaceTable + = vectorAppend(t, t->vm->jniInterfaceTable, method); -// return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | (1 << BitsPerWord); -// } else { -// return methodOffset(t, method); -// } -// } + return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | InterfaceMethodID; + } else { + return methodOffset(t, method); + } +} -// jmethodID JNICALL -// GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) -// { -// object method = findMethod(t, *c, name, spec); -// if (UNLIKELY(t->exception)) return 0; +jmethodID JNICALL +GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) +{ + ENTER(t, Thread::ActiveState); -// return methodOffset(t, method); -// } + object method = findMethod(t, *c, name, spec); + if (UNLIKELY(t->exception)) return 0; + + return methodOffset(t, method); +} + +inline object +getMethod(Thread* t, object o, jmethodID m) +{ + if (m & InterfaceMethodID) { + return vectorBody(t, t->vm->jniInterfaceTable, m & (~InterfaceMethodID)); + } else { + return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m); + } +} + +jobject JNICALL +CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jobject JNICALL +CallObjectMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jobject r = CallObjectMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jboolean JNICALL +CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return booleanValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jboolean JNICALL +CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jboolean r = CallBooleanMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jbyte JNICALL +CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return byteValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jbyte JNICALL +CallByteMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jbyte r = CallByteMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jchar JNICALL +CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return charValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jchar JNICALL +CallCharMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jchar r = CallCharMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jshort JNICALL +CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return shortValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jshort JNICALL +CallShortMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jshort r = CallShortMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jint JNICALL +CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return intValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jint JNICALL +CallIntMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jint r = CallIntMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jlong JNICALL +CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return longValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jlong JNICALL +CallLongMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jlong r = CallLongMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jfloat JNICALL +CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return floatValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jfloat JNICALL +CallFloatMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jfloat r = CallFloatMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +jdouble JNICALL +CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return doubleValue(t, run(t, getMethod(t, *o, m), *o, true, a)); +} + +jdouble JNICALL +CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jdouble r = CallDoubleMethodV(t, o, m, a); + + va_end(a); + + return r; +} + +void JNICALL +CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + run(t, getMethod(t, *o, m), *o, true, a); +} + +void JNICALL +CallVoidMethod(Thread* t, jobject o, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + CallVoidMethodV(t, o, m, a); + + va_end(a); +} + +inline object +getStaticMethod(Thread* t, object class_, jmethodID m) +{ + return arrayBody(t, classMethodTable(t, class_), m); +} + +jobject JNICALL +CallStaticObjectMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jobject JNICALL +CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jobject r = CallStaticObjectMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jboolean JNICALL +CallStaticBooleanMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return booleanValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jboolean JNICALL +CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jboolean r = CallStaticBooleanMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jbyte JNICALL +CallStaticByteMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return byteValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jbyte JNICALL +CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jbyte r = CallStaticByteMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jchar JNICALL +CallStaticCharMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return charValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jchar JNICALL +CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jchar r = CallStaticCharMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jshort JNICALL +CallStaticShortMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return shortValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jshort JNICALL +CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jshort r = CallStaticShortMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jint JNICALL +CallStaticIntMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return intValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jint JNICALL +CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jint r = CallStaticIntMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jlong JNICALL +CallStaticLongMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return longValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jlong JNICALL +CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jlong r = CallStaticLongMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jfloat JNICALL +CallStaticFloatMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return floatValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jfloat JNICALL +CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jfloat r = CallStaticFloatMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +jdouble JNICALL +CallStaticDoubleMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + return doubleValue(t, run(t, getStaticMethod(t, *c, m), 0, true, a)); +} + +jdouble JNICALL +CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + jdouble r = CallStaticDoubleMethodV(t, c, m, a); + + va_end(a); + + return r; +} + +void JNICALL +CallStaticVoidMethodV(Thread* t, jclass c, jmethodID m, va_list a) +{ + ENTER(t, Thread::ActiveState); + + run(t, getStaticMethod(t, *c, m), 0, true, a); +} + +void JNICALL +CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...) +{ + va_list a; + va_start(a, m); + + CallStaticVoidMethodV(t, c, m, a); + + va_end(a); +} object findField(Thread* t, object class_, const char* name, const char* spec) @@ -177,6 +605,8 @@ findField(Thread* t, object class_, const char* name, const char* spec) jfieldID JNICALL GetFieldID(Thread* t, jclass c, const char* name, const char* spec) { + ENTER(t, Thread::ActiveState); + object field = findField(t, *c, name, spec); if (UNLIKELY(t->exception)) return 0; @@ -186,6 +616,8 @@ GetFieldID(Thread* t, jclass c, const char* name, const char* spec) jfieldID JNICALL GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec) { + ENTER(t, Thread::ActiveState); + object field = findField(t, *c, name, spec); if (UNLIKELY(t->exception)) return 0; @@ -195,126 +627,168 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec) jobject JNICALL GetObjectField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return pushReference(t, cast(*o, field)); } jboolean JNICALL -GetBooleanField(Thread*, jobject o, jfieldID field) +GetBooleanField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jbyte JNICALL -GetByteField(Thread*, jobject o, jfieldID field) +GetByteField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jchar JNICALL -GetCharField(Thread*, jobject o, jfieldID field) +GetCharField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jshort JNICALL -GetShortField(Thread*, jobject o, jfieldID field) +GetShortField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jint JNICALL -GetIntField(Thread*, jobject o, jfieldID field) +GetIntField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jlong JNICALL -GetLongField(Thread*, jobject o, jfieldID field) +GetLongField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jfloat JNICALL -GetFloatField(Thread*, jobject o, jfieldID field) +GetFloatField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } jdouble JNICALL -GetDoubleField(Thread*, jobject o, jfieldID field) +GetDoubleField(Thread* t, jobject o, jfieldID field) { + ENTER(t, Thread::ActiveState); + return cast(*o, field); } void JNICALL SetObjectField(Thread* t, jobject o, jfieldID field, jobject v) { + ENTER(t, Thread::ActiveState); + set(t, cast(*o, field), (v ? *v : 0)); } void JNICALL -SetBooleanField(Thread*, jobject o, jfieldID field, jboolean v) +SetBooleanField(Thread* t, jobject o, jfieldID field, jboolean v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetByteField(Thread*, jobject o, jfieldID field, jbyte v) +SetByteField(Thread* t, jobject o, jfieldID field, jbyte v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetCharField(Thread*, jobject o, jfieldID field, jchar v) +SetCharField(Thread* t, jobject o, jfieldID field, jchar v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetShortField(Thread*, jobject o, jfieldID field, jshort v) +SetShortField(Thread* t, jobject o, jfieldID field, jshort v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetIntField(Thread*, jobject o, jfieldID field, jint v) +SetIntField(Thread* t, jobject o, jfieldID field, jint v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetLongField(Thread*, jobject o, jfieldID field, jlong v) +SetLongField(Thread* t, jobject o, jfieldID field, jlong v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetFloatField(Thread*, jobject o, jfieldID field, jfloat v) +SetFloatField(Thread* t, jobject o, jfieldID field, jfloat v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } void JNICALL -SetDoubleField(Thread*, jobject o, jfieldID field, jdouble v) +SetDoubleField(Thread* t, jobject o, jfieldID field, jdouble v) { + ENTER(t, Thread::ActiveState); + cast(*o, field) = v; } jobject JNICALL GetStaticObjectField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + return pushReference(t, arrayBody(t, classStaticTable(t, *c), field)); } jboolean JNICALL GetStaticBooleanField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + return intValue(t, arrayBody(t, classStaticTable(t, *c), field)) != 0; } jbyte JNICALL GetStaticByteField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + return static_cast (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); } @@ -322,6 +796,8 @@ GetStaticByteField(Thread* t, jclass c, jfieldID field) jchar JNICALL GetStaticCharField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + return static_cast (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); } @@ -329,6 +805,8 @@ GetStaticCharField(Thread* t, jclass c, jfieldID field) jshort JNICALL GetStaticShortField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + return static_cast (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); } @@ -336,6 +814,8 @@ GetStaticShortField(Thread* t, jclass c, jfieldID field) jint JNICALL GetStaticIntField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + return intValue(t, arrayBody(t, classStaticTable(t, *c), field)); } @@ -348,6 +828,8 @@ GetStaticLongField(Thread* t, jclass c, jfieldID field) jfloat JNICALL GetStaticFloatField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + jint i = intValue(t, arrayBody(t, classStaticTable(t, *c), field)); jfloat v; memcpy(&v, &i, 4); return v; @@ -356,6 +838,8 @@ GetStaticFloatField(Thread* t, jclass c, jfieldID field) jdouble JNICALL GetStaticDoubleField(Thread* t, jclass c, jfieldID field) { + ENTER(t, Thread::ActiveState); + jlong i = longValue(t, arrayBody(t, classStaticTable(t, *c), field)); jdouble v; memcpy(&v, &i, 8); return v; @@ -364,12 +848,16 @@ GetStaticDoubleField(Thread* t, jclass c, jfieldID field) void JNICALL SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v) { + ENTER(t, Thread::ActiveState); + set(t, arrayBody(t, classStaticTable(t, *c), field), (v ? *v : 0)); } void JNICALL SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v) { + ENTER(t, Thread::ActiveState); + object o = makeInt(t, v ? 1 : 0); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } @@ -377,6 +865,8 @@ SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v) void JNICALL SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v) { + ENTER(t, Thread::ActiveState); + object o = makeInt(t, v); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } @@ -384,6 +874,8 @@ SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v) void JNICALL SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v) { + ENTER(t, Thread::ActiveState); + object o = makeInt(t, v); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } @@ -391,6 +883,8 @@ SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v) void JNICALL SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v) { + ENTER(t, Thread::ActiveState); + object o = makeInt(t, v); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } @@ -398,6 +892,8 @@ SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v) void JNICALL SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v) { + ENTER(t, Thread::ActiveState); + object o = makeInt(t, v); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } @@ -405,6 +901,8 @@ SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v) void JNICALL SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v) { + ENTER(t, Thread::ActiveState); + object o = makeLong(t, v); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } @@ -412,6 +910,8 @@ SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v) void JNICALL SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v) { + ENTER(t, Thread::ActiveState); + jint i; memcpy(&i, &v, 4); object o = makeInt(t, i); set(t, arrayBody(t, classStaticTable(t, *c), field), o); @@ -420,11 +920,466 @@ SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v) void JNICALL SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v) { + ENTER(t, Thread::ActiveState); + jlong i; memcpy(&i, &v, 8); object o = makeLong(t, i); set(t, arrayBody(t, classStaticTable(t, *c), field), o); } +jobject JNICALL +NewGlobalRef(Thread* t, jobject o) +{ + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->vm->referenceLock); + + t->vm->jniReferences = new (t->vm->system->allocate(sizeof(Reference))) + Reference(*o, t->vm->jniReferences); + + return &(t->vm->jniReferences->target); +} + +void JNICALL +DeleteGlobalRef(Thread* t, jobject o) +{ + ENTER(t, Thread::ActiveState); + + ACQUIRE(t, t->vm->referenceLock); + + for (Reference** r = &(t->vm->jniReferences); *r;) { + if (&((*r)->target) == o) { + *r = (*r)->next; + break; + } else { + r = &((*r)->next); + } + } +} + +jthrowable JNICALL +ExceptionOccurred(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, t->exception); +} + +void JNICALL +ExceptionDescribe(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + return printTrace(t, t->exception); +} + +void JNICALL +ExceptionClear(Thread* t) +{ + ENTER(t, Thread::ActiveState); + + t->exception = 0; +} + +jboolean* JNICALL +GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean); + jboolean* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &booleanArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jbyte* JNICALL +GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = byteArrayLength(t, *array) * sizeof(jbyte); + jbyte* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &byteArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jchar* JNICALL +GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = charArrayLength(t, *array) * sizeof(jchar); + jchar* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &charArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jshort* JNICALL +GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = shortArrayLength(t, *array) * sizeof(jshort); + jshort* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &shortArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jint* JNICALL +GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = intArrayLength(t, *array) * sizeof(jint); + jint* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &intArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jlong* JNICALL +GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = longArrayLength(t, *array) * sizeof(jlong); + jlong* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &longArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jfloat* JNICALL +GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = floatArrayLength(t, *array) * sizeof(jfloat); + jfloat* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &floatArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +jdouble* JNICALL +GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy) +{ + ENTER(t, Thread::ActiveState); + + unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble); + jdouble* p = static_cast(t->vm->system->allocate(size)); + if (size) { + memcpy(p, &doubleArrayBody(t, *array, 0), size); + } + + if (isCopy) { + *isCopy = true; + } + + return p; +} + +void JNICALL +ReleaseBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* p, + jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean); + if (size) { + memcpy(&booleanArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = byteArrayLength(t, *array) * sizeof(jbyte); + if (size) { + memcpy(&byteArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = charArrayLength(t, *array) * sizeof(jchar); + if (size) { + memcpy(&charArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseShortArrayElements(Thread* t, jshortArray array, jshort* p, jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = shortArrayLength(t, *array) * sizeof(jshort); + if (size) { + memcpy(&shortArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = intArrayLength(t, *array) * sizeof(jint); + if (size) { + memcpy(&intArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = longArrayLength(t, *array) * sizeof(jlong); + if (size) { + memcpy(&longArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseFloatArrayElements(Thread* t, jfloatArray array, jfloat* p, jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = floatArrayLength(t, *array) * sizeof(jfloat); + if (size) { + memcpy(&floatArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +ReleaseDoubleArrayElements(Thread* t, jdoubleArray array, jdouble* p, + jint mode) +{ + if (mode == 0 or mode == JNI_COMMIT) { + ENTER(t, Thread::ActiveState); + + unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble); + if (size) { + memcpy(&doubleArrayBody(t, *array, 0), p, size); + } + } + + if (mode == 0 or mode == JNI_ABORT) { + t->vm->system->free(p); + } +} + +void JNICALL +GetBooleanArrayRegion(Thread* t, jbooleanArray array, jint offset, jint length, + jboolean* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &booleanArrayBody(t, *array, offset), length); +} + +void JNICALL +GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, + jbyte* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &byteArrayBody(t, *array, offset), length); +} + +void JNICALL +SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, + const jbyte* src) +{ + ENTER(t, Thread::ActiveState); + + memcpy(&byteArrayBody(t, *array, offset), src, length); +} + +void JNICALL +GetCharArrayRegion(Thread* t, jcharArray array, jint offset, jint length, + jchar* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &charArrayBody(t, *array, offset), length); +} + +void JNICALL +GetShortArrayRegion(Thread* t, jshortArray array, jint offset, jint length, + jshort* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &shortArrayBody(t, *array, offset), length); +} + +void JNICALL +GetIntArrayRegion(Thread* t, jintArray array, jint offset, jint length, + jint* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &intArrayBody(t, *array, offset), length); +} + +void JNICALL +GetLongArrayRegion(Thread* t, jlongArray array, jint offset, jint length, + jlong* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &longArrayBody(t, *array, offset), length); +} + +void JNICALL +GetFloatArrayRegion(Thread* t, jfloatArray array, jint offset, jint length, + jfloat* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &floatArrayBody(t, *array, offset), length); +} + +void JNICALL +GetDoubleArrayRegion(Thread* t, jdoubleArray array, jint offset, jint length, + jdouble* dst) +{ + ENTER(t, Thread::ActiveState); + + memcpy(dst, &doubleArrayBody(t, *array, offset), length); +} + +void* JNICALL +GetPrimitiveArrayCritical(Thread* t, jarray array, jboolean* isCopy) +{ + if ((t->criticalLevel ++) == 0) { + enter(t, Thread::ActiveState); + } + + if (isCopy) { + *isCopy = true; + } + + return reinterpret_cast(*array) + 2; +} + +void JNICALL +ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint) +{ + if ((-- t->criticalLevel) == 0) { + enter(t, Thread::IdleState); + } +} + +jint JNICALL +GetJavaVM(Thread* t, JavaVM** vm) +{ +#warning todo +} + +jboolean JNICALL +IsSameObject(Thread* t, jobject a, jobject b) +{ + ENTER(t, Thread::ActiveState); + + return a == b; +} + } // namespace namespace vm { diff --git a/src/machine.cpp b/src/machine.cpp index 57e21ffc14..993e8f88f2 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1273,6 +1273,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder): finder(finder), rootThread(0), exclusive(0), + jniReferences(0), activeCount(0), liveCount(0), stateLock(0), @@ -1286,6 +1287,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder): monitorMap(0), stringMap(0), types(0), + jniInterfaceTable(0), finalizers(0), tenuredFinalizers(0), finalizeQueue(0), @@ -1316,6 +1318,12 @@ Machine::dispose() if (libraries) { libraries->dispose(); } + + for (Reference* r = jniReferences; r;) { + Reference* t = r; + r = r->next; + system->free(t); + } } Thread::Thread(Machine* m, object javaThread, Thread* parent): @@ -1325,6 +1333,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): peer((parent ? parent->child : 0)), child(0), state(NoState), + criticalLevel(0), systemThread(0), javaThread(javaThread), code(0), @@ -1417,6 +1426,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): m->monitorMap = makeWeakHashMap(this, 0, 0); m->stringMap = makeWeakHashMap(this, 0, 0); + m->jniInterfaceTable = makeVector(this, 0, 0, false); + populateBuiltinMap(t, m->builtinMap); t->javaThread = makeThread @@ -2504,6 +2515,11 @@ collect(Thread* t, Heap::CollectionType type) v->visit(&(m->monitorMap)); v->visit(&(m->stringMap)); v->visit(&(m->types)); + v->visit(&(m->jniInterfaceTable)); + + for (Reference* r = m->jniReferences; r; r = r->next) { + v->visit(&(r->target)); + } for (Thread* t = m->rootThread; t; t = t->peer) { ::visitRoots(t, v); diff --git a/src/machine.h b/src/machine.h index 44df9b4abb..d2a0121af6 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1090,6 +1090,17 @@ strcmp(const int8_t* a, const int8_t* b) void noop(); +class Reference { + public: + Reference(object target, Reference* next): + target(target), + next(next) + { } + + object target; + Reference* next; +}; + class Machine { public: enum { @@ -1111,6 +1122,7 @@ class Machine { Finder* finder; Thread* rootThread; Thread* exclusive; + Reference* jniReferences; unsigned activeCount; unsigned liveCount; System::Monitor* stateLock; @@ -1124,6 +1136,7 @@ class Machine { object monitorMap; object stringMap; object types; + object jniInterfaceTable; object finalizers; object tenuredFinalizers; object finalizeQueue; @@ -1221,6 +1234,7 @@ class Thread { Thread* peer; Thread* child; State state; + unsigned criticalLevel; System::Thread* systemThread; object javaThread; object code; diff --git a/src/run.cpp b/src/run.cpp index 8f099d887e..7e75969db6 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -2425,7 +2425,8 @@ run(Thread* t, const char* className, int argc, const char** argv) } void -pushArguments(Thread* t, object this_, const char* spec, va_list a) +pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects, + va_list a) { if (this_) { pushObject(t, this_); @@ -2438,7 +2439,8 @@ pushArguments(Thread* t, object this_, const char* spec, va_list a) case 'L': while (*s and *s != ';') ++ s; ++ s; - pushObject(t, va_arg(a, object)); + pushObject + (t, (indirectObjects ? va_arg(a, object) : *va_arg(a, object*))); break; case '[': @@ -2453,7 +2455,8 @@ pushArguments(Thread* t, object this_, const char* spec, va_list a) ++ s; break; } - pushObject(t, va_arg(a, object)); + pushObject + (t, (indirectObjects ? va_arg(a, object) : *va_arg(a, object*))); break; case 'J': @@ -2637,7 +2640,7 @@ invoke(Thread* t, object method) namespace vm { object -run(Thread* t, object method, object this_, ...) +run(Thread* t, object method, object this_, bool indirectObjects, va_list a) { assert(t, t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); @@ -2651,16 +2654,24 @@ run(Thread* t, object method, object this_, ...) return 0; } + const char* spec = reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), 0)); + pushArguments(t, this_, spec, indirectObjects, a); + + return invoke(t, method); +} + +object +run(Thread* t, object method, object this_, ...) +{ va_list a; va_start(a, this_); - const char* spec = reinterpret_cast - (&byteArrayBody(t, methodSpec(t, method), 0)); - pushArguments(t, this_, spec, a); - + object r = run(t, method, this_, false, a); + va_end(a); - return invoke(t, method); + return r; } object @@ -2702,7 +2713,7 @@ run(Thread* t, const char* className, const char* methodName, va_list a; va_start(a, this_); - pushArguments(t, this_, methodSpec, a); + pushArguments(t, this_, methodSpec, false, a); va_end(a); diff --git a/src/run.h b/src/run.h index 837ec6a7aa..ef2f1b7226 100644 --- a/src/run.h +++ b/src/run.h @@ -8,6 +8,9 @@ namespace vm { +object +run(Thread* t, object method, object this_, bool indirectObjects, va_list a); + object run(Thread* t, object method, object this_, ...);