diff --git a/src/constants.h b/src/constants.h index 7e5896d4e6..ec1c836b89 100644 --- a/src/constants.h +++ b/src/constants.h @@ -252,6 +252,18 @@ const unsigned ACC_STRICT = 1 << 11; const int JNI_COMMIT = 1; const int JNI_ABORT = 2; +const int JNI_OK = 0; +const int JNI_ERR = -1; +const int JNI_EDETACHED = -2; +const int JNI_EVERSION = -3; +const int JNI_ENOMEM = -4; +const int JNI_EEXIST = -5; +const int JNI_EINVAL = -6; + +const int JNI_VERSION_1_1 = 0x00010001; +const int JNI_VERSION_1_2 = 0x00010002; +const int JNI_VERSION_1_4 = 0x00010004; + } // namespace vm #endif//CONSTANTS_H diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 7c7de36d4e..5485cff887 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -9,6 +9,45 @@ namespace { const uintptr_t InterfaceMethodID = (static_cast(1) << (BitsPerWord - 1)); +jint JNICALL +AttachCurrentThread(Machine* m, Thread** t, void*) +{ + *t = static_cast(m->localThread->get()); + if (*t == 0) { + *t = new (m->system->allocate(sizeof(Thread))) Thread(m, 0, m->rootThread); + + m->localThread->set(*t); + } + return 0; +} + +jint JNICALL +DetachCurrentThread(Machine* m) +{ + Thread* t = static_cast(m->localThread->get()); + if (t) { + t->exit(); + return 0; + } else { + return -1; + } +} + +jint JNICALL +GetEnv(Machine* m, Thread** t, jint version) +{ + *t = static_cast(m->localThread->get()); + if (*t) { + if (version <= JNI_VERSION_1_4) { + return JNI_OK; + } else { + return JNI_EVERSION; + } + } else { + return JNI_EDETACHED; + } +} + jsize JNICALL GetStringUTFLength(Thread* t, jstring s) { @@ -981,6 +1020,70 @@ ExceptionClear(Thread* t) t->exception = 0; } +jbooleanArray JNICALL +NewBooleanArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeBooleanArray(t, length, true)); +} + +jbyteArray JNICALL +NewByteArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeByteArray(t, length, true)); +} + +jcharArray JNICALL +NewCharArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeCharArray(t, length, true)); +} + +jshortArray JNICALL +NewShortArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeShortArray(t, length, true)); +} + +jintArray JNICALL +NewIntArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeIntArray(t, length, true)); +} + +jlongArray JNICALL +NewLongArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeLongArray(t, length, true)); +} + +jfloatArray JNICALL +NewFloatArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeFloatArray(t, length, true)); +} + +jdoubleArray JNICALL +NewDoubleArray(Thread* t, jsize length) +{ + ENTER(t, Thread::ActiveState); + + return pushReference(t, makeDoubleArray(t, length, true)); +} + jboolean* JNICALL GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy) { @@ -1367,9 +1470,10 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint) } jint JNICALL -GetJavaVM(Thread* t, JavaVM** vm) +GetJavaVM(Thread* t, Machine** m) { -#warning todo + *m = t->vm; + return 0; } jboolean JNICALL @@ -1377,7 +1481,7 @@ IsSameObject(Thread* t, jobject a, jobject b) { ENTER(t, Thread::ActiveState); - return a == b; + return *a == *b; } } // namespace @@ -1385,60 +1489,149 @@ IsSameObject(Thread* t, jobject a, jobject b) namespace vm { void -populateJNITable(JNIEnvVTable* table) +populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) { - memset(table, 0, sizeof(JNIEnvVTable)); + memset(vmTable, 0, sizeof(JavaVMVTable)); - table->GetStringUTFLength = ::GetStringUTFLength; - table->GetStringUTFChars = ::GetStringUTFChars; - table->ReleaseStringUTFChars = ::ReleaseStringUTFChars; - table->NewStringUTF = ::NewStringUTF; - table->GetByteArrayRegion = ::GetByteArrayRegion; - table->SetByteArrayRegion = ::SetByteArrayRegion; - table->FindClass = ::FindClass; - table->ThrowNew = ::ThrowNew; - table->ExceptionCheck = ::ExceptionCheck; - table->DeleteLocalRef = ::DeleteLocalRef; - table->GetObjectClass = ::GetObjectClass; - table->IsInstanceOf = ::IsInstanceOf; - table->GetFieldID = ::GetFieldID; - table->GetStaticFieldID = ::GetStaticFieldID; - table->GetObjectField = ::GetObjectField; - table->GetBooleanField = ::GetBooleanField; - table->GetByteField = ::GetByteField; - table->GetCharField = ::GetCharField; - table->GetShortField = ::GetShortField; - table->GetIntField = ::GetIntField; - table->GetLongField = ::GetLongField; - table->GetFloatField = ::GetFloatField; - table->GetDoubleField = ::GetDoubleField; - table->SetObjectField = ::SetObjectField; - table->SetBooleanField = ::SetBooleanField; - table->SetByteField = ::SetByteField; - table->SetCharField = ::SetCharField; - table->SetShortField = ::SetShortField; - table->SetIntField = ::SetIntField; - table->SetLongField = ::SetLongField; - table->SetFloatField = ::SetFloatField; - table->SetDoubleField = ::SetDoubleField; - table->GetStaticObjectField = ::GetStaticObjectField; - table->GetStaticBooleanField = ::GetStaticBooleanField; - table->GetStaticByteField = ::GetStaticByteField; - table->GetStaticCharField = ::GetStaticCharField; - table->GetStaticShortField = ::GetStaticShortField; - table->GetStaticIntField = ::GetStaticIntField; - table->GetStaticLongField = ::GetStaticLongField; - table->GetStaticFloatField = ::GetStaticFloatField; - table->GetStaticDoubleField = ::GetStaticDoubleField; - table->SetStaticObjectField = ::SetStaticObjectField; - table->SetStaticBooleanField = ::SetStaticBooleanField; - table->SetStaticByteField = ::SetStaticByteField; - table->SetStaticCharField = ::SetStaticCharField; - table->SetStaticShortField = ::SetStaticShortField; - table->SetStaticIntField = ::SetStaticIntField; - table->SetStaticLongField = ::SetStaticLongField; - table->SetStaticFloatField = ::SetStaticFloatField; - table->SetStaticDoubleField = ::SetStaticDoubleField; + vmTable->AttachCurrentThread = AttachCurrentThread; + vmTable->DetachCurrentThread = DetachCurrentThread; + vmTable->GetEnv = GetEnv; + + memset(envTable, 0, sizeof(JNIEnvVTable)); + + envTable->GetStringUTFLength = ::GetStringUTFLength; + envTable->GetStringUTFChars = ::GetStringUTFChars; + envTable->ReleaseStringUTFChars = ::ReleaseStringUTFChars; + envTable->NewStringUTF = ::NewStringUTF; + envTable->GetByteArrayRegion = ::GetByteArrayRegion; + envTable->SetByteArrayRegion = ::SetByteArrayRegion; + envTable->FindClass = ::FindClass; + envTable->ThrowNew = ::ThrowNew; + envTable->ExceptionCheck = ::ExceptionCheck; + envTable->DeleteLocalRef = ::DeleteLocalRef; + envTable->GetObjectClass = ::GetObjectClass; + envTable->IsInstanceOf = ::IsInstanceOf; + envTable->GetFieldID = ::GetFieldID; + envTable->GetMethodID = ::GetMethodID; + envTable->GetStaticMethodID = ::GetStaticMethodID; + envTable->CallObjectMethodV = ::CallObjectMethodV; + envTable->CallObjectMethod = ::CallObjectMethod; + envTable->CallBooleanMethodV = ::CallBooleanMethodV; + envTable->CallBooleanMethod = ::CallBooleanMethod; + envTable->CallByteMethodV = ::CallByteMethodV; + envTable->CallByteMethod = ::CallByteMethod; + envTable->CallCharMethodV = ::CallCharMethodV; + envTable->CallCharMethod = ::CallCharMethod; + envTable->CallShortMethodV = ::CallShortMethodV; + envTable->CallShortMethod = ::CallShortMethod; + envTable->CallIntMethodV = ::CallIntMethodV; + envTable->CallIntMethod = ::CallIntMethod; + envTable->CallLongMethodV = ::CallLongMethodV; + envTable->CallLongMethod = ::CallLongMethod; + envTable->CallFloatMethodV = ::CallFloatMethodV; + envTable->CallFloatMethod = ::CallFloatMethod; + envTable->CallDoubleMethodV = ::CallDoubleMethodV; + envTable->CallDoubleMethod = ::CallDoubleMethod; + envTable->CallVoidMethodV = ::CallVoidMethodV; + envTable->CallVoidMethod = ::CallVoidMethod; + envTable->CallStaticObjectMethodV = ::CallStaticObjectMethodV; + envTable->CallStaticObjectMethod = ::CallStaticObjectMethod; + envTable->CallStaticBooleanMethodV = ::CallStaticBooleanMethodV; + envTable->CallStaticBooleanMethod = ::CallStaticBooleanMethod; + envTable->CallStaticByteMethodV = ::CallStaticByteMethodV; + envTable->CallStaticByteMethod = ::CallStaticByteMethod; + envTable->CallStaticCharMethodV = ::CallStaticCharMethodV; + envTable->CallStaticCharMethod = ::CallStaticCharMethod; + envTable->CallStaticShortMethodV = ::CallStaticShortMethodV; + envTable->CallStaticShortMethod = ::CallStaticShortMethod; + envTable->CallStaticIntMethodV = ::CallStaticIntMethodV; + envTable->CallStaticIntMethod = ::CallStaticIntMethod; + envTable->CallStaticLongMethodV = ::CallStaticLongMethodV; + envTable->CallStaticLongMethod = ::CallStaticLongMethod; + envTable->CallStaticFloatMethodV = ::CallStaticFloatMethodV; + envTable->CallStaticFloatMethod = ::CallStaticFloatMethod; + envTable->CallStaticDoubleMethodV = ::CallStaticDoubleMethodV; + envTable->CallStaticDoubleMethod = ::CallStaticDoubleMethod; + envTable->CallStaticVoidMethodV = ::CallStaticVoidMethodV; + envTable->CallStaticVoidMethod = ::CallStaticVoidMethod; + envTable->GetStaticFieldID = ::GetStaticFieldID; + envTable->GetObjectField = ::GetObjectField; + envTable->GetBooleanField = ::GetBooleanField; + envTable->GetByteField = ::GetByteField; + envTable->GetCharField = ::GetCharField; + envTable->GetShortField = ::GetShortField; + envTable->GetIntField = ::GetIntField; + envTable->GetLongField = ::GetLongField; + envTable->GetFloatField = ::GetFloatField; + envTable->GetDoubleField = ::GetDoubleField; + envTable->SetObjectField = ::SetObjectField; + envTable->SetBooleanField = ::SetBooleanField; + envTable->SetByteField = ::SetByteField; + envTable->SetCharField = ::SetCharField; + envTable->SetShortField = ::SetShortField; + envTable->SetIntField = ::SetIntField; + envTable->SetLongField = ::SetLongField; + envTable->SetFloatField = ::SetFloatField; + envTable->SetDoubleField = ::SetDoubleField; + envTable->GetStaticObjectField = ::GetStaticObjectField; + envTable->GetStaticBooleanField = ::GetStaticBooleanField; + envTable->GetStaticByteField = ::GetStaticByteField; + envTable->GetStaticCharField = ::GetStaticCharField; + envTable->GetStaticShortField = ::GetStaticShortField; + envTable->GetStaticIntField = ::GetStaticIntField; + envTable->GetStaticLongField = ::GetStaticLongField; + envTable->GetStaticFloatField = ::GetStaticFloatField; + envTable->GetStaticDoubleField = ::GetStaticDoubleField; + envTable->SetStaticObjectField = ::SetStaticObjectField; + envTable->SetStaticBooleanField = ::SetStaticBooleanField; + envTable->SetStaticByteField = ::SetStaticByteField; + envTable->SetStaticCharField = ::SetStaticCharField; + envTable->SetStaticShortField = ::SetStaticShortField; + envTable->SetStaticIntField = ::SetStaticIntField; + envTable->SetStaticLongField = ::SetStaticLongField; + envTable->SetStaticFloatField = ::SetStaticFloatField; + envTable->SetStaticDoubleField = ::SetStaticDoubleField; + envTable->NewGlobalRef = ::NewGlobalRef; + envTable->DeleteGlobalRef = ::DeleteGlobalRef; + envTable->ExceptionOccurred = ::ExceptionOccurred; + envTable->ExceptionDescribe = ::ExceptionDescribe; + envTable->ExceptionClear = ::ExceptionClear; + envTable->NewBooleanArray = ::NewBooleanArray; + envTable->NewByteArray = ::NewByteArray; + envTable->NewCharArray = ::NewCharArray; + envTable->NewShortArray = ::NewShortArray; + envTable->NewIntArray = ::NewIntArray; + envTable->NewLongArray = ::NewLongArray; + envTable->NewFloatArray = ::NewFloatArray; + envTable->NewDoubleArray = ::NewDoubleArray; + envTable->GetBooleanArrayElements = ::GetBooleanArrayElements; + envTable->GetByteArrayElements = ::GetByteArrayElements; + envTable->GetCharArrayElements = ::GetCharArrayElements; + envTable->GetShortArrayElements = ::GetShortArrayElements; + envTable->GetIntArrayElements = ::GetIntArrayElements; + envTable->GetLongArrayElements = ::GetLongArrayElements; + envTable->GetFloatArrayElements = ::GetFloatArrayElements; + envTable->GetDoubleArrayElements = ::GetDoubleArrayElements; + envTable->ReleaseBooleanArrayElements = ::ReleaseBooleanArrayElements; + envTable->ReleaseByteArrayElements = ::ReleaseByteArrayElements; + envTable->ReleaseCharArrayElements = ::ReleaseCharArrayElements; + envTable->ReleaseShortArrayElements = ::ReleaseShortArrayElements; + envTable->ReleaseIntArrayElements = ::ReleaseIntArrayElements; + envTable->ReleaseLongArrayElements = ::ReleaseLongArrayElements; + envTable->ReleaseFloatArrayElements = ::ReleaseFloatArrayElements; + envTable->ReleaseDoubleArrayElements = ::ReleaseDoubleArrayElements; + envTable->GetBooleanArrayRegion = ::GetBooleanArrayRegion; + envTable->GetByteArrayRegion = ::GetByteArrayRegion; + envTable->GetCharArrayRegion = ::GetCharArrayRegion; + envTable->GetShortArrayRegion = ::GetShortArrayRegion; + envTable->GetIntArrayRegion = ::GetIntArrayRegion; + envTable->GetLongArrayRegion = ::GetLongArrayRegion; + envTable->GetFloatArrayRegion = ::GetFloatArrayRegion; + envTable->GetDoubleArrayRegion = ::GetDoubleArrayRegion; + envTable->GetPrimitiveArrayCritical = ::GetPrimitiveArrayCritical; + envTable->ReleasePrimitiveArrayCritical = ::ReleasePrimitiveArrayCritical; + envTable->GetJavaVM = ::GetJavaVM; + envTable->IsSameObject = ::IsSameObject; } } // namespace vm diff --git a/src/jnienv.h b/src/jnienv.h index 98b6b461fb..eef7c32ff8 100644 --- a/src/jnienv.h +++ b/src/jnienv.h @@ -6,7 +6,7 @@ namespace vm { void -populateJNITable(JNIEnvVTable* table); +populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable); } // namespace vm diff --git a/src/machine.cpp b/src/machine.cpp index 993e8f88f2..44bf11d36f 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1268,6 +1268,7 @@ removeString(Thread* t, object o) namespace vm { Machine::Machine(System* system, Heap* heap, Finder* finder): + vtable(&javaVMVTable), system(system), heap(heap), finder(finder), @@ -1276,6 +1277,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder): jniReferences(0), activeCount(0), liveCount(0), + localThread(0), stateLock(0), heapLock(0), classLock(0), @@ -1296,9 +1298,10 @@ Machine::Machine(System* system, Heap* heap, Finder* finder): unsafe(false), heapPoolIndex(0) { - populateJNITable(&jniEnvVTable); + populateJNITables(&javaVMVTable, &jniEnvVTable); - if (not system->success(system->make(&stateLock)) or + if (not system->success(system->make(&localThread)) or + not system->success(system->make(&stateLock)) or not system->success(system->make(&heapLock)) or not system->success(system->make(&classLock)) or not system->success(system->make(&referenceLock))) @@ -1310,6 +1313,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder): void Machine::dispose() { + localThread->dispose(); stateLock->dispose(); heapLock->dispose(); classLock->dispose(); @@ -1430,12 +1434,17 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): populateBuiltinMap(t, m->builtinMap); - t->javaThread = makeThread - (t, reinterpret_cast(t), 0, 0, 0, 0, t->vm->loader); + m->localThread->set(this); } else { - threadPeer(this, javaThread) = reinterpret_cast(this); parent->child = this; } + + if (javaThread) { + threadPeer(this, javaThread) = reinterpret_cast(this); + } else { + this->javaThread = makeThread + (this, reinterpret_cast(this), 0, 0, 0, 0, m->loader); + } } void diff --git a/src/machine.h b/src/machine.h index d2a0121af6..4e5e01797f 100644 --- a/src/machine.h +++ b/src/machine.h @@ -65,12 +65,14 @@ const unsigned PrimitiveFlag = 1 << 4; // method flags: const unsigned ClassInitFlag = 1 << 0; +class Machine; class Thread; struct Object { }; typedef Object* object; +typedef Machine JavaVM; typedef Thread JNIEnv; typedef uint8_t jboolean; @@ -123,14 +125,6 @@ struct JNINativeMethod { void* function; }; -struct JavaVMVTable; - -struct JavaVM { - JavaVM(JavaVMVTable* vtable): vtable(vtable) { } - - JavaVMVTable* vtable; -}; - struct JavaVMVTable { void* reserved0; void* reserved1; @@ -142,7 +136,7 @@ struct JavaVMVTable { jint (JNICALL *AttachCurrentThread) - (JavaVM*, void**, void*); + (JavaVM*, JNIEnv**, void*); jint (JNICALL *DetachCurrentThread) @@ -150,11 +144,11 @@ struct JavaVMVTable { jint (JNICALL *GetEnv) - (JavaVM*, void**, jint); + (JavaVM*, JNIEnv**, jint); jint (JNICALL *AttachCurrentThreadAsDaemon) - (JavaVM*, void**, void*); + (JavaVM*, JNIEnv**, void*); }; struct JNIEnvVTable { @@ -1117,6 +1111,7 @@ class Machine { void dispose(); + JavaVMVTable* vtable; System* system; Heap* heap; Finder* finder; @@ -1125,6 +1120,7 @@ class Machine { Reference* jniReferences; unsigned activeCount; unsigned liveCount; + System::Local* localThread; System::Monitor* stateLock; System::Monitor* heapLock; System::Monitor* classLock; @@ -1143,6 +1139,7 @@ class Machine { object weakReferences; object tenuredWeakReferences; bool unsafe; + JavaVMVTable javaVMVTable; JNIEnvVTable jniEnvVTable; uintptr_t* heapPool[HeapPoolSize]; unsigned heapPoolIndex; @@ -1197,6 +1194,8 @@ class Thread { } virtual void run() { + t->vm->localThread->set(t); + vm::run(t, "java/lang/Thread", "run", "()V", t->javaThread); if (t->exception) { diff --git a/src/system.cpp b/src/system.cpp index a966ae6cd2..e4dc124907 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -349,6 +349,33 @@ class MySystem: public System { unsigned depth; }; + class Local: public System::Local { + public: + Local(System* s): s(s) { + int r = pthread_key_create(&key, 0); + assert(s, r); + } + + virtual void* get() { + return pthread_getspecific(key); + } + + virtual void set(void* p) { + int r = pthread_setspecific(key, p); + assert(s, r); + } + + virtual void dispose() { + int r = pthread_key_delete(key); + assert(s, r); + + s->free(this); + } + + System* s; + pthread_key_t key; + }; + class Library: public System::Library { public: Library(System* s, void* p, const char* name, System::Library* next): @@ -475,6 +502,11 @@ class MySystem: public System { return 0; } + virtual Status make(System::Local** l) { + *l = new (System::allocate(sizeof(Local))) Local(this); + return 0; + } + virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) { diff --git a/src/system.h b/src/system.h index 29b07712fb..f449538697 100644 --- a/src/system.h +++ b/src/system.h @@ -47,6 +47,14 @@ class System: public Allocator { virtual void dispose() = 0; }; + class Local { + public: + virtual ~Local() { } + virtual void* get() = 0; + virtual void set(void* p) = 0; + virtual void dispose() = 0; + }; + class Library { public: virtual ~Library() { } @@ -62,6 +70,7 @@ class System: public Allocator { virtual Status attach(Runnable*) = 0; virtual Status start(Runnable*) = 0; virtual Status make(Monitor**) = 0; + virtual Status make(Local**) = 0; virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, unsigned count, unsigned size, unsigned returnType) = 0;