#ifndef MACHINE_H #define MACHINE_H #include "common.h" #include "system.h" #include "heap.h" #include "class-finder.h" #define JNIEXPORT __attribute__ ((visibility("default"))) #define JNIIMPORT __attribute__ ((visibility("hidden"))) #define JNICALL #define PROTECT(thread, name) \ Thread::Protector MAKE_NAME(protector_) (thread, &name); #define ACQUIRE(t, x) MonitorResource MAKE_NAME(monitorResource_) (t, x) #define ACQUIRE_RAW(t, x) RawMonitorResource MAKE_NAME(monitorResource_) (t, x) #define ENTER(t, state) StateResource MAKE_NAME(stateResource_) (t, state) namespace vm { const bool Verbose = false; const bool Debug = false; const bool DebugRun = true; const bool DebugStack = true; const uintptr_t HashTakenMark = 1; const uintptr_t ExtendedMark = 2; const unsigned FrameBaseOffset = 0; const unsigned FrameNextOffset = 1; const unsigned FrameMethodOffset = 2; const unsigned FrameIpOffset = 3; const unsigned FrameFootprint = 4; enum FieldCode { VoidField, ByteField, CharField, DoubleField, FloatField, IntField, LongField, ShortField, BooleanField, ObjectField }; enum StackTag { IntTag, // must be zero ObjectTag }; const int NativeLine = -1; const int UnknownLine = -2; const unsigned WeakReferenceFlag = 1 << 0; class Thread; typedef Thread JNIEnv; typedef uint8_t jboolean; typedef int8_t jbyte; typedef uint16_t jchar; typedef int16_t jshort; typedef int32_t jint; typedef int64_t jlong; typedef float jfloat; typedef double jdouble; typedef jint jsize; typedef void** jobject; typedef jobject jclass; typedef jobject jthrowable; typedef jobject jstring; typedef jobject jweak; typedef jobject jarray; typedef jarray jbooleanArray; typedef jarray jbyteArray; typedef jarray jcharArray; typedef jarray jshortArray; typedef jarray jintArray; typedef jarray jlongArray; typedef jarray jfloatArray; typedef jarray jdoubleArray; typedef jarray jobjectArray; typedef void** jfieldID; typedef void** jmethodID; union jvalue { jboolean z; jbyte b; jchar c; jshort s; jint i; jlong j; jfloat f; jdouble d; jobject l; }; struct JNINativeMethod { char* name; char* signature; void* function; }; struct JavaVMVTable; struct JavaVM { JavaVM(JavaVMVTable* vtable): vtable(vtable) { } JavaVMVTable* vtable; }; struct JavaVMVTable { void* reserved0; void* reserved1; void* reserved2; jint (JNICALL *DestroyJavaVM) (JavaVM*); jint (JNICALL *AttachCurrentThread) (JavaVM*, void**, void*); jint (JNICALL *DetachCurrentThread) (JavaVM*); jint (JNICALL *GetEnv) (JavaVM*, void**, jint); jint (JNICALL *AttachCurrentThreadAsDaemon) (JavaVM*, void**, void*); }; struct JNIEnvVTable { void* reserved0; void* reserved1; void* reserved2; void* reserved3; jint (JNICALL *GetVersion) (JNIEnv*); jclass (JNICALL *DefineClass) (JNIEnv*, const char*, jobject, const jbyte*, jsize); jclass (JNICALL *FindClass) (JNIEnv*, const char*); jmethodID (JNICALL *FromReflectedMethod) (JNIEnv*, jobject); jfieldID (JNICALL *FromReflectedField) (JNIEnv*, jobject); jobject (JNICALL *ToReflectedMethod) (JNIEnv*, jclass, jmethodID, jboolean); jclass (JNICALL *GetSuperclass) (JNIEnv*, jclass); jboolean (JNICALL *IsAssignableFrom) (JNIEnv*, jclass, jclass); jobject (JNICALL *ToReflectedField) (JNIEnv*, jclass, jfieldID, jboolean); jint (JNICALL *Throw) (JNIEnv*, jthrowable); jint (JNICALL *ThrowNew) (JNIEnv*, jclass, const char*); jthrowable (JNICALL *ExceptionOccurred) (JNIEnv*); void (JNICALL *ExceptionDescribe) (JNIEnv*); void (JNICALL *ExceptionClear) (JNIEnv*); void (JNICALL *FatalError) (JNIEnv*, const char*); jint (JNICALL *PushLocalFrame) (JNIEnv*, jint); jobject (JNICALL *PopLocalFrame) (JNIEnv*, jobject); jobject (JNICALL *NewGlobalRef) (JNIEnv*, jobject); void (JNICALL *DeleteGlobalRef) (JNIEnv*, jobject); void (JNICALL *DeleteLocalRef) (JNIEnv*, jobject); jboolean (JNICALL *IsSameObject) (JNIEnv*, jobject, jobject); jobject (JNICALL *NewLocalRef) (JNIEnv*, jobject); jint (JNICALL *EnsureLocalCapacity) (JNIEnv*, jint); jobject (JNICALL *AllocObject) (JNIEnv*, jclass); jobject (JNICALL *NewObject) (JNIEnv*, jclass, jmethodID, ...); jobject (JNICALL *NewObjectV) (JNIEnv*, jclass, jmethodID, va_list); jobject (JNICALL *NewObjectA) (JNIEnv*, jclass, jmethodID, const jvalue*); jclass (JNICALL *GetObjectClass) (JNIEnv*, jobject); jboolean (JNICALL *IsInstanceOf) (JNIEnv*, jobject, jclass); jmethodID (JNICALL *GetMethodID) (JNIEnv*, jclass, const char*, const char*); jobject (JNICALL *CallObjectMethod) (JNIEnv*, jobject, jmethodID, ...); jobject (JNICALL *CallObjectMethodV) (JNIEnv*, jobject, jmethodID, va_list); jobject (JNICALL *CallObjectMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jboolean (JNICALL *CallBooleanMethod) (JNIEnv*, jobject, jmethodID, ...); jboolean (JNICALL *CallBooleanMethodV) (JNIEnv*, jobject, jmethodID, va_list); jboolean (JNICALL *CallBooleanMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jbyte (JNICALL *CallByteMethod) (JNIEnv*, jobject, jmethodID, ...); jbyte (JNICALL *CallByteMethodV) (JNIEnv*, jobject, jmethodID, va_list); jbyte (JNICALL *CallByteMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jchar (JNICALL *CallCharMethod) (JNIEnv*, jobject, jmethodID, ...); jchar (JNICALL *CallCharMethodV) (JNIEnv*, jobject, jmethodID, va_list); jchar (JNICALL *CallCharMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jshort (JNICALL *CallShortMethod) (JNIEnv*, jobject, jmethodID, ...); jshort (JNICALL *CallShortMethodV) (JNIEnv*, jobject, jmethodID, va_list); jshort (JNICALL *CallShortMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jint (JNICALL *CallIntMethod) (JNIEnv*, jobject, jmethodID, ...); jint (JNICALL *CallIntMethodV) (JNIEnv*, jobject, jmethodID, va_list); jint (JNICALL *CallIntMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jlong (JNICALL *CallLongMethod) (JNIEnv*, jobject, jmethodID, ...); jlong (JNICALL *CallLongMethodV) (JNIEnv*, jobject, jmethodID, va_list); jlong (JNICALL *CallLongMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jfloat (JNICALL *CallFloatMethod) (JNIEnv*, jobject, jmethodID, ...); jfloat (JNICALL *CallFloatMethodV) (JNIEnv*, jobject, jmethodID, va_list); jfloat (JNICALL *CallFloatMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jdouble (JNICALL *CallDoubleMethod) (JNIEnv*, jobject, jmethodID, ...); jdouble (JNICALL *CallDoubleMethodV) (JNIEnv*, jobject, jmethodID, va_list); jdouble (JNICALL *CallDoubleMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); void (JNICALL *CallVoidMethod) (JNIEnv*, jobject, jmethodID, ...); void (JNICALL *CallVoidMethodV) (JNIEnv*, jobject, jmethodID, va_list); void (JNICALL *CallVoidMethodA) (JNIEnv*, jobject, jmethodID, const jvalue*); jobject (JNICALL *CallNonvirtualObjectMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jobject (JNICALL *CallNonvirtualObjectMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jobject (JNICALL *CallNonvirtualObjectMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jboolean (JNICALL *CallNonvirtualBooleanMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jboolean (JNICALL *CallNonvirtualBooleanMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jboolean (JNICALL *CallNonvirtualBooleanMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jbyte (JNICALL *CallNonvirtualByteMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jbyte (JNICALL *CallNonvirtualByteMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jbyte (JNICALL *CallNonvirtualByteMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jchar (JNICALL *CallNonvirtualCharMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jchar (JNICALL *CallNonvirtualCharMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jchar (JNICALL *CallNonvirtualCharMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jshort (JNICALL *CallNonvirtualShortMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jshort (JNICALL *CallNonvirtualShortMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jshort (JNICALL *CallNonvirtualShortMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jint (JNICALL *CallNonvirtualIntMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jint (JNICALL *CallNonvirtualIntMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jint (JNICALL *CallNonvirtualIntMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jlong (JNICALL *CallNonvirtualLongMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jlong (JNICALL *CallNonvirtualLongMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jlong (JNICALL *CallNonvirtualLongMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jfloat (JNICALL *CallNonvirtualFloatMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jfloat (JNICALL *CallNonvirtualFloatMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jfloat (JNICALL *CallNonvirtualFloatMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jdouble (JNICALL *CallNonvirtualDoubleMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); jdouble (JNICALL *CallNonvirtualDoubleMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); jdouble (JNICALL *CallNonvirtualDoubleMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); void (JNICALL *CallNonvirtualVoidMethod) (JNIEnv*, jobject, jclass, jmethodID, ...); void (JNICALL *CallNonvirtualVoidMethodV) (JNIEnv*, jobject, jclass, jmethodID, va_list); void (JNICALL *CallNonvirtualVoidMethodA) (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); jfieldID (JNICALL *GetFieldID) (JNIEnv*, jclass, const char*, const char*); jobject (JNICALL *GetObjectField) (JNIEnv*, jobject, jfieldID); jboolean (JNICALL *GetBooleanField) (JNIEnv*, jobject, jfieldID); jbyte (JNICALL *GetByteField) (JNIEnv*, jobject, jfieldID); jchar (JNICALL *GetCharField) (JNIEnv*, jobject, jfieldID); jshort (JNICALL *GetShortField) (JNIEnv*, jobject, jfieldID); jint (JNICALL *GetIntField) (JNIEnv*, jobject, jfieldID); jlong (JNICALL *GetLongField) (JNIEnv*, jobject, jfieldID); jfloat (JNICALL *GetFloatField) (JNIEnv*, jobject, jfieldID); jdouble (JNICALL *GetDoubleField) (JNIEnv*, jobject, jfieldID); void (JNICALL *SetObjectField) (JNIEnv*, jobject, jfieldID, jobject); void (JNICALL *SetBooleanField) (JNIEnv*, jobject, jfieldID, jboolean); void (JNICALL *SetByteField) (JNIEnv*, jobject, jfieldID, jbyte); void (JNICALL *SetCharField) (JNIEnv*, jobject, jfieldID, jchar); void (JNICALL *SetShortField) (JNIEnv*, jobject, jfieldID, jshort); void (JNICALL *SetIntField) (JNIEnv*, jobject, jfieldID, jint); void (JNICALL *SetLongField) (JNIEnv*, jobject, jfieldID, jlong); void (JNICALL *SetFloatField) (JNIEnv*, jobject, jfieldID, jfloat); void (JNICALL *SetDoubleField) (JNIEnv*, jobject, jfieldID, jdouble); jmethodID (JNICALL *GetStaticMethodID) (JNIEnv*, jclass, const char*, const char*); jobject (JNICALL *CallStaticObjectMethod) (JNIEnv*, jclass, jmethodID, ...); jobject (JNICALL *CallStaticObjectMethodV) (JNIEnv*, jclass, jmethodID, va_list); jobject (JNICALL *CallStaticObjectMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jboolean (JNICALL *CallStaticBooleanMethod) (JNIEnv*, jclass, jmethodID, ...); jboolean (JNICALL *CallStaticBooleanMethodV) (JNIEnv*, jclass, jmethodID, va_list); jboolean (JNICALL *CallStaticBooleanMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jbyte (JNICALL *CallStaticByteMethod) (JNIEnv*, jclass, jmethodID, ...); jbyte (JNICALL *CallStaticByteMethodV) (JNIEnv*, jclass, jmethodID, va_list); jbyte (JNICALL *CallStaticByteMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jchar (JNICALL *CallStaticCharMethod) (JNIEnv*, jclass, jmethodID, ...); jchar (JNICALL *CallStaticCharMethodV) (JNIEnv*, jclass, jmethodID, va_list); jchar (JNICALL *CallStaticCharMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jshort (JNICALL *CallStaticShortMethod) (JNIEnv*, jclass, jmethodID, ...); jshort (JNICALL *CallStaticShortMethodV) (JNIEnv*, jclass, jmethodID, va_list); jshort (JNICALL *CallStaticShortMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jint (JNICALL *CallStaticIntMethod) (JNIEnv*, jclass, jmethodID, ...); jint (JNICALL *CallStaticIntMethodV) (JNIEnv*, jclass, jmethodID, va_list); jint (JNICALL *CallStaticIntMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jlong (JNICALL *CallStaticLongMethod) (JNIEnv*, jclass, jmethodID, ...); jlong (JNICALL *CallStaticLongMethodV) (JNIEnv*, jclass, jmethodID, va_list); jlong (JNICALL *CallStaticLongMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jfloat (JNICALL *CallStaticFloatMethod) (JNIEnv*, jclass, jmethodID, ...); jfloat (JNICALL *CallStaticFloatMethodV) (JNIEnv*, jclass, jmethodID, va_list); jfloat (JNICALL *CallStaticFloatMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jdouble (JNICALL *CallStaticDoubleMethod) (JNIEnv*, jclass, jmethodID, ...); jdouble (JNICALL *CallStaticDoubleMethodV) (JNIEnv*, jclass, jmethodID, va_list); jdouble (JNICALL *CallStaticDoubleMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); void (JNICALL *CallStaticVoidMethod) (JNIEnv*, jclass, jmethodID, ...); void (JNICALL *CallStaticVoidMethodV) (JNIEnv*, jclass, jmethodID, va_list); void (JNICALL *CallStaticVoidMethodA) (JNIEnv*, jclass, jmethodID, const jvalue*); jfieldID (JNICALL *GetStaticFieldID) (JNIEnv*, jclass, const char*, const char*); jobject (JNICALL *GetStaticObjectField) (JNIEnv*, jclass, jfieldID); jboolean (JNICALL *GetStaticBooleanField) (JNIEnv*, jclass, jfieldID); jbyte (JNICALL *GetStaticByteField) (JNIEnv*, jclass, jfieldID); jchar (JNICALL *GetStaticCharField) (JNIEnv*, jclass, jfieldID); jshort (JNICALL *GetStaticShortField) (JNIEnv*, jclass, jfieldID); jint (JNICALL *GetStaticIntField) (JNIEnv*, jclass, jfieldID); jlong (JNICALL *GetStaticLongField) (JNIEnv*, jclass, jfieldID); jfloat (JNICALL *GetStaticFloatField) (JNIEnv*, jclass, jfieldID); jdouble (JNICALL *GetStaticDoubleField) (JNIEnv*, jclass, jfieldID); void (JNICALL *SetStaticObjectField) (JNIEnv*, jclass, jfieldID, jobject); void (JNICALL *SetStaticBooleanField) (JNIEnv*, jclass, jfieldID, jboolean); void (JNICALL *SetStaticByteField) (JNIEnv*, jclass, jfieldID, jbyte); void (JNICALL *SetStaticCharField) (JNIEnv*, jclass, jfieldID, jchar); void (JNICALL *SetStaticShortField) (JNIEnv*, jclass, jfieldID, jshort); void (JNICALL *SetStaticIntField) (JNIEnv*, jclass, jfieldID, jint); void (JNICALL *SetStaticLongField) (JNIEnv*, jclass, jfieldID, jlong); void (JNICALL *SetStaticFloatField) (JNIEnv*, jclass, jfieldID, jfloat); void (JNICALL *SetStaticDoubleField) (JNIEnv*, jclass, jfieldID, jdouble); jstring (JNICALL *NewString) (JNIEnv*, const jchar*, jsize); jsize (JNICALL *GetStringLength) (JNIEnv*, jstring); const jchar* (JNICALL *GetStringChars) (JNIEnv*, jstring, jboolean*); void (JNICALL *ReleaseStringChars) (JNIEnv*, jstring, const jchar*); jstring (JNICALL *NewStringUTF) (JNIEnv*, const char*); jsize (JNICALL *GetStringUTFLength) (JNIEnv*, jstring); const char* (JNICALL *GetStringUTFChars) (JNIEnv*, jstring, jboolean*); void (JNICALL *ReleaseStringUTFChars) (JNIEnv*, jstring, const char*); jsize (JNICALL *GetArrayLength) (JNIEnv*, jarray); jobjectArray (JNICALL *NewObjectArray) (JNIEnv*, jsize, jclass, jobject); jobject (JNICALL *GetObjectArrayElement) (JNIEnv*, jobjectArray, jsize); void (JNICALL *SetObjectArrayElement) (JNIEnv*, jobjectArray, jsize, jobject); jbooleanArray (JNICALL *NewBooleanArray) (JNIEnv*, jsize); jbyteArray (JNICALL *NewByteArray) (JNIEnv*, jsize); jcharArray (JNICALL *NewCharArray) (JNIEnv*, jsize); jshortArray (JNICALL *NewShortArray) (JNIEnv*, jsize); jintArray (JNICALL *NewIntArray) (JNIEnv*, jsize); jlongArray (JNICALL *NewLongArray) (JNIEnv*, jsize); jfloatArray (JNICALL *NewFloatArray) (JNIEnv*, jsize); jdoubleArray (JNICALL *NewDoubleArray) (JNIEnv*, jsize); jboolean* (JNICALL *GetBooleanArrayElements) (JNIEnv*, jbooleanArray, jboolean*); jbyte* (JNICALL *GetByteArrayElements) (JNIEnv*, jbyteArray, jboolean*); jchar* (JNICALL *GetCharArrayElements) (JNIEnv*, jcharArray, jboolean*); jshort* (JNICALL *GetShortArrayElements) (JNIEnv*, jshortArray, jboolean*); jint* (JNICALL *GetIntArrayElements) (JNIEnv*, jintArray, jboolean*); jlong* (JNICALL *GetLongArrayElements) (JNIEnv*, jlongArray, jboolean*); jfloat* (JNICALL *GetFloatArrayElements) (JNIEnv*, jfloatArray, jboolean*); jdouble* (JNICALL *GetDoubleArrayElements) (JNIEnv*, jdoubleArray, jboolean*); void (JNICALL *ReleaseBooleanArrayElements) (JNIEnv*, jbooleanArray, jboolean*, jint); void (JNICALL *ReleaseByteArrayElements) (JNIEnv*, jbyteArray, jbyte*, jint); void (JNICALL *ReleaseCharArrayElements) (JNIEnv*, jcharArray, jchar*, jint); void (JNICALL *ReleaseShortArrayElements) (JNIEnv*, jshortArray, jshort*, jint); void (JNICALL *ReleaseIntArrayElements) (JNIEnv*, jintArray, jint*, jint); void (JNICALL *ReleaseLongArrayElements) (JNIEnv*, jlongArray, jlong*, jint); void (JNICALL *ReleaseFloatArrayElements) (JNIEnv*, jfloatArray, jfloat*, jint); void (JNICALL *ReleaseDoubleArrayElements) (JNIEnv*, jdoubleArray, jdouble*, jint); void (JNICALL *GetBooleanArrayRegion) (JNIEnv*, jbooleanArray, jsize, jsize, jboolean*); void (JNICALL *GetByteArrayRegion) (JNIEnv*, jbyteArray, jsize, jsize, jbyte*); void (JNICALL *GetCharArrayRegion) (JNIEnv*, jcharArray, jsize, jsize, jchar*); void (JNICALL *GetShortArrayRegion) (JNIEnv*, jshortArray, jsize, jsize, jshort*); void (JNICALL *GetIntArrayRegion) (JNIEnv*, jintArray, jsize, jsize, jint*); void (JNICALL *GetLongArrayRegion) (JNIEnv*, jlongArray, jsize, jsize, jlong*); void (JNICALL *GetFloatArrayRegion) (JNIEnv*, jfloatArray, jsize, jsize, jfloat*); void (JNICALL *GetDoubleArrayRegion) (JNIEnv*, jdoubleArray, jsize, jsize, jdouble*); void (JNICALL *SetBooleanArrayRegion) (JNIEnv*, jbooleanArray, jsize, jsize, const jboolean*); void (JNICALL *SetByteArrayRegion) (JNIEnv*, jbyteArray, jsize, jsize, const jbyte*); void (JNICALL *SetCharArrayRegion) (JNIEnv*, jcharArray, jsize, jsize, const jchar*); void (JNICALL *SetShortArrayRegion) (JNIEnv*, jshortArray, jsize, jsize, const jshort*); void (JNICALL *SetIntArrayRegion) (JNIEnv*, jintArray, jsize, jsize, const jint*); void (JNICALL *SetLongArrayRegion) (JNIEnv*, jlongArray, jsize, jsize, const jlong*); void (JNICALL *SetFloatArrayRegion) (JNIEnv*, jfloatArray, jsize, jsize, const jfloat*); void (JNICALL *SetDoubleArrayRegion) (JNIEnv*, jdoubleArray, jsize, jsize, const jdouble*); jint (JNICALL *RegisterNatives) (JNIEnv*, jclass, const JNINativeMethod*, jint); jint (JNICALL *UnregisterNatives) (JNIEnv*, jclass); jint (JNICALL *MonitorEnter) (JNIEnv*, jobject); jint (JNICALL *MonitorExit) (JNIEnv*, jobject); jint (JNICALL *GetJavaVM) (JNIEnv*, JavaVM**); void (JNICALL *GetStringRegion) (JNIEnv*, jstring, jsize, jsize, jchar*); void (JNICALL *GetStringUTFRegion) (JNIEnv*, jstring, jsize, jsize, char*); void* (JNICALL *GetPrimitiveArrayCritical) (JNIEnv*, jarray, jboolean*); void (JNICALL *ReleasePrimitiveArrayCritical) (JNIEnv*, jarray, void*, jint); const jchar* (JNICALL *GetStringCritical) (JNIEnv*, jstring, jboolean*); void (JNICALL *ReleaseStringCritical) (JNIEnv*, jstring, const jchar*); jweak (JNICALL *NewWeakGlobalRef) (JNIEnv*, jobject); void (JNICALL *DeleteWeakGlobalRef) (JNIEnv*, jweak); jboolean (JNICALL *ExceptionCheck) (JNIEnv*); jobject (JNICALL *NewDirectByteBuffer) (JNIEnv*, void*, jlong); void* (JNICALL *GetDirectBufferAddress) (JNIEnv* env, jobject); jlong (JNICALL *GetDirectBufferCapacity) (JNIEnv*, jobject); }; inline int strcmp(const int8_t* a, const int8_t* b) { return ::strcmp(reinterpret_cast(a), reinterpret_cast(b)); } void noop(); class Machine { public: enum { #include "type-enums.cpp" } Type; Machine(System* system, Heap* heap, ClassFinder* classFinder); ~Machine() { dispose(); } void dispose(); System* system; Heap* heap; ClassFinder* classFinder; Thread* rootThread; Thread* exclusive; unsigned activeCount; unsigned liveCount; System::Monitor* stateLock; System::Monitor* heapLock; System::Monitor* classLock; System::Monitor* finalizerLock; System::Library* libraries; object classMap; object bootstrapClassMap; object builtinMap; object monitorMap; object types; object finalizers; object tenuredFinalizers; object finalizeQueue; object weakReferences; object tenuredWeakReferences; bool unsafe; JNIEnvVTable jniEnvVTable; }; class Thread { public: enum State { NoState, ActiveState, IdleState, ZombieState, ExclusiveState, ExitState }; class Protector { public: Protector(Thread* t, object* p): t(t), p(p), next(t->protector) { t->protector = this; } ~Protector() { t->protector = next; } Thread* t; object* p; Protector* next; }; static const unsigned HeapSizeInBytes = 64 * 1024; static const unsigned StackSizeInBytes = 64 * 1024; static const unsigned HeapSizeInWords = HeapSizeInBytes / BytesPerWord; static const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord; Thread(Machine* m, Allocator* allocator, object javaThread, Thread* parent); ~Thread() { exit(); } void exit(); void dispose(); JNIEnvVTable* vtable; Machine* vm; Allocator* allocator; Thread* parent; Thread* peer; Thread* child; State state; System::Thread* systemThread; object javaThread; object code; object exception; object large; unsigned ip; unsigned sp; int frame; unsigned heapIndex; Protector* protector; uintptr_t stack[StackSizeInWords]; object heap[HeapSizeInWords]; }; inline object objectClass(Thread*, object o) { return mask(cast(o, 0)); } void enter(Thread* t, Thread::State state); class StateResource { public: StateResource(Thread* t, Thread::State state): t(t), oldState(t->state) { enter(t, state); } ~StateResource() { enter(t, oldState); } private: Thread* t; Thread::State oldState; }; class MonitorResource { public: MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { if (not m->tryAcquire(t)) { ENTER(t, Thread::IdleState); m->acquire(t); } } ~MonitorResource() { m->release(t); } private: Thread* t; System::Monitor* m; }; class RawMonitorResource { public: RawMonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { m->acquire(t); } ~RawMonitorResource() { m->release(t); } private: Thread* t; System::Monitor* m; }; inline void NO_RETURN abort(Thread* t) { abort(t->vm->system); } inline void assert(Thread* t, bool v) { assert(t->vm->system, v); } inline void expect(Thread* t, bool v) { expect(t->vm->system, v); } inline object allocateLarge(Thread* t, unsigned sizeInBytes) { return t->large = t->vm->system->allocate(sizeInBytes); } inline object allocateSmall(Thread* t, unsigned sizeInBytes) { object o = t->heap + t->heapIndex; t->heapIndex += divide(sizeInBytes, BytesPerWord); return o; } object allocate2(Thread* t, unsigned sizeInBytes); inline object allocate(Thread* t, unsigned sizeInBytes) { if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord) >= Thread::HeapSizeInWords or t->vm->exclusive)) { return allocate2(t, sizeInBytes); } else { return allocateSmall(t, sizeInBytes); } } inline void set(Thread* t, object& target, object value) { target = value; if (t->vm->heap->needsMark(&target)) { ACQUIRE_RAW(t, t->vm->heapLock); t->vm->heap->mark(&target); } } object& arrayBodyUnsafe(Thread*, object, unsigned); #include "type-declarations.cpp" object makeTrace(Thread* t, int frame); object makeTrace(Thread* t); inline object makeRuntimeException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeRuntimeException(t, message, trace, 0); } inline object makeIllegalStateException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeIllegalStateException(t, message, trace, 0); } inline object makeIllegalMonitorStateException(Thread* t) { return makeIllegalMonitorStateException(t, 0, makeTrace(t), 0); } inline object makeArrayIndexOutOfBoundsException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeArrayIndexOutOfBoundsException(t, message, trace, 0); } inline object makeArrayStoreException(Thread* t) { return makeArrayStoreException(t, 0, makeTrace(t), 0); } inline object makeNegativeArraySizeException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeNegativeArraySizeException(t, message, trace, 0); } inline object makeClassCastException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeClassCastException(t, message, trace, 0); } inline object makeClassNotFoundException(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeClassNotFoundException(t, message, trace, 0); } inline object makeNullPointerException(Thread* t) { return makeNullPointerException(t, 0, makeTrace(t), 0); } inline object makeStackOverflowError(Thread* t) { return makeStackOverflowError(t, 0, makeTrace(t), 0); } inline object makeNoSuchFieldError(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeNoSuchFieldError(t, message, trace, 0); } inline object makeNoSuchMethodError(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeNoSuchMethodError(t, message, trace, 0); } inline object makeUnsatisfiedLinkError(Thread* t, object message) { PROTECT(t, message); object trace = makeTrace(t); return makeUnsatisfiedLinkError(t, message, trace, 0); } object makeByteArray(Thread* t, const char* format, ...); object makeString(Thread* t, const char* format, ...); void stringChars(Thread* t, object string, char* chars); inline void pushObject(Thread* t, object o) { if (DebugStack) { fprintf(stderr, "push object %p at %d\n", o, t->sp); } assert(t, t->sp + 1 < Thread::StackSizeInWords / 2); t->stack[(t->sp * 2) ] = ObjectTag; t->stack[(t->sp * 2) + 1] = reinterpret_cast(o); ++ t->sp; } inline void pushInt(Thread* t, uint32_t v) { if (DebugStack) { fprintf(stderr, "push int %d at %d\n", v, t->sp); } assert(t, t->sp + 1 < Thread::StackSizeInWords / 2); t->stack[(t->sp * 2) ] = IntTag; t->stack[(t->sp * 2) + 1] = v; ++ t->sp; } inline void pushLong(Thread* t, uint64_t v) { if (DebugStack) { fprintf(stderr, "push long " LLD " at %d\n", v, t->sp); } pushInt(t, v >> 32); pushInt(t, v & 0xFF); } inline object popObject(Thread* t) { if (DebugStack) { fprintf(stderr, "pop object %p at %d\n", reinterpret_cast(t->stack[((t->sp - 1) * 2) + 1]), t->sp - 1); } assert(t, t->stack[(t->sp - 1) * 2] == ObjectTag); return reinterpret_cast(t->stack[((-- t->sp) * 2) + 1]); } inline uint32_t popInt(Thread* t) { if (DebugStack) { fprintf(stderr, "pop int " LD " at %d\n", t->stack[((t->sp - 1) * 2) + 1], t->sp - 1); } assert(t, t->stack[(t->sp - 1) * 2] == IntTag); return t->stack[((-- t->sp) * 2) + 1]; } inline uint64_t popLong(Thread* t) { if (DebugStack) { fprintf(stderr, "pop long " LLD " at %d\n", (static_cast(t->stack[((t->sp - 2) * 2) + 1]) << 32) | static_cast(t->stack[((t->sp - 1) * 2) + 1]), t->sp - 2); } uint64_t a = popInt(t); uint64_t b = popInt(t); return (b << 32) | a; } inline object peekObject(Thread* t, unsigned index) { if (DebugStack) { fprintf(stderr, "peek object %p at %d\n", reinterpret_cast(t->stack[(index * 2) + 1]), index); } assert(t, index < Thread::StackSizeInWords / 2); assert(t, t->stack[index * 2] == ObjectTag); return *reinterpret_cast(t->stack + (index * 2) + 1); } inline uint32_t peekInt(Thread* t, unsigned index) { if (DebugStack) { fprintf(stderr, "peek int " LD " at %d\n", t->stack[(index * 2) + 1], index); } assert(t, index < Thread::StackSizeInWords / 2); assert(t, t->stack[index * 2] == IntTag); return t->stack[(index * 2) + 1]; } inline uint64_t peekLong(Thread* t, unsigned index) { if (DebugStack) { fprintf(stderr, "peek long " LLD " at %d\n", (static_cast(t->stack[(index * 2) + 1]) << 32) | static_cast(t->stack[((index + 1) * 2) + 1]), index); } return (static_cast(peekInt(t, index)) << 32) | static_cast(peekInt(t, index + 1)); } inline void pokeObject(Thread* t, unsigned index, object value) { if (DebugStack) { fprintf(stderr, "poke object %p at %d\n", value, index); } t->stack[index * 2] = ObjectTag; t->stack[(index * 2) + 1] = reinterpret_cast(value); } inline void pokeInt(Thread* t, unsigned index, uint32_t value) { if (DebugStack) { fprintf(stderr, "poke int %d at %d\n", value, index); } t->stack[index * 2] = IntTag; t->stack[(index * 2) + 1] = value; } inline void pokeLong(Thread* t, unsigned index, uint64_t value) { if (DebugStack) { fprintf(stderr, "poke long " LLD " at %d\n", value, index); } pokeInt(t, index, value >> 32); pokeInt(t, index + 1, value & 0xFF); } inline object* pushReference(Thread* t, object o) { expect(t, t->sp + 1 < Thread::StackSizeInWords / 2); pushObject(t, o); return reinterpret_cast(t->stack + ((t->sp - 1) * 2) + 1); } inline int frameNext(Thread* t, int frame) { return peekInt(t, frame + FrameNextOffset); } inline object frameMethod(Thread* t, int frame) { return peekObject(t, frame + FrameMethodOffset); } inline unsigned frameIp(Thread* t, int frame) { return peekInt(t, frame + FrameIpOffset); } inline unsigned frameBase(Thread* t, int frame) { return peekInt(t, frame + FrameBaseOffset); } inline object localObject(Thread* t, unsigned index) { return peekObject(t, frameBase(t, t->frame) + index); } inline uint32_t localInt(Thread* t, unsigned index) { return peekInt(t, frameBase(t, t->frame) + index); } inline uint64_t localLong(Thread* t, unsigned index) { return peekLong(t, frameBase(t, t->frame) + index); } inline void setLocalObject(Thread* t, unsigned index, object value) { pokeObject(t, frameBase(t, t->frame) + index, value); } inline void setLocalInt(Thread* t, unsigned index, uint32_t value) { pokeInt(t, frameBase(t, t->frame) + index, value); } inline void setLocalLong(Thread* t, unsigned index, uint64_t value) { pokeLong(t, frameBase(t, t->frame) + index, value); } inline object makeTrace(Thread* t) { pokeInt(t, t->frame + FrameIpOffset, t->ip); return makeTrace(t, t->frame); } inline uint32_t hash(const int8_t* s, unsigned length) { uint32_t h = 0; for (unsigned i = 0; i < length; ++i) h = (h * 31) + s[i]; return h; } inline unsigned baseSize(Thread* t, object o, object class_) { if (classArrayElementSize(t, class_)) { noop(); if (cast(o, classFixedSize(t, class_) - BytesPerWord)) { noop(); } } return divide(classFixedSize(t, class_), BytesPerWord) + divide(classArrayElementSize(t, class_) * cast(o, classFixedSize(t, class_) - BytesPerWord), BytesPerWord); } inline bool objectExtended(Thread*, object o) { return (cast(o, 0) & (~PointerMask)) == ExtendedMark; } inline uintptr_t& extendedWord(Thread* t, object o, unsigned baseSize) { assert(t, objectExtended(t, o)); return cast(o, baseSize * BytesPerWord); } inline unsigned extendedSize(Thread* t, object o, unsigned baseSize) { return baseSize + objectExtended(t, o); } inline bool hashTaken(Thread*, object o) { return (cast(o, 0) & (~PointerMask)) == HashTakenMark; } inline void markHashTaken(Thread* t, object o) { assert(t, not objectExtended(t, o)); cast(o, 0) |= HashTakenMark; } inline uint32_t takeHash(Thread*, object o) { return reinterpret_cast(o) / BytesPerWord; } inline uint32_t objectHash(Thread* t, object o) { if (objectExtended(t, o)) { return extendedWord(t, o, baseSize(t, o, objectClass(t, o))); } else { markHashTaken(t, o); return takeHash(t, o); } } inline bool objectEqual(Thread*, object a, object b) { return a == b; } inline uint32_t referenceHash(Thread* t, object o) { return objectHash(t, jreferenceTarget(t, o)); } inline bool referenceEqual(Thread* t, object a, object b) { return a == jreferenceTarget(t, b); } inline uint32_t byteArrayHash(Thread* t, object array) { return hash(&byteArrayBody(t, array, 0), byteArrayLength(t, array)); } inline bool byteArrayEqual(Thread* t, object a, object b) { return a == b or ((byteArrayLength(t, a) == byteArrayLength(t, b)) and memcmp(&byteArrayBody(t, a, 0), &byteArrayBody(t, b, 0), byteArrayLength(t, a)) == 0); } inline bool intArrayEqual(Thread* t, object a, object b) { return a == b or ((intArrayLength(t, a) == intArrayLength(t, b)) and memcmp(&intArrayBody(t, a, 0), &intArrayBody(t, b, 0), intArrayLength(t, a) * 4) == 0); } inline uint32_t methodHash(Thread* t, object method) { return byteArrayHash(t, methodName(t, method)) ^ byteArrayHash(t, methodSpec(t, method)); } inline bool methodEqual(Thread* t, object a, object b) { return a == b or (byteArrayEqual(t, methodName(t, a), methodName(t, b)) and byteArrayEqual(t, methodSpec(t, a), methodSpec(t, b))); } object hashMapFindNode(Thread* t, object map, object key, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)); inline object hashMapFind(Thread* t, object map, object key, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)) { object n = hashMapFindNode(t, map, key, hash, equal); return (n ? tripleSecond(t, n) : 0); } void hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object), unsigned size); void hashMapInsert(Thread* t, object map, object key, object value, uint32_t (*hash)(Thread*, object)); inline bool hashMapInsertOrReplace(Thread* t, object map, object key, object value, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)) { object n = hashMapFindNode(t, map, key, hash, equal); if (n == 0) { hashMapInsert(t, map, key, value, hash); return true; } else { set(t, tripleSecond(t, n), value); return false; } } inline bool hashMapInsertMaybe(Thread* t, object map, object key, object value, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)) { object n = hashMapFindNode(t, map, key, hash, equal); if (n == 0) { hashMapInsert(t, map, key, value, hash); return true; } else { return false; } } object hashMapRemove(Thread* t, object map, object key, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)); object hashMapIterator(Thread* t, object map); object hashMapIteratorNext(Thread* t, object it); void listAppend(Thread* t, object list, object value); void addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); System::Monitor* objectMonitor(Thread* t, object o); inline void acquire(Thread* t, object o) { System::Monitor* m = objectMonitor(t, o); if (not m->tryAcquire(t)) { ENTER(t, Thread::IdleState); m->acquire(t); } } inline void release(Thread* t, object o) { objectMonitor(t, o)->release(t); } inline void wait(Thread* t, object o, int64_t milliseconds) { System::Monitor* m = objectMonitor(t, o); if (m->owner() == t) { ENTER(t, Thread::IdleState); m->wait(t, milliseconds); } else { t->exception = makeIllegalMonitorStateException(t); } } inline void notify(Thread* t, object o) { System::Monitor* m = objectMonitor(t, o); if (m->owner() == t) { m->notify(t); } else { t->exception = makeIllegalMonitorStateException(t); } } inline void notifyAll(Thread* t, object o) { System::Monitor* m = objectMonitor(t, o); if (m->owner() == t) { m->notifyAll(t); } else { t->exception = makeIllegalMonitorStateException(t); } } void exit(Thread* t); } // namespace vm #endif//MACHINE_H