Initial repository layout
llvm-svn: 48661
diff --git a/vmkit/lib/JnJVM/Classpath/Classpath.cpp b/vmkit/lib/JnJVM/Classpath/Classpath.cpp
new file mode 100644
index 0000000..db17b7b
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/Classpath.cpp
@@ -0,0 +1,95 @@
+//===-------- Classpath.cpp - Configuration for classpath -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+
+#include "Classpath.h"
+
+#include "ClasspathConstructor.h"
+#include "ClasspathMethod.h"
+#include "ClasspathVMClass.h"
+#include "ClasspathVMClassLoader.h"
+#include "ClasspathVMField.h"
+#include "ClasspathVMObject.h"
+#include "ClasspathVMRuntime.h"
+#include "ClasspathVMStackWalker.h"
+#include "ClasspathVMSystem.h"
+#include "ClasspathVMSystemProperties.h"
+#include "ClasspathVMThread.h"
+#include "ClasspathVMThrowable.h"
+
+#include "JavaClass.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+
+typedef void (*function_t) (void);
+
+function_t faketable[] = {
+ (function_t)Java_java_lang_VMSystem_arraycopy,
+ (function_t)Java_java_lang_VMSystem_identityHashCode,
+ (function_t)Java_java_lang_VMThread_currentThread,
+ (function_t)Java_java_lang_VMClassLoader_getPrimitiveClass,
+ (function_t)Java_java_lang_VMClass_isArray,
+ (function_t)Java_java_lang_VMClass_getDeclaredConstructors,
+ (function_t)Java_java_lang_VMClass_getDeclaredMethods,
+ (function_t)Java_java_lang_VMClass_forName,
+ (function_t)Java_java_lang_VMClass_getModifiers,
+ (function_t)Java_gnu_classpath_VMSystemProperties_preInit,
+ (function_t)Java_java_lang_VMObject_clone,
+ (function_t)Java_java_lang_VMObject_getClass,
+ (function_t)Java_java_lang_VMRuntime_mapLibraryName,
+ (function_t)Java_java_lang_VMRuntime_nativeLoad,
+ (function_t)Java_java_lang_reflect_Constructor_getParameterTypes,
+ (function_t)Java_java_lang_reflect_Constructor_getModifiersInternal,
+ (function_t)Java_java_lang_reflect_Method_getModifiersInternal,
+ (function_t)Java_java_lang_reflect_Constructor_constructNative,
+ (function_t)Java_java_lang_VMClassLoader_findLoadedClass,
+ (function_t)Java_java_lang_VMClassLoader_loadClass,
+ (function_t)Java_java_lang_VMClass_getName,
+ (function_t)Java_java_lang_VMThrowable_fillInStackTrace,
+ (function_t)Java_java_lang_VMClassLoader_defineClass,
+ (function_t)Java_java_lang_VMClassLoader_resolveClass,
+ (function_t)Java_java_lang_VMClass_isPrimitive,
+ (function_t)Java_java_lang_VMClass_isInterface,
+ (function_t)Java_java_lang_VMClass_getComponentType,
+ (function_t)Java_java_lang_VMRuntime_gc,
+ (function_t)Java_java_lang_VMClass_getClassLoader,
+ (function_t)Java_java_lang_VMClass_isAssignableFrom,
+ (function_t)Java_java_lang_reflect_Field_getModifiersInternal,
+ (function_t)Java_gnu_classpath_VMStackWalker_getClassContext
+};
+
+
+
+extern "C" int ClasspathBoot(int argc, char** argv, char** env) {
+ void* p;
+ p = &faketable;
+ p = &GNUClasspathLibs;
+ p = &GNUClasspathGlibj;
+ return 1;
+}
+
+using namespace jnjvm;
+
+extern "C" {
+JNIEXPORT bool JNICALL Java_java_io_VMObjectStreamClass_hasClassInitializer(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl) {
+
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, true);
+ if (cl->lookupMethodDontThrow(Jnjvm::clinitName, Jnjvm::clinitType, true, false))
+ return true;
+ else
+ return false;
+}
+}
diff --git a/vmkit/lib/JnJVM/Classpath/Classpath.h.in b/vmkit/lib/JnJVM/Classpath/Classpath.h.in
new file mode 100644
index 0000000..fdddeb4
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/Classpath.h.in
@@ -0,0 +1,14 @@
+//===-------- Classpath.h - Configuration for classpath -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+char* GNUClasspathLibs = "@classpathlibs@";
+char* GNUClasspathGlibj = "@classpathglibj@";
+char* GNUClasspathVersion = "@gnuclasspathversion@";
+
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathConstructor.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathConstructor.cpp
new file mode 100644
index 0000000..68730a8
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathConstructor.cpp
@@ -0,0 +1,112 @@
+//===- ClasspathConstructor.cpp -------------------------------------------===//
+//===----------- GNU classpath java/lang/reflect/Constructor --------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_getParameterTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons) {
+ JavaMethod* meth = (JavaMethod*)((*Classpath::constructorSlot)((JavaObject*)cons).IntVal.getZExtValue());
+ JavaObject* loader = meth->classDef->classLoader;
+ return (jobject)(NativeUtil::getParameterTypes(loader, meth));
+}
+
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Constructor_getModifiersInternal(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons) {
+ JavaMethod* meth = (JavaMethod*)((*Classpath::constructorSlot)((JavaObject*)cons).IntVal.getZExtValue());
+ return meth->access;
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_constructNative(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject _cons,
+ jobject _args,
+ jclass Clazz,
+ jint _meth) {
+ JavaMethod* meth = (JavaMethod*)_meth;
+ ArrayObject* args = (ArrayObject*)_args;
+ sint32 nbArgs = args ? args->size : 0;
+ sint32 size = meth->signature->args.size();
+ Jnjvm* vm = JavaThread::get()->isolate;
+
+ void** buf = (void**)alloca(size * sizeof(uint64));
+ void* _buf = (void*)buf;
+ sint32 index = 0;
+ if (nbArgs == size) {
+ CommonClass* _cl = NativeUtil::resolvedImplClass(Clazz, false);
+ if (!_cl->isArray) {
+ Class* cl = (Class*)_cl;
+ cl->initialiseClass();
+
+ JavaObject* res = cl->doNew();
+
+ for (std::vector<Typedef*>::iterator i = meth->signature->args.begin(),
+ e = meth->signature->args.end(); i != e; ++i, ++index) {
+ NativeUtil::decapsulePrimitive(vm, buf, args->at(index), *i);
+ }
+
+ JavaObject* excp = 0;
+ try {
+ meth->invokeIntSpecialBuf(res, _buf);
+ }catch(...) {
+ excp = JavaThread::getJavaException();
+ JavaThread::clearException();
+ }
+ if (excp) {
+ if (excp->classOf->isAssignableFrom(Classpath::newException)) {
+ JavaThread::get()->isolate->invocationTargetException(excp);
+ } else {
+ JavaThread::throwException(excp);
+ }
+ }
+
+ return (jobject)res;
+ }
+ }
+ vm->illegalArgumentExceptionForMethod(meth, 0, 0);
+ return 0;
+}
+
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_Constructor_getExceptionTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons) {
+ verifyNull(cons);
+ JavaMethod* meth = (JavaMethod*)(*Classpath::constructorSlot)((JavaObject*)cons).IntVal.getZExtValue();
+ return (jobjectArray)NativeUtil::getExceptionTypes(meth);
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathConstructor.h b/vmkit/lib/JnJVM/Classpath/ClasspathConstructor.h
new file mode 100644
index 0000000..1c8dd85
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathConstructor.h
@@ -0,0 +1,80 @@
+//===-------- ClasspathConstructor.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef _JAVA_LANG_REFLECT_CONSTRUCTOR_H
+#define _JAVA_LANG_REFLECT_CONSTRUCTOR_H
+
+#include <jni.h>
+
+extern "C" {
+
+/*
+ * Class: java/lang/reflect/Constructor
+ * Method: getParameterTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_getParameterTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons
+);
+
+/*
+ * Class: java/lang/reflect/Constructor
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Constructor_getModifiersInternal(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons);
+
+
+/*
+ * Class: java/lang/reflect/Constructor
+ * Method: constructNative
+ * Signature: ([Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
+ */
+
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Constructor_constructNative(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons, jobject args, jclass Clazz, jint meth);
+
+
+
+/*
+ * Class: java/lang/reflect/Constructor
+ * Method: getExceptionTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_Constructor_getExceptionTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject cons);
+
+
+
+#if 0
+/*
+ * Class: java/lang/reflect/Constructor
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_java_lang_reflect_Constructor_getSignature(JNIEnv *env, struct java_lang_reflect_Constructor* this);
+
+#endif
+
+}
+#endif
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathMethod.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathMethod.cpp
new file mode 100644
index 0000000..1a1b247
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathMethod.cpp
@@ -0,0 +1,195 @@
+//===- ClasspathMethod.cpp ------------------------------------------------===//
+//===------------- GNU classpath java/lang/reflect/Method -----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Method_getModifiersInternal(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject Meth) {
+ JavaMethod* meth = (JavaMethod*)((*Classpath::methodSlot)((JavaObject*)Meth).IntVal.getZExtValue());
+ return meth->access;
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_reflect_Method_getReturnType(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject Meth) {
+ JavaMethod* meth = (JavaMethod*)((*Classpath::methodSlot)((JavaObject*)Meth).IntVal.getZExtValue());
+ JavaObject* loader = meth->classDef->classLoader;
+ return (jclass)NativeUtil::getClassType(loader, meth->signature->ret);
+}
+
+
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_getParameterTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+
+ jobject Meth) {
+ JavaMethod* meth = (JavaMethod*)((*Classpath::methodSlot)((JavaObject*)Meth).IntVal.getZExtValue());
+ JavaObject* loader = meth->classDef->classLoader;
+ return (jobject)(NativeUtil::getParameterTypes(loader, meth));
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_invokeNative(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject Meth, jobject _obj, jobject _args, jclass Cl, jint _meth) {
+
+ JavaMethod* meth = (JavaMethod*)_meth;
+ ArrayObject* args = (ArrayObject*)_args;
+ sint32 nbArgs = args ? args->size : 0;
+ sint32 size = meth->signature->args.size();
+ Jnjvm* vm = JavaThread::get()->isolate;
+ JavaObject* obj = (JavaObject*)_obj;
+
+ void** buf = (void**)alloca(size * sizeof(uint64));
+ void* _buf = (void*)buf;
+ sint32 index = 0;
+ if (nbArgs == size) {
+ CommonClass* _cl = NativeUtil::resolvedImplClass(Cl, false);
+ Class* cl = (Class*)_cl;
+
+ if (isVirtual(meth->access)) {
+ verifyNull(obj);
+ if (!(obj->classOf->isAssignableFrom(meth->classDef))) {
+ vm->illegalArgumentExceptionForMethod(meth, meth->classDef, obj->classOf);
+ }
+
+ } else {
+ cl->initialiseClass();
+ }
+
+
+ for (std::vector<Typedef*>::iterator i = meth->signature->args.begin(),
+ e = meth->signature->args.end(); i != e; ++i, ++index) {
+ NativeUtil::decapsulePrimitive(vm, buf, args->at(index), *i);
+ }
+
+ JavaObject* exc = 0;
+
+#define RUN_METH(TYPE) \
+ try{ \
+ if (isVirtual(meth->access)) { \
+ if (isPublic(meth->access)) { \
+ val = meth->invoke##TYPE##VirtualBuf(obj, _buf); \
+ } else { \
+ val = meth->invoke##TYPE##SpecialBuf(obj, _buf); \
+ } \
+ } else { \
+ val = meth->invoke##TYPE##StaticBuf(_buf); \
+ } \
+ }catch(...) { \
+ exc = JavaThread::getJavaException(); \
+ assert(exc && "no exception?"); \
+ JavaThread::clearException(); \
+ } \
+ \
+ if (exc) { \
+ if (exc->classOf->isAssignableFrom(Classpath::newException)) { \
+ JavaThread::get()->isolate->invocationTargetException(exc); \
+ } else { \
+ JavaThread::throwException(exc); \
+ } \
+ } \
+
+ JavaObject* res = 0;
+ const AssessorDesc* retType = meth->signature->ret->funcs;
+ if (retType == AssessorDesc::dVoid) {
+ res = 0;
+ uint32 val = 0;
+ RUN_METH(Int);
+ } else if (retType == AssessorDesc::dBool) {
+ uint32 val = 0;
+ RUN_METH(Int);
+ res = (*Classpath::boolClass)();
+ (*Classpath::boolValue)(res, val);
+ } else if (retType == AssessorDesc::dByte) {
+ uint32 val = 0;
+ RUN_METH(Int);
+ res = (*Classpath::byteClass)();
+ (*Classpath::byteValue)(res, val);
+ } else if (retType == AssessorDesc::dChar) {
+ uint32 val = 0;
+ RUN_METH(Int);
+ res = (*Classpath::charClass)();
+ (*Classpath::charValue)(res, val);
+ } else if (retType == AssessorDesc::dShort) {
+ uint32 val = 0;
+ RUN_METH(Int);
+ res = (*Classpath::shortClass)();
+ (*Classpath::shortValue)(res, val);
+ } else if (retType == AssessorDesc::dInt) {
+ uint32 val = 0;
+ RUN_METH(Int);
+ res = (*Classpath::intClass)();
+ (*Classpath::intValue)(res, val);
+ } else if (retType == AssessorDesc::dLong) {
+ sint64 val = 0;
+ RUN_METH(Long);
+ res = (*Classpath::longClass)();
+ (*Classpath::longValue)(res, val);
+ } else if (retType == AssessorDesc::dFloat) {
+ float val = 0;
+ RUN_METH(Float);
+ res = (*Classpath::floatClass)();
+ (*Classpath::floatValue)(res, val);
+ } else if (retType == AssessorDesc::dDouble) {
+ double val = 0;
+ RUN_METH(Double);
+ res = (*Classpath::doubleClass)();
+ (*Classpath::doubleValue)(res, val);
+ } else if (retType == AssessorDesc::dTab || retType == AssessorDesc::dRef) {
+ JavaObject* val = 0;
+ RUN_METH(JavaObject);
+ res = val;
+ } else {
+ vm->unknownError("should not be here");
+ }
+ return (jobject)res;
+ }
+ vm->illegalArgumentExceptionForMethod(meth, 0, 0);
+ return 0;
+}
+
+#undef RUN_METH
+
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_Method_getExceptionTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject _meth) {
+ verifyNull(_meth);
+ JavaMethod* meth = (JavaMethod*)(*Classpath::methodSlot)((JavaObject*)_meth).IntVal.getZExtValue();
+ return (jobjectArray)NativeUtil::getExceptionTypes(meth);
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathMethod.h b/vmkit/lib/JnJVM/Classpath/ClasspathMethod.h
new file mode 100644
index 0000000..7a7bd96
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathMethod.h
@@ -0,0 +1,89 @@
+//===----------- ClasspathMethod.h - Classpath methods --------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_REFLECT_METHOD_H
+#define _JAVA_LANG_REFLECT_METHOD_H
+
+
+extern "C" {
+/*
+ * Class: java/lang/reflect/Method
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Method_getModifiersInternal(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject meth);
+
+
+/*
+ * Class: java/lang/reflect/Method
+ * Method: getReturnType
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_reflect_Method_getReturnType(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject meth);
+
+
+/*
+ * Class: java/lang/reflect/Method
+ * Method: getParameterTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_getParameterTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject Meth);
+
+/*
+ * Class: java/lang/reflect/Method
+ * Method: invokeNative
+ * Signature: (Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Method_invokeNative(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject Meth, jobject obj, jobject Args, jclass Cl, jint meth);
+
+
+/*
+ * Class: java/lang/reflect/Method
+ * Method: getExceptionTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_Method_getExceptionTypes(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ jobject meth);
+
+
+
+#if 0
+/*
+ * Class: java/lang/reflect/Method
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_java_lang_reflect_Method_getSignature(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+ struct java_lang_reflect_Method* this);
+#endif
+}
+#endif
+
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMClass.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMClass.cpp
new file mode 100644
index 0000000..4b56afe
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMClass.cpp
@@ -0,0 +1,426 @@
+//===---- ClasspathVMClass.cpp - GNU classpath java/lang/VMClass ----------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaAccess.h"
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+#include "Reader.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isArray(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject klass) {
+
+ CommonClass* cl =
+ (CommonClass*)(((*Classpath::vmdataClass)((JavaObject*)klass)).PointerVal);
+
+ return cl->isArray;
+
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_forName(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+
+ jobject str,
+ jboolean clinit,
+ jobject loader) {
+
+ Jnjvm* vm = JavaThread::get()->isolate;
+ CommonClass* cl = vm->lookupClassFromJavaString((JavaString*)str,
+ (JavaObject*)loader, true,
+ false, false);
+ if (cl != 0) {
+ if (clinit) {
+ cl->initialiseClass();
+ }
+ return (jclass)(cl->getClassDelegatee());
+ } else {
+ vm->error(Jnjvm::ClassNotFoundException, "unable to load %s",
+ ((JavaString*)str)->strToUTF8(vm)->printString());
+ return 0;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredConstructors(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+
+ jclass Cl,
+ jboolean publicOnly) {
+
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, false);
+
+ if (cl->isArray || isInterface(cl->access)) {
+ return (jobject)ArrayObject::acons(0, Classpath::constructorArrayClass);
+ } else {
+ std::vector<JavaMethod*> meths = cl->virtualMethods;
+ std::vector<JavaMethod*> res;
+ for (std::vector<JavaMethod*>::iterator i = meths.begin(), e = meths.end();
+ i != e; ++i) {
+ if ((*i)->name == Jnjvm::initName && (!publicOnly || isPublic((*i)->access))) {
+ res.push_back(*i);
+ }
+ }
+
+ ArrayObject* ret = ArrayObject::acons(res.size(), Classpath::constructorArrayClass);
+ sint32 index = 0;
+ for (std::vector<JavaMethod*>::iterator i = res.begin(), e = res.end();
+ i != e; ++i, ++index) {
+ JavaMethod* meth = *i;
+ // TODO: check parameter types
+ JavaObject* tmp = (*Classpath::newConstructor)();
+ Classpath::initConstructor->invokeIntSpecial(tmp, Cl, meth);
+ ret->setAt(index, tmp);
+ }
+ return (jobject)ret;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredMethods(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+
+ jclass Cl,
+ jboolean publicOnly) {
+
+ Jnjvm* vm = JavaThread::get()->isolate;
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, false);
+
+ if (cl->isArray) {
+ return (jobject)ArrayObject::acons(0, Classpath::methodArrayClass);
+ } else {
+ std::vector<JavaMethod*> meths = cl->virtualMethods;
+ std::vector<JavaMethod*> res;
+ for (std::vector<JavaMethod*>::iterator i = meths.begin(), e = meths.end();
+ i != e; ++i) {
+ if ((*i)->name != Jnjvm::initName && (!publicOnly || isPublic((*i)->access))) {
+ res.push_back(*i);
+ }
+ }
+ meths = cl->staticMethods;
+ for (std::vector<JavaMethod*>::iterator i = meths.begin(), e = meths.end();
+ i != e; ++i) {
+ if ((*i)->name != Jnjvm::clinitName && (!publicOnly || isPublic((*i)->access))) {
+ res.push_back(*i);
+ }
+ }
+
+ ArrayObject* ret = ArrayObject::acons(res.size(), Classpath::methodArrayClass);
+ sint32 index = 0;
+ for (std::vector<JavaMethod*>::iterator i = res.begin(), e = res.end();
+ i != e; ++i, ++index) {
+ JavaMethod* meth = *i;
+ // TODO: check parameter types
+ JavaObject* tmp = (*Classpath::newMethod)();
+ Classpath::initMethod->invokeIntSpecial(tmp, Cl, vm->UTF8ToStr(meth->name), meth);
+ ret->setAt(index, tmp);
+ }
+ return (jobject)ret;
+ }
+}
+
+JNIEXPORT jint JNICALL Java_java_lang_VMClass_getModifiers(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jclass Cl,
+ jboolean ignore) {
+
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, false);
+ return cl->access;
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getName(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jobject Cl) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ CommonClass* cl =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl).PointerVal);
+
+ AssessorDesc* ass = AssessorDesc::bogusClassToPrimitive(cl);
+ const UTF8* res = 0;
+ if (ass) {
+ res = cl->name;
+ } else {
+ const UTF8* iname = cl->name;
+ res = iname->internalToJava(vm, 0, iname->size);
+ }
+ return (jobject)(vm->UTF8ToStr(res));
+}
+
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isPrimitive(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jclass Cl) {
+ CommonClass* cl =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl).PointerVal);
+
+ AssessorDesc* ass = AssessorDesc::bogusClassToPrimitive(cl);
+ if (ass == 0) return false;
+ else return true;
+}
+
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isInterface(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jclass Cl) {
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, false);
+
+ return isInterface(cl->access);
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getComponentType(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jclass Cl) {
+ CommonClass* cl =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl).PointerVal);
+
+ if (cl->isArray) {
+ CommonClass* bc = ((ClassArray*)cl)->baseClass();
+ return (jclass)(bc->getClassDelegatee());
+ } else {
+ return 0;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getClassLoader(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl) {
+ CommonClass* cl =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl).PointerVal);
+ return (jobject)cl->classLoader;
+}
+
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isAssignableFrom(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl1, jclass Cl2) {
+ CommonClass* cl1 =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl1).PointerVal);
+ CommonClass* cl2 =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl2).PointerVal);
+
+ AssessorDesc* ass = AssessorDesc::bogusClassToPrimitive(cl1);
+ if (ass) {
+ return ass == AssessorDesc::bogusClassToPrimitive(cl2);
+ } else {
+ cl2->resolveClass(false);
+ return cl2->isAssignableFrom(cl1);
+ }
+
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getSuperclass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl) {
+ CommonClass* cl =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl).PointerVal);
+ if (isInterface(cl->access))
+ return 0;
+ else {
+ cl->resolveClass(false);
+ if (cl->super) return (jobject)JavaThread::get()->isolate->getClassDelegatee(cl->super);
+ else return 0;
+ }
+}
+
+JNIEXPORT bool JNICALL Java_java_lang_VMClass_isInstance(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl, jobject obj) {
+ CommonClass* cl =
+ (CommonClass*)((*Classpath::vmdataClass)((JavaObject*)Cl).PointerVal);
+ return ((JavaObject*)obj)->instanceOf(cl);
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredFields(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl, jboolean publicOnly) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, false);
+
+ if (cl->isArray) {
+ return (jobject)ArrayObject::acons(0, Classpath::fieldArrayClass);
+ } else {
+ std::vector<JavaField*> fields = cl->virtualFields;
+ std::vector<JavaField*> res;
+ for (std::vector<JavaField*>::iterator i = fields.begin(), e = fields.end();
+ i != e; ++i) {
+ if (!publicOnly || isPublic((*i)->access)) {
+ res.push_back(*i);
+ }
+ }
+ fields = cl->staticFields;
+ for (std::vector<JavaField*>::iterator i = fields.begin(), e = fields.end();
+ i != e; ++i) {
+ if (!publicOnly || isPublic((*i)->access)) {
+ res.push_back(*i);
+ }
+ }
+
+ ArrayObject* ret = ArrayObject::acons(res.size(), Classpath::fieldArrayClass);
+ sint32 index = 0;
+ for (std::vector<JavaField*>::iterator i = res.begin(), e = res.end();
+ i != e; ++i, ++index) {
+ JavaField* field = *i;
+ // TODO: check parameter types
+ JavaObject* tmp = (*Classpath::newField)();
+ Classpath::initField->invokeIntSpecial(tmp, Cl, vm->UTF8ToStr(field->name), field);
+ ret->setAt(index, tmp);
+ }
+ return (jobject)ret;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getInterfaces(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ CommonClass* cl = NativeUtil::resolvedImplClass(Cl, false);
+ std::vector<Class*> & interfaces = cl->interfaces;
+ ArrayObject* ret = ArrayObject::acons(interfaces.size(), Classpath::classArrayClass);
+ sint32 index = 0;
+ for (std::vector<Class*>::iterator i = interfaces.begin(), e = interfaces.end();
+ i != e; ++i, ++index) {
+ Class* klass = *i;
+ ret->setAt(index, vm->getClassDelegatee(klass));
+ }
+ return (jobject)ret;
+}
+
+static void resolveInnerOuterClasses(Class* cl) {
+ Attribut* attribut = Attribut::lookup(&cl->attributs,
+ Attribut::innerClassesAttribut);
+ if (attribut != 0) {
+ Reader* reader = attribut->toReader(cl->bytes, attribut);
+
+ uint16 nbi = reader->readU2();
+ for (uint16 i = 0; i < nbi; ++i) {
+ uint16 inner = reader->readU2();
+ uint16 outer = reader->readU2();
+ //uint16 innerName =
+ reader->readU2();
+ uint16 accessFlags = reader->readU2();
+ Class* clInner = (Class*)cl->ctpInfo->loadClass(inner);
+ Class* clOuter = (Class*)cl->ctpInfo->loadClass(outer);
+
+ if (clInner == cl) {
+ cl->outerClass = clOuter;
+ } else if (clOuter == cl) {
+ clInner->innerAccess = accessFlags;
+ cl->innerClasses.push_back(clInner);
+ }
+ }
+ }
+ cl->innerOuterResolved = true;
+}
+
+
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getDeclaringClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ Class* cl = (Class*)NativeUtil::resolvedImplClass(Cl, false);
+ if (!(cl->innerOuterResolved))
+ resolveInnerOuterClasses(cl);
+ if (cl->outerClass) {
+ return (jclass)vm->getClassDelegatee(cl->outerClass);
+ } else {
+ return 0;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredClasses(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl, bool publicOnly) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ Class* cl = (Class*)NativeUtil::resolvedImplClass(Cl, false);
+ if (!(cl->innerOuterResolved))
+ resolveInnerOuterClasses(cl);
+ ArrayObject* res = ArrayObject::acons(cl->innerClasses.size(), Classpath::constructorArrayClass);
+ uint32 index = 0;
+ for (std::vector<Class*>::iterator i = cl->innerClasses.begin(),
+ e = cl->innerClasses.end(); i!= e; i++) {
+ res->elements[index++] = vm->getClassDelegatee(*i);
+ }
+
+ return (jobject)res;
+}
+
+
+JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject throwable) {
+ JavaThread::throwException((JavaObject*)throwable);
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMClass.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMClass.h
new file mode 100644
index 0000000..2f4c524
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMClass.h
@@ -0,0 +1,359 @@
+//===---------- ClasspathVMClass.h - Classpath methods --------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMCLASS_H
+#define _JAVA_LANG_VMCLASS_H
+
+#include <jni.h>
+
+extern "C" {
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isArray
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isArray(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject klass);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: forName
+ * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_forName(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject str, jboolean clinit, jobject loader);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredConstructors
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredConstructors(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject cl, jboolean publicOnly);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredMethods
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredMethods(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass cl, jboolean publicOnly);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getModifiers
+ * Signature: (Ljava/lang/Class;Z)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMClass_getModifiers(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl, jboolean ignore);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getName
+ * Signature: (Ljava/lang/Class;)Ljava/lang/String;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getName(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject Cl);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isPrimitive
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isPrimitive(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isInterface
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isInterface(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getComponentType
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getComponentType(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getClassLoader
+ * Signature: (Ljava/lang/Class;)Ljava/lang/ClassLoader;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getClassLoader(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isAssignableFrom
+ * Signature: (Ljava/lang/Class;Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isAssignableFrom(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl1, jclass Cl2);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getSuperclass
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getSuperclass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isInstance
+ * Signature: (Ljava/lang/Class;Ljava/lang/Object;)Z
+ */
+JNIEXPORT bool JNICALL Java_java_lang_VMClass_isInstance(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass par1, jobject par2);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredFields
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getDeclaredFields(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass par1, jboolean publicOnly);
+
+
+
+
+
+
+
+
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getInterfaces
+ * Signature: (Ljava/lang/Class;)[Ljava/lang/Class;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getInterfaces(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass par1);
+
+
+
+
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaringClass
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getDeclaringClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+/*
+ * Class: java/lang/VMClass
+ * Method: throwException
+ * Signature: (Ljava/lang/Throwable;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject throwable);
+
+#if 0
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredClasses
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/Class;
+ */
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredClasses(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1, s4 par2);
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredAnnotations
+ * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
+ */
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredAnnotations(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getEnclosingClass
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT struct java_lang_Class* JNICALL Java_java_lang_VMClass_getEnclosingClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getEnclosingConstructor
+ * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+ */
+JNIEXPORT struct java_lang_reflect_Constructor* JNICALL Java_java_lang_VMClass_getEnclosingConstructor(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getEnclosingMethod
+ * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
+ */
+JNIEXPORT struct java_lang_reflect_Method* JNICALL Java_java_lang_VMClass_getEnclosingMethod(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getClassSignature
+ * Signature: (Ljava/lang/Class;)Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_java_lang_VMClass_getClassSignature(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isAnonymousClass
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAnonymousClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isLocalClass
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isMemberClass
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Class* par1);
+#endif
+}
+#endif
+
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMClassLoader.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMClassLoader.cpp
new file mode 100644
index 0000000..caf361b
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMClassLoader.cpp
@@ -0,0 +1,124 @@
+//===- ClasspathVMClassLoader.cpp - GNU classpath java/lang/VMClassLoader -===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "LockedMap.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jchar byteId) {
+
+ AssessorDesc* ass = AssessorDesc::byteIdToPrimitive(byteId);
+ Jnjvm* vm = JavaThread::get()->isolate;
+ if (!ass)
+ vm->unknownError("unknown byte primitive %c", byteId);
+
+ return (jobject)ass->classType->getClassDelegatee();
+
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_findLoadedClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject loader,
+ jobject _name) {
+
+ Jnjvm* vm = JavaThread::get()->isolate;
+ JavaString* name = (JavaString*)_name;
+ const UTF8* utf8 = name->strToUTF8(vm);
+ CommonClass* cl = vm->lookupClass(utf8, (JavaObject*)loader);
+
+ if (cl) return (jclass)(cl->getClassDelegatee());
+ else return 0;
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_loadClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject _str,
+ jboolean doResolve) {
+ JavaString* str = (JavaString*)_str;
+ Jnjvm* vm = JavaThread::get()->isolate;
+
+ CommonClass* cl = vm->lookupClassFromJavaString(str, 0, doResolve, false, false);
+
+ if (cl != 0) {
+ return (jclass)cl->getClassDelegatee();
+ } else {
+ return 0;
+ }
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject loader,
+ jobject _str,
+ jobject bytes,
+ jint off,
+ jint len,
+ jobject pd) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ JavaString* str = (JavaString*)_str;
+ const UTF8* name = str->value->javaToInternal(vm, str->offset, str->count);
+ Class* cl = vm->constructClass(name, (JavaObject*)loader);
+
+ if (cl->status == hashed) {
+ cl->aquire();
+ if (cl->status == hashed) {
+ cl->bytes = (ArrayUInt8*)bytes;
+ cl->status = loaded;
+#ifdef SINGLE_VM
+ cl->delegatee = (JavaObject*)pd;
+#else
+ vm->delegatees->hash(cl, (JavaObject*)pd);
+#endif
+ }
+ cl->release();
+ }
+ return (jclass)(cl->getClassDelegatee());
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jclass Cl) {
+ verifyNull(Cl);
+ NativeUtil::resolvedImplClass(Cl, false);
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMClassLoader.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMClassLoader.h
new file mode 100644
index 0000000..de3ef82
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMClassLoader.h
@@ -0,0 +1,101 @@
+//===------ ClasspathVMClassLoader.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMCLASSLOADER_H
+#define _JAVA_LANG_VMCLASSLOADER_H
+
+#include <jni.h>
+
+extern "C" {
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: getPrimitiveClass
+ * Signature: (C)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jchar par1);
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: findLoadedClass
+ * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_findLoadedClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject loader, jobject name);
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: loadClass
+ * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_loadClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject str, jboolean doResolve);
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: defineClass
+ * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject loader, jobject str, jobject bytes, jint off, jint len, jobject pd);
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: resolveClass
+ * Signature: (Ljava/lang/Class;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+
+
+#if 0
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: nativeGetResources
+ * Signature: (Ljava/lang/String;)Ljava/util/Vector;
+ */
+JNIEXPORT struct java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_String* par1);
+
+
+
+
+#endif
+
+}
+
+#endif
+
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMField.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMField.cpp
new file mode 100644
index 0000000..2277ddd
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMField.cpp
@@ -0,0 +1,377 @@
+//===- ClasspathVMField.cpp - GNU classpath java/lang/reflect/Field -------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ClasspathVMField.h"
+#include "JavaClass.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Field_getModifiersInternal(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)obj).IntVal.getZExtValue());
+ return field->access;
+}
+
+JNIEXPORT jclass JNICALL Java_java_lang_reflect_Field_getType(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)obj).IntVal.getZExtValue());
+ JavaObject* loader = field->classDef->classLoader;
+ CommonClass* cl = field->signature->assocClass(loader);
+ return (jclass)cl->getClassDelegatee();
+}
+
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Field_getInt(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dInt && ass != AssessorDesc::dChar && ass != AssessorDesc::dByte && ass != AssessorDesc::dShort)
+ JavaThread::get()->isolate->illegalArgumentException("");
+
+ return (sint32)(*field)((JavaObject*)obj).IntVal.getZExtValue();
+}
+
+JNIEXPORT jlong JNICALL Java_java_lang_reflect_Field_getLong(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dInt && ass != AssessorDesc::dChar && ass != AssessorDesc::dByte && ass != AssessorDesc::dShort &&
+ ass != AssessorDesc::dLong)
+ JavaThread::get()->isolate->illegalArgumentException("");
+
+ return (sint64)(*field)((JavaObject*)obj).IntVal.getZExtValue();
+}
+
+JNIEXPORT jboolean JNICALL Java_java_lang_reflect_Field_getBoolean(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dBool)
+ JavaThread::get()->isolate->illegalArgumentException("");
+ return (uint8)(*field)((JavaObject*)obj).IntVal.getZExtValue();
+}
+
+JNIEXPORT jfloat JNICALL Java_java_lang_reflect_Field_getFloat(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dByte || ass == AssessorDesc::dInt || ass == AssessorDesc::dShort || ass == AssessorDesc::dLong) {
+ return (jfloat)(*field)((JavaObject*)obj).IntVal.getSExtValue();
+ } else if (ass == AssessorDesc::dChar) {
+ return (jfloat)(*field)((JavaObject*)obj).IntVal.getZExtValue();
+ } else if (ass == AssessorDesc::dFloat) {
+ return (jfloat)(*field)((JavaObject*)obj).FloatVal;
+ }
+ JavaThread::get()->isolate->illegalArgumentException("");
+ return 0.0;
+}
+
+JNIEXPORT jbyte JNICALL Java_java_lang_reflect_Field_getByte(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dByte)
+ JavaThread::get()->isolate->illegalArgumentException("");
+ return (sint8)(*field)((JavaObject*)obj).IntVal.getSExtValue();
+}
+
+JNIEXPORT jchar JNICALL Java_java_lang_reflect_Field_getChar(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dChar)
+ JavaThread::get()->isolate->illegalArgumentException("");
+ return (uint16)(*field)((JavaObject*)obj).IntVal.getZExtValue();
+}
+
+JNIEXPORT jshort JNICALL Java_java_lang_reflect_Field_getShort(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dShort && ass != AssessorDesc::dByte)
+ JavaThread::get()->isolate->illegalArgumentException("");
+ return (sint16)(*field)((JavaObject*)obj).IntVal.getSExtValue();
+}
+
+JNIEXPORT jdouble JNICALL Java_java_lang_reflect_Field_getDouble(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dByte || ass == AssessorDesc::dInt || ass == AssessorDesc::dShort || ass == AssessorDesc::dLong) {
+ return (jdouble)(*field)((JavaObject*)obj).IntVal.getSExtValue();
+ } else if (ass == AssessorDesc::dChar) {
+ return (jdouble)(*field)((JavaObject*)obj).IntVal.getZExtValue();
+ } else if (ass == AssessorDesc::dFloat) {
+ return (jdouble)(*field)((JavaObject*)obj).FloatVal;
+ } else if (ass == AssessorDesc::dDouble) {
+ return (jdouble)(*field)((JavaObject*)obj).DoubleVal;
+ }
+ JavaThread::get()->isolate->illegalArgumentException("");
+ return 0.0;
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Field_get(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject _obj) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ Typedef* type = field->signature;
+ const AssessorDesc* ass = type->funcs;
+ JavaObject* obj = (JavaObject*)_obj;
+ llvm::GenericValue gv = (*field)(obj);
+
+ JavaObject* res = 0;
+ if (ass == AssessorDesc::dBool) {
+ res = (*Classpath::boolClass)();
+ (*Classpath::boolValue)(res, (uint32)gv.IntVal.getBoolValue());
+ } else if (ass == AssessorDesc::dByte) {
+ res = (*Classpath::byteClass)();
+ (*Classpath::byteValue)(res, (uint32)gv.IntVal.getSExtValue());
+ } else if (ass == AssessorDesc::dChar) {
+ res = (*Classpath::charClass)();
+ (*Classpath::charValue)(res, (uint32)gv.IntVal.getZExtValue());
+ } else if (ass == AssessorDesc::dShort) {
+ res = (*Classpath::shortClass)();
+ (*Classpath::shortValue)(res, (uint32)gv.IntVal.getSExtValue());
+ } else if (ass == AssessorDesc::dInt) {
+ res = (*Classpath::intClass)();
+ (*Classpath::intValue)(res, (uint32)gv.IntVal.getSExtValue());
+ } else if (ass == AssessorDesc::dLong) {
+ res = (*Classpath::longClass)();
+ (*Classpath::longValue)(res, (sint64)gv.IntVal.getSExtValue());
+ } else if (ass == AssessorDesc::dFloat) {
+ res = (*Classpath::floatClass)();
+ (*Classpath::floatValue)(res, gv.FloatVal);
+ } else if (ass == AssessorDesc::dDouble) {
+ res = (*Classpath::doubleClass)();
+ (*Classpath::doubleValue)(res, gv.DoubleVal);
+ } else if (ass == AssessorDesc::dTab || ass == AssessorDesc::dRef) {
+ res = (JavaObject*)gv.PointerVal;
+ } else {
+ JavaThread::get()->isolate->unknownError("should not be here");
+ }
+ return (jobject)res;
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_set(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jobject val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ void** buf = (void**)alloca(sizeof(uint64));
+ void* _buf = (void*)buf;
+ NativeUtil::decapsulePrimitive(JavaThread::get()->isolate, buf, (JavaObject*)val, field->signature);
+
+ const AssessorDesc* ass = field->signature->funcs;
+
+ if (ass == AssessorDesc::dBool) {
+ (*field)((JavaObject*)obj, ((uint32*)_buf)[0]);
+ } else if (ass == AssessorDesc::dByte) {
+ (*field)((JavaObject*)obj, ((uint32*)_buf)[0]);
+ } else if (ass == AssessorDesc::dChar) {
+ (*field)((JavaObject*)obj, ((uint32*)_buf)[0]);
+ } else if (ass == AssessorDesc::dShort) {
+ (*field)((JavaObject*)obj, ((uint32*)_buf)[0]);
+ } else if (ass == AssessorDesc::dInt) {
+ (*field)((JavaObject*)obj, ((uint32*)_buf)[0]);
+ } else if (ass == AssessorDesc::dLong) {
+ (*field)((JavaObject*)obj, ((sint64*)_buf)[0]);
+ } else if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, ((float*)_buf)[0]);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, ((double*)_buf)[0]);
+ } else if (ass == AssessorDesc::dTab || ass == AssessorDesc::dRef) {
+ (*field)((JavaObject*)obj, ((JavaObject**)_buf)[0]);
+ } else {
+ JavaThread::get()->isolate->unknownError("should not be here");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setBoolean(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jboolean val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass != AssessorDesc::dBool)
+ JavaThread::get()->isolate->illegalArgumentException("");
+ (*field)((JavaObject*)obj, (uint32)val);
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setByte(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jbyte val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dByte || ass == AssessorDesc::dShort || ass == AssessorDesc::dInt) {
+ (*field)((JavaObject*)obj, (uint32)val);
+ } else if (ass == AssessorDesc::dLong) {
+ (*field)((JavaObject*)obj, (sint64)val);
+ } else if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, (float)val);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setChar(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jchar val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dChar || ass == AssessorDesc::dInt) {
+ (*field)((JavaObject*)obj, (uint32)val);
+ } else if (ass == AssessorDesc::dLong) {
+ (*field)((JavaObject*)obj, (sint64)val);
+ } else if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, (float)val);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setShort(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jshort val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dShort || ass == AssessorDesc::dInt) {
+ (*field)((JavaObject*)obj, (uint32)val);
+ } else if (ass == AssessorDesc::dLong) {
+ (*field)((JavaObject*)obj, (sint64)val);
+ } else if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, (float)val);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setInt(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jint val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dInt) {
+ (*field)((JavaObject*)obj, (uint32)val);
+ } else if (ass == AssessorDesc::dLong) {
+ (*field)((JavaObject*)obj, (sint64)val);
+ } else if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, (float)val);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setLong(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jlong val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dLong) {
+ (*field)((JavaObject*)obj, (sint64)val);
+ } else if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, (float)val);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setFloat(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jfloat val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dFloat) {
+ (*field)((JavaObject*)obj, (float)val);
+ } else if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setDouble(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jdouble val) {
+ JavaField* field = (JavaField*)((*Classpath::fieldSlot)((JavaObject*)Field).IntVal.getZExtValue());
+ const AssessorDesc* ass = field->signature->funcs;
+ if (ass == AssessorDesc::dDouble) {
+ (*field)((JavaObject*)obj, (double)val);
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("");
+ }
+}
+
+
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMField.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMField.h
new file mode 100644
index 0000000..0f83a95
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMField.h
@@ -0,0 +1,268 @@
+//===------------ ClasspathVMField.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_REFLECT_FIELD_H
+#define _JAVA_LANG_REFLECT_FIELD_H
+
+#include <jni.h>
+
+extern "C" {
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Field_getModifiersInternal(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getType
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_reflect_Field_getType(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject field);
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getInt
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_Field_getInt(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getLong
+ * Signature: (Ljava/lang/Object;)J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_reflect_Field_getLong(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: get
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_Field_get(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject _obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getBoolean
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_reflect_Field_getBoolean(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject _obj);
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getFloat
+ * Signature: (Ljava/lang/Object;)F
+ */
+JNIEXPORT jfloat JNICALL Java_java_lang_reflect_Field_getFloat(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject _obj);
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getByte
+ * Signature: (Ljava/lang/Object;)B
+ */
+JNIEXPORT jbyte JNICALL Java_java_lang_reflect_Field_getByte(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getChar
+ * Signature: (Ljava/lang/Object;)C
+ */
+JNIEXPORT jchar JNICALL Java_java_lang_reflect_Field_getChar(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getShort
+ * Signature: (Ljava/lang/Object;)S
+ */
+JNIEXPORT jshort JNICALL Java_java_lang_reflect_Field_getShort(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getDouble
+ * Signature: (Ljava/lang/Object;)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_reflect_Field_getDouble(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: set
+ * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_set(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jobject val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setBoolean
+ * Signature: (Ljava/lang/Object;Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setBoolean(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jboolean val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setByte
+ * Signature: (Ljava/lang/Object;B)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setByte(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jbyte val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setChar
+ * Signature: (Ljava/lang/Object;C)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setChar(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jchar val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setShort
+ * Signature: (Ljava/lang/Object;S)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setShort(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jshort val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setInt
+ * Signature: (Ljava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setInt(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jint val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setLong
+ * Signature: (Ljava/lang/Object;J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setLong(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jlong val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setFloat
+ * Signature: (Ljava/lang/Object;F)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setFloat(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jfloat val);
+
+
+/*
+ * Class: java/lang/reflect/Field
+ * Method: setDouble
+ * Signature: (Ljava/lang/Object;D)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setDouble(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject Field, jobject obj, jdouble val);
+
+#if 0
+/*
+ * Class: java/lang/reflect/Field
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_java_lang_reflect_Field_getSignature(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+struct java_lang_reflect_Field* this);
+#endif
+}
+#endif
+
+
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMObject.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMObject.cpp
new file mode 100644
index 0000000..425433e
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMObject.cpp
@@ -0,0 +1,93 @@
+//===------ ClasspathVMObject.cpp - GNU classpath java/lang/VMObject ------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject _src) {
+
+ JavaObject* src = (JavaObject*)_src;
+ uint64 size = src->objectSize() + 4; // + VT
+ JavaObject* res = (JavaObject*)
+ gc::operator new(size, src->getVirtualTable());
+ memcpy(res, src, size);
+ return (jobject)res;
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMObject_getClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject _obj) {
+ JavaObject* obj = (JavaObject*)_obj;
+ return (jobject)(obj->classOf->getClassDelegatee());
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+
+ jobject _obj) {
+ JavaObject* obj = (JavaObject*)_obj;
+ obj->notifyAll();
+}
+
+
+JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject _object, jlong ms, jint ns) {
+ uint32 sec = (uint32) (ms / 1000);
+ uint32 usec = (ns / 1000) + 1000 * (ms % 1000);
+ JavaObject* obj = (JavaObject*)_object;
+ if (sec || usec) {
+ struct timeval t;
+ t.tv_sec = sec;
+ t.tv_usec = usec;
+ obj->timedWait(t);
+ } else {
+ obj->wait();
+ }
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject obj) {
+ ((JavaObject*)obj)->notify();
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMObject.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMObject.h
new file mode 100644
index 0000000..406bd30
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMObject.h
@@ -0,0 +1,78 @@
+//===----------- ClasspathVMObject.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMOBJECT_H
+#define _JAVA_LANG_VMOBJECT_H
+
+extern "C" {
+
+/*
+ * Class: java/lang/VMObject
+ * Method: clone
+ * Signature: (Ljava/lang/Cloneable;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject par1);
+
+/*
+ * Class: java/lang/VMObject
+ * Method: getClass
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Class;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMObject_getClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject obj);
+
+/*
+ * Class: java/lang/VMObject
+ * Method: notifyAll
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject par1);
+
+/*
+ * Class: java/lang/VMObject
+ * Method: wait
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject par1, jlong par2, jint par3);
+
+/*
+ * Class: java/lang/VMObject
+ * Method: notify
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject obj);
+
+
+
+}
+#endif
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMRuntime.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMRuntime.cpp
new file mode 100644
index 0000000..e0acb2e
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMRuntime.cpp
@@ -0,0 +1,153 @@
+//===------ ClasspathVMRuntime.cpp - GNU classpath java/lang/VMRuntime ----===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <dlfcn.h>
+#include <string.h>
+
+#include "mvm/GC/GC.h"
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+
+using namespace jnjvm;
+
+extern "C" {
+
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMRuntime_mapLibraryName(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jobject _strLib) {
+ JavaString* strLib = (JavaString*)_strLib;
+ Jnjvm* vm = JavaThread::get()->isolate;
+
+ const UTF8* utf8Lib = strLib->value;
+ uint32 stLib = strLib->offset;
+ sint32 lgLib = strLib->count;
+ sint32 lgPre = vm->prelib->size;
+ sint32 lgPost = vm->postlib->size;
+
+ UTF8* res = UTF8::acons(lgPre + lgLib + lgPost, JavaArray::ofChar);
+
+ memmove(res->elements, vm->prelib->elements, lgPre * sizeof(uint16));
+ memmove(&(res->elements[lgPre]), &(utf8Lib->elements[stLib]), lgLib * sizeof(uint16));
+ memmove(&(res->elements[lgPre + lgLib]), vm->postlib->elements, lgPost * sizeof(uint16));
+
+ return (jobject)(vm->UTF8ToStr(res));
+
+}
+
+typedef int (*onLoad_t)(const void**, void*);
+
+JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_nativeLoad(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject _str,
+ jobject _loader) {
+ JavaString* str = (JavaString*)_str;
+ Jnjvm* vm = JavaThread::get()->isolate;
+
+ char* buf = str->strToAsciiz();
+
+ void* res = dlopen(buf, RTLD_LAZY | RTLD_LOCAL);
+ if (res != 0) {
+ vm->nativeLibs.push_back(res);
+ onLoad_t onLoad = (onLoad_t)dlsym(res, "JNI_OnLoad");
+ if (onLoad) onLoad(&vm->javavmEnv, 0);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_gc(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ gc::collect();
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalization(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ return;
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizationForExit(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ return;
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_exit(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jint par1) {
+#ifdef SINGLE_VM
+ exit(par1);
+#else
+ // TODO: do a longjmp
+ exit(par1);
+#endif
+}
+
+JNIEXPORT jlong Java_java_lang_VMRuntime_freeMemory(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ return (jlong)512*1000;//gc::getFreeMemory();
+}
+
+JNIEXPORT jlong Java_java_lang_VMRuntime_totalMemory(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ return (jlong)512*1000;//gc::getTotalMemory();
+}
+
+JNIEXPORT jlong Java_java_lang_VMRuntime_maxMemory(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ return (jlong)512*1000;//gc::getMaxMemory();
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMRuntime.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMRuntime.h
new file mode 100644
index 0000000..cc36400
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMRuntime.h
@@ -0,0 +1,193 @@
+//===-------- ClasspathVMRuntime.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMRUNTIME_H
+#define _JAVA_LANG_VMRUNTIME_H
+
+#include <jni.h>
+
+extern "C" {
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: mapLibraryName
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMRuntime_mapLibraryName(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject strLib);
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: nativeLoad
+ * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_nativeLoad(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject _str, jobject _loader);
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: gc
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_gc(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: runFinalization
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalization(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: runFinalizationForExit
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizationForExit(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: exit
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_exit(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jint par1);
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: freeMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_VMRuntime_freeMemory(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz
+#endif
+);
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: totalMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_VMRuntime_totalMemory(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz
+#endif
+);
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: maxMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_VMRuntime_maxMemory(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz
+#endif
+);
+
+#if 0
+/*
+ * Class: java/lang/VMRuntime
+ * Method: availableProcessors
+ * Signature: ()I
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_availableProcessors(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz);
+
+
+
+
+
+
+
+
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: traceInstructions
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceInstructions(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, s4 par1);
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: traceMethodCalls
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceMethodCalls(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, s4 par1);
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: runFinalizersOnExit
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizersOnExit(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, s4 par1);
+
+
+
+
+
+
+
+#endif
+
+}
+
+#endif
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMStackWalker.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMStackWalker.cpp
new file mode 100644
index 0000000..a6f36fb
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMStackWalker.cpp
@@ -0,0 +1,119 @@
+//===- ClasspathVMStackWalker.cpp -----------------------------------------===//
+//===------------ GNU classpath gnu/classpath/VMStackWalker ---------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+#include <execinfo.h>
+
+using namespace jnjvm;
+
+extern "C" JavaMethod* ip_to_meth(int* ip);
+
+extern "C" {
+
+ArrayObject* recGetClassContext(int** stack, uint32 size, uint32 first, uint32 rec) {
+ if (size != first) {
+ int *begIp = (int*)gc::begOf(stack[first]);
+ JavaMethod* meth = ip_to_meth(begIp);
+ if (meth) {
+ ArrayObject* res = recGetClassContext(stack, size, first + 1, rec + 1);
+ res->setAt(rec, meth->classDef->getClassDelegatee());
+ return res;
+ } else {
+ return recGetClassContext(stack, size, first + 1, rec);
+ }
+ } else {
+ return ArrayObject::acons(rec, Classpath::classArrayClass);
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getClassContext(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ int* ips[100];
+ int real_size = backtrace((void**)(void*)ips, 100);
+ int i = 0;
+ int first = 0;
+ CommonClass* cl = Classpath::vmStackWalker;
+
+ while (i < real_size) {
+ int *begIp = (int*)gc::begOf(ips[i++]);
+ JavaMethod* meth = ip_to_meth(begIp);
+ if (meth && meth->classDef == cl) {
+ first = i;
+ break;
+ }
+ }
+
+ return (jobject)recGetClassContext(ips, real_size, first, 0);
+}
+
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getClassLoader(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass _Cl) {
+ JavaObject* Cl = (JavaObject*)_Cl;
+ CommonClass* cl = (CommonClass*)((*Cl)(Classpath::vmdataClass).PointerVal);
+ return (jobject)cl->classLoader;
+}
+
+extern "C" JavaObject* getCallingClass() {
+ int* ips[10];
+ int real_size = backtrace((void**)(void*)ips, 100);
+ int n = 0;
+ int i = 0;
+
+ while (i < real_size) {
+ int *begIp = (int*)gc::begOf(ips[i++]);
+ JavaMethod* meth = ip_to_meth(begIp);
+ if (meth) {
+ ++n;
+ if (n == 1) return meth->classDef->getClassDelegatee();
+ }
+ }
+
+ return 0;
+}
+
+extern "C" JavaObject* getCallingClassLoader() {
+ int* ips[10];
+ int real_size = backtrace((void**)(void*)ips, 100);
+ int n = 0;
+ int i = 0;
+
+ while (i < real_size) {
+ int *begIp = (int*)gc::begOf(ips[i++]);
+ JavaMethod* meth = ip_to_meth(begIp);
+ if (meth) {
+ ++n;
+ if (n == 1) return meth->classDef->classLoader;
+ }
+ }
+
+ return 0;
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMStackWalker.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMStackWalker.h
new file mode 100644
index 0000000..f218d3b
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMStackWalker.h
@@ -0,0 +1,61 @@
+//===------- ClasspathVMStackWalker.h - Classpath methods -----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GNU_CLASSPATH_VMSTACKWALKER_H
+#define _GNU_CLASSPATH_VMSTACKWALKER_H
+
+extern "C" {
+
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: getClassContext
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getClassContext(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getClassLoader(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jclass Cl);
+
+#if 0
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: getCallingClass
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_gnu_classpath_VMStackWalker_getCallingClass(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz);
+
+
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: getCallingClassLoader
+ * Signature: ()Ljava/lang/ClassLoader;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getCallingClassLoader(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz);
+#endif
+
+}
+
+#endif
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMSystem.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystem.cpp
new file mode 100644
index 0000000..4f1a644
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystem.cpp
@@ -0,0 +1,109 @@
+//===-- ClasspathVMSystem.cpp - GNU classpath java/lang/VMSystem ----------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass _cl,
+#endif
+ jobject _src,
+ jint sstart,
+ jobject _dst,
+ jint dstart,
+ jint len) {
+ jnjvm::Jnjvm *vm = JavaThread::get()->isolate;
+ JavaArray* src = (JavaArray*)_src;
+ JavaArray* dst = (JavaArray*)_dst;
+
+ verifyNull(src);
+ verifyNull(dst);
+
+ if (!(src->classOf->isArray && dst->classOf->isArray)) {
+ vm->arrayStoreException();
+ }
+
+ ClassArray* ts = (ClassArray*)src->classOf;
+ ClassArray* td = (ClassArray*)dst->classOf;
+ AssessorDesc* srcFuncs = ts->funcs();
+ AssessorDesc* dstFuncs = ts->funcs();
+ CommonClass* dstType = td->baseClass();
+
+ if (len > src->size) {
+ vm->indexOutOfBounds(src, len);
+ } else if (len > dst->size) {
+ vm->indexOutOfBounds(dst, len);
+ } else if (len + sstart > src->size) {
+ vm->indexOutOfBounds(src, len + sstart);
+ } else if (len + dstart > dst->size) {
+ vm->indexOutOfBounds(dst, len + dstart);
+ } else if (dstart < 0) {
+ vm->indexOutOfBounds(dst, dstart);
+ } else if (sstart < 0) {
+ vm->indexOutOfBounds(src, sstart);
+ } else if (len < 0) {
+ vm->indexOutOfBounds(src, len);
+ } else if (srcFuncs != dstFuncs) {
+ vm->arrayStoreException();
+ }
+
+ jint i = sstart;
+ bool doThrow = false;
+ if (srcFuncs == AssessorDesc::dTab || srcFuncs == AssessorDesc::dRef) {
+ while (i < sstart + len && !doThrow) {
+ JavaObject* cur = ((ArrayObject*)src)->at(i);
+ if (cur) {
+ if (!(cur->classOf->isAssignableFrom(dstType))) {
+ doThrow = true;
+ len = i;
+ }
+ }
+ ++i;
+ }
+ }
+
+ uint32 size = srcFuncs->llvmType->getPrimitiveSizeInBits() / 8;
+ if (size == 0) size = sizeof(void*);
+ void* ptrDst = (void*)((int64_t)(dst->elements) + size * dstart);
+ void* ptrSrc = (void*)((int64_t)(src->elements) + size * sstart);
+ memmove(ptrDst, ptrSrc, size * len);
+
+ if (doThrow)
+ vm->arrayStoreException();
+
+
+}
+
+JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+ jclass clazz,
+#endif
+ jobject obj) {
+ return (jint)obj;
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMSystem.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystem.h
new file mode 100644
index 0000000..295dfb4
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystem.h
@@ -0,0 +1,105 @@
+//===----------- ClasspathVMSystem.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMSYSTEM_H
+#define _JAVA_LANG_VMSYSTEM_H
+
+#include <jni.h>
+
+
+extern "C" {
+/*
+ * Class: java/lang/VMSystem
+ * Method: arraycopy
+ * Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject par1, jint par2, jobject par3, jint par4, jint par5);
+
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: identityHashCode
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject obj);
+
+
+#if 0
+/*
+ * Class: java/lang/VMSystem
+ * Method: setIn
+ * Signature: (Ljava/io/InputStream;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_setIn(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_io_InputStream* par1);
+
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: setOut
+ * Signature: (Ljava/io/PrintStream;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_setOut(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_io_PrintStream* par1);
+
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: setErr
+ * Signature: (Ljava/io/PrintStream;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_setErr(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_io_PrintStream* par1);
+
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: currentTimeMillis
+ * Signature: ()J
+ */
+JNIEXPORT s8 JNICALL Java_java_lang_VMSystem_currentTimeMillis(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz);
+
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: getenv
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_java_lang_VMSystem_getenv(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_String* par1);
+
+#endif
+}
+#endif
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp
new file mode 100644
index 0000000..b7d3521
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp
@@ -0,0 +1,122 @@
+//===- ClasspathVMSystem/Properties.cpp -----------------------------------===//
+//===--------------------- GNU classpath gnu/classpath/VMSystemProperties -===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+#include <sys/utsname.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+static void setProperty(Jnjvm* vm, JavaObject* prop, const char* key,
+ const char* val) {
+ Classpath::setProperty->invokeIntSpecial(prop, vm->asciizToStr(key), vm->asciizToStr(val));
+}
+
+static void setUnameProp(Jnjvm* vm, JavaObject* prop) {
+ struct utsname infos;
+ uname(&infos);
+ setProperty(vm, prop, "os.name", infos.sysname);
+ setProperty(vm, prop, "os.arch", infos.machine);
+ setProperty(vm, prop, "os.version", infos.version);
+ if (!strcmp(infos.machine, "ppc")) {
+ setProperty(vm, prop, "gnu.cpu.endian","big");
+ } else {
+ setProperty(vm, prop, "gnu.cpu.endian","little");
+ }
+}
+
+JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_preInit(
+
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject _prop) {
+
+ JavaObject* prop = (JavaObject*)_prop;
+ Jnjvm* vm = JavaThread::get()->isolate;
+ const char* tmp;
+ setProperty(vm, prop, "java.vm.specification.version", "1.0");
+ setProperty(vm, prop, "java.vm.specification.vendor", "Sun Microsystems, Inc");
+ setProperty(vm, prop, "java.vm.specification.name", "Java Virtual Machine Specification");
+ setProperty(vm, prop, "java.specification.version", "1.4");
+ setProperty(vm, prop, "java.specification.vendor", "Sun Microsystems, Inc");
+ setProperty(vm, prop, "java.specification.name", "Java Platform API Specification");
+ setProperty(vm, prop, "java.version", "1.4");
+ setProperty(vm, prop, "java.runtime.version", "1.4");
+ setProperty(vm, prop, "java.vendor", "VVM Project");
+ setProperty(vm, prop, "java.vendor.url", "http://vvm.lip6.fr");
+
+ tmp = getenv("JAVA_HOME");
+ if (!tmp) tmp = "";
+ setProperty(vm, prop, "java.home", tmp);
+
+ setProperty(vm, prop, "java.class.version", "48.0");
+ setProperty(vm, prop, "java.class.path", vm->classpath);
+ setProperty(vm, prop, "java.boot.class.path", vm->bootClasspathEnv);
+ setProperty(vm, prop, "sun.boot.class.path", vm->bootClasspathEnv);
+ setProperty(vm, prop, "java.vm.version", "2.0");
+ setProperty(vm, prop, "java.vm.vendor", "VVM Project");
+ setProperty(vm, prop, "java.vm.name", "JnJVM");
+ setProperty(vm, prop, "java.specification.version", "1.4");
+ setProperty(vm, prop, "java.library.path", vm->libClasspathEnv);
+ setProperty(vm, prop, "java.io.tmpdir", "/tmp");
+
+ tmp = getenv("JAVA_COMPILER");
+ if (!tmp) tmp = "gcj";
+ setProperty(vm, prop, "java.compiler", tmp);
+
+ setProperty(vm, prop, "build.compiler", "gcj");
+ setProperty(vm, prop, "gcj.class.path", vm->bootClasspathEnv);
+
+ setUnameProp(vm, prop);
+
+ setProperty(vm, prop, "file.separator", vm->dirSeparator);
+ setProperty(vm, prop, "path.separator", vm->envSeparator);
+ setProperty(vm, prop, "line.separator", "\n");
+
+ tmp = getenv("USERNAME");
+ if (!tmp) tmp = getenv("LOGNAME");
+ else if (!tmp) tmp = getenv("NAME");
+ else if (!tmp) tmp = "";
+ setProperty(vm, prop, "user.name", tmp);
+
+ tmp = getenv("HOME");
+ if (!tmp) tmp = "";
+ setProperty(vm, prop, "user.home", tmp);
+
+ tmp = getenv("PWD");
+ if (!tmp) tmp = "";
+ setProperty(vm, prop, "user.dir", tmp);
+
+ //setProperty(vm, prop, "gnu.classpath.nio.charset.provider.iconv", "true")
+
+ setProperty(vm, prop, "file.encoding", "ISO8859_1");
+
+
+}
+
+
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMSystemProperties.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystemProperties.h
new file mode 100644
index 0000000..0c40570
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMSystemProperties.h
@@ -0,0 +1,29 @@
+//===----- ClasspathVMSystemProperties.h - Classpath methods --------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GNU_CLASSPATH_VMSYSTEMPROPERTIES_H
+#define _GNU_CLASSPATH_VMSYSTEMPROPERTIES_H
+
+extern "C" {
+/*
+ * Class: gnu/classpath/VMSystemProperties
+ * Method: preInit
+ * Signature: (Ljava/util/Properties;)V
+ */
+JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_preInit(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject par1);
+
+}
+
+#endif
+
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp
new file mode 100644
index 0000000..724982f
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.cpp
@@ -0,0 +1,167 @@
+//===- ClasspathVMThread.cpp - GNU classpath java/lang/VMThread -----------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "mvm/Threads/Thread.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaIsolate.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+using namespace jnjvm;
+
+extern "C" {
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMThread_currentThread(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz
+#endif
+) {
+ return (jobject)(JavaThread::currentThread());
+}
+
+typedef struct arg_thread_t {
+ JavaObject* vmThread;
+ JavaThread* intern;
+}arg_thread_t;
+
+static void start(arg_thread_t* arg) {
+ int argc;
+ gc::inject_my_thread(&argc);
+ JavaObject* vmThread = arg->vmThread;
+ JavaThread* intern = arg->intern;
+ delete arg;
+ JavaThread::threadKey->set(intern);
+ CommonClass* vmthClass = vmThread->classOf;
+ JavaObject* thread = (JavaObject*)((*ClasspathThread::assocThread)(vmThread).PointerVal);
+ JavaIsolate* isolate = (JavaIsolate*)(intern->isolate);
+ ThreadSystem* ts = isolate->threadSystem;
+ bool isDaemon = (*ClasspathThread::daemon)(thread).IntVal.getBoolValue();
+
+ if (!isDaemon) {
+ ts->nonDaemonLock->lock();
+ ts->nonDaemonThreads++;
+ ts->nonDaemonLock->unlock();
+ }
+
+ JavaMethod* method = vmthClass->lookupMethod(Jnjvm::runName, Jnjvm::clinitType, ACC_VIRTUAL, true);
+ method->invokeIntSpecial(vmThread);
+
+
+ if (!isDaemon) {
+ ts->nonDaemonLock->lock();
+ ts->nonDaemonThreads--;
+ if (ts->nonDaemonThreads == 0)
+ ts->nonDaemonVar->signal();
+ ts->nonDaemonLock->unlock();
+ }
+ gc::remove_my_thread();
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMThread_start(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject _vmThread, sint64 stackSize) {
+ JavaObject* vmThread = (JavaObject*)_vmThread;
+ JavaObject* javaThread = (JavaObject*)(*ClasspathThread::assocThread)(vmThread).PointerVal;
+ assert(javaThread);
+
+ JavaThread* th = JavaThread::allocate(javaThread, JavaThread::get()->isolate);
+ (*ClasspathThread::vmdata)(vmThread, (JavaObject*)th);
+ int tid = 0;
+ arg_thread_t* arg = (arg_thread_t*)malloc(sizeof(arg_thread_t));
+ arg->intern = th;
+ arg->vmThread = vmThread;
+ mvm::Thread::start(&tid, (int (*)(void *))start, (void*)arg);
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject _vmthread) {
+ JavaObject* vmthread = (JavaObject*)_vmthread;
+
+ while ((*ClasspathThread::vmdata)(vmthread).PointerVal == 0) mvm::Thread::yield();
+
+ JavaThread* th = (JavaThread*)(*ClasspathThread::vmdata)(vmthread).PointerVal;
+ th->lock->lock();
+ th->interruptFlag = 1;
+
+ // here we could also raise a signal for interrupting I/O
+ if (th->state == JavaThread::StateWaiting) {
+ th->state = JavaThread::StateInterrupted;
+ th->varcond->signal();
+ }
+
+ th->lock->unlock();
+}
+
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_interrupted(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ JavaThread* th = JavaThread::get();
+ uint32 interrupt = th->interruptFlag;
+ th->interruptFlag = 0;
+ return (jboolean)interrupt;
+}
+
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_isInterrupted(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject _vmthread) {
+ JavaObject* vmthread = (JavaObject*)_vmthread;
+ JavaThread* th = (JavaThread*)(*ClasspathThread::vmdata)(vmthread).PointerVal;
+ return (jboolean)th->interruptFlag;
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthread, jint prio) {
+ // Currently not implemented
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeStop(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthread, jobject exc) {
+ // Currently not implemented
+}
+
+JNIEXPORT void JNICALL Java_java_lang_VMThread_yield(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+) {
+ mvm::Thread::yield();
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.h
new file mode 100644
index 0000000..baefd57
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMThread.h
@@ -0,0 +1,174 @@
+//===----------- ClasspathVMThread.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMTHREAD_H
+#define _JAVA_LANG_VMTHREAD_H
+
+#include <jni.h>
+#include "types.h"
+
+extern "C" {
+
+/*
+ * Class: java/lang/VMThread
+ * Method: currentThread
+ * Signature: ()Ljava/lang/Thread;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMThread_currentThread(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: start
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_start(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject obj, sint64 stackSize);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: interrupt
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthread);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: interrupted
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_interrupted(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: isInterrupted
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_isInterrupted(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthread);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: nativeSetPriority
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthread, jint prio);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: nativeStop
+ * Signature: (Ljava/lang/Throwable;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeStop(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthread, jobject exc);
+
+/*
+ * Class: java/lang/VMThread
+ * Method: yield
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_yield(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+);
+
+#if 0
+/*
+ * Class: java/lang/VMThread
+ * Method: countStackFrames
+ * Signature: ()I
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_VMThread_countStackFrames(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+struct java_lang_VMThread* this);
+
+
+
+
+
+
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: suspend
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_suspend(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+struct java_lang_VMThread* this);
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: resume
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_resume(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+struct java_lang_VMThread* this);
+
+
+
+
+
+
+
+
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: holdsLock
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_VMThread_holdsLock(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jclass clazz, struct java_lang_Object* par1);
+
+#endif
+}
+
+#endif
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMThrowable.cpp b/vmkit/lib/JnJVM/Classpath/ClasspathVMThrowable.cpp
new file mode 100644
index 0000000..3dde18c
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMThrowable.cpp
@@ -0,0 +1,117 @@
+//===- ClasspathVMClassLoader.cpp - GNU classpath java/lang/VMClassLoader -===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaAccess.h"
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaTypes.h"
+#include "JavaThread.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+#include "Reader.h"
+
+#include <execinfo.h>
+
+using namespace jnjvm;
+
+extern "C" int backtrace_fp(int** ips, int size, int**);
+extern "C" JavaMethod* ip_to_meth(int* ip);
+
+extern "C" {
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_fillInStackTrace(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+ jobject throwable) {
+ //int** fp = (int**)__builtin_frame_address(0);
+ int** stack = (int**)alloca(sizeof(int*) * 100);
+ int real_size = backtrace((void**)stack, 100);
+ ArrayUInt32* obj = ArrayUInt32::acons(real_size, JavaArray::ofInt);
+ memcpy(obj->elements, stack, real_size * sizeof(int));
+ JavaObject* vmThrowable = (*Classpath::newVMThrowable)();
+ Classpath::initVMThrowable->invokeIntSpecial(vmThrowable);
+ (*Classpath::vmDataVMThrowable)(vmThrowable, obj);
+ return (jobject)vmThrowable;
+}
+
+JavaObject* consStackElement(JavaMethod* meth, int* ip) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ JavaObject* methodName = vm->UTF8ToStr(meth->name);
+ Class* cl = meth->classDef;
+ JavaObject* className = vm->UTF8ToStr(cl->name->internalToJava(vm, 0, cl->name->size));
+ JavaObject* sourceName = 0;
+
+ Attribut* sourceAtt = Attribut::lookup(&cl->attributs,
+ Attribut::sourceFileAttribut);
+
+ if (sourceAtt) {
+ Reader* reader = sourceAtt->toReader(cl->bytes, sourceAtt);
+ uint16 index = reader->readU2();
+ sourceName = vm->UTF8ToStr(cl->ctpInfo->UTF8At(index));
+ }
+
+ bool native = isNative(meth->access);
+
+ JavaObject* res = (*Classpath::newStackTraceElement)();
+ Classpath::initStackTraceElement->invokeIntSpecial(res, sourceName, (int)ip, className, methodName, native);
+ return res;
+}
+
+ArrayObject* recGetStackTrace(int** stack, uint32 size, uint32 first, uint32 rec) {
+ if (size != first) {
+ int *begIp = (int*)gc::begOf(stack[first]);
+ JavaMethod* meth = ip_to_meth(begIp);
+ if (meth) {
+ ArrayObject* res = recGetStackTrace(stack, size, first + 1, rec + 1);
+ res->setAt(rec, consStackElement(meth, stack[first]));
+ return res;
+ } else {
+ return recGetStackTrace(stack, size, first + 1, rec);
+ }
+ } else {
+ return ArrayObject::acons(rec, JavaArray::ofObject);
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_getStackTrace(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject vmthrow, jobject throwable) {
+ ArrayUInt32* array = (ArrayUInt32*)(*Classpath::vmDataVMThrowable)((JavaObject*)vmthrow).PointerVal;
+ uint32* stack = array->elements;
+ CommonClass* cl = ((JavaObject*)throwable)->classOf;
+ uint32 first = 0;
+ sint32 i = 0;
+
+ while (i < array->size) {
+ int *begIp = (int*)gc::begOf((void*)stack[i++]);
+ JavaMethod* meth = ip_to_meth(begIp);
+ if (meth && meth->classDef == cl) {
+ first = i;
+ break;
+ }
+ }
+ return (jobject)recGetStackTrace((int**)(uint32**)stack, array->size, first, 0);
+}
+
+}
diff --git a/vmkit/lib/JnJVM/Classpath/ClasspathVMThrowable.h b/vmkit/lib/JnJVM/Classpath/ClasspathVMThrowable.h
new file mode 100644
index 0000000..4c8887a
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/ClasspathVMThrowable.h
@@ -0,0 +1,39 @@
+//===-------- ClasspathVMThrowable.h - Classpath methods ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _JAVA_LANG_VMTHROWABLE_H
+#define _JAVA_LANG_VMTHROWABLE_H
+
+extern "C" {
+/*
+ * Class: java/lang/VMThrowable
+ * Method: fillInStackTrace
+ * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_fillInStackTrace(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+jclass clazz,
+#endif
+jobject throwable);
+
+/*
+ * Class: java/lang/VMThrowable
+ * Method: getStackTrace
+ * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_getStackTrace(
+#ifdef NATIVE_JNI
+JNIEnv *env,
+#endif
+jobject obj, jobject par1);
+
+}
+#endif
+
diff --git a/vmkit/lib/JnJVM/Classpath/Makefile.am b/vmkit/lib/JnJVM/Classpath/Makefile.am
new file mode 100644
index 0000000..9628de6
--- /dev/null
+++ b/vmkit/lib/JnJVM/Classpath/Makefile.am
@@ -0,0 +1,22 @@
+# $Id: Makefile.am,v 1.6 2008/03/21 11:12:38 varth Exp $
+lib_LTLIBRARIES = libClasspath.la
+
+THREADDIR=../../Mvm/CommonThread
+ALLOCDIR=../../Mvm/Allocator
+GCDIR=../../Mvm/GCMmap2
+INCLUDEDIRS=-I@srcdir@/$(THREADDIR) -I@srcdir@/$(ALLOCDIR) -I@srcdir@/$(GCDIR)\
+ -I../VMCore
+
+PREFIX=@prefix@
+LIBSUVM=$(LIBLLVM) $(LIBGC) $(LIBALLOC) $(LIBTHREAD)
+
+libClasspath_la_SOURCES = \
+ ClasspathVMSystem.cpp ClasspathVMSystem.h Classpath.cpp \
+ ClasspathVMThread.cpp ClasspathVMThread.h ClasspathVMClassLoader.h \
+ ClasspathVMClassLoader.cpp ClasspathVMClass.cpp ClasspathVMClass.h ClasspathVMSystemProperties.h \
+ ClasspathVMSystemProperties.cpp ClasspathVMObject.h ClasspathVMObject.cpp \
+ ClasspathVMRuntime.h ClasspathVMRuntime.cpp ClasspathConstructor.cpp ClasspathConstructor.h \
+ ClasspathVMThrowable.h ClasspathVMThrowable.cpp ClasspathMethod.h ClasspathMethod.cpp \
+ ClasspathVMField.h ClasspathVMField.cpp ClasspathVMStackWalker.cpp ClasspathVMStackWalker.h
+
+libClasspath_la_CXXFLAGS =$(INCLUDEDIRS) -DPREFIX=\"$(PREFIX)\" -W -Wall -ansi -Wno-unused-parameter -Wno-long-long -Wno-unused-function -fno-omit-frame-pointer -DSINGLE_VM -O2 -g -Werror
diff --git a/vmkit/lib/JnJVM/Main.cpp b/vmkit/lib/JnJVM/Main.cpp
new file mode 100644
index 0000000..247bd69
--- /dev/null
+++ b/vmkit/lib/JnJVM/Main.cpp
@@ -0,0 +1,83 @@
+//===--------- Main.cpp - Simple execution of JnJVM -----------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Pierre et Marie Curie
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/GC/GC.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/VMLet.h"
+
+
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "llvm/Support/ManagedStatic.h"
+
+#include "mvm/Threads/Thread.h"
+
+using namespace mvm;
+
+
+static void clearSignals(void) {
+ signal(SIGINT, SIG_DFL);
+ signal(SIGILL, SIG_DFL);
+#if !defined(WIN32)
+ signal(SIGIOT, SIG_DFL);
+ signal(SIGBUS, SIG_DFL);
+#endif
+ signal(SIGSEGV, SIG_DFL);
+}
+
+extern "C" int boot();
+extern "C" int start_app(int, char**);
+extern "C" int ClasspathBoot(int, char**, char**);
+
+#include "VMCore/JavaJIT.h"
+
+void handler2(int n, void *context) {
+ printf("[%d] crashed\n", (int)mvm::Thread::self());
+ jnjvm::JavaJIT::printBacktrace();
+ assert(0);
+}
+
+void handler(int n, siginfo_t *_info, void *context) {
+ printf("[%d] crashed\n", (int)mvm::Thread::self());
+ jnjvm::JavaJIT::printBacktrace();
+ assert(0);
+}
+
+int main(int argc, char **argv, char **envp) {
+ llvm::llvm_shutdown_obj X;
+ int base;
+
+ struct sigaction sa;
+
+ sigaction(SIGINT, 0, &sa);
+ sa.sa_sigaction = handler;
+ sa.sa_flags |= (SA_RESTART | SA_SIGINFO | SA_NODEFER);
+ sigaction(SIGINT, &sa, 0);
+
+ sigaction(SIGILL, 0, &sa);
+ sa.sa_sigaction = handler;
+ sa.sa_flags |= (SA_RESTART | SA_SIGINFO | SA_NODEFER);
+ sigaction(SIGILL, &sa, 0);
+
+
+ VMLet::register_sigsegv_handler(handler2);
+
+ Object::initialise(&base);
+ VMLet::initialise();
+ ClasspathBoot(argc, argv, envp);
+ boot();
+ start_app(argc, argv);
+
+ clearSignals();
+
+ return 0;
+}
diff --git a/vmkit/lib/JnJVM/Makefile.am b/vmkit/lib/JnJVM/Makefile.am
new file mode 100644
index 0000000..56ec573
--- /dev/null
+++ b/vmkit/lib/JnJVM/Makefile.am
@@ -0,0 +1,26 @@
+# $Id: Makefile.am,v 1.6 2008/03/21 11:12:38 varth Exp $
+SUBDIRS = VMCore Classpath
+EXTRA_DIST = OpcodeNames.def
+bin_PROGRAMS = main
+lib_LTLIBRARIES = libjnjvm.la
+
+THREADDIR=../Mvm/CommonThread
+ALLOCDIR=../Mvm/Allocator
+GCDIR=../Mvm/GCMmap2
+INCLUDEDIRS=-I@srcdir@/$(THREADDIR) -I@srcdir@/$(ALLOCDIR) -I@srcdir@/$(GCDIR)
+
+LIBTHREAD=$(THREADDIR)/libuvm_@vvmthreadtype@_thread.a
+LIBALLOC=$(ALLOCDIR)/libuvm_alloc.a
+LIBGC=$(GCDIR)/libuvm_gc_@vvmgctype@.a @GC_LIBS@
+PREFIX=@prefix@
+LIBSUVM=$(LIBLLVM) $(LIBGC) $(LIBALLOC) $(LIBTHREAD)
+
+main_SOURCES = ../Mvm/Object.cc ../Mvm/Sigsegv.cc Main.cpp ../Mvm/MvmMemoryManager.cpp ../Mvm/JIT.cc ../Mvm/EscapeAnalysis.cpp
+
+
+main_CXXFLAGS = $(libJnJVM_la_CXXFLAGS)
+main_LDADD = VMCore/.libs/libJnJVM.a Classpath/.libs/libClasspath.a $(LIBSUVM) @LLVMDYLIB@ -lopcodes -lbfd -liberty -lz
+main_LDFLAGS = @rdynamic@
+
+libjnjvm.la:
+ gcc -shared VMCore/.libs/libJnJVM.so Classpath/.libs/libClasspath.so -o libjnjvm.so
diff --git a/vmkit/lib/JnJVM/README b/vmkit/lib/JnJVM/README
new file mode 100644
index 0000000..df98d05
--- /dev/null
+++ b/vmkit/lib/JnJVM/README
@@ -0,0 +1,33 @@
+1 - GNU Classpath
+Current version 0.93. Use gcj > 4 or ecj
+
+ a - unzip classpath
+ tar -xzf classpath-0.93
+ b - compile classpath
+ cd classpath-0.93
+ ./configure && make
+
+IMPORTANT: for local use
+cd classpath-x.y/lib;
+ln -s ../native/jni/gtk-peer/.libs/libgtkpeer.so;
+ln -s ../native/jni/gconf-peer/.libs/libgconfpeer.so;
+ln -s ../native/jni/java-io/.libs/libjavaio.so;
+ln -s ../native/jni/java-lang/.libs/libjavalangreflect.so;
+ln -s ../native/jni/java-lang/.libs/libjavalang.so;
+ln -s ../native/jni/java-net/.libs/libjavanet.so;
+ln -s ../native/jni/java-nio/.libs/libjavanio.so;
+ln -s ../native/jni/java-util/.libs/libjavautil.so;
+
+Or for Darwin
+ln -s ../native/jni/gtk-peer/.libs/libgtkpeer.dylib;
+ln -s ../native/jni/gconf-peer/.libs/libgconfpeer.dylib;
+ln -s ../native/jni/java-io/.libs/libjavaio.dylib;
+ln -s ../native/jni/java-lang/.libs/libjavalangreflect.dylib;
+ln -s ../native/jni/java-lang/.libs/libjavalang.dylib;
+ln -s ../native/jni/java-net/.libs/libjavanet.dylib;
+ln -s ../native/jni/java-nio/.libs/libjavanio.dylib;
+ln -s ../native/jni/java-util/.libs/libjavautil.dylib;
+
+
+2 - Run JnJVM
+./main HelloWorld
diff --git a/vmkit/lib/JnJVM/TODO b/vmkit/lib/JnJVM/TODO
new file mode 100644
index 0000000..69eff2c
--- /dev/null
+++ b/vmkit/lib/JnJVM/TODO
@@ -0,0 +1,4 @@
+Patch on getVirtualField
+Patch on newLookup
+
+Stubs are currently GC roots, make them isolate-objects
diff --git a/vmkit/lib/JnJVM/VMCore/JavaAccess.h b/vmkit/lib/JnJVM/VMCore/JavaAccess.h
new file mode 100644
index 0000000..80c6d68
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaAccess.h
@@ -0,0 +1,54 @@
+//===----------- JavaAccess.h - Java access description -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_ACCESS_H
+#define JNJVM_JAVA_ACCESS_H
+
+namespace jnjvm {
+
+#define ACC_PUBLIC 0x0001
+#define ACC_PRIVATE 0x0002
+#define ACC_PROTECTED 0x0004
+#define ACC_VIRTUAL 0x0000
+#define ACC_STATIC 0x0008
+#define ACC_FINAL 0x0010
+#define ACC_SYNCHRONIZED 0x0020
+#define ACC_SUPER 0x0020
+#define ACC_VOLATILE 0x0040
+#define ACC_TRANSIENT 0x0080
+#define ACC_NATIVE 0x0100
+#define ACC_INTERFACE 0x0200
+#define ACC_ABSTRACT 0x0400
+#define ACC_STRICT 0x0800
+
+#define MK_VERIFIER(name, flag) \
+ inline bool name(unsigned int param) { \
+ return (flag & param) != 0; \
+ } \
+
+MK_VERIFIER(isStatic, ACC_STATIC)
+MK_VERIFIER(isNative, ACC_NATIVE)
+MK_VERIFIER(isInterface, ACC_INTERFACE)
+MK_VERIFIER(isSynchro, ACC_SYNCHRONIZED)
+MK_VERIFIER(isPublic, ACC_PUBLIC)
+MK_VERIFIER(isPrivate, ACC_PRIVATE)
+MK_VERIFIER(isAbstract, ACC_ABSTRACT)
+MK_VERIFIER(isProtected, ACC_PROTECTED)
+MK_VERIFIER(isFinal, ACC_FINAL)
+MK_VERIFIER(isSuper, ACC_SUPER)
+
+inline bool isVirtual(unsigned int param) {
+ return !(ACC_STATIC & param);
+}
+
+#undef MK_VERIFIER
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaArray.cpp b/vmkit/lib/JnJVM/VMCore/JavaArray.cpp
new file mode 100644
index 0000000..20898a8
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaArray.cpp
@@ -0,0 +1,285 @@
+//===----------------- JavaArray.cpp - Java arrays ------------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+#include "JavaThread.h"
+
+
+using namespace jnjvm;
+
+const sint32 JavaArray::MaxArraySize = 268435455;
+const unsigned int JavaArray::T_BOOLEAN = 4;
+const unsigned int JavaArray::T_CHAR = 5;
+const unsigned int JavaArray::T_FLOAT = 6;
+const unsigned int JavaArray::T_DOUBLE = 7;
+const unsigned int JavaArray::T_BYTE = 8;
+const unsigned int JavaArray::T_SHORT = 9;
+const unsigned int JavaArray::T_INT = 10;
+const unsigned int JavaArray::T_LONG = 11;
+
+#define ACONS(name, elmt, primSize) \
+ name *name::acons(sint32 n, ClassArray* atype) { \
+ if (n < 0) \
+ JavaThread::get()->isolate->negativeArraySizeException(n); \
+ else if (n > JavaArray::MaxArraySize) \
+ JavaThread::get()->isolate->outOfMemoryError(n); \
+ name* res = (name*) \
+ (Object*) operator new(sizeof(name) + n * primSize, name::VT); \
+ res->initialise(atype); \
+ res->size = n; \
+ memset(res->elements, 0, primSize * n); \
+ return res; \
+ }
+
+#define AT(name, elmt) \
+ elmt name::at(sint32 offset) const { \
+ if (offset >= size) \
+ JavaThread::get()->isolate->indexOutOfBounds(this, offset); \
+ return elements[offset]; \
+ } \
+ void name::setAt(sint32 offset, elmt value) { \
+ if (offset >= size) \
+ JavaThread::get()->isolate->indexOutOfBounds(this, offset); \
+ elements[offset] = value; \
+ }
+
+#define ARRAYCLASS(name, elmt, size) \
+ ACONS(name, elmt, size) \
+ AT(name, elmt) \
+
+ARRAYCLASS(ArrayUInt8, uint8, 1)
+ARRAYCLASS(ArraySInt8, sint8, 1)
+ARRAYCLASS(ArrayUInt16, uint16, 2)
+ARRAYCLASS(ArraySInt16, sint16, 2)
+ARRAYCLASS(ArrayUInt32, uint32, 4)
+ARRAYCLASS(ArraySInt32, sint32, 4)
+ARRAYCLASS(ArrayLong, sint64, 8)
+ARRAYCLASS(ArrayFloat, float, 4)
+ARRAYCLASS(ArrayDouble, double, 8)
+ARRAYCLASS(UTF8, uint16, 4)
+
+AT(ArrayObject, JavaObject*)
+
+#undef ARRAYCLASS
+#undef ACONS
+#undef AT
+
+ArrayObject *ArrayObject::acons(sint32 n, ClassArray* atype) {
+ if (n < 0)
+ JavaThread::get()->isolate->negativeArraySizeException(n);
+ else if (n > JavaArray::MaxArraySize)
+ JavaThread::get()->isolate->outOfMemoryError(n);
+ ArrayObject* res = (ArrayObject*)
+ (Object*) operator new(sizeof(ArrayObject) + n * sizeof(JavaObject*), JavaObject::VT);
+ res->initialise(atype);
+ res->size = n;
+ memset(res->elements, 0, sizeof(JavaObject*) * n);
+ res->setVT(ArrayObject::VT);
+ return res;
+}
+
+
+void JavaArray::print(mvm::PrintBuffer *buf) const {
+ assert(0 && "should not be here");
+}
+
+
+void ArrayUInt8::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS4(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArraySInt8::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS4(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArrayUInt16::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS4(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArraySInt16::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS4(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArrayUInt32::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS4(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArraySInt32::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS4(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArrayLong::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeS8(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArrayFloat::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeFP(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArrayDouble::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeFP(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+void ArrayObject::print(mvm::PrintBuffer *buf) const {
+ buf->write("Array<");
+ for (int i = 0; i < size; i++) {
+ buf->writeObj(elements[i]);
+ buf->write(" ");
+ }
+ buf->write(">");
+}
+
+
+void UTF8::print(mvm::PrintBuffer* buf) const {
+ for (int i = 0; i < size; i++)
+ buf->writeChar((char)elements[i]);
+}
+
+const UTF8* UTF8::javaToInternal(Jnjvm* vm, unsigned int start,
+ unsigned int len) const {
+ uint16* java = (uint16*) alloca(len * sizeof(uint16));
+ for (uint32 i = 0; i < len; i++) {
+ uint16 cur = at(start + i);
+ if (cur == '.') java[i] = '/';
+ else java[i] = cur;
+ }
+
+ return readerConstruct(vm, java, len);
+}
+
+const UTF8* UTF8::internalToJava(Jnjvm *vm, unsigned int start,
+ unsigned int len) const {
+ uint16* java = (uint16*) alloca(len * sizeof(uint16));
+ for (uint32 i = 0; i < len; i++) {
+ uint16 cur = at(start + i);
+ if (cur == '/') java[i] = '.';
+ else java[i] = cur;
+ }
+
+ return readerConstruct(vm, java, len);
+}
+
+const UTF8* UTF8::extract(Jnjvm *vm, uint32 start, uint32 end) const {
+ uint32 len = end - start;
+ uint16* buf = (uint16*)alloca(sizeof(uint16) * len);
+
+ for (uint32 i = 0; i < len; i++) {
+ buf[i] = at(i + start);
+ }
+
+ return readerConstruct(vm, buf, len);
+}
+
+const UTF8* UTF8::asciizConstruct(Jnjvm* vm, char* asciiz) {
+ return vm->asciizConstructUTF8(asciiz);
+}
+
+const UTF8* UTF8::readerConstruct(Jnjvm* vm, uint16* buf, uint32 n) {
+ return vm->readerConstructUTF8(buf, n);
+}
+
+char* UTF8::UTF8ToAsciiz() const {
+ mvm::NativeString* buf = mvm::NativeString::alloc(size + 1);
+ for (sint32 i = 0; i < size; ++i) {
+ buf->setAt(i, elements[i]);
+ }
+ buf->setAt(size, 0);
+ return buf->cString();
+}
+
+static JavaArray* multiCallNewIntern(arrayCtor_t ctor, ClassArray* cl,
+ uint32 len,
+ sint32* dims) {
+ if (len <= 0) JavaThread::get()->isolate->unknownError("Can not happen");
+ JavaArray* _res = ctor(dims[0], cl);
+ if (len > 1) {
+ ArrayObject* res = (ArrayObject*)_res;
+ CommonClass* _base = cl->baseClass();
+ if (_base->isArray) {
+ ClassArray* base = (ClassArray*)_base;
+ AssessorDesc* func = base->funcs();
+ arrayCtor_t newCtor = func->arrayCtor;
+ if (dims[0] > 0) {
+ for (sint32 i = 0; i < dims[0]; ++i) {
+ res->setAt(i, multiCallNewIntern(newCtor, base, (len - 1), &dims[1]));
+ }
+ } else {
+ for (uint32 i = 1; i < len; ++i) {
+ sint32 p = dims[i];
+ if (p < 0) JavaThread::get()->isolate->negativeArraySizeException(p);
+ }
+ }
+ } else {
+ JavaThread::get()->isolate->unknownError("Can not happen");
+ }
+ }
+ return _res;
+}
+
+JavaArray* JavaArray::multiCallNew(ClassArray* cl, uint32 len, ...) {
+ va_list ap;
+ va_start(ap, len);
+ sint32 dims[len];
+ for (uint32 i = 0; i < len; ++i){
+ dims[i] = va_arg(ap, int);
+ }
+ return multiCallNewIntern((arrayCtor_t)ArrayObject::acons, cl, len, dims);
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaArray.h b/vmkit/lib/JnJVM/VMCore/JavaArray.h
new file mode 100644
index 0000000..6fb8d0d
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaArray.h
@@ -0,0 +1,131 @@
+//===----------------- JavaArray.h - Java arrays --------------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_ARRAY_H
+#define JNJVM_JAVA_ARRAY_H
+
+#include "mvm/PrintBuffer.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "JavaObject.h"
+
+namespace jnjvm {
+
+class ClassArray;
+class CommonClass;
+class JavaObject;
+class Jnjvm;
+
+class JavaArray : public JavaObject {
+public:
+ static VirtualTable* VT;
+ sint32 size;
+ void* elements[0];
+ static const sint32 MaxArraySize;
+ static const unsigned int T_BOOLEAN;
+ static const unsigned int T_CHAR;
+ static const unsigned int T_FLOAT;
+ static const unsigned int T_DOUBLE;
+ static const unsigned int T_BYTE;
+ static const unsigned int T_SHORT;
+ static const unsigned int T_INT;
+ static const unsigned int T_LONG;
+
+ static ClassArray* ofByte;
+ static ClassArray* ofChar;
+ static ClassArray* ofString;
+ static ClassArray* ofInt;
+ static ClassArray* ofShort;
+ static ClassArray* ofBool;
+ static ClassArray* ofLong;
+ static ClassArray* ofFloat;
+ static ClassArray* ofDouble;
+ static ClassArray* ofObject;
+ static const llvm::Type* llvmType;
+
+ static llvm::ConstantInt* sizeOffset();
+ static llvm::ConstantInt* elementsOffset();
+ static JavaArray* multiCallNew(ClassArray* cl, uint32 len, ...);
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+};
+
+typedef JavaArray* (*arrayCtor_t)(uint32 len, CommonClass* cl);
+
+#define ARRAYCLASS(name, elmt) \
+class name : public JavaArray { \
+public: \
+ static VirtualTable* VT; \
+ static const llvm::Type* llvmType; \
+ elmt elements[0]; \
+ static name *acons(sint32 n, ClassArray* cl); \
+ elmt at(sint32) const; \
+ void setAt(sint32, elmt); \
+ virtual void print(mvm::PrintBuffer* buf) const; \
+ virtual void tracer(size_t sz); \
+}
+
+ARRAYCLASS(ArrayUInt8, uint8);
+ARRAYCLASS(ArraySInt8, sint8);
+ARRAYCLASS(ArrayUInt16, uint16);
+ARRAYCLASS(ArraySInt16, sint16);
+ARRAYCLASS(ArrayUInt32, uint32);
+ARRAYCLASS(ArraySInt32, sint32);
+ARRAYCLASS(ArrayLong, sint64);
+ARRAYCLASS(ArrayFloat, float);
+ARRAYCLASS(ArrayDouble, double);
+
+#undef ARRAYCLASS
+
+class ArrayObject : public JavaArray {
+public:
+ static VirtualTable* VT;
+ static const llvm::Type* llvmType;
+ JavaObject* elements[0];
+ static ArrayObject *acons(sint32 n, ClassArray* cl);
+ JavaObject* at(sint32) const;
+ void setAt(sint32, JavaObject*);
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+};
+
+class UTF8 : public JavaArray {
+public:
+ static VirtualTable* VT;
+ uint16 elements[0];
+
+ static const llvm::Type* llvmType;
+ static UTF8* acons(sint32 n, ClassArray* cl);
+
+ unsigned short int at(sint32) const;
+ void setAt(sint32, uint16);
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+
+ const UTF8* internalToJava(Jnjvm *vm, unsigned int start,
+ unsigned int len) const;
+
+ const UTF8* javaToInternal(Jnjvm *vm, unsigned int start,
+ unsigned int len) const;
+
+ char* UTF8ToAsciiz() const;
+ static const UTF8* asciizConstruct(Jnjvm *vm, char* asciiz);
+ static const UTF8* readerConstruct(Jnjvm *vm, uint16* buf, uint32 n);
+
+ const UTF8* extract(Jnjvm *vm, uint32 start, uint32 len) const;
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaBacktrace.cpp b/vmkit/lib/JnJVM/VMCore/JavaBacktrace.cpp
new file mode 100644
index 0000000..9ab83ee
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaBacktrace.cpp
@@ -0,0 +1,236 @@
+//===---------- JavaBacktrace.cpp - Backtrace utilities -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <dlfcn.h>
+
+#include "llvm/Function.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+#include "mvm/Object.h"
+
+#include "JavaClass.h"
+#include "JavaJIT.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+
+using namespace jnjvm;
+
+extern "C" int** get_frame_pointer() {
+/*
+ int** fp = 0;
+#if defined (__PPC__)
+ asm volatile("1:\n"
+ " mr %0, 1\n"
+ : "=&r"(fp));
+#else
+ asm volatile("1:\n"
+ " movl %%ebp, %0\n"
+ : "=&r"(fp));
+#endif
+ return fp;
+*/
+ return (int**)__builtin_frame_address(0);
+}
+
+extern "C" int *debug_frame_ip(int **fp) {
+#if defined(__MACH__) && !defined(__i386__)
+ return fp[2];
+#else
+ return fp[1];
+#endif
+}
+
+extern "C" int **debug_frame_caller_fp(int **fp) {
+ return (int**)fp[0];
+}
+
+
+extern "C" int **debug_frame_caller_from_first_fp(int **fp) {
+#if defined (__PPC__)
+ return fp;
+#else
+ return fp;
+#endif
+}
+
+extern "C" bool frame_end(int **fp) {
+#if defined(__PPC__)
+ return fp == 0;
+#else
+ return fp == 0;
+#endif
+}
+
+extern "C" JavaMethod* ip_to_meth(int* begIp) {
+ if (begIp) {
+ const llvm::GlobalValue * glob =
+ mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
+ if (glob) {
+ if (llvm::isa<llvm::Function>(glob)) {
+ mvm::Code* c = (mvm::Code*)begIp;
+ mvm::Method* m = c->method();
+ JavaMethod* meth = (JavaMethod*)m->definition();
+ if (meth && meth->getVirtualTable() == JavaMethod::VT) {
+ return meth;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+#if 0
+extern "C" int backtrace(void** ips, int size) {
+ int** fp = get_frame_pointer();
+ fp = debug_frame_caller_from_first_fp(fp);
+ int i = 0;
+ while ((!frame_end(fp)) && (debug_frame_ip(fp) != 0) && i < size) {
+ int * ip = debug_frame_ip(fp);
+ ips[i++] = (void*)ip;
+ fp = debug_frame_caller_fp(fp);
+ }
+ return i;
+}
+#else
+#include <execinfo.h>
+#endif
+extern "C" int backtrace_fp(int** ips, int size, int** fp) {
+ fp = debug_frame_caller_from_first_fp(fp);
+ int i = 0;
+ while ((!frame_end(fp)) && (debug_frame_ip(fp) != 0) && i < size) {
+ int * ip = debug_frame_ip(fp);
+ ips[i++] = ip;
+ fp = debug_frame_caller_fp(fp);
+ }
+ return i;
+}
+
+extern "C" void debug_backtrace(int **fp) {
+ fp = debug_frame_caller_from_first_fp(fp);
+ while ((!frame_end(fp)) && (debug_frame_ip(fp) != 0)) {
+ int * ip = debug_frame_ip(fp);
+ int *begIp = (int*)gc::begOf(ip);
+ if (begIp) {
+ const llvm::GlobalValue * glob =
+ mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
+ if (glob) {
+ if (llvm::isa<llvm::Function>(glob)) {
+ printf("; 0x%08x in %s\n", (uint32) ip,
+ ((llvm::Function*)glob)->getNameStr().c_str());
+ } else JavaThread::get()->isolate->unknownError("in global variable?");
+ } else printf("; 0x%08x in stub\n", (uint32) ip);
+ } else {
+ Dl_info info;
+ int res = dladdr(begIp, &info);
+ if (res != 0) {
+ printf("; 0x%08x in %s\n", (uint32) ip, info.dli_fname);
+ }
+ }
+ fp = debug_frame_caller_fp(fp);
+ }
+}
+
+
+void JavaJIT::printBacktrace() {
+ int* ips[100];
+ int real_size = backtrace((void**)(void*)ips, 100);
+ int n = 0;
+ while (n < real_size) {
+ int *begIp = (int*)gc::begOf(ips[n++]);
+ if (begIp) {
+ const llvm::GlobalValue * glob =
+ mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
+ if (glob) {
+ if (llvm::isa<llvm::Function>(glob)) {
+ mvm::Code* c = (mvm::Code*)begIp;
+ mvm::Method* m = c->method();
+ JavaMethod* meth = (JavaMethod*)m->definition();
+ if (meth)
+ printf("; 0x%08x in %s\n", (uint32) ips[n - 1], meth->printString());
+ else
+ printf("; 0x%08x in %s\n", (uint32) ips[n - 1], ((llvm::Function*)glob)->getNameStr().c_str());
+ } else JavaThread::get()->isolate->unknownError("in global variable?");
+ } else printf("; 0x%08x in stub\n", (uint32) ips[n - 1]);
+ } else {
+ Dl_info info;
+ int res = dladdr(begIp, &info);
+ if (res != 0) {
+ printf("; 0x%08x in %s\n", (uint32) ips[n - 1], info.dli_fname);
+ } else {
+ printf("; 0x%08x in Unknown\n", (uint32) ips[n - 1]);
+ }
+ }
+ }
+}
+
+
+
+
+Class* JavaJIT::getCallingClass() {
+ int* ips[10];
+ int real_size = backtrace((void**)(void*)ips, 10);
+ int n = 0;
+ int i = 0;
+ while (n < real_size) {
+ int *begIp = (int*)gc::begOf(ips[n++]);
+ if (begIp) {
+ const llvm::GlobalValue * glob =
+ mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
+ if (glob) {
+ if (llvm::isa<llvm::Function>(glob)) {
+ mvm::Code* c = (mvm::Code*)begIp;
+ mvm::Method* m = c->method();
+ JavaMethod* meth = (JavaMethod*)m->definition();
+ if (meth && i == 1) return meth->classDef;
+ else ++i;
+ } else {
+ JavaThread::get()->isolate->unknownError("in global variable?");
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+Class* JavaJIT::getCallingClassWalker() {
+ int* ips[10];
+ int real_size = backtrace((void**)(void*)ips, 10);
+ int n = 0;
+ int i = 0;
+ while (n < real_size) {
+ int *begIp = (int*)gc::begOf(ips[n++]);
+ if (begIp) {
+ const llvm::GlobalValue * glob =
+ mvm::jit::executionEngine->getGlobalValueAtAddress(begIp + 1);
+ if (glob) {
+ if (llvm::isa<llvm::Function>(glob)) {
+ mvm::Code* c = (mvm::Code*)begIp;
+ mvm::Method* m = c->method();
+ JavaMethod* meth = (JavaMethod*)m->definition();
+ if (meth && i == 1) {
+ return meth->classDef;
+ } else ++i;
+ } else {
+ JavaThread::get()->isolate->unknownError("in global variable?");
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+JavaObject* JavaJIT::getCallingClassLoader() {
+ Class* cl = getCallingClassWalker();
+ if (!cl) return 0;
+ else return cl->classLoader;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaCache.cpp b/vmkit/lib/JnJVM/VMCore/JavaCache.cpp
new file mode 100644
index 0000000..26cf6b1
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaCache.cpp
@@ -0,0 +1,163 @@
+//===------ JavaCache.cpp - Inline cache for virtual calls -----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <iostream>
+#include <vector>
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+
+#include "mvm/JIT.h"
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+#include "JavaCache.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+
+#include "types.h"
+
+using namespace jnjvm;
+using namespace llvm;
+
+void CacheNode::print(mvm::PrintBuffer* buf) const {
+ buf->write("CacheNode<");
+ if (lastCible) {
+ lastCible->print(buf);
+ buf->write(" -- ");
+ ((mvm::Object*)((void**)methPtr - 1))->print(buf);
+ }
+ buf->write(" in ");
+ enveloppe->print(buf);
+ buf->write(">");
+}
+
+void Enveloppe::print(mvm::PrintBuffer* buf) const {
+ buf->write("Enveloppe<>");
+}
+
+CacheNode* CacheNode::allocate() {
+ CacheNode* cache = gc_new(CacheNode)();
+ cache->lastCible = 0;
+ cache->methPtr = 0;
+ cache->next = 0;
+ return cache;
+}
+
+Enveloppe* Enveloppe::allocate(JavaCtpInfo* ctp, uint32 index) {
+ Enveloppe* enveloppe = gc_new(Enveloppe)();
+ enveloppe->firstCache = CacheNode::allocate();
+ enveloppe->firstCache->enveloppe = enveloppe;
+ enveloppe->cacheLock = mvm::Lock::allocNormal();
+ enveloppe->ctpInfo = ctp;
+ enveloppe->index = index;
+ return enveloppe;
+}
+
+void JavaJIT::invokeInterfaceOrVirtual(uint16 index) {
+
+ // Do the usual
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ Signdef* signature = ctpInfo->infoOfInterfaceOrVirtualMethod(index);
+
+ std::vector<Value*> args; // size = [signature->nbIn + 3];
+
+ FunctionType::param_iterator it = signature->virtualType->param_end();
+ makeArgs(it, index, args, signature->nbIn + 1);
+
+ const llvm::Type* retType = signature->virtualType->getReturnType();
+ BasicBlock* endBlock = createBasicBlock("end virtual invoke");
+ PHINode * node = 0;
+ if (retType != Type::VoidTy) {
+ node = new PHINode(retType, "", endBlock);
+ }
+
+ // ok now the cache
+ Enveloppe* enveloppe = Enveloppe::allocate(compilingClass->ctpInfo, index);
+ compilingMethod->caches.push_back(enveloppe);
+
+ Value* zero = mvm::jit::constantZero;
+ Value* one = mvm::jit::constantOne;
+ Value* two = mvm::jit::constantTwo;
+
+ mvm::jit::protectConstants();//->lock();
+ Value* llvmEnv =
+ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (enveloppe)),
+ Enveloppe::llvmType);
+ mvm::jit::unprotectConstants();//->unlock();
+
+
+ JITVerifyNull(args[0]);
+
+ std::vector<Value*> args1;
+ args1.push_back(zero);
+ args1.push_back(one);
+ Value* cachePtr = new GetElementPtrInst(llvmEnv, args1.begin(), args1.end(),
+ "", currentBlock);
+ Value* cache = new LoadInst(cachePtr, "", currentBlock);
+
+ std::vector<Value*> args2;
+ args2.push_back(zero);
+ args2.push_back(JavaObject::classOffset());
+ Value* classPtr = new GetElementPtrInst(args[0], args2.begin(),
+ args2.end(), "",
+ currentBlock);
+
+ Value* cl = new LoadInst(classPtr, "", currentBlock);
+ std::vector<Value*> args3;
+ args3.push_back(zero);
+ args3.push_back(two);
+ Value* lastCiblePtr = new GetElementPtrInst(cache, args3.begin(), args3.end(),
+ "", currentBlock);
+ Value* lastCible = new LoadInst(lastCiblePtr, "", currentBlock);
+
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, cl, lastCible, "", currentBlock);
+
+ BasicBlock* ifTrue = createBasicBlock("cache ok");
+ BasicBlock* ifFalse = createBasicBlock("cache not ok");
+ new BranchInst(ifTrue, ifFalse, cmp, currentBlock);
+
+ currentBlock = ifFalse;
+ Value* _meth = invoke(virtualLookupLLVM, cache, args[0], "", ifFalse);
+ Value* meth = new BitCastInst(_meth, signature->virtualTypePtr, "",
+ currentBlock);
+ Value* ret = invoke(meth, args, "", currentBlock);
+ if (node) {
+ node->addIncoming(ret, currentBlock);
+ }
+ new BranchInst(endBlock, currentBlock);
+
+ currentBlock = ifTrue;
+
+ Value* methPtr = new GetElementPtrInst(cache, args1.begin(), args1.end(),
+ "", currentBlock);
+
+ _meth = new LoadInst(methPtr, "", currentBlock);
+ meth = new BitCastInst(_meth, signature->virtualTypePtr, "", currentBlock);
+
+ ret = invoke(meth, args, "", currentBlock);
+ new BranchInst(endBlock, currentBlock);
+
+ if (node) {
+ node->addIncoming(ret, currentBlock);
+ }
+
+ currentBlock = endBlock;
+ if (node) {
+ push(node, signature->ret->funcs);
+ if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ }
+ }
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaCache.h b/vmkit/lib/JnJVM/VMCore/JavaCache.h
new file mode 100644
index 0000000..6126019
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaCache.h
@@ -0,0 +1,61 @@
+//===------- JavaCache.h - Inline cache for virtual calls -----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_CACHE_H
+#define JNJVM_JAVA_CACHE_H
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+#include "llvm/Type.h"
+
+#include "types.h"
+
+namespace jnjvm {
+
+class Class;
+class Enveloppe;
+class JavaCtpInfo;
+
+class CacheNode : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ void* methPtr;
+ Class* lastCible;
+ CacheNode* next;
+ Enveloppe* enveloppe;
+ static const llvm::Type* llvmType;
+
+ static CacheNode* allocate();
+
+};
+
+class Enveloppe : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ virtual void tracer(size_t sz);
+ virtual void print(mvm::PrintBuffer* buf) const;
+
+ CacheNode *firstCache;
+ JavaCtpInfo* ctpInfo;
+ mvm::Lock* cacheLock;
+ uint32 index;
+ static const llvm::Type* llvmType;
+
+ static Enveloppe* allocate(JavaCtpInfo* info, uint32 index);
+
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaClass.cpp b/vmkit/lib/JnJVM/VMCore/JavaClass.cpp
new file mode 100644
index 0000000..b5b33e2
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaClass.cpp
@@ -0,0 +1,646 @@
+//===-------- JavaClass.cpp - Java class representation -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include <string.h>
+
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+
+
+#include "mvm/JIT.h"
+#include "mvm/GC/GC.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+#include "Reader.h"
+
+using namespace jnjvm;
+
+const int CommonClass::MaxDisplay = 6;
+
+void Attribut::print(mvm::PrintBuffer* buf) const {
+ buf->write("Attribut<");
+ buf->writeObj(name);
+ buf->write(">");
+}
+
+Attribut* Attribut::derive(const UTF8* name, unsigned int length, const Reader*
+ reader) {
+
+ Attribut* attr = gc_new(Attribut)();
+ attr->start = reader->cursor;
+ attr->nbb = length;
+ attr->name = name;
+
+ return attr;
+}
+
+// TODO: Optimize
+Attribut* Attribut::lookup(const std::vector<Attribut*>* vec,
+ const UTF8* key ) {
+
+ for (uint32 i = 0; i < vec->size(); i++) {
+ Attribut* cur = vec->at(i);
+ if (cur->name == key) return cur;
+ }
+
+ return 0;
+}
+
+Reader* Attribut::toReader(ArrayUInt8* array, Attribut* attr) {
+ return Reader::allocateReader(array, attr->start, attr->nbb);
+}
+
+
+static void printClassNameIntern(const UTF8* name, unsigned int start,
+ unsigned int end, mvm::PrintBuffer* buf) {
+
+ uint16 first = name->at(start);
+ if (first == AssessorDesc::I_TAB) {
+ unsigned int stepsEnd = start;
+ while (name->at(stepsEnd) == AssessorDesc::I_TAB) stepsEnd++;
+ if (name->at(stepsEnd) == AssessorDesc::I_REF) {
+ printClassNameIntern(name, (stepsEnd + 1),(end - 1), buf);
+ } else {
+ AssessorDesc * funcs = 0;
+ uint32 next = 0;
+ AssessorDesc::analyseIntern(name, stepsEnd, 0, funcs, next);
+ buf->write(funcs->asciizName);
+ }
+ buf->write(" ");
+ for (uint32 i = start; i < stepsEnd; i++)
+ buf->write("[]");
+ } else {
+ char* tmp = (char*)(alloca(1 + (end - start)));
+ for (uint32 i = start; i < end; i++) {
+ short int cur = name->at(i);
+ tmp[i - start] = (cur == '/' ? '.' : cur);
+ }
+ tmp[end - start] = 0;
+ buf->write(tmp);
+ }
+}
+
+void CommonClass::printClassName(const UTF8* name, mvm::PrintBuffer* buf) {
+ printClassNameIntern(name, 0, name->size, buf);
+}
+
+void CommonClass::print(mvm::PrintBuffer* buf) const {
+ buf->write("CommonClass<");
+ printClassName(name, buf);
+ buf->write(">");
+}
+
+void CommonClass::initialise(Jnjvm* isolate, bool isArray) {
+ this->lockVar = mvm::Lock::allocRecursive();
+ this->condVar = mvm::Cond::allocCond();
+ this->status = hashed;
+ this->isolate = isolate;
+ this->dim = -1;
+ this->isArray = isArray;
+ this->_llvmVar = 0;
+#ifdef SINGLE_VM
+ this->_llvmDelegatee = 0;
+ this->delegatee = 0;
+#endif
+}
+
+void CommonClass::aquire() {
+ lockVar->lock();
+}
+
+void CommonClass::release() {
+ lockVar->unlock();
+}
+
+void CommonClass::waitClass() {
+ condVar->wait(lockVar);
+}
+
+void CommonClass::broadcastClass() {
+ condVar->broadcast();
+}
+
+bool CommonClass::ownerClass() {
+ return mvm::Lock::selfOwner(lockVar);
+}
+
+void Class::print(mvm::PrintBuffer* buf) const {
+ buf->write("Class<");
+ printClassName(name, buf);
+ buf->write(">");
+}
+
+void ClassArray::print(mvm::PrintBuffer* buf) const {
+ buf->write("ClassArray<");
+ printClassName(name, buf);
+ buf->write(">");
+}
+
+void ClassArray::resolveComponent() {
+ AssessorDesc::introspectArray(isolate, classLoader, name, 0, _funcs,
+ _baseClass);
+}
+
+CommonClass* ClassArray::baseClass() {
+ if (_baseClass == 0) {
+ this->resolveComponent();
+ }
+ return _baseClass;
+}
+
+AssessorDesc* ClassArray::funcs() {
+ if (_funcs == 0) {
+ this->resolveComponent();
+ }
+ return _funcs;
+}
+
+JavaObject* ClassArray::arrayLoader(Jnjvm* isolate, const UTF8* name,
+ JavaObject* loader,
+ unsigned int start, unsigned int len) {
+
+ if (name->at(start) == AssessorDesc::I_TAB) {
+ return arrayLoader(isolate, name, loader, start + 1, len - 1);
+ } else if (name->at(start) == AssessorDesc::I_REF) {
+ const UTF8* componentName = name->javaToInternal(isolate, start + 1,
+ len - 2);
+ CommonClass* cl = isolate->loadName(componentName, loader, false, false,
+ true);
+ return cl->classLoader;
+ } else {
+ return 0;
+ }
+}
+
+void* JavaMethod::compiledPtr() {
+ if (code != 0) return code;
+ else {
+ classDef->aquire();
+ if (code == 0) {
+ if (isStatic(access)) {
+ llvmType = signature->staticType;
+ } else {
+ llvmType = signature->virtualType;
+ }
+ if (!methPtr) {
+ JavaJIT* jit = gc_new(JavaJIT)();
+ jit->compilingClass = classDef;
+ jit->compilingMethod = this;
+ if (isNative(access)) {
+ methPtr = jit->nativeCompile();
+ } else {
+ methPtr = jit->javaCompile();
+ }
+ }
+ // We can compile it, since if we're here, it's for a good reason
+ void* val = mvm::jit::executionEngine->getPointerToGlobal(methPtr);
+ if (gc::isObject(val)) {
+ mvm::Code* temp = (mvm::Code*)((unsigned*)val - 1);
+ temp->method()->definition(this);
+ }
+ code = (mvm::Code*)val;
+ classDef->release();
+ } else {
+ classDef->release();
+ }
+ return code;
+ }
+}
+
+void JavaMethod::print(mvm::PrintBuffer* buf) const {
+ buf->write("JavaMethod<");
+ signature->printWithSign(classDef, name, buf);
+ buf->write(">");
+}
+
+void JavaField::print(mvm::PrintBuffer* buf) const {
+ buf->write("JavaField<");
+ if (isStatic(access))
+ buf->write("static ");
+ else
+ buf->write("virtual ");
+ signature->tPrintBuf(buf);
+ buf->write(" ");
+ classDef->print(buf);
+ buf->write("::");
+ name->print(buf);
+ buf->write(">");
+}
+
+JavaMethod* CommonClass::lookupMethodDontThrow(const UTF8* name,
+ const UTF8* type, bool isStatic,
+ bool recurse) {
+#ifndef SINGLE_VM
+ if (isolate == Jnjvm::bootstrapVM) {
+ name = Jnjvm::bootstrapVM->readerConstructUTF8(name->elements,
+ name->size);
+ type = Jnjvm::bootstrapVM->readerConstructUTF8(type->elements,
+ type->size);
+
+ }
+#endif
+
+ std::vector<JavaMethod*>* meths = (isStatic? &staticMethods :
+ &virtualMethods);
+
+ JavaMethod *cur, *res = 0;
+ int i = 0;
+ int nbm = meths->size();
+
+ while (!res && i < nbm) {
+ cur = meths->at(i);
+ if (cur->name == name && cur->type == type) {
+ return cur;
+ }
+ ++i;
+ }
+
+ if (recurse) {
+ if (super) res = super->lookupMethodDontThrow(name, type, isStatic,
+ recurse);
+ if (!res && isStatic) {
+ int nbi = interfaces.size();
+ i = 0;
+ while (res == 0 && i < nbi) {
+ res = interfaces[i]->lookupMethodDontThrow(name, type, isStatic,
+ recurse);
+ ++i;
+ }
+ }
+ }
+
+ return res;
+}
+
+JavaMethod* CommonClass::lookupMethod(const UTF8* name, const UTF8* type,
+ bool isStatic, bool recurse) {
+ JavaMethod* res = lookupMethodDontThrow(name, type, isStatic, recurse);
+ if (!res) {
+ JavaThread::get()->isolate->error(Jnjvm::NoSuchMethodError,
+ "unable to find %s in %s",
+ name->printString(), this->printString());
+ }
+ return res;
+}
+
+JavaField* CommonClass::lookupFieldDontThrow(const UTF8* name,
+ const UTF8* type, bool isStatic,
+ bool recurse) {
+
+#ifndef SINGLE_VM
+ if (isolate == Jnjvm::bootstrapVM) {
+ name = Jnjvm::bootstrapVM->readerConstructUTF8(name->elements,
+ name->size);
+ type = Jnjvm::bootstrapVM->readerConstructUTF8(type->elements,
+ type->size);
+
+ }
+#endif
+
+ std::vector<JavaField*>* fields = (isStatic? &staticFields : &virtualFields);
+
+ JavaField *cur, *res = 0;
+ int i = 0;
+ int nbm = fields->size();
+
+ while (!res && i < nbm) {
+ cur = fields->at(i);
+ if (cur->name == name && cur->type == type) {
+ return cur;
+ }
+ ++i;
+ }
+
+ if (recurse) {
+ if (super) res = super->lookupFieldDontThrow(name, type, isStatic,
+ recurse);
+ if (!res && isStatic) {
+ int nbi = interfaces.size();
+ i = 0;
+ while (res == 0 && i < nbi) {
+ res = interfaces[i]->lookupFieldDontThrow(name, type, isStatic,
+ recurse);
+ ++i;
+ }
+ }
+ }
+
+ return res;
+}
+
+JavaField* CommonClass::lookupField(const UTF8* name, const UTF8* type,
+ bool isStatic, bool recurse) {
+
+ JavaField* res = lookupFieldDontThrow(name, type, isStatic, recurse);
+ if (!res) {
+ JavaThread::get()->isolate->error(Jnjvm::NoSuchFieldError,
+ "unable to find %s in %s",
+ name->printString(), this->printString());
+ }
+ return res;
+}
+
+JavaObject* Class::doNew() {
+ JavaObject* res = (JavaObject*)gc::operator new(virtualSize, virtualVT);
+ memcpy(res, virtualInstance, virtualSize);
+ return res;
+}
+
+// Copy doNew because LLVM wants two different pointers (for simplicity)
+JavaObject* Class::doNewUnknown() {
+ JavaObject* res = (JavaObject*)gc::operator new(virtualSize, virtualVT);
+ memcpy(res, virtualInstance, virtualSize);
+ return res;
+}
+
+JavaObject* Class::initialiseObject(JavaObject* res) {
+ memcpy(res, virtualInstance, virtualSize);
+ return res;
+}
+
+#ifndef SINGLE_VM
+JavaObject* Class::doNewIsolate() {
+ if (!isReady())
+ initialiseClass();
+ JavaObject* res = (JavaObject*)gc::operator new(virtualSize, virtualVT);
+ memcpy(res, virtualInstance, virtualSize);
+ return res;
+}
+#endif
+
+bool CommonClass::inheritName(const UTF8* Tname) {
+ if (name == Tname) {
+ return true;
+ } else if (AssessorDesc::bogusClassToPrimitive(this)) {
+ return true;
+ } else if (super) {
+ if (super->inheritName(Tname)) return true;
+ }
+
+ for (uint32 i = 0; i < interfaces.size(); ++i) {
+ if (interfaces[i]->inheritName(Tname)) return true;
+ }
+ return false;
+}
+
+bool CommonClass::isOfTypeName(const UTF8* Tname) {
+ if (inheritName(Tname)) {
+ return true;
+ } else if (isArray) {
+ CommonClass* curS = this;
+ uint32 prof = 0;
+ uint32 len = Tname->size;
+ bool res = true;
+
+ while (res && Tname->at(prof) == AssessorDesc::I_TAB) {
+ CommonClass* cl = ((ClassArray*)curS)->baseClass();
+ Jnjvm *vm = cl->isolate;
+ ++prof;
+ vm->resolveClass(cl, false);
+ res = curS->isArray && cl && (prof < len);
+ curS = cl;
+ }
+
+ Jnjvm *vm = this->isolate;
+ return (Tname->at(prof) == AssessorDesc::I_REF) &&
+ (res && curS->inheritName(Tname->extract(vm, prof + 1, len - 1)));
+ } else {
+ return false;
+ }
+}
+
+bool CommonClass::implements(CommonClass* cl) {
+ if (this == cl) return true;
+ else {
+ for (uint32 i = 0; i < interfaces.size(); i++) {
+ CommonClass* cur = interfaces[i];
+ if (cur == cl) return true;
+ else if (cur->implements(cl)) return true;
+ }
+ if (super) {
+ return super->implements(cl);
+ }
+ }
+ return false;
+}
+
+bool CommonClass::instantiationOfArray(CommonClass* cl) {
+ if (this == cl) return true;
+ else {
+ if (isArray && cl->isArray) {
+ CommonClass* baseThis = ((ClassArray*)this)->baseClass();
+ CommonClass* baseCl = ((ClassArray*)cl)->baseClass();
+
+ if (isInterface(baseThis->access) && isInterface(baseCl->access)) {
+ return baseThis->implements(baseCl);
+ } else {
+ return baseThis->isAssignableFrom(baseCl);
+ }
+ }
+ }
+ return false;
+}
+
+bool CommonClass::subclassOf(CommonClass* cl) {
+ if (cl->depth < display.size()) {
+ return display[cl->depth] == cl;
+ } else {
+ return false;
+ }
+}
+
+bool CommonClass::isAssignableFrom(CommonClass* cl) {
+ if (this == cl) {
+ return true;
+ } else if (isInterface(cl->access)) {
+ return this->implements(cl);
+ } else if (cl->isArray) {
+ return this->instantiationOfArray(cl);
+ } else {
+ return this->subclassOf(cl);
+ }
+}
+
+void JavaField::initField(JavaObject* obj) {
+ const AssessorDesc* funcs = signature->funcs;
+ Attribut* attribut = Attribut::lookup(&attributs,
+ Attribut::constantAttribut);
+
+ if (!attribut) {
+ JavaJIT::initField(this, obj);
+ } else {
+ Reader* reader = attribut->toReader(classDef->bytes, attribut);
+ JavaCtpInfo * ctpInfo = classDef->ctpInfo;
+ uint16 idx = reader->readU2();
+ if (funcs == AssessorDesc::dLong) {
+ JavaJIT::initField(this, obj, (uint64)ctpInfo->LongAt(idx));
+ } else if (funcs == AssessorDesc::dDouble) {
+ JavaJIT::initField(this, obj, ctpInfo->DoubleAt(idx));
+ } else if (funcs == AssessorDesc::dFloat) {
+ JavaJIT::initField(this, obj, ctpInfo->FloatAt(idx));
+ } else if (funcs == AssessorDesc::dRef) {
+ const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[idx]);
+ JavaJIT::initField(this, obj,
+ (JavaObject*)ctpInfo->resolveString(utf8, idx));
+ } else if (funcs == AssessorDesc::dInt || funcs == AssessorDesc::dChar ||
+ funcs == AssessorDesc::dShort || funcs == AssessorDesc::dByte ||
+ funcs == AssessorDesc::dBool) {
+ JavaJIT::initField(this, obj, (uint64)ctpInfo->IntegerAt(idx));
+ } else {
+ JavaThread::get()->isolate->
+ unknownError("unknown constant %c", funcs->byteId);
+ }
+ }
+
+}
+
+static void resolveStaticFields(Class* cl) {
+
+ std::vector<const llvm::Type*> fields;
+ fields.push_back(JavaObject::llvmType->getContainedType(0));
+ uint64 offset = 0;
+ mvm::jit::protectConstants();//->lock();
+ for (std::vector<JavaField*>::iterator i = cl->staticFields.begin(),
+ e = cl->staticFields.end(); i!= e; ++i) {
+ // preincrement because 0 is JavaObject
+ (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset);
+ fields.push_back((*i)->signature->funcs->llvmType);
+ }
+ mvm::jit::unprotectConstants();//->unlock();
+
+ mvm::jit::protectTypes();//->lock();
+ cl->staticType = llvm::PointerType::getUnqual(llvm::StructType::get(fields, false));
+ mvm::jit::unprotectTypes();//->unlock();
+
+ VirtualTable* VT = JavaJIT::makeVT(cl, true);
+
+ uint64 size = mvm::jit::getTypeSize(cl->staticType->getContainedType(0));
+#ifndef SINGLE_VM
+ cl->staticSize = size;
+ cl->staticVT = VT;
+ if (cl->isolate != Jnjvm::bootstrapVM) {
+#endif
+ JavaObject* val = (JavaObject*)mvm::Object::gcmalloc(size, VT);
+ cl->setStaticInstance(val);
+ val->initialise(cl);
+ for (std::vector<JavaField*>::iterator i = cl->staticFields.begin(),
+ e = cl->staticFields.end(); i!= e; ++i) {
+
+ (*i)->initField(val);
+ }
+#ifndef SINGLE_VM
+ }
+#endif
+}
+
+static void resolveVirtualFields(Class* cl) {
+
+ std::vector<const llvm::Type*> fields;
+ if (cl->super) {
+ fields.push_back(cl->super->virtualType->getContainedType(0));
+ } else {
+ fields.push_back(JavaObject::llvmType->getContainedType(0));
+ }
+ uint64 offset = 0;
+ mvm::jit::protectConstants();//->lock();
+ for (std::vector<JavaField*>::iterator i = cl->virtualFields.begin(),
+ e = cl->virtualFields.end(); i!= e; ++i) {
+ // preincrement because 0 is JavaObject
+ (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset);
+ fields.push_back((*i)->signature->funcs->llvmType);
+ }
+ mvm::jit::unprotectConstants();//->unlock();
+
+ mvm::jit::protectTypes();//->lock();
+ cl->virtualType = llvm::PointerType::getUnqual(llvm::StructType::get(fields, false));
+ mvm::jit::unprotectTypes();//->unlock();
+
+ VirtualTable* VT = JavaJIT::makeVT(cl, false);
+
+ uint64 size = mvm::jit::getTypeSize(cl->virtualType->getContainedType(0));
+ cl->virtualSize = size;
+ cl->virtualVT = VT;
+ cl->virtualInstance = (JavaObject*)mvm::Object::gcmalloc(size, VT);
+ cl->virtualInstance->initialise(cl);
+
+ for (std::vector<JavaField*>::iterator i = cl->virtualFields.begin(),
+ e = cl->virtualFields.end(); i!= e; ++i) {
+ // Virtual fields apparenty do not have inititizalizers, which is good
+ // for isolates. I should not have to do this, but just to make sure.
+ (*i)->initField(cl->virtualInstance);
+ }
+}
+
+void Class::resolveFields() {
+ resolveStaticFields(this);
+ resolveVirtualFields(this);
+}
+
+JavaObject* CommonClass::getClassDelegatee() {
+ return JavaThread::get()->isolate->getClassDelegatee(this);
+}
+
+void CommonClass::resolveClass(bool doClinit) {
+ isolate->resolveClass(this, doClinit);
+}
+
+void CommonClass::initialiseClass() {
+ return isolate->initialiseClass(this);
+}
+
+#ifndef SINGLE_VM
+void Class::setStaticInstance(JavaObject* val) {
+ _staticInstance = val;
+}
+
+JavaObject* Class::staticInstance() {
+ if (isolate == Jnjvm::bootstrapVM) {
+ Class* cl = this;
+ std::pair<uint8, JavaObject*>* val = JavaThread::get()->isolate->statics->lookup(cl);
+ assert(val);
+ return val->second;
+ } else {
+ return _staticInstance;
+ }
+}
+
+JavaObject* Class::createStaticInstance() {
+ JavaObject* val = (JavaObject*)mvm::Object::gcmalloc(staticSize, staticVT);
+ val->initialise(this);
+ for (std::vector<JavaField*>::iterator i = this->staticFields.begin(),
+ e = this->staticFields.end(); i!= e; ++i) {
+
+ (*i)->initField(val);
+ }
+ return val;
+}
+
+bool CommonClass::isReady() {
+ if (isolate == Jnjvm::bootstrapVM) {
+ Class* cl = this;
+ std::pair<uint8, JavaObject*>* val = JavaThread::get()->isolate->statics->lookup(cl);
+ return val && val->first;
+ } else {
+ return status == ready;
+ }
+}
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaClass.h b/vmkit/lib/JnJVM/VMCore/JavaClass.h
new file mode 100644
index 0000000..19bab01
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaClass.h
@@ -0,0 +1,351 @@
+//===-------- JavaClass.h - Java class representation -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_CLASS_H
+#define JNJVM_JAVA_CLASS_H
+
+#include <vector>
+
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+#include "types.h"
+
+#include "mvm/Method.h"
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+
+#include "JavaAccess.h"
+
+namespace jnjvm {
+
+class ArrayUInt8;
+class AssessorDesc;
+class Enveloppe;
+class Class;
+class JavaCtpInfo;
+class JavaField;
+class JavaMethod;
+class JavaObject;
+class Jnjvm;
+class Reader;
+class Signdef;
+class Typedef;
+class UTF8;
+
+
+typedef enum JavaState {
+ hashed = 0, loaded, readed, prepared, resolved, clinitParent, inClinit, ready
+}JavaState;
+
+
+class Attribut : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ const UTF8* name;
+ unsigned int start;
+ unsigned int nbb;
+
+ static Attribut* derive(const UTF8* name, unsigned int length,
+ const Reader* reader);
+ static Attribut* lookup(const std::vector<Attribut*> * vec,
+ const UTF8* key);
+ Reader* toReader(ArrayUInt8* array, Attribut* attr);
+
+ static const UTF8* codeAttribut;
+ static const UTF8* exceptionsAttribut;
+ static const UTF8* constantAttribut;
+ static const UTF8* lineNumberTableAttribut;
+ static const UTF8* innerClassesAttribut;
+ static const UTF8* sourceFileAttribut;
+
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+};
+
+class CommonClass : public mvm::Object {
+private:
+ llvm::GlobalVariable* _llvmVar;
+#ifdef SINGLE_VM
+ llvm::GlobalVariable* _llvmDelegatee;
+#endif
+public:
+ static VirtualTable* VT;
+ const llvm::Type * virtualType;
+ const llvm::Type * staticType;
+ const UTF8* name;
+ CommonClass * super;
+ const UTF8* superUTF8;
+ std::vector<const UTF8*> interfacesUTF8;
+ std::vector<Class*> interfaces;
+ mvm::Lock* lockVar;
+ mvm::Cond* condVar;
+ std::vector<JavaMethod*> virtualMethods;
+ std::vector<JavaMethod*> staticMethods;
+ std::vector<JavaField*> virtualFields;
+ std::vector<JavaField*> staticFields;
+ JavaObject* classLoader;
+#ifdef SINGLE_VM
+ JavaObject* delegatee;
+#endif
+ std::vector<CommonClass*> display;
+ unsigned int dim;
+ unsigned int depth;
+ bool isArray;
+ JavaState status;
+ unsigned int access;
+ Jnjvm *isolate;
+
+
+ static const int MaxDisplay;
+ static JavaObject* jnjvmClassLoader;
+
+ llvm::GlobalVariable* llvmVar(llvm::Module* compilingModule);
+#ifdef SINGLE_VM
+ llvm::GlobalVariable* llvmDelegatee();
+#endif
+ static void printClassName(const UTF8* name, mvm::PrintBuffer* buf);
+ void initialise(Jnjvm* isolate, bool array);
+ void aquire();
+ void release();
+ void waitClass();
+ void broadcastClass();
+ bool ownerClass();
+
+ JavaMethod* lookupMethodDontThrow(const UTF8* name, const UTF8* type,
+ bool isStatic, bool recurse);
+
+ JavaMethod* lookupMethod(const UTF8* name, const UTF8* type, bool isStatic,
+ bool recurse);
+
+ JavaField* lookupFieldDontThrow(const UTF8* name, const UTF8* type,
+ bool isStatic, bool recurse);
+
+ JavaField* lookupField(const UTF8* name, const UTF8* type, bool isStatic,
+ bool recurse);
+
+
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+
+ bool inheritName(const UTF8* Tname);
+ bool isOfTypeName(const UTF8* Tname);
+ bool implements(CommonClass* cl);
+ bool instantiationOfArray(CommonClass* cl);
+ bool subclassOf(CommonClass* cl);
+ bool isAssignableFrom(CommonClass* cl);
+ JavaObject* getClassDelegatee();
+ void initialiseClass();
+ void resolveClass(bool doClinit);
+
+#ifdef SINGLE_VM
+ bool isReady() {
+ return status == ready;
+ }
+#else
+ bool isReady();
+#endif
+
+};
+
+class Class : public CommonClass {
+private:
+ llvm::GlobalVariable* _staticVar;
+
+public:
+ static VirtualTable* VT;
+ unsigned int minor;
+ unsigned int major;
+ ArrayUInt8* bytes;
+ JavaObject* _staticInstance;
+ JavaObject* virtualInstance;
+ llvm::Function* virtualTracer;
+ llvm::Function* staticTracer;
+ mvm::Code* codeVirtualTracer;
+ mvm::Code* codeStaticTracer;
+ JavaCtpInfo* ctpInfo;
+ std::vector<Attribut*> attributs;
+ std::vector<Class*> innerClasses;
+ Class* outerClass;
+ uint32 innerAccess;
+ bool innerOuterResolved;
+
+ void resolveFields();
+ llvm::GlobalVariable* staticVar(llvm::Module* compilingModule);
+
+ uint64 virtualSize;
+ VirtualTable* virtualVT;
+#ifndef SINGLE_VM
+ uint64 staticSize;
+ VirtualTable* staticVT;
+ JavaObject* doNewIsolate();
+#endif
+ JavaObject* doNew();
+ JavaObject* doNewUnknown();
+ JavaObject* initialiseObject(JavaObject* obj);
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+
+ JavaObject* operator()();
+
+#ifdef SINGLE_VM
+ void setStaticInstance(JavaObject* val) {
+ _staticInstance = val;
+ }
+ JavaObject* staticInstance() {
+ return _staticInstance;
+ }
+#else
+ void setStaticInstance(JavaObject* val);
+ JavaObject* staticInstance();
+ JavaObject* createStaticInstance();
+#endif
+
+};
+
+
+class ClassArray : public CommonClass {
+public:
+ static VirtualTable* VT;
+ CommonClass* _baseClass;
+ AssessorDesc* _funcs;
+
+ void resolveComponent();
+ CommonClass* baseClass();
+ AssessorDesc* funcs();
+ static JavaObject* arrayLoader(Jnjvm* isolate, const UTF8* name,
+ JavaObject* loader, unsigned int start,
+ unsigned int end);
+
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+
+ static CommonClass* SuperArray;
+ static std::vector<Class*> InterfacesArray;
+ static std::vector<JavaMethod*> VirtualMethodsArray;
+ static std::vector<JavaMethod*> StaticMethodsArray;
+ static std::vector<JavaField*> VirtualFieldsArray;
+ static std::vector<JavaField*> StaticFieldsArray;
+};
+
+
+class JavaMethod : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ llvm::Function* methPtr;
+ unsigned int access;
+ Signdef* signature;
+ std::vector<Attribut*> attributs;
+ std::vector<Enveloppe*> caches;
+ Class* classDef;
+ const UTF8* name;
+ const UTF8* type;
+ bool canBeInlined;
+ mvm::Code* code;
+
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+
+ void* compiledPtr();
+ const llvm::FunctionType* llvmType;
+
+ uint32 invokeIntSpecialAP(JavaObject* obj, va_list ap);
+ float invokeFloatSpecialAP(JavaObject* obj, va_list ap);
+ double invokeDoubleSpecialAP(JavaObject* obj, va_list ap);
+ sint64 invokeLongSpecialAP(JavaObject* obj, va_list ap);
+ JavaObject* invokeJavaObjectSpecialAP(JavaObject* obj, va_list ap);
+
+ uint32 invokeIntVirtualAP(JavaObject* obj, va_list ap);
+ float invokeFloatVirtualAP(JavaObject* obj, va_list ap);
+ double invokeDoubleVirtualAP(JavaObject* obj, va_list ap);
+ sint64 invokeLongVirtualAP(JavaObject* obj, va_list ap);
+ JavaObject* invokeJavaObjectVirtualAP(JavaObject* obj, va_list ap);
+
+ uint32 invokeIntStaticAP(va_list ap);
+ float invokeFloatStaticAP(va_list ap);
+ double invokeDoubleStaticAP(va_list ap);
+ sint64 invokeLongStaticAP(va_list ap);
+ JavaObject* invokeJavaObjectStaticAP(va_list ap);
+
+ uint32 invokeIntSpecialBuf(JavaObject* obj, void* buf);
+ float invokeFloatSpecialBuf(JavaObject* obj, void* buf);
+ double invokeDoubleSpecialBuf(JavaObject* obj, void* buf);
+ sint64 invokeLongSpecialBuf(JavaObject* obj, void* buf);
+ JavaObject* invokeJavaObjectSpecialBuf(JavaObject* obj, void* buf);
+
+ uint32 invokeIntVirtualBuf(JavaObject* obj, void* buf);
+ float invokeFloatVirtualBuf(JavaObject* obj, void* buf);
+ double invokeDoubleVirtualBuf(JavaObject* obj, void* buf);
+ sint64 invokeLongVirtualBuf(JavaObject* obj, void* buf);
+ JavaObject* invokeJavaObjectVirtualBuf(JavaObject* obj, void* buf);
+
+ uint32 invokeIntStaticBuf(void* buf);
+ float invokeFloatStaticBuf(void* buf);
+ double invokeDoubleStaticBuf(void* buf);
+ sint64 invokeLongStaticBuf(void* buf);
+ JavaObject* invokeJavaObjectStaticBuf(void* buf);
+
+ uint32 invokeIntSpecial(JavaObject* obj, ...);
+ float invokeFloatSpecial(JavaObject* obj, ...);
+ double invokeDoubleSpecial(JavaObject* obj, ...);
+ sint64 invokeLongSpecial(JavaObject* obj, ...);
+ JavaObject* invokeJavaObjectSpecial(JavaObject* obj, ...);
+
+ uint32 invokeIntVirtual(JavaObject* obj, ...);
+ float invokeFloatVirtual(JavaObject* obj, ...);
+ double invokeDoubleVirtual(JavaObject* obj, ...);
+ sint64 invokeLongVirtual(JavaObject* obj, ...);
+ JavaObject* invokeJavaObjectVirtual(JavaObject* obj, ...);
+
+ uint32 invokeIntStatic(...);
+ float invokeFloatStatic(...);
+ double invokeDoubleStatic(...);
+ sint64 invokeLongStatic(...);
+ JavaObject* invokeJavaObjectStatic(...);
+};
+
+class JavaField : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ llvm::ConstantInt* offset;
+ unsigned int access;
+ const UTF8* name;
+ Typedef* signature;
+ const UTF8* type;
+ std::vector<Attribut*> attributs;
+ Class* classDef;
+ uint64 ptrOffset;
+
+ void initField(JavaObject* obj);
+
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+
+ llvm::GenericValue operator()(JavaObject* obj = 0);
+ void operator()(JavaObject* obj, float val);
+ void operator()(JavaObject* obj, double val);
+ void operator()(JavaObject* obj, uint32 val);
+ void operator()(JavaObject* obj, sint64 val);
+ void operator()(JavaObject* obj, JavaObject* val);
+ void operator()(float val);
+ void operator()(double val);
+ void operator()(uint32 val);
+ void operator()(sint64 val);
+
+
+};
+
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaConstantPool.cpp b/vmkit/lib/JnJVM/VMCore/JavaConstantPool.cpp
new file mode 100644
index 0000000..a349a51
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaConstantPool.cpp
@@ -0,0 +1,519 @@
+//===--- JavaConstantPool.cpp - Java constant pool definition ---------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <alloca.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "llvm/GlobalValue.h"
+
+#include "debug.h"
+
+#include "JavaAccess.h"
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Reader.h"
+
+using namespace jnjvm;
+
+const uint32 JavaCtpInfo::ConstantUTF8 = 1;
+const uint32 JavaCtpInfo::ConstantInteger = 3;
+const uint32 JavaCtpInfo::ConstantFloat = 4;
+const uint32 JavaCtpInfo::ConstantLong = 5;
+const uint32 JavaCtpInfo::ConstantDouble = 6;
+const uint32 JavaCtpInfo::ConstantClass = 7;
+const uint32 JavaCtpInfo::ConstantString = 8;
+const uint32 JavaCtpInfo::ConstantFieldref = 9;
+const uint32 JavaCtpInfo::ConstantMethodref = 10;
+const uint32 JavaCtpInfo::ConstantInterfaceMethodref = 11;
+const uint32 JavaCtpInfo::ConstantNameAndType = 12;
+
+
+void JavaCtpInfo::print(mvm::PrintBuffer* buf) {
+ buf->write("CtpInfoOf<");
+ classDef->print(buf);
+ buf->write(">");
+}
+
+static uint32 unimplemented(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "unknown constant pool type %d",
+ type);
+ return 1;
+}
+
+
+uint32 JavaCtpInfo::CtpReaderClass(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef,
+ void** ctpRes, uint8* ctpType) {
+ uint16 entry = reader->readU2();
+ ctpDef[e] = entry;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <class>\t\tutf8 is at %d\n", e,
+ entry);
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderInteger(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef,
+ void** ctpRes, uint8* ctpType) {
+ uint32 val = reader->readU4();
+ ctpDef[e] = val;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <class>\tinteger: %d\n", e,
+ val);
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderFloat(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType) {
+ uint32 val = reader->readU4();
+ ctpDef[e] = val;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <class>\tfloat: %p\n", e,
+ val);
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderUTF8(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef, void** ctpRes,
+ uint8* ctpType) {
+ uint16 len = reader->readU2();
+ uint16* buf = (uint16*)alloca(len * sizeof(uint16));
+ uint32 n = 0;
+ uint32 i = 0;
+
+ while (i < len) {
+ uint32 cur = reader->readU1();
+ if (cur & 0x80) {
+ uint32 y = reader->readU1();
+ if (cur & 0x20) {
+ uint32 z = reader->readU1();
+ cur = ((cur & 0x0F) << 12) +
+ ((y & 0x3F) << 6) +
+ (z & 0x3F);
+ i += 3;
+ } else {
+ cur = ((cur & 0x1F) << 6) +
+ (y & 0x3F);
+ i += 2;
+ }
+ } else {
+ ++i;
+ }
+ buf[n] = ((uint16)cur);
+ ++n;
+ }
+
+ const UTF8* utf8 = UTF8::readerConstruct(vm, buf, n);
+ ctpRes[e] = (UTF8*)utf8;
+
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <utf8>\t\t\"%s\"\n", e,
+ utf8->printString());
+
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderNameAndType(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef,
+ void** ctpRes, uint8* ctpType) {
+ uint32 entry = reader->readU4();
+ ctpDef[e] = entry;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL,
+ "; [%5d] <name/type>\tname is at %d, type is at %d\n", e,
+ (entry >> 16), (entry & 0xffff));
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderFieldref(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef,
+ void** ctpRes, uint8* ctpType) {
+ uint32 entry = reader->readU4();
+ ctpDef[e] = entry;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL,
+ "; [%5d] <fieldref>\tclass is at %d, name/type is at %d\n", e,
+ (entry >> 16), (entry & 0xffff));
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderString(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes,
+ uint8* ctpType) {
+ uint16 entry = reader->readU2();
+ ctpDef[e] = entry;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <string>\tutf8 is at %d\n",
+ e, entry);
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderMethodref(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes,
+ uint8* ctpType) {
+ uint32 entry = reader->readU4();
+ ctpDef[e] = entry;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL,
+ "; [%5d] <methodref>\tclass is at %d, name/type is at %d\n", e,
+ (entry >> 16), (entry & 0xffff));
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderInterfaceMethodref(Jnjvm* vm, uint32 type,
+ uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes,
+ uint8* ctpType) {
+ uint32 entry = reader->readU4();
+ ctpDef[e] = entry;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL,
+ "; [%5d] <Interface xmethodref>\tclass is at %d, name/type is at %d\n",
+ e, (entry >> 16), (entry & 0xffff));
+ return 1;
+}
+
+uint32 JavaCtpInfo::CtpReaderLong(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef, void** ctpRes,
+ uint8* ctpType) {
+ ctpDef[e + 1] = reader->readU4();
+ ctpDef[e] = reader->readU4();
+ ctpType[e] = ConstantLong;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <long>\%d %d\n", e,
+ ctpDef[e], ctpDef[e + 1]);
+ return 2;
+}
+
+uint32 JavaCtpInfo::CtpReaderDouble(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes,
+ uint8* ctpType) {
+ ctpDef[e + 1] = reader->readU4();
+ ctpDef[e] = reader->readU4();
+ ctpType[e] = ConstantDouble;
+ PRINT_DEBUG(JNJVM_LOAD, 3, COLOR_NORMAL, "; [%5d] <double>\%d %d\n", e,
+ ctpDef[e], ctpDef[e + 1]);
+ return 2;
+}
+
+void JavaCtpInfo::read(Jnjvm *vm, Class* cl, Reader* reader) {
+ uint32 nbCtp = reader->readU2();
+ JavaCtpInfo* res = gc_new(JavaCtpInfo)();
+
+ res->ctpRes = (void**)malloc(sizeof(void*)*nbCtp);
+ res->ctpDef = (sint32*)malloc(sizeof(sint32)*nbCtp);
+ res->ctpType = (uint8*)malloc(sizeof(uint8)*nbCtp);
+ memset(res->ctpRes, 0, sizeof(void**)*nbCtp);
+ memset(res->ctpDef, 0, sizeof(sint32)*nbCtp);
+ memset(res->ctpType, 0, sizeof(uint8)*nbCtp);
+
+ res->ctpSize = nbCtp;
+ res->classDef = cl;
+ cl->ctpInfo = res;
+
+ uint32 cur = 1;
+ while (cur < nbCtp) {
+ uint8 curType = reader->readU1();
+ res->ctpType[cur] = curType;
+ cur += ((funcsReader[curType])(vm, curType, cur, reader, res->ctpDef,
+ res->ctpRes, res->ctpType));
+ }
+}
+
+bool JavaCtpInfo::isAStaticCall(uint32 index) {
+ return (ctpType[index] & 0x80) != 0;
+}
+
+void JavaCtpInfo::markAsStaticCall(uint32 index) {
+ ctpType[index] |= 0x80;
+}
+
+uint8 JavaCtpInfo::typeAt(uint32 index) {
+ return ctpType[index] & 0x7F;
+}
+
+const UTF8* JavaCtpInfo::UTF8At(uint32 entry) {
+ if (! (entry > 0) && (entry < ctpSize) &&
+ typeAt(entry) == ConstantUTF8) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for utf8 at entry %d", entry);
+ }
+ return (const UTF8*)ctpRes[entry];
+}
+
+float JavaCtpInfo::FloatAt(uint32 entry) {
+ if (! (entry > 0) && (entry < ctpSize) &&
+ typeAt(entry) == ConstantFloat) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for float at entry %d", entry);
+ }
+ return ((float*)ctpDef)[entry];
+}
+
+sint32 JavaCtpInfo::IntegerAt(uint32 entry) {
+ if (! (entry > 0) && (entry < ctpSize) &&
+ typeAt(entry) == ConstantInteger) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for integer at entry %d", entry);
+ }
+ return ((sint32*)ctpDef)[entry];
+}
+
+sint64 JavaCtpInfo::LongAt(uint32 entry) {
+ if (! (entry > 0) && (entry < ctpSize) &&
+ typeAt(entry) == ConstantLong) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for long at entry %d", entry);
+ }
+ return Reader::readLong(ctpDef[entry], ctpDef[entry + 1]);
+}
+
+double JavaCtpInfo::DoubleAt(uint32 entry) {
+ if (! (entry > 0) && (entry < ctpSize) &&
+ typeAt(entry) == ConstantDouble) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for double at entry %d", entry);
+ }
+ return Reader::readDouble(ctpDef[entry], ctpDef[entry + 1]);
+}
+
+CommonClass* JavaCtpInfo::isLoadedClassOrClassName(uint32 entry) {
+ if (! (entry > 0) && (entry < ctpSize) &&
+ typeAt(entry) == ConstantClass) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for class at entry %d", entry);
+ }
+ return (CommonClass*)ctpRes[entry];
+}
+
+const UTF8* JavaCtpInfo::resolveClassName(uint32 index) {
+ CommonClass* cl = isLoadedClassOrClassName(index);
+ if (cl) return cl->name;
+ else return UTF8At(ctpDef[index]);
+}
+
+CommonClass* JavaCtpInfo::loadClass(uint32 index) {
+ CommonClass* temp = isLoadedClassOrClassName(index);
+ if (!temp) {
+ JavaObject* loader = classDef->classLoader;
+ const UTF8* name = UTF8At(ctpDef[index]);
+ if (name->at(0) == AssessorDesc::I_TAB) {
+ // Don't put into ctpRes because the class can be isolate specific
+ temp = JavaThread::get()->isolate->constructArray(name, loader);
+ } else {
+ // Put into ctpRes because there is only one representation of the class
+ ctpRes[index] = temp = classDef->isolate->loadName(name, loader, false,
+ false, false);
+ }
+ }
+ return temp;
+}
+
+CommonClass* JavaCtpInfo::getMethodClassIfLoaded(uint32 index) {
+ CommonClass* temp = isLoadedClassOrClassName(index);
+ if (!temp) {
+ JavaObject* loader = classDef->classLoader;
+ const UTF8* name = UTF8At(ctpDef[index]);
+ temp = JavaThread::get()->isolate->lookupClass(name, loader);
+ if (!temp) temp = Jnjvm::bootstrapVM->lookupClass(name, CommonClass::jnjvmClassLoader);
+ }
+ return temp;
+}
+
+void JavaCtpInfo::checkInfoOfClass(uint32 index) {
+ if (typeAt(index) != ConstantClass)
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for class at entry %d", index);
+ /*if (!(ctpRes[index]))
+ ctpRes[index] = JavaJIT::newLookupLLVM;*/
+}
+
+Typedef* JavaCtpInfo::resolveNameAndType(uint32 index) {
+ void* res = ctpRes[index];
+ if (!res) {
+ if (typeAt(index) != ConstantNameAndType) {
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for name/type at entry %d", index);
+ }
+ sint32 entry = ctpDef[index];
+ const UTF8* type = UTF8At(entry & 0xFFFF);
+ Typedef* sign = JavaThread::get()->isolate->constructType(type);
+ ctpRes[index] = sign;
+ return sign;
+ }
+ return (Typedef*)res;
+}
+
+Typedef* JavaCtpInfo::infoOfField(uint32 index) {
+ if (typeAt(index) != ConstantFieldref)
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for field at entry %d", index);
+ return resolveNameAndType(ctpDef[index] & 0xFFFF);
+}
+
+void JavaCtpInfo::infoOfMethod(uint32 index, uint32 access,
+ CommonClass*& cl, JavaMethod*& meth) {
+ uint8 id = typeAt(index);
+ if (id != ConstantMethodref && id != ConstantInterfaceMethodref)
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for method at entry %d", index);
+
+ Signdef* sign = (Signdef*)resolveNameAndType(ctpDef[index] & 0xFFFF);
+ sint32 entry = ctpDef[index];
+ sint32 ntIndex = entry & 0xFFFF;
+ const UTF8* utf8 = UTF8At(ctpDef[ntIndex] >> 16);
+ cl = getMethodClassIfLoaded(entry >> 16);
+ if (cl && cl->status >= readed) {
+ // lookup the method
+ meth = cl->lookupMethodDontThrow(utf8, sign->keyName, isStatic(access), false);
+ }
+}
+
+void JavaCtpInfo::nameOfStaticOrSpecialMethod(uint32 index,
+ const UTF8*& cl,
+ const UTF8*& name,
+ Signdef*& sign) {
+ uint8 id = typeAt(index);
+ if (id != ConstantMethodref && id != ConstantInterfaceMethodref)
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for method at entry %d", index);
+
+ sign = (Signdef*)resolveNameAndType(ctpDef[index] & 0xFFFF);
+ sint32 entry = ctpDef[index];
+ sint32 ntIndex = entry & 0xFFFF;
+ name = UTF8At(ctpDef[ntIndex] >> 16);
+ cl = resolveClassName(entry >> 16);
+}
+
+llvm::Function* JavaCtpInfo::infoOfStaticOrSpecialMethod(
+ uint32 index,
+ uint32 access,
+ Signdef*& sign,
+ JavaMethod*& meth) {
+ uint8 id = typeAt(index);
+ if (id != ConstantMethodref && id != ConstantInterfaceMethodref)
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for method at entry %d", index);
+
+ sign = (Signdef*)resolveNameAndType(ctpDef[index] & 0xFFFF);
+ sint32 entry = ctpDef[index];
+ sint32 ntIndex = entry & 0xFFFF;
+ const UTF8* utf8 = UTF8At(ctpDef[ntIndex] >> 16);
+ CommonClass* cl = getMethodClassIfLoaded(entry >> 16);
+ if (cl && cl->status >= readed) {
+ // lookup the method
+ meth = cl->lookupMethodDontThrow(utf8, sign->keyName, isStatic(access), false);
+ if (meth) { // don't throw if no meth, the exception will be thrown just in time
+ if (meth->methPtr) {
+ ctpRes[index] = (void*)meth->methPtr;
+ return (llvm::Function*)ctpRes[index];
+ }
+ }
+ }
+
+ // Must be a callback
+ if (ctpRes[index]) {
+ return (llvm::Function*)ctpRes[index];
+ } else {
+ // Create the callback
+ const llvm::FunctionType* type = 0;
+ if (isStatic(access)) {
+ type = sign->staticType;
+ } else {
+ type = sign->virtualType;
+ }
+ llvm::Function* func = new llvm::Function(type,
+ llvm::GlobalValue::GhostLinkage,
+ "callback", classDef->isolate->module);
+ classDef->isolate->TheModuleProvider->functions->hash(func,
+ new std::pair<Class*, uint32>(classDef, index));
+ ctpRes[index] = func;
+ return func;
+ }
+}
+
+
+Signdef* JavaCtpInfo::infoOfInterfaceOrVirtualMethod(uint32 index) {
+
+ uint8 id = typeAt(index);
+ if (id != ConstantMethodref && id != ConstantInterfaceMethodref)
+ JavaThread::get()->isolate->error(Jnjvm::ClassFormatError,
+ "bad constant pool number for method at entry %d", index);
+
+ Signdef* sign = (Signdef*)resolveNameAndType(ctpDef[index] & 0xFFFF);
+
+ return sign;
+}
+
+void JavaCtpInfo::resolveInterfaceOrMethod(uint32 index,
+ CommonClass*& cl, const UTF8*& utf8,
+ Signdef*& sign) {
+ sint32 entry = ctpDef[index];
+ sint32 ntIndex = entry & 0xFFFF;
+ sign = (Signdef*)ctpRes[ntIndex];
+ utf8 = UTF8At(ctpDef[ntIndex] >> 16);
+ cl = loadClass(entry >> 16);
+ cl->resolveClass(true);
+}
+
+void JavaCtpInfo::resolveField(uint32 index, CommonClass*& cl,
+ const UTF8*& utf8, Typedef*& sign) {
+ sint32 entry = ctpDef[index];
+ sint32 ntIndex = entry & 0xFFFF;
+ sign = (Typedef*)ctpRes[ntIndex];
+ utf8 = UTF8At(ctpDef[ntIndex] >> 16);
+ cl = loadClass(entry >> 16);
+ cl->resolveClass(true);
+}
+
+JavaField* JavaCtpInfo::lookupField(uint32 index, bool stat) {
+ if (!(ctpRes[index])) {
+ sint32 entry = ctpDef[index];
+ sint32 ntIndex = entry & 0xFFFF;
+ Typedef* sign = (Typedef*)ctpRes[ntIndex];
+ const UTF8* utf8 = UTF8At(ctpDef[ntIndex] >> 16);
+ CommonClass* cl = getMethodClassIfLoaded(entry >> 16);
+ if (cl && cl->status >= resolved) {
+ JavaField* field = cl->lookupFieldDontThrow(utf8, sign->keyName, stat,
+ true);
+ // don't throw if no field, the exception will be thrown just in time
+ if (field) {
+ ctpRes[index] = field;
+ return field;
+ }
+ } else {
+ return 0;
+ }
+ }
+ return (JavaField*)ctpRes[index];
+}
+
+JavaString* JavaCtpInfo::resolveString(const UTF8* utf8, uint16 index) {
+ JavaString* str = JavaThread::get()->isolate->UTF8ToStr(utf8);
+ return str;
+}
+
+ctpReader JavaCtpInfo::funcsReader[16] = {
+ unimplemented,
+ CtpReaderUTF8,
+ unimplemented,
+ CtpReaderInteger,
+ CtpReaderFloat,
+ CtpReaderLong,
+ CtpReaderDouble,
+ CtpReaderClass,
+ CtpReaderString,
+ CtpReaderFieldref,
+ CtpReaderMethodref,
+ CtpReaderInterfaceMethodref,
+ CtpReaderNameAndType,
+ unimplemented,
+ unimplemented,
+ unimplemented
+};
diff --git a/vmkit/lib/JnJVM/VMCore/JavaConstantPool.h b/vmkit/lib/JnJVM/VMCore/JavaConstantPool.h
new file mode 100644
index 0000000..9a2d17e
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaConstantPool.h
@@ -0,0 +1,136 @@
+//===--- JavaConstantPool.h - Java constant pool definition ---------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_CONSTANT_POOL_H
+#define JNJVM_JAVA_CONSTANT_POOL_H
+
+#include "mvm/Object.h"
+
+#include "types.h"
+
+#include "llvm/Type.h"
+
+namespace jnjvm {
+
+class Class;
+class Jnjvm;
+class JavaString;
+class Reader;
+class Signdef;
+class Typedef;
+class UTF8;
+
+typedef uint32 (*ctpReader)(Jnjvm*, uint32, uint32, Reader*, sint32*, void**, uint8*);
+
+class JavaCtpInfo : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ Class* classDef;
+ void** ctpRes;
+ sint32* ctpDef;
+ uint8* ctpType;
+ uint32 ctpSize;
+
+ static const uint32 ConstantUTF8;
+ static const uint32 ConstantInteger;
+ static const uint32 ConstantFloat;
+ static const uint32 ConstantLong;
+ static const uint32 ConstantDouble;
+ static const uint32 ConstantClass;
+ static const uint32 ConstantString;
+ static const uint32 ConstantFieldref;
+ static const uint32 ConstantMethodref;
+ static const uint32 ConstantInterfaceMethodref;
+ static const uint32 ConstantNameAndType;
+
+ virtual void print(mvm::PrintBuffer* buf);
+ virtual void tracer(size_t sz);
+
+ static ctpReader funcsReader[16];
+
+ static uint32 CtpReaderClass(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderInteger(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderFloat(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderUTF8(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderNameAndType(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes,
+ uint8* ctpType);
+
+ static uint32 CtpReaderFieldref(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderString(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderMethodref(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderInterfaceMethodref(Jnjvm* vm, uint32 type, uint32 e,
+ Reader* reader, sint32* ctpDef,
+ void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderLong(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static uint32 CtpReaderDouble(Jnjvm* vm, uint32 type, uint32 e, Reader* reader,
+ sint32* ctpDef, void** ctpRes, uint8* ctpType);
+
+ static void read(Jnjvm *vm, Class* cl, Reader* reader);
+
+ bool isAStaticCall(uint32 index);
+ void markAsStaticCall(uint32 index);
+
+ uint8 typeAt(uint32 index);
+ const UTF8* UTF8At(uint32 entry);
+ float FloatAt(uint32 entry);
+ sint32 IntegerAt(uint32 entry);
+ sint64 LongAt(uint32 entry);
+ double DoubleAt(uint32 entry);
+
+ CommonClass* isLoadedClassOrClassName(uint32 index);
+ const UTF8* resolveClassName(uint32 index);
+ CommonClass* loadClass(uint32 index);
+ void checkInfoOfClass(uint32 index);
+ Typedef* resolveNameAndType(uint32 index);
+ Typedef* infoOfField(uint32 index);
+ Signdef* infoOfInterfaceOrVirtualMethod(uint32 index);
+ llvm::Function* infoOfStaticOrSpecialMethod(uint32 index,
+ uint32 access,
+ Signdef*& sign,
+ JavaMethod*& meth);
+
+ void nameOfStaticOrSpecialMethod(uint32 index, const UTF8*& cl,
+ const UTF8*& name, Signdef*& sign);
+
+ CommonClass* getMethodClassIfLoaded(uint32 index);
+ void resolveInterfaceOrMethod(uint32 index, CommonClass*& cl,
+ const UTF8*& utf8, Signdef*& sign);
+ void infoOfMethod(uint32 index, uint32 access, CommonClass*& cl,
+ JavaMethod*& meth);
+ void resolveField(uint32 index, CommonClass*& cl, const UTF8*& utf8,
+ Typedef*& sign);
+
+ JavaString* resolveString(const UTF8* utf8, uint16 index);
+
+ JavaField* lookupField(uint32 index, bool stat);
+
+
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaInitialise.cpp b/vmkit/lib/JnJVM/VMCore/JavaInitialise.cpp
new file mode 100644
index 0000000..d6fd945
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaInitialise.cpp
@@ -0,0 +1,359 @@
+//===-------- JavaInitialise.cpp - Initialization of JnJVM ----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <vector>
+
+#include "mvm/VMLet.h"
+#include "mvm/Threads/Locks.h"
+
+#include "JavaArray.h"
+#include "JavaCache.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaIsolate.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+#include "NativeUtil.h"
+#include "Reader.h"
+#include "LockedMap.h"
+#include "Zip.h"
+
+
+
+
+using namespace jnjvm;
+
+ClassArray* JavaArray::ofByte = 0;
+ClassArray* JavaArray::ofChar = 0;
+ClassArray* JavaArray::ofInt = 0;
+ClassArray* JavaArray::ofShort = 0;
+ClassArray* JavaArray::ofBool = 0;
+ClassArray* JavaArray::ofLong = 0;
+ClassArray* JavaArray::ofFloat = 0;
+ClassArray* JavaArray::ofDouble = 0;
+ClassArray* JavaArray::ofString = 0;
+ClassArray* JavaArray::ofObject = 0;
+
+const UTF8* Attribut::codeAttribut = 0;
+const UTF8* Attribut::exceptionsAttribut = 0;
+const UTF8* Attribut::constantAttribut = 0;
+const UTF8* Attribut::lineNumberTableAttribut = 0;
+const UTF8* Attribut::innerClassesAttribut = 0;
+const UTF8* Attribut::sourceFileAttribut = 0;
+
+JavaObject* CommonClass::jnjvmClassLoader = 0;
+
+CommonClass* ClassArray::SuperArray = 0;
+std::vector<Class*> ClassArray::InterfacesArray;
+std::vector<JavaMethod*> ClassArray::VirtualMethodsArray;
+std::vector<JavaMethod*> ClassArray::StaticMethodsArray;
+std::vector<JavaField*> ClassArray::VirtualFieldsArray;
+std::vector<JavaField*> ClassArray::StaticFieldsArray;
+
+
+llvm::Function* JavaJIT::getSJLJBufferLLVM = 0;
+llvm::Function* JavaJIT::throwExceptionLLVM = 0;
+llvm::Function* JavaJIT::getExceptionLLVM = 0;
+llvm::Function* JavaJIT::getJavaExceptionLLVM = 0;
+llvm::Function* JavaJIT::clearExceptionLLVM = 0;
+llvm::Function* JavaJIT::compareExceptionLLVM = 0;
+llvm::Function* JavaJIT::nullPointerExceptionLLVM = 0;
+llvm::Function* JavaJIT::classCastExceptionLLVM = 0;
+llvm::Function* JavaJIT::indexOutOfBoundsExceptionLLVM = 0;
+llvm::Function* JavaJIT::markAndTraceLLVM = 0;
+llvm::Function* JavaJIT::javaObjectTracerLLVM = 0;
+llvm::Function* JavaJIT::virtualLookupLLVM = 0;
+llvm::Function* JavaJIT::fieldLookupLLVM = 0;
+llvm::Function* JavaJIT::UTF8AconsLLVM = 0;
+llvm::Function* JavaJIT::Int8AconsLLVM = 0;
+llvm::Function* JavaJIT::Int32AconsLLVM = 0;
+llvm::Function* JavaJIT::Int16AconsLLVM = 0;
+llvm::Function* JavaJIT::FloatAconsLLVM = 0;
+llvm::Function* JavaJIT::DoubleAconsLLVM = 0;
+llvm::Function* JavaJIT::LongAconsLLVM = 0;
+llvm::Function* JavaJIT::ObjectAconsLLVM = 0;
+llvm::Function* JavaJIT::printExecutionLLVM = 0;
+llvm::Function* JavaJIT::printMethodStartLLVM = 0;
+llvm::Function* JavaJIT::printMethodEndLLVM = 0;
+llvm::Function* JavaJIT::jniProceedPendingExceptionLLVM = 0;
+llvm::Function* JavaJIT::doNewLLVM = 0;
+llvm::Function* JavaJIT::doNewUnknownLLVM = 0;
+llvm::Function* JavaJIT::initialiseObjectLLVM = 0;
+llvm::Function* JavaJIT::newLookupLLVM = 0;
+llvm::Function* JavaJIT::instanceOfLLVM = 0;
+llvm::Function* JavaJIT::aquireObjectLLVM = 0;
+llvm::Function* JavaJIT::releaseObjectLLVM = 0;
+llvm::Function* JavaJIT::multiCallNewLLVM = 0;
+llvm::Function* JavaJIT::runtimeUTF8ToStrLLVM = 0;
+llvm::Function* JavaJIT::getStaticInstanceLLVM = 0;
+llvm::Function* JavaJIT::getClassDelegateeLLVM = 0;
+llvm::Function* JavaJIT::arrayLengthLLVM = 0;
+#ifndef SINGLE_VM
+llvm::Function* JavaJIT::doNewIsolateLLVM = 0;
+#endif
+
+
+const llvm::FunctionType* JavaJIT::markAndTraceLLVMType = 0;
+
+mvm::Lock* JavaObject::globalLock = 0;
+const llvm::Type* JavaObject::llvmType = 0;
+const llvm::Type* JavaArray::llvmType = 0;
+const llvm::Type* ArrayUInt8::llvmType = 0;
+const llvm::Type* ArraySInt8::llvmType = 0;
+const llvm::Type* ArrayUInt16::llvmType = 0;
+const llvm::Type* ArraySInt16::llvmType = 0;
+const llvm::Type* ArrayUInt32::llvmType = 0;
+const llvm::Type* ArraySInt32::llvmType = 0;
+const llvm::Type* ArrayFloat::llvmType = 0;
+const llvm::Type* ArrayDouble::llvmType = 0;
+const llvm::Type* ArrayLong::llvmType = 0;
+const llvm::Type* ArrayObject::llvmType = 0;
+const llvm::Type* UTF8::llvmType = 0;
+const llvm::Type* CacheNode::llvmType = 0;
+const llvm::Type* Enveloppe::llvmType = 0;
+
+
+mvm::Key<JavaThread>* JavaThread::threadKey = 0;
+
+
+Jnjvm* Jnjvm::bootstrapVM = 0;
+const UTF8* Jnjvm::initName = 0;
+const UTF8* Jnjvm::clinitName = 0;
+const UTF8* Jnjvm::clinitType = 0;
+const UTF8* Jnjvm::runName = 0;
+const UTF8* Jnjvm::prelib = 0;
+const UTF8* Jnjvm::postlib = 0;
+const UTF8* Jnjvm::mathName = 0;
+
+#define DEF_UTF8(var) \
+ const UTF8* Jnjvm::var = 0;
+
+ DEF_UTF8(abs);
+ DEF_UTF8(sqrt);
+ DEF_UTF8(sin);
+ DEF_UTF8(cos);
+ DEF_UTF8(tan);
+ DEF_UTF8(asin);
+ DEF_UTF8(acos);
+ DEF_UTF8(atan);
+ DEF_UTF8(atan2);
+ DEF_UTF8(exp);
+ DEF_UTF8(log);
+ DEF_UTF8(pow);
+ DEF_UTF8(ceil);
+ DEF_UTF8(floor);
+ DEF_UTF8(rint);
+ DEF_UTF8(cbrt);
+ DEF_UTF8(cosh);
+ DEF_UTF8(expm1);
+ DEF_UTF8(hypot);
+ DEF_UTF8(log10);
+ DEF_UTF8(log1p);
+ DEF_UTF8(sinh);
+ DEF_UTF8(tanh);
+
+#undef DEF_UTF8
+
+
+static void initialiseVT() {
+
+# define INIT(X) { \
+ X fake; \
+ X::VT = ((void**)(void*)(&fake))[0]; }
+
+ INIT(JavaArray);
+ INIT(ArrayUInt8);
+ INIT(ArraySInt8);
+ INIT(ArrayUInt16);
+ INIT(ArraySInt16);
+ INIT(ArrayUInt32);
+ INIT(ArraySInt32);
+ INIT(ArrayLong);
+ INIT(ArrayFloat);
+ INIT(ArrayDouble);
+ INIT(ArrayObject);
+ INIT(UTF8);
+ INIT(Attribut);
+ INIT(CommonClass);
+ INIT(Class);
+ INIT(ClassArray);
+ INIT(JavaMethod);
+ INIT(JavaField);
+ INIT(JavaCtpInfo);
+ INIT(Exception);
+ INIT(JavaJIT);
+ INIT(JavaCond);
+ INIT(LockObj);
+ INIT(JavaObject);
+ INIT(JavaThread);
+ //mvm::Key<JavaThread>::VT = mvm::ThreadKey::VT;
+ INIT(AssessorDesc);
+ INIT(Typedef);
+ INIT(Signdef);
+ INIT(ThreadSystem);
+ INIT(Jnjvm);
+ INIT(Reader);
+ INIT(ZipFile);
+ INIT(ZipArchive);
+ INIT(UTF8Map);
+ INIT(ClassMap);
+ INIT(FieldMap);
+ INIT(MethodMap);
+ INIT(ZipFileMap);
+ INIT(StringMap);
+ INIT(jnjvm::TypeMap);
+ INIT(JavaIsolate);
+ INIT(JavaString);
+ INIT(CacheNode);
+ INIT(Enveloppe);
+#undef INIT
+
+}
+
+static void initialiseStatics() {
+ JavaObject::globalLock = mvm::Lock::allocNormal();
+ //mvm::Object::pushRoot((mvm::Object*)JavaObject::globalLock);
+
+ JavaThread::threadKey = new mvm::Key<JavaThread>();
+ //JavaThread::threadKey = gc_new(mvm::Key<JavaThread>);
+ //mvm::Object::pushRoot((mvm::Object*)JavaThread::threadKey);
+
+ Jnjvm* vm = JavaIsolate::bootstrapVM = JavaIsolate::allocateBootstrap();
+ mvm::Object::pushRoot((mvm::Object*)JavaIsolate::bootstrapVM);
+
+ // Array initialization
+ const UTF8* utf8OfChar = vm->asciizConstructUTF8("[C");
+ JavaArray::ofChar = vm->constructArray(utf8OfChar,
+ CommonClass::jnjvmClassLoader);
+ ((UTF8*)utf8OfChar)->classOf = JavaArray::ofChar;
+
+ AssessorDesc::initialise(vm);
+
+
+
+ ClassArray::InterfacesArray.push_back(
+ vm->constructClass(vm->asciizConstructUTF8("java/lang/Cloneable"),
+ CommonClass::jnjvmClassLoader));
+
+ ClassArray::InterfacesArray.push_back(
+ vm->constructClass(vm->asciizConstructUTF8("java/io/Serializable"),
+ CommonClass::jnjvmClassLoader));
+
+ ClassArray::SuperArray =
+ vm->constructClass(vm->asciizConstructUTF8("java/lang/Object"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofChar->interfaces = ClassArray::InterfacesArray;
+ JavaArray::ofChar->super = ClassArray::SuperArray;
+
+ JavaArray::ofByte = vm->constructArray(vm->asciizConstructUTF8("[B"),
+ CommonClass::jnjvmClassLoader);
+ JavaArray::ofString =
+ vm->constructArray(vm->asciizConstructUTF8("[Ljava/lang/String;"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofObject =
+ vm->constructArray(vm->asciizConstructUTF8("[Ljava/lang/Object;"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofInt = vm->constructArray(vm->asciizConstructUTF8("[I"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofBool = vm->constructArray(vm->asciizConstructUTF8("[Z"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofLong = vm->constructArray(vm->asciizConstructUTF8("[J"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofFloat = vm->constructArray(vm->asciizConstructUTF8("[F"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofDouble = vm->constructArray(vm->asciizConstructUTF8("[D"),
+ CommonClass::jnjvmClassLoader);
+
+ JavaArray::ofShort = vm->constructArray(vm->asciizConstructUTF8("[S"),
+ CommonClass::jnjvmClassLoader);
+
+ // End array initialization
+
+ Attribut::codeAttribut = vm->asciizConstructUTF8("Code");
+ Attribut::exceptionsAttribut = vm->asciizConstructUTF8("Exceptions");
+ Attribut::constantAttribut = vm->asciizConstructUTF8("ConstantValue");
+ Attribut::lineNumberTableAttribut =
+ vm->asciizConstructUTF8("LineNumberTable");
+ Attribut::innerClassesAttribut = vm->asciizConstructUTF8("InnerClasses");
+ Attribut::sourceFileAttribut = vm->asciizConstructUTF8("SourceFile");
+
+ Jnjvm::initName = vm->asciizConstructUTF8("<init>");
+ Jnjvm::clinitName = vm->asciizConstructUTF8("<clinit>");
+ Jnjvm::clinitType = vm->asciizConstructUTF8("()V");
+ Jnjvm::runName = vm->asciizConstructUTF8("run");
+ Jnjvm::prelib = vm->asciizConstructUTF8("lib");
+ Jnjvm::postlib = vm->asciizConstructUTF8(".so");
+ Jnjvm::mathName = vm->asciizConstructUTF8("java/lang/Math");
+
+#define DEF_UTF8(var) \
+ Jnjvm::var = vm->asciizConstructUTF8(#var)
+
+ DEF_UTF8(abs);
+ DEF_UTF8(sqrt);
+ DEF_UTF8(sin);
+ DEF_UTF8(cos);
+ DEF_UTF8(tan);
+ DEF_UTF8(asin);
+ DEF_UTF8(acos);
+ DEF_UTF8(atan);
+ DEF_UTF8(atan2);
+ DEF_UTF8(exp);
+ DEF_UTF8(log);
+ DEF_UTF8(pow);
+ DEF_UTF8(ceil);
+ DEF_UTF8(floor);
+ DEF_UTF8(rint);
+ DEF_UTF8(cbrt);
+ DEF_UTF8(cosh);
+ DEF_UTF8(expm1);
+ DEF_UTF8(hypot);
+ DEF_UTF8(log10);
+ DEF_UTF8(log1p);
+ DEF_UTF8(sinh);
+ DEF_UTF8(tanh);
+
+#undef DEF_UTF8
+
+}
+
+extern "C" void sigsegv_handler(int val, void* addr) {
+ printf("SIGSEGV in JnJVM at %p\n", addr);
+ JavaJIT::printBacktrace();
+ assert(0);
+}
+
+
+extern "C" int boot() {
+ JavaJIT::initialise();
+ initialiseVT();
+ initialiseStatics();
+ Classpath::initialiseClasspath(JavaIsolate::bootstrapVM);
+ //mvm::VMLet::register_sigsegv_handler(sigsegv_handler);
+ return 0;
+}
+
+extern "C" int start_app(int argc, char** argv) {
+ JavaIsolate* vm = JavaIsolate::allocateIsolate(JavaIsolate::bootstrapVM);
+ vm->runMain(argc, argv);
+ return 0;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaIsolate.cpp b/vmkit/lib/JnJVM/VMCore/JavaIsolate.cpp
new file mode 100644
index 0000000..5a9b3eb
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaIsolate.cpp
@@ -0,0 +1,528 @@
+//===------------ JavaIsolate.cpp - Start an isolate ----------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <jni.h>
+
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetData.h"
+
+#include "mvm/JIT.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Cond.h"
+
+#include "JavaClass.h"
+#include "JavaIsolate.h"
+#include "JavaJIT.h"
+#include "JavaString.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "JnjvmModuleProvider.h"
+#include "LockedMap.h"
+#include "Zip.h"
+
+#define PATH_MANIFEST "META-INF/MANIFEST.MF"
+#define MAIN_CLASS "Main-Class: "
+#define PREMAIN_CLASS "Premain-Class: "
+#define BOOT_CLASS_PATH "Boot-Class-Path: "
+#define CAN_REDEFINE_CLASS_PATH "Can-Redefine-Classes: "
+
+#define LENGTH_MAIN_CLASS 12
+#define LENGTH_PREMAIN_CLASS 15
+#define LENGTH_BOOT_CLASS_PATH 17
+
+using namespace jnjvm;
+
+extern "C" struct JNINativeInterface JNI_JNIEnvTable;
+extern "C" const struct JNIInvokeInterface JNI_JavaVMTable;
+
+
+class ClArgumentsInfo {
+public:
+ uint32 appArgumentsPos;
+ char* className;
+ std::vector< std::pair<char*, char*> > agents;
+
+ void readArgs(int argc, char** argv, Jnjvm *vm);
+ void extractClassFromJar(Jnjvm* vm, int argc, char** argv, int i);
+ void javaAgent(char* cur);
+
+ void printInformation();
+ void nyi();
+ void printVersion();
+};
+
+void ClArgumentsInfo::javaAgent(char* cur) {
+ assert(0 && "implement me");
+}
+
+extern "C" int strnstr(char *haystack, char *needle) {
+ char * res = strstr(haystack, needle);
+ if (res) return (int)res - (int)haystack;
+ else return -1;
+}
+
+
+static char* findInformation(ArrayUInt8* manifest, char* entry, uint32 len) {
+ uint8* ptr = manifest->elements;
+ sint32 index = strnstr((char*)ptr, entry);
+ if (index != -1) {
+ index += len;
+ sint32 end = strnstr((char*)&(ptr[index]), "\n");
+ if (end == -1) end = manifest->size;
+ else end += index;
+
+ sint32 length = end - index - 1;
+ char* name = (char*)malloc(length + 1);
+ memcpy(name, &(ptr[index]), length);
+ name[length] = 0;
+ return name;
+ } else {
+ return 0;
+ }
+}
+
+void ClArgumentsInfo::extractClassFromJar(Jnjvm* vm, int argc, char** argv,
+ int i) {
+ char* jarFile = argv[i];
+ char* temp =
+ (char*)malloc(2 + strlen(vm->classpath) + strlen(jarFile));
+
+ sprintf(temp, "%s:%s", vm->classpath, jarFile);
+ vm->setClasspath(temp);
+
+ ZipArchive* archive = ZipArchive::singleArchive(jarFile);
+ if (archive) {
+ ZipFile* file = archive->getFile(PATH_MANIFEST);
+ if (file) {
+ ArrayUInt8* res = ArrayUInt8::acons(file->ucsize, JavaArray::ofByte);
+ int ok = archive->readFile(res, file);
+ if (ok) {
+ char* mainClass = findInformation(res, MAIN_CLASS, LENGTH_MAIN_CLASS);
+ archive->remove();
+ if (mainClass) {
+ className = mainClass;
+ } else {
+ printf("No Main-Class: in Manifest of archive %s.\n", jarFile);
+ }
+ } else {
+ printf("Can't extract Manifest file from archive %s\n", jarFile);
+ }
+ } else {
+ printf("Can't find Manifest file in archive %s\n", jarFile);
+ }
+ } else {
+ printf("Can't find archive %s\n", jarFile);
+ }
+}
+
+void ClArgumentsInfo::nyi() {
+ fprintf(stdout, "Not yet implemented\n");
+}
+
+void ClArgumentsInfo::printVersion() {
+ fprintf(stdout, "JnJVM for Java 1.1 -- 1.5\n");
+}
+
+void ClArgumentsInfo::printInformation() {
+ fprintf(stdout,
+ "Usage: java [-options] class [args...] (to execute a class)\n"
+ "or java [-options] -jar jarfile [args...]\n"
+ "(to execute a jar file) where options include:\n"
+ "-client to select the \"client\" VM\n"
+ "-server to select the \"server\" VM\n"
+ "-hotspot is a synonym for the \"client\" VM [deprecated]\n"
+ " The default VM is client.\n"
+ "\n"
+ "-cp <class search path of directories and zip/jar files>\n"
+ "-classpath <class search path of directories and zip/jar files>\n"
+ " A : separated list of directories, JAR archives,\n"
+ " and ZIP archives to search for class files.\n"
+ "-D<name>=<value>\n"
+ " set a system property\n"
+ "-verbose[:class|gc|jni]\n"
+ " enable verbose output\n"
+ "-version print product version and exit\n"
+ "-version:<value>\n"
+ " require the specified version to run\n"
+ "-showversion print product version and continue\n"
+ "-jre-restrict-search | -jre-no-restrict-search\n"
+ " include/exclude user private JREs in the version search\n"
+ "-? -help print this help message\n"
+ "-X print help on non-standard options\n"
+ "-ea[:<packagename>...|:<classname>]\n"
+ "-enableassertions[:<packagename>...|:<classname>]\n"
+ " enable assertions\n"
+ "-da[:<packagename>...|:<classname>]\n"
+ "-disableassertions[:<packagename>...|:<classname>]\n"
+ " disable assertions\n"
+ "-esa | -enablesystemassertions\n"
+ " enable system assertions\n"
+ "-dsa | -disablesystemassertions\n"
+ " disable system assertions\n"
+ "-agentlib:<libname>[=<options>]\n"
+ " load native agent library <libname>, e.g. -agentlib:hprof\n"
+ " see also, -agentlib:jdwp=help and -agentlib:hprof=help\n"
+ "-agentpath:<pathname>[=<options>]\n"
+ " load native agent library by full pathname\n"
+ "-javaagent:<jarpath>[=<options>]\n"
+ " load Java programming language agent, see java.lang.instrument\n");
+}
+
+void ClArgumentsInfo::readArgs(int argc, char** argv, Jnjvm* vm) {
+ className = 0;
+ appArgumentsPos = 0;
+ sint32 i = 1;
+ if (i == argc) printInformation();
+ while (i < argc) {
+ char* cur = argv[i];
+ if (!(strcmp(cur, "-client"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-server"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-classpath"))) {
+ ++i;
+ if (i == argc) printInformation();
+ else vm->setClasspath(argv[i]);
+ } else if (!(strcmp(cur, "-cp"))) {
+ ++i;
+ if (i == argc) printInformation();
+ else vm->setClasspath(argv[i]);
+ } else if (!(strcmp(cur, "-debug"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-D"))) {
+ uint32 len = strlen(cur);
+ if (len == 2) {
+ printInformation();
+ } else {
+ char* key = &cur[2];
+ char* value = strchr(key, '=');
+ if (!value) {
+ printInformation();
+ return;
+ } else {
+ value[0] = 0;
+ vm->addProperty(key, &value[1]);
+ }
+ }
+ } else if (!(strcmp(cur, "-enableassertions"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-ea"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-disableassertions"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-da"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-enablesystemassertions"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-esa"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-disablesystemassertions"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-dsa"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-jar"))) {
+ ++i;
+ if (i == argc) {
+ printInformation();
+ } else {
+ extractClassFromJar(vm, argc, argv, i);
+ appArgumentsPos = i;
+ return;
+ }
+ } else if (!(strcmp(cur, "-jre-restrict-research"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-jre-no-restrict-research"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-noclassgc"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-ms"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-mx"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-ss"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-verbose"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-verbose:class"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-verbosegc"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-verbose:gc"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-verbose:jni"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-version"))) {
+ printVersion();
+ } else if (!(strcmp(cur, "-showversion"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-?"))) {
+ printInformation();
+ } else if (!(strcmp(cur, "-help"))) {
+ printInformation();
+ } else if (!(strcmp(cur, "-X"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-agentlib"))) {
+ nyi();
+ } else if (!(strcmp(cur, "-agentpath"))) {
+ nyi();
+ } else if (cur[0] == '-') {
+ } else if (!(strcmp(cur, "-javaagent"))) {
+ javaAgent(cur);
+ } else {
+ className = cur;
+ appArgumentsPos = i;
+ return;
+ }
+ ++i;
+ }
+}
+
+
+void ThreadSystem::print(mvm::PrintBuffer* buf) const {
+ buf->write("ThreadSystem<>");
+}
+
+void JavaIsolate::print(mvm::PrintBuffer* buf) const {
+ buf->write("Java isolate: ");
+ buf->write(name);
+
+}
+
+ThreadSystem* ThreadSystem::allocateThreadSystem() {
+ ThreadSystem* res = gc_new(ThreadSystem)();
+ res->nonDaemonThreads = 1;
+ res->nonDaemonLock = mvm::Lock::allocNormal();
+ res->nonDaemonVar = mvm::Cond::allocCond();
+ return res;
+}
+
+JavaObject* JavaIsolate::loadAppClassLoader() {
+ if (appClassLoader == 0) {
+ appClassLoader = Classpath::getSystemClassLoader->invokeJavaObjectStatic();
+ }
+ return appClassLoader;
+}
+
+void JavaIsolate::mapInitialThread() {
+ ClasspathThread::mapInitialThread(this);
+}
+
+void JavaIsolate::loadBootstrap() {
+ mapInitialThread();
+ loadAppClassLoader();
+ Classpath::setContextClassLoader->invokeIntSpecial(JavaThread::currentThread(), appClassLoader);
+ // load and initialise math since it is responsible for dlopen'ing
+ // libjavalang.so and we are optimizing some math operations
+ loadName(asciizConstructUTF8("java/lang/Math"),
+ CommonClass::jnjvmClassLoader, true, true, true);
+}
+
+void JavaIsolate::executeClass(const char* className, ArrayObject* args) {
+ try {
+ JavaJIT::invokeOnceVoid(this, appClassLoader, className, "main",
+ "([Ljava/lang/String;)V", ACC_STATIC, args);
+ }catch(...) {
+ }
+
+ JavaObject* exc = JavaThread::get()->pendingException;
+ if (exc) {
+ JavaThread::clearException();
+ JavaObject* obj = JavaThread::currentThread();
+ JavaObject* group = (JavaObject*)((*obj)(ClasspathThread::group)).PointerVal;
+ try{
+ ClasspathThread::uncaughtException->invokeIntSpecial(group, obj, exc);
+ }catch(...) {
+ printf("Even uncaught exception throwed an exception!\n");
+ assert(0);
+ }
+ }
+}
+
+void JavaIsolate::executePremain(const char* className, JavaString* args,
+ JavaObject* instrumenter) {
+ JavaJIT::invokeOnceVoid(this, appClassLoader, className, "premain",
+ "(Ljava/lang/String;Ljava/lang/instrument/Instrumentation;)V",
+ ACC_STATIC, args, instrumenter);
+}
+
+void JavaIsolate::waitForExit() {
+ threadSystem->nonDaemonLock->lock();
+ --(threadSystem->nonDaemonThreads);
+
+ while (threadSystem->nonDaemonThreads) {
+ threadSystem->nonDaemonVar->wait(threadSystem->nonDaemonLock);
+ }
+
+ threadSystem->nonDaemonLock->unlock();
+ return;
+}
+
+void JavaIsolate::runMain(int argc, char** argv) {
+ ClArgumentsInfo info;
+
+ info.readArgs(argc, argv, this);
+ if (info.className) {
+ int pos = info.appArgumentsPos;
+ //llvm::cl::ParseCommandLineOptions(pos, argv,
+ // " JnJVM Java Virtual Machine\n");
+ argv = argv + pos - 1;
+ argc = argc - pos + 1;
+
+ loadBootstrap();
+
+ if (info.agents.size()) {
+ assert(0 && "implement me");
+ JavaObject* instrumenter = 0;//createInstrumenter();
+ for (std::vector< std::pair<char*, char*> >::iterator i = info.agents.begin(),
+ e = info.agents.end(); i!= e; ++i) {
+ JavaString* args = asciizToStr(i->second);
+ executePremain(i->first, args, instrumenter);
+ }
+ }
+
+ ArrayObject* args = ArrayObject::acons(argc - 2, JavaArray::ofString);
+ for (int i = 2; i < argc; ++i) {
+ args->setAt(i - 2, (JavaObject*)asciizToStr(argv[i]));
+ }
+
+ executeClass(info.className, args);
+ waitForExit();
+ }
+}
+
+void JavaIsolate::runIsolate(const char* className, ArrayObject* args) {
+ JavaIsolate *isolate = allocateIsolate(bootstrapVM);
+ isolate->loadBootstrap();
+ isolate->executeClass(className, args);
+ isolate->waitForExit();
+}
+
+extern const char* GNUClasspathGlibj;
+extern const char* GNUClasspathLibs;
+
+JavaIsolate* JavaIsolate::allocateIsolate(Jnjvm* callingVM) {
+ JavaIsolate *isolate= gc_new(JavaIsolate)();
+
+ isolate->classpath = getenv("CLASSPATH");
+ if (!(isolate->classpath)) {
+ isolate->classpath = ".";
+ }
+ isolate->bootClasspathEnv = getenv("JNJVM_BOOTCLASSPATH");
+ if (!(isolate->bootClasspathEnv)) {
+ isolate->bootClasspathEnv = GNUClasspathGlibj;
+ }
+ isolate->libClasspathEnv = getenv("JNJVM_LIBCLASSPATH");
+ if (!(isolate->libClasspathEnv)) {
+ isolate->libClasspathEnv = GNUClasspathLibs;
+ }
+
+ isolate->analyseClasspathEnv(isolate->bootClasspathEnv);
+
+#ifndef SINGLE_VM
+ isolate->functions = FunctionMap::allocate();
+ isolate->module = new llvm::Module("Isolate JnJVM");
+ isolate->protectModule = mvm::Lock::allocNormal();
+ isolate->TheModuleProvider = new JnjvmModuleProvider(isolate->module,
+ isolate->functions);
+ JavaJIT::initialiseJITIsolateVM(isolate);
+#else
+ isolate->protectModule = callingVM->protectModule;
+ isolate->functions = callingVM->functions;
+ isolate->module = callingVM->module;
+ isolate->TheModuleProvider = callingVM->TheModuleProvider;
+#endif
+
+ isolate->bootstrapThread = JavaThread::allocate(0, isolate);
+ JavaThread::threadKey->set(isolate->bootstrapThread);
+
+
+ isolate->threadSystem = ThreadSystem::allocateThreadSystem();
+ isolate->name = "isolate";
+ isolate->appClassLoader = 0;
+ isolate->jniEnv = &JNI_JNIEnvTable;
+ isolate->javavmEnv = &JNI_JavaVMTable;
+#ifndef SINGLE_VM
+ isolate->hashUTF8 = bootstrapVM->hashUTF8->copy();
+ isolate->hashStr = StringMap::allocate();
+ isolate->bootstrapClasses = callingVM->bootstrapClasses;
+ isolate->loadedMethods = MethodMap::allocate();
+ isolate->loadedFields = FieldMap::allocate();
+ isolate->javaTypes = jnjvm::TypeMap::allocate();
+ isolate->globalRefsLock = mvm::Lock::allocNormal();
+ isolate->statics = StaticInstanceMap::allocate();
+ isolate->delegatees = DelegateeMap::allocate();
+#else
+ isolate->hashUTF8 = callingVM->hashUTF8;
+ isolate->hashStr = callingVM->hashStr;
+ isolate->bootstrapClasses = callingVM->bootstrapClasses;
+ isolate->loadedMethods = callingVM->loadedMethods;
+ isolate->loadedFields = callingVM->loadedFields;
+ isolate->javaTypes = callingVM->javaTypes;
+ isolate->globalRefsLock = callingVM->globalRefsLock;
+#endif
+
+ return isolate;
+}
+
+JavaIsolate* JavaIsolate::allocateBootstrap() {
+ JavaIsolate *isolate= gc_new(JavaIsolate)();
+
+ isolate->classpath = getenv("CLASSPATH");
+ if (!(isolate->classpath)) {
+ isolate->classpath = ".";
+ }
+ isolate->bootClasspathEnv = getenv("JNJVM_BOOTCLASSPATH");
+ if (!(isolate->bootClasspathEnv)) {
+ isolate->bootClasspathEnv = GNUClasspathGlibj;
+ }
+ isolate->libClasspathEnv = getenv("JNJVM_LIBCLASSPATH");
+ if (!(isolate->libClasspathEnv)) {
+ isolate->libClasspathEnv = GNUClasspathLibs;
+ }
+
+ isolate->analyseClasspathEnv(isolate->bootClasspathEnv);
+
+ isolate->functions = FunctionMap::allocate();
+ isolate->protectModule = mvm::Lock::allocNormal();
+ isolate->module = new llvm::Module("Bootstrap JnJVM");
+ isolate->TheModuleProvider = new JnjvmModuleProvider(isolate->module,
+ isolate->functions);
+ JavaJIT::initialiseJITBootstrapVM(isolate);
+
+ isolate->bootstrapThread = JavaThread::allocate(0, isolate);
+ JavaThread::threadKey->set(isolate->bootstrapThread);
+
+ isolate->name = "bootstrapVM";
+ isolate->appClassLoader = 0;
+ isolate->hashUTF8 = UTF8Map::allocate();
+ isolate->hashStr = StringMap::allocate();
+ isolate->bootstrapClasses = ClassMap::allocate();
+ isolate->loadedMethods = MethodMap::allocate();
+ isolate->loadedFields = FieldMap::allocate();
+ isolate->jniEnv = &JNI_JNIEnvTable;
+ isolate->javavmEnv = &JNI_JavaVMTable;
+ isolate->globalRefsLock = mvm::Lock::allocNormal();
+ isolate->javaTypes = jnjvm::TypeMap::allocate();
+#ifndef SINGLE_VM
+ isolate->statics = StaticInstanceMap::allocate();
+ isolate->delegatees = DelegateeMap::allocate();
+#endif
+
+ return isolate;
+}
+
+void JavaIsolate::destroyer(size_t sz) {
+ mvm::jit::protectEngine->lock();
+ mvm::jit::executionEngine->removeModuleProvider(TheModuleProvider);
+ mvm::jit::protectEngine->unlock();
+ delete TheModuleProvider;
+ delete module;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaIsolate.h b/vmkit/lib/JnJVM/VMCore/JavaIsolate.h
new file mode 100644
index 0000000..b59dfd1
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaIsolate.h
@@ -0,0 +1,65 @@
+//===---------------- JavaIsolate.h - Isolates ----------------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_ISOLATE_H
+#define JNJVM_JAVA_ISOLATE_H
+
+
+#include "mvm/Object.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+
+namespace jnjvm {
+
+class ThreadSystem : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ uint16 nonDaemonThreads;
+ mvm::Lock* nonDaemonLock;
+ mvm::Cond* nonDaemonVar;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ static ThreadSystem* allocateThreadSystem();
+};
+
+class JavaIsolate : public Jnjvm {
+public:
+ static VirtualTable* VT;
+ ThreadSystem* threadSystem;
+ JavaThread* bootstrapThread;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+ virtual void destroyer(size_t sz);
+
+ JavaObject* loadAppClassLoader();
+ void loadBootstrap();
+ void executeClass(const char* className, ArrayObject* args);
+ void executePremain(const char* className, JavaString* args,
+ JavaObject* instrumenter);
+ void waitForExit();
+ void runMain(int argc, char** argv);
+ void mapInitialThread();
+ static void runIsolate(const char* className, ArrayObject* args);
+ static JavaIsolate* allocateIsolate(Jnjvm* callingVM);
+ static JavaIsolate* allocateBootstrap();
+
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaJIT.cpp b/vmkit/lib/JnJVM/VMCore/JavaJIT.cpp
new file mode 100644
index 0000000..729e002
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaJIT.cpp
@@ -0,0 +1,1528 @@
+//===----------- JavaJIT.cpp - Java just in time compiler -----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#define DEBUG 0
+#define JNJVM_COMPILE 0
+#define JNJVM_EXECUTE 0
+
+#include <string.h>
+
+#include <llvm/Type.h>
+#include <llvm/Support/CFG.h>
+#include <llvm/Module.h>
+#include <llvm/Constants.h>
+#include <llvm/Type.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Assembly/PrintModulePass.h>
+#include <llvm/Target/TargetOptions.h>
+#include <llvm/CodeGen/MachineCodeEmitter.h>
+#include <llvm/CodeGen/MachineBasicBlock.h>
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/PassManager.h"
+#include "llvm/ValueSymbolTable.h"
+#include "llvm/Analysis/LoadValueNumbering.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <llvm/Transforms/IPO.h>
+
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+
+#include "debug.h"
+#include "JavaArray.h"
+#include "JavaCache.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaObject.h"
+#include "JavaJIT.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+#include "NativeUtil.h"
+#include "Reader.h"
+#include "Zip.h"
+
+#include <iostream>
+
+
+using namespace jnjvm;
+using namespace llvm;
+
+void Exception::print(mvm::PrintBuffer* buf) const {
+ buf->write("Exception<>");
+}
+
+void JavaJIT::print(mvm::PrintBuffer* buf) const {
+ buf->write("JavaJIT<>");
+}
+
+BasicBlock* JavaJIT::createBasicBlock(const char* name) {
+ return new BasicBlock(name, llvmFunction);
+}
+
+Value* JavaJIT::top() {
+ return stack.back().first;
+}
+
+Value* JavaJIT::pop() {
+ llvm::Value * ret = top();
+ stack.pop_back();
+ return ret;
+}
+
+Value* JavaJIT::popAsInt() {
+ llvm::Value * ret = top();
+ const AssessorDesc* ass = topFunc();
+ stack.pop_back();
+
+ if (ret->getType() != Type::Int32Ty) {
+ if (ass == AssessorDesc::dChar) {
+ ret = new ZExtInst(ret, Type::Int32Ty, "", currentBlock);
+ } else {
+ ret = new SExtInst(ret, Type::Int32Ty, "", currentBlock);
+ }
+ }
+
+ return ret;
+}
+
+void JavaJIT::push(llvm::Value* val, const AssessorDesc* ass) {
+ assert(ass->llvmType == val->getType());
+ stack.push_back(std::make_pair(val, ass));
+}
+
+void JavaJIT::push(std::pair<llvm::Value*, const AssessorDesc*> pair) {
+ assert(pair.second->llvmType == pair.first->getType());
+ stack.push_back(pair);
+}
+
+
+const AssessorDesc* JavaJIT::topFunc() {
+ return stack.back().second;
+}
+
+uint32 JavaJIT::stackSize() {
+ return stack.size();
+}
+
+std::pair<llvm::Value*, const AssessorDesc*> JavaJIT::popPair() {
+ std::pair<Value*, const AssessorDesc*> ret = stack.back();
+ stack.pop_back();
+ return ret;
+}
+
+llvm::Function* JavaJIT::nativeCompile(void* natPtr) {
+
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "native compile %s\n",
+ compilingMethod->printString());
+
+ bool stat = isStatic(compilingMethod->access);
+
+ const FunctionType *funcType = compilingMethod->llvmType;
+
+ bool jnjvm = false;
+ natPtr = natPtr ? natPtr :
+ NativeUtil::nativeLookup(compilingClass, compilingMethod, jnjvm);
+
+
+
+ compilingClass->isolate->protectModule->lock();
+ Function* func = llvmFunction = new llvm::Function(funcType,
+ GlobalValue::ExternalLinkage,
+ compilingMethod->printString(),
+ compilingClass->isolate->module);
+ compilingClass->isolate->protectModule->unlock();
+
+ if (jnjvm) {
+ mvm::jit::executionEngine->addGlobalMapping(func, natPtr);
+ return llvmFunction;
+ }
+
+ currentBlock = createBasicBlock("start");
+ BasicBlock* executeBlock = createBasicBlock("execute");
+ endBlock = createBasicBlock("end block");
+ if (funcType->getReturnType() != Type::VoidTy)
+ endNode = new PHINode(funcType->getReturnType(), "", endBlock);
+
+ Value* buf = new CallInst(getSJLJBufferLLVM, "", currentBlock);
+ Value* test = new CallInst(mvm::jit::setjmpLLVM, buf, "", currentBlock);
+ test = new ICmpInst(ICmpInst::ICMP_EQ, test, mvm::jit::constantZero, "", currentBlock);
+ new BranchInst(executeBlock, endBlock, test, currentBlock);
+ if (compilingMethod->signature->ret->funcs != AssessorDesc::dVoid)
+ endNode->addIncoming(compilingMethod->signature->ret->funcs->llvmNullConstant, currentBlock);
+
+ currentBlock = executeBlock;
+ if (isSynchro(compilingMethod->access))
+ beginSynchronize();
+
+
+ uint32 nargs = func->arg_size() + 1 + (stat ? 1 : 0); // + vm + cl/obj
+ std::vector<Value*> nativeArgs;
+
+ mvm::jit::protectConstants();//->lock();
+ nativeArgs.push_back(
+ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty,
+ (int64_t)&(compilingClass->isolate->jniEnv)),
+ mvm::jit::ptrType));
+ mvm::jit::unprotectConstants();//->unlock();
+
+ uint32 index = 0;
+ if (stat) {
+#ifdef SINGLE_VM
+ nativeArgs.push_back(new LoadInst(compilingClass->llvmDelegatee(), "", currentBlock));
+#else
+ Value* ld = new LoadInst(compilingClass->llvmVar(compilingClass->isolate->module), "", currentBlock);
+ nativeArgs.push_back(new CallInst(getClassDelegateeLLVM, ld, "", currentBlock));
+#endif
+ index = 2;
+ } else {
+ index = 1;
+ }
+ for (Function::arg_iterator i = func->arg_begin();
+ index < nargs; ++i, ++index) {
+
+ nativeArgs.push_back(i);
+ }
+
+
+ const llvm::Type* valPtrType = compilingMethod->signature->nativeTypePtr;
+ mvm::jit::protectConstants();//->lock();
+ Value* valPtr =
+ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (uint64)natPtr),
+ valPtrType);
+ mvm::jit::unprotectConstants();//->unlock();
+
+ Value* result = new CallInst(valPtr, nativeArgs.begin(), nativeArgs.end(), "", currentBlock);
+ if (funcType->getReturnType() != Type::VoidTy)
+ endNode->addIncoming(result, currentBlock);
+ new BranchInst(endBlock, currentBlock);
+
+ currentBlock = endBlock;
+ if (isSynchro(compilingMethod->access))
+ endSynchronize();
+
+ new CallInst(jniProceedPendingExceptionLLVM, "", currentBlock);
+
+ if (funcType->getReturnType() != Type::VoidTy)
+ new ReturnInst(result, currentBlock);
+ else
+ new ReturnInst(currentBlock);
+
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "end native compile %s\n",
+ compilingMethod->printString());
+
+ return llvmFunction;
+}
+
+#if defined __PPC__
+extern "C"
+{
+# include <dis-asm.h>
+# include <bfd.h>
+};
+
+
+
+static struct disassemble_info info;
+static int initialised= 0;
+
+// this is the only function exported from this file
+
+extern "C" int disassemble(unsigned int *addr)
+{
+
+ if (!initialised)
+ {
+ INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
+ info.flavour= bfd_target_elf_flavour;
+ info.arch= bfd_arch_powerpc;
+ info.mach= bfd_mach_ppc_750; // generic(ish) == PPC G3
+ info.endian= BFD_ENDIAN_BIG;
+ info.buffer_length= 65536;
+ }
+ info.buffer= (bfd_byte *)addr;
+ info.buffer_vma= (bfd_vma)(long)addr;
+ return print_insn_big_powerpc((bfd_vma)(long)addr, &info);
+
+}
+
+#else
+extern "C"
+{
+# include <bfd.h> // bfd types
+# include <dis-asm.h> // disassemble_info
+ int print_insn_i386_att(bfd_vma, disassemble_info *);
+};
+
+
+static struct disassemble_info info;
+static int initialised= 0;
+
+// this is the only function exported from this file
+
+extern "C" int disassemble(unsigned int *addr)
+{
+ if (!initialised)
+ {
+ INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
+ info.flavour= bfd_target_elf_flavour;
+ info.arch= bfd_arch_i386;
+ info.mach= bfd_mach_i386_i386;
+ info.endian= BFD_ENDIAN_LITTLE;
+ info.buffer_length= 65536;
+ }
+ info.buffer= (bfd_byte *)addr;
+ info.buffer_vma= (bfd_vma)(long)addr;
+ return print_insn_i386_att((bfd_vma)(long)addr, &info);
+}
+
+#endif
+
+
+void JavaJIT::beginSynchronize() {
+ std::vector<Value*> argsSync;
+ if (isVirtual(compilingMethod->access)) {
+ argsSync.push_back(llvmFunction->arg_begin());
+ } else {
+ Value* arg = new LoadInst(compilingClass->staticVar(compilingClass->isolate->module), "", currentBlock);
+#ifndef SINGLE_VM
+ if (compilingClass->isolate == Jnjvm::bootstrapVM) {
+ arg = new CallInst(getStaticInstanceLLVM, arg, "", currentBlock);
+ }
+#endif
+ argsSync.push_back(arg);
+ }
+ new CallInst(aquireObjectLLVM, argsSync.begin(), argsSync.end(), "", currentBlock);
+}
+
+void JavaJIT::endSynchronize() {
+ std::vector<Value*> argsSync;
+ if (isVirtual(compilingMethod->access)) {
+ argsSync.push_back(llvmFunction->arg_begin());
+ } else {
+ Value* arg = new LoadInst(compilingClass->staticVar(compilingClass->isolate->module), "", currentBlock);
+#ifndef SINGLE_VM
+ if (compilingClass->isolate == Jnjvm::bootstrapVM) {
+ arg = new CallInst(getStaticInstanceLLVM, arg, "", currentBlock);
+ }
+#endif
+ argsSync.push_back(arg);
+ }
+ new CallInst(releaseObjectLLVM, argsSync.begin(), argsSync.end(), "", currentBlock);
+}
+
+
+Instruction* JavaJIT::inlineCompile(Function* parentFunction, BasicBlock*& curBB,
+ BasicBlock* endExBlock,
+ std::vector<Value*>& args) {
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "inline compile %s\n",
+ compilingMethod->printString());
+
+
+ Attribut* codeAtt = Attribut::lookup(&compilingMethod->attributs,
+ Attribut::codeAttribut);
+
+ if (!codeAtt)
+ JavaThread::get()->isolate->unknownError("unable to find the code attribut in %s",
+ compilingMethod->printString());
+
+ Reader* reader = codeAtt->toReader(compilingClass->bytes, codeAtt);
+ maxStack = reader->readU2();
+ maxLocals = reader->readU2();
+ codeLen = reader->readU4();
+ uint32 start = reader->cursor;
+
+ reader->seek(codeLen, Reader::SeekCur);
+
+ const FunctionType *funcType = compilingMethod->llvmType;
+ returnType = funcType->getReturnType();
+
+ llvmFunction = parentFunction;
+ currentBlock = curBB;
+ endExceptionBlock = 0;
+
+ opcodeInfos = (Opinfo*)alloca(codeLen * sizeof(Opinfo));
+ memset(opcodeInfos, 0, codeLen * sizeof(Opinfo));
+ for (uint32 i = 0; i < codeLen; ++i) {
+ opcodeInfos[i].exceptionBlock = endExBlock;
+ }
+
+ for (int i = 0; i < maxLocals; i++) {
+ intLocals.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock));
+ doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock));
+ longLocals.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock));
+ floatLocals.push_back(new AllocaInst(Type::FloatTy, "", currentBlock));
+ objectLocals.push_back(new AllocaInst(JavaObject::llvmType, "",
+ currentBlock));
+ }
+
+ uint32 index = 0;
+ uint32 count = 0;
+ for (std::vector<Value*>::iterator i = args.begin();
+ count < args.size(); ++i, ++index, ++count) {
+
+ const Type* cur = (*i)->getType();
+
+ if (cur == Type::Int64Ty ){
+ new StoreInst(*i, longLocals[index], false, currentBlock);
+ ++index;
+ } else if (cur == Type::Int8Ty || cur == Type::Int16Ty) {
+ new StoreInst(new ZExtInst(*i, Type::Int32Ty, "", currentBlock),
+ intLocals[index], false, currentBlock);
+ } else if (cur == Type::Int32Ty) {
+ new StoreInst(*i, intLocals[index], false, currentBlock);
+ } else if (cur == Type::DoubleTy) {
+ new StoreInst(*i, doubleLocals[index], false, currentBlock);
+ ++index;
+ } else if (cur == Type::FloatTy) {
+ new StoreInst(*i, floatLocals[index], false, currentBlock);
+ } else {
+ new StoreInst(*i, objectLocals[index], false, currentBlock);
+ }
+ }
+
+ exploreOpcodes(&compilingClass->bytes->elements[start], codeLen);
+
+ endBlock = createBasicBlock("end");
+
+ if (returnType != Type::VoidTy) {
+ endNode = new PHINode(returnType, "", endBlock);
+ }
+
+ compileOpcodes(&compilingClass->bytes->elements[start], codeLen);
+
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end inline compiling %s\n",
+ compilingMethod->printString());
+
+ curBB = endBlock;
+ return endNode;
+
+}
+
+
+llvm::Function* JavaJIT::javaCompile() {
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "compiling %s\n",
+ compilingMethod->printString());
+
+
+ Attribut* codeAtt = Attribut::lookup(&compilingMethod->attributs,
+ Attribut::codeAttribut);
+
+ if (!codeAtt)
+ JavaThread::get()->isolate->unknownError("unable to find the code attribut in %s",
+ compilingMethod->printString());
+
+ Reader* reader = codeAtt->toReader(compilingClass->bytes, codeAtt);
+ maxStack = reader->readU2();
+ maxLocals = reader->readU2();
+ codeLen = reader->readU4();
+ uint32 start = reader->cursor;
+
+ reader->seek(codeLen, Reader::SeekCur);
+
+ const FunctionType *funcType = compilingMethod->llvmType;
+ returnType = funcType->getReturnType();
+
+ compilingClass->isolate->protectModule->lock();
+ Function* func = llvmFunction = new llvm::Function(funcType,
+ GlobalValue::ExternalLinkage,
+ compilingMethod->printString(),
+ compilingClass->isolate->module);
+ compilingClass->isolate->protectModule->unlock();
+
+ currentBlock = createBasicBlock("start");
+ endExceptionBlock = createBasicBlock("endExceptionBlock");
+ unifiedUnreachable = createBasicBlock("unifiedUnreachable");
+
+ opcodeInfos = (Opinfo*)alloca(codeLen * sizeof(Opinfo));
+ memset(opcodeInfos, 0, codeLen * sizeof(Opinfo));
+ for (uint32 i = 0; i < codeLen; ++i) {
+ opcodeInfos[i].exceptionBlock = endExceptionBlock;
+ }
+
+#if JNJVM_EXECUTE > 0
+ {
+ std::vector<llvm::Value*> args;
+ mvm::jit::protectConstants();//->lock();
+ args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
+ mvm::jit::unprotectConstants();//->unlock();
+ new CallInst(printMethodStartLLVM, args.begin(), args.end(), "", currentBlock);
+ }
+#endif
+
+ unsigned nbe = readExceptionTable(reader);
+
+ for (int i = 0; i < maxLocals; i++) {
+ intLocals.push_back(new AllocaInst(Type::Int32Ty, "", currentBlock));
+ doubleLocals.push_back(new AllocaInst(Type::DoubleTy, "", currentBlock));
+ longLocals.push_back(new AllocaInst(Type::Int64Ty, "", currentBlock));
+ floatLocals.push_back(new AllocaInst(Type::FloatTy, "", currentBlock));
+ objectLocals.push_back(new AllocaInst(JavaObject::llvmType, "",
+ currentBlock));
+ }
+
+ uint32 index = 0;
+ uint32 count = 0;
+ for (Function::arg_iterator i = func->arg_begin();
+ count < func->arg_size(); ++i, ++index, ++count) {
+
+ const Type* cur = i->getType();
+
+ if (cur == Type::Int64Ty ){
+ new StoreInst(i, longLocals[index], false, currentBlock);
+ ++index;
+ } else if (cur == Type::Int8Ty || cur == Type::Int16Ty) {
+ new StoreInst(new ZExtInst(i, Type::Int32Ty, "", currentBlock),
+ intLocals[index], false, currentBlock);
+ } else if (cur == Type::Int32Ty) {
+ new StoreInst(i, intLocals[index], false, currentBlock);
+ } else if (cur == Type::DoubleTy) {
+ new StoreInst(i, doubleLocals[index], false, currentBlock);
+ ++index;
+ } else if (cur == Type::FloatTy) {
+ new StoreInst(i, floatLocals[index], false, currentBlock);
+ } else {
+ new StoreInst(i, objectLocals[index], false, currentBlock);
+ }
+ }
+
+
+ exploreOpcodes(&compilingClass->bytes->elements[start], codeLen);
+
+
+
+ endBlock = createBasicBlock("end");
+
+ if (returnType != Type::VoidTy) {
+ endNode = new PHINode(returnType, "", endBlock);
+ }
+
+ if (isSynchro(compilingMethod->access))
+ beginSynchronize();
+
+ compileOpcodes(&compilingClass->bytes->elements[start], codeLen);
+ currentBlock = endBlock;
+
+ if (isSynchro(compilingMethod->access))
+ endSynchronize();
+
+#if JNJVM_EXECUTE > 0
+ {
+ std::vector<llvm::Value*> args;
+ mvm::jit::protectConstants();//->lock();
+ args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
+ mvm::jit::unprotectConstants();//->unlock();
+ new CallInst(printMethodEndLLVM, args.begin(), args.end(), "", currentBlock);
+ }
+#endif
+
+ if (returnType != Type::VoidTy)
+ new ReturnInst(endNode, endBlock);
+ else
+ new ReturnInst(endBlock);
+
+ pred_iterator PI = pred_begin(endExceptionBlock);
+ pred_iterator PE = pred_end(endExceptionBlock);
+ if (PI == PE) {
+ endExceptionBlock->eraseFromParent();
+ } else {
+ CallInst* ptr_eh_ptr = new CallInst(getExceptionLLVM, "eh_ptr",
+ endExceptionBlock);
+ new CallInst(mvm::jit::unwindResume, ptr_eh_ptr, "", endExceptionBlock);
+ new UnreachableInst(endExceptionBlock);
+ }
+
+ PI = pred_begin(unifiedUnreachable);
+ PE = pred_end(unifiedUnreachable);
+ if (PI == PE) {
+ unifiedUnreachable->eraseFromParent();
+ } else {
+ new UnreachableInst(unifiedUnreachable);
+ }
+
+ mvm::jit::runPasses(llvmFunction, JavaThread::get()->perFunctionPasses);
+
+ /*
+ if (compilingMethod->name == compilingClass->isolate->asciizConstructUTF8("main")) {
+ llvmFunction->print(llvm::cout);
+ void* res = mvm::jit::executionEngine->getPointerToGlobal(llvmFunction);
+ void* base = res;
+ while (base < (void*)((char*)res + ((mvm::Code*)res)->objectSize())) {
+ printf("%08x\t", (unsigned)base);
+ int n= disassemble((unsigned int *)base);
+ printf("\n");
+ base= ((void *)((char *)base + n));
+ }
+ printf("\n");
+ fflush(stdout);
+ }*/
+
+
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "--> end compiling %s\n",
+ compilingMethod->printString());
+
+ if (nbe == 0 && codeLen < 50)
+ compilingMethod->canBeInlined = false;
+
+ return llvmFunction;
+}
+
+
+unsigned JavaJIT::readExceptionTable(Reader* reader) {
+ uint16 nbe = reader->readU2();
+ unsigned sync = isSynchro(compilingMethod->access) ? 1 : 0;
+ nbe += sync;
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ if (nbe) {
+ supplLocal = new AllocaInst(JavaObject::llvmType, "exceptionVar",
+ currentBlock);
+ }
+
+ BasicBlock* realEndExceptionBlock = endExceptionBlock;
+ if (sync) {
+ BasicBlock* synchronizeExceptionBlock = createBasicBlock("synchronizeExceptionBlock");
+ BasicBlock* trySynchronizeExceptionBlock = createBasicBlock("trySynchronizeExceptionBlock");
+ realEndExceptionBlock = synchronizeExceptionBlock;
+ std::vector<Value*> argsSync;
+ if (isVirtual(compilingMethod->access)) {
+ argsSync.push_back(llvmFunction->arg_begin());
+ } else {
+ Value* arg = new LoadInst(compilingClass->staticVar(compilingClass->isolate->module), "", currentBlock);
+#ifndef SINGLE_VM
+ if (compilingClass->isolate == Jnjvm::bootstrapVM) {
+ arg = new CallInst(getStaticInstanceLLVM, arg, "", currentBlock);
+ }
+#endif
+ argsSync.push_back(arg);
+ }
+ new CallInst(releaseObjectLLVM, argsSync.begin(), argsSync.end(), "", synchronizeExceptionBlock);
+ new BranchInst(endExceptionBlock, synchronizeExceptionBlock);
+
+ const PointerType* PointerTy_0 = mvm::jit::ptrType;
+ std::vector<Value*> int32_eh_select_params;
+ Instruction* ptr_eh_ptr = new CallInst(mvm::jit::llvmGetException, "eh_ptr", trySynchronizeExceptionBlock);
+ int32_eh_select_params.push_back(ptr_eh_ptr);
+ int32_eh_select_params.push_back(ConstantExpr::getCast(Instruction::BitCast, mvm::jit::personality, PointerTy_0));
+ int32_eh_select_params.push_back(mvm::jit::constantPtrNull);
+ new CallInst(mvm::jit::exceptionSelector, int32_eh_select_params.begin(), int32_eh_select_params.end(), "eh_select", trySynchronizeExceptionBlock);
+ new BranchInst(synchronizeExceptionBlock, trySynchronizeExceptionBlock);
+
+ for (uint16 i = 0; i < codeLen; ++i) {
+ if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
+ opcodeInfos[i].exceptionBlock = trySynchronizeExceptionBlock;
+ }
+ }
+ }
+
+ for (uint16 i = 0; i < nbe - sync; ++i) {
+ Exception* ex = gc_new(Exception)();
+ ex->startpc = reader->readU2();
+ ex->endpc = reader->readU2();
+ ex->handlerpc = reader->readU2();
+
+ uint16 catche = reader->readU2();
+
+ if (catche) {
+ ex->catchClass = (Class*)ctpInfo->loadClass(catche);
+ } else {
+ ex->catchClass = Classpath::newThrowable;
+ }
+
+ ex->test = createBasicBlock("testException");
+
+ // We can do this because readExceptionTable is the first function to be
+ // called after creation of Opinfos
+ for (uint16 i = ex->startpc; i < ex->endpc; ++i) {
+ if (opcodeInfos[i].exceptionBlock == realEndExceptionBlock) {
+ opcodeInfos[i].exceptionBlock = ex->test;
+ }
+ }
+
+ if (!(opcodeInfos[ex->handlerpc].newBlock)) {
+ opcodeInfos[ex->handlerpc].newBlock = createBasicBlock("handlerException");
+ }
+
+ ex->handler = opcodeInfos[ex->handlerpc].newBlock;
+ opcodeInfos[ex->handlerpc].reqSuppl = true;
+
+ exceptions.push_back(ex);
+ }
+
+ bool first = true;
+ for (std::vector<Exception*>::iterator i = exceptions.begin(),
+ e = exceptions.end(); i!= e; ++i) {
+
+ Exception* cur = *i;
+ Exception* next = 0;
+ if (i + 1 != e) {
+ next = *(i + 1);
+ }
+
+ if (first) {
+ cur->realTest = createBasicBlock("realTestException");
+ } else {
+ cur->realTest = cur->test;
+ }
+
+ cur->exceptionPHI = new PHINode(mvm::jit::ptrType, "", cur->realTest);
+
+ if (next && cur->startpc == next->startpc && cur->endpc == next->endpc)
+ first = false;
+ else
+ first = true;
+
+ }
+
+ for (std::vector<Exception*>::iterator i = exceptions.begin(),
+ e = exceptions.end(); i!= e; ++i) {
+
+ Exception* cur = *i;
+ Exception* next = 0;
+ BasicBlock* bbNext = 0;
+ PHINode* nodeNext = 0;
+ if (i + 1 != e) {
+ next = *(i + 1);
+ if (!(cur->startpc >= next->startpc && cur->endpc <= next->endpc)) {
+ bbNext = realEndExceptionBlock;
+ } else {
+ bbNext = next->realTest;
+ nodeNext = next->exceptionPHI;
+ }
+ } else {
+ bbNext = realEndExceptionBlock;
+ }
+
+ if (cur->realTest != cur->test) {
+ const PointerType* PointerTy_0 = mvm::jit::ptrType;
+ std::vector<Value*> int32_eh_select_params;
+ Instruction* ptr_eh_ptr = new CallInst(mvm::jit::llvmGetException, "eh_ptr", cur->test);
+ int32_eh_select_params.push_back(ptr_eh_ptr);
+ int32_eh_select_params.push_back(ConstantExpr::getCast(Instruction::BitCast, mvm::jit::personality, PointerTy_0));
+ int32_eh_select_params.push_back(mvm::jit::constantPtrNull);
+ new CallInst(mvm::jit::exceptionSelector, int32_eh_select_params.begin(), int32_eh_select_params.end(), "eh_select", cur->test);
+ new BranchInst(cur->realTest, cur->test);
+ cur->exceptionPHI->addIncoming(ptr_eh_ptr, cur->test);
+ }
+
+ Value* cl = new LoadInst(cur->catchClass->llvmVar(compilingClass->isolate->module), "", cur->realTest);
+ Value* cmp = new CallInst(compareExceptionLLVM, cl, "", cur->realTest);
+ new BranchInst(cur->handler, bbNext, cmp, cur->realTest);
+ if (nodeNext)
+ nodeNext->addIncoming(cur->exceptionPHI, cur->realTest);
+
+ if (cur->handler->empty()) {
+ cur->handlerPHI = new PHINode(mvm::jit::ptrType, "", cur->handler);
+ cur->handlerPHI->addIncoming(cur->exceptionPHI, cur->realTest);
+ Value* exc = new CallInst(getJavaExceptionLLVM, "", cur->handler);
+ new CallInst(clearExceptionLLVM, "", cur->handler);
+ new CallInst(mvm::jit::exceptionBeginCatch, cur->handlerPHI, "tmp8", cur->handler);
+ std::vector<Value*> void_28_params;
+ new CallInst(mvm::jit::exceptionEndCatch, void_28_params.begin(), void_28_params.end(), "", cur->handler);
+ new StoreInst(exc, supplLocal, false, cur->handler);
+ } else {
+ Instruction* insn = cur->handler->begin();
+ ((PHINode*)insn)->addIncoming(cur->exceptionPHI, cur->realTest);
+ }
+
+ }
+
+ return nbe;
+
+}
+
+void JavaJIT::compareFP(Value* val1, Value* val2, const Type* ty, bool l) {
+ Value* one = mvm::jit::constantOne;
+ Value* zero = mvm::jit::constantZero;
+ Value* minus = mvm::jit::constantMinusOne;
+
+ Value* c = new FCmpInst(FCmpInst::FCMP_UGT, val1, val2, "", currentBlock);
+ Value* r = new SelectInst(c, one, zero, "", currentBlock);
+ c = new FCmpInst(FCmpInst::FCMP_ULT, val1, val2, "", currentBlock);
+ r = new SelectInst(c, minus, r, "", currentBlock);
+ c = new FCmpInst(FCmpInst::FCMP_UNO, val1, val2, "", currentBlock);
+ r = new SelectInst(c, l ? one : minus, r, "", currentBlock);
+
+ push(r, AssessorDesc::dInt);
+
+}
+
+void JavaJIT::_ldc(uint16 index) {
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ uint8 type = ctpInfo->typeAt(index);
+
+ if (type == JavaCtpInfo::ConstantString) {
+ Value* toPush = 0;
+ if (ctpInfo->ctpRes[index] == 0) {
+ compilingClass->aquire();
+ if (ctpInfo->ctpRes[index] == 0) {
+ const UTF8* utf8 = ctpInfo->UTF8At(ctpInfo->ctpDef[index]);
+ void* val = 0;
+ GlobalVariable* gv = 0;
+#ifndef SINGLE_VM
+ if (compilingClass->isolate != Jnjvm::bootstrapVM) {
+#endif
+ val = compilingClass->isolate->UTF8ToStr(utf8);
+ compilingClass->isolate->protectModule->lock();
+ gv =
+ new GlobalVariable(JavaObject::llvmType, false,
+ GlobalValue::ExternalLinkage,
+ constantJavaObjectNull, "",
+ compilingClass->isolate->module);
+ compilingClass->isolate->protectModule->unlock();
+#ifndef SINGLE_VM
+ } else {
+ val = (void*)utf8;
+ compilingClass->isolate->protectModule->lock();
+ gv =
+ new GlobalVariable(UTF8::llvmType, false,
+ GlobalValue::ExternalLinkage,
+ constantUTF8Null, "",
+ compilingClass->isolate->module);
+ compilingClass->isolate->protectModule->unlock();
+ }
+#endif
+
+ // TODO: put an initializer in here
+ void* ptr = mvm::jit::executionEngine->getPointerToGlobal(gv);
+ GenericValue Val = GenericValue(val);
+ llvm::GenericValue * Ptr = (llvm::GenericValue*)ptr;
+ mvm::jit::executionEngine->StoreValueToMemory(Val, Ptr, JavaObject::llvmType);
+ toPush = new LoadInst(gv, "", currentBlock);
+ ctpInfo->ctpRes[index] = gv;
+ compilingClass->release();
+ } else {
+ compilingClass->release();
+ toPush = new LoadInst((GlobalVariable*)ctpInfo->ctpRes[index], "", currentBlock);
+ }
+ } else {
+ toPush = new LoadInst((GlobalVariable*)ctpInfo->ctpRes[index], "", currentBlock);
+ }
+#ifndef SINGLE_VM
+ if (compilingClass->isolate == Jnjvm::bootstrapVM)
+ push(new CallInst(runtimeUTF8ToStrLLVM, toPush, "", currentBlock), AssessorDesc::dRef);
+ else
+#endif
+ push(toPush, AssessorDesc::dRef);
+ } else if (type == JavaCtpInfo::ConstantLong) {
+ mvm::jit::protectConstants();//->lock();
+ push(ConstantInt::get(Type::Int64Ty, ctpInfo->LongAt(index)), AssessorDesc::dLong);
+ mvm::jit::unprotectConstants();//->unlock();
+ } else if (type == JavaCtpInfo::ConstantDouble) {
+ mvm::jit::protectConstants();//->lock();
+ push(ConstantFP::get(Type::DoubleTy, APFloat(ctpInfo->DoubleAt(index))), AssessorDesc::dDouble);
+ mvm::jit::unprotectConstants();//->unlock();
+ } else if (type == JavaCtpInfo::ConstantInteger) {
+ mvm::jit::protectConstants();//->lock();
+ push(ConstantInt::get(Type::Int32Ty, ctpInfo->IntegerAt(index)), AssessorDesc::dInt);
+ mvm::jit::unprotectConstants();//->unlock();
+ } else if (type == JavaCtpInfo::ConstantFloat) {
+ mvm::jit::protectConstants();//->lock();
+ push(ConstantFP::get(Type::FloatTy, APFloat(ctpInfo->FloatAt(index))), AssessorDesc::dFloat);
+ mvm::jit::unprotectConstants();//->unlock();
+ } else if (type == JavaCtpInfo::ConstantClass) {
+ assert(0 && "implement ConstantClass in ldc!");
+ } else {
+ JavaThread::get()->isolate->unknownError("unknown type %d", type);
+ }
+}
+
+void JavaJIT::JITVerifyNull(Value* obj) {
+
+ JavaJIT* jit = this;
+ Constant* zero = constantJavaObjectNull;
+ Value* test = new ICmpInst(ICmpInst::ICMP_EQ, obj, zero, "",
+ jit->currentBlock);
+
+ BasicBlock* exit = jit->createBasicBlock("verifyNullExit");
+ BasicBlock* cont = jit->createBasicBlock("verifyNullCont");
+
+ new BranchInst(exit, cont, test, jit->currentBlock);
+ std::vector<Value*> args;
+ if (currentExceptionBlock != endExceptionBlock) {
+ new InvokeInst(JavaJIT::nullPointerExceptionLLVM, unifiedUnreachable,
+ currentExceptionBlock, args.begin(),
+ args.end(), "", exit);
+ } else {
+ new CallInst(JavaJIT::nullPointerExceptionLLVM, args.begin(),
+ args.end(), "", exit);
+ new UnreachableInst(exit);
+ }
+
+
+ jit->currentBlock = cont;
+
+}
+
+Value* JavaJIT::verifyAndComputePtr(Value* obj, Value* index,
+ const Type* arrayType, bool verif) {
+ JITVerifyNull(obj);
+
+ if (index->getType() != Type::Int32Ty) {
+ index = new SExtInst(index, Type::Int32Ty, "", currentBlock);
+ }
+
+ if (true) {
+ Value* size = arraySize(obj);
+
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_ULT, index, size, "", currentBlock);
+
+ BasicBlock* ifTrue = createBasicBlock("true verifyAndComputePtr");
+ BasicBlock* ifFalse = createBasicBlock("false verifyAndComputePtr");
+
+ branch(cmp, ifTrue, ifFalse, currentBlock);
+
+ std::vector<Value*>args;
+ args.push_back(obj);
+ args.push_back(index);
+ if (currentExceptionBlock != endExceptionBlock) {
+ new InvokeInst(JavaJIT::indexOutOfBoundsExceptionLLVM, unifiedUnreachable,
+ currentExceptionBlock, args.begin(),
+ args.end(), "", ifFalse);
+ } else {
+ new CallInst(JavaJIT::indexOutOfBoundsExceptionLLVM, args.begin(),
+ args.end(), "", ifFalse);
+ new UnreachableInst(ifFalse);
+ }
+
+ currentBlock = ifTrue;
+ }
+
+ Constant* zero = mvm::jit::constantZero;
+ Value* val = new BitCastInst(obj, arrayType, "", currentBlock);
+
+ std::vector<Value*> indexes; //[3];
+ indexes.push_back(zero);
+ indexes.push_back(JavaArray::elementsOffset());
+ indexes.push_back(index);
+ Value* ptr = new GetElementPtrInst(val, indexes.begin(), indexes.end(),
+ "", currentBlock);
+
+ return ptr;
+
+}
+
+void JavaJIT::setCurrentBlock(BasicBlock* newBlock) {
+
+ std::vector< std::pair<Value*, const AssessorDesc*> > newStack;
+ uint32 index = 0;
+ for (BasicBlock::iterator i = newBlock->begin(), e = newBlock->end(); i != e;
+ ++i, ++index) {
+ // case 2 happens with handlers
+ if (!(isa<PHINode>(i)) || i->getType() == mvm::jit::ptrType) {
+ break;
+ } else {
+ const llvm::Type* type = i->getType();
+ if (type == Type::Int32Ty || type == Type::Int16Ty ||
+ type == Type::Int8Ty) {
+ newStack.push_back(std::make_pair(i, AssessorDesc::dInt));
+ } else {
+ newStack.push_back(std::make_pair(i, stack[index].second));
+ }
+ }
+ }
+
+ stack = newStack;
+ currentBlock = newBlock;
+}
+
+static void testPHINodes(BasicBlock* dest, BasicBlock* insert, JavaJIT* jit) {
+ if(dest->empty()) {
+ for (std::vector< std::pair<Value*, const AssessorDesc*> >::iterator i = jit->stack.begin(),
+ e = jit->stack.end(); i!= e; ++i) {
+ Value* cur = i->first;
+ const AssessorDesc* func = i->second;
+ PHINode* node = 0;
+ if (func == AssessorDesc::dChar || func == AssessorDesc::dBool) {
+ node = new PHINode(Type::Int32Ty, "", dest);
+ cur = new ZExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
+ } else if (func == AssessorDesc::dByte || func == AssessorDesc::dShort) {
+ node = new PHINode(Type::Int32Ty, "", dest);
+ cur = new SExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
+ } else {
+ node = new PHINode(cur->getType(), "", dest);
+ }
+ node->addIncoming(cur, insert);
+ }
+ } else {
+ std::vector< std::pair<Value*, const AssessorDesc*> >::iterator stackit = jit->stack.begin();
+ for (BasicBlock::iterator i = dest->begin(), e = dest->end(); i != e;
+ ++i) {
+ if (!(isa<PHINode>(i))) {
+ break;
+ } else {
+ Instruction* ins = i;
+ Value* cur = stackit->first;
+ const AssessorDesc* func = stackit->second;
+
+ if (func == AssessorDesc::dChar || func == AssessorDesc::dBool) {
+ cur = new ZExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
+ } else if (func == AssessorDesc::dByte || func == AssessorDesc::dShort) {
+ cur = new SExtInst(cur, Type::Int32Ty, "", jit->currentBlock);
+ }
+
+ ((PHINode*)ins)->addIncoming(cur, insert);
+ ++stackit;
+ }
+ }
+ }
+}
+
+void JavaJIT::branch(llvm::BasicBlock* dest, llvm::BasicBlock* insert) {
+ testPHINodes(dest, insert, this);
+ new BranchInst(dest, insert);
+}
+
+void JavaJIT::branch(llvm::Value* test, llvm::BasicBlock* ifTrue,
+ llvm::BasicBlock* ifFalse, llvm::BasicBlock* insert) {
+ testPHINodes(ifTrue, insert, this);
+ testPHINodes(ifFalse, insert, this);
+ new BranchInst(ifTrue, ifFalse, test, insert);
+}
+
+void JavaJIT::makeArgs(FunctionType::param_iterator it,
+ uint32 index, std::vector<Value*>& Args, uint32 nb) {
+ Args.reserve(nb + 2);
+ Value* args[nb];
+ for (sint32 i = nb - 1; i >= 0; --i) {
+ it--;
+ if (it->get() == Type::Int64Ty || it->get() == Type::DoubleTy) {
+ pop();
+ }
+ const AssessorDesc* func = topFunc();
+ Value* tmp = pop();
+
+ const Type* type = it->get();
+ if (tmp->getType() != type) { // int8 or int16
+ if (type == Type::Int32Ty) {
+ if (func == AssessorDesc::dChar) {
+ tmp = new ZExtInst(tmp, type, "", currentBlock);
+ } else {
+ tmp = new SExtInst(tmp, type, "", currentBlock);
+ }
+ } else {
+ tmp = new TruncInst(tmp, type, "", currentBlock);
+ }
+ }
+ args[i] = tmp;
+
+ }
+
+ for (uint32 i = 0; i < nb; ++i) {
+ Args.push_back(args[i]);
+ }
+
+}
+
+Instruction* JavaJIT::lowerMathOps(const UTF8* name,
+ std::vector<Value*>& args) {
+ if (name == Jnjvm::abs) {
+ const Type* Ty = args[0]->getType();
+ if (Ty == Type::Int32Ty) {
+ Constant* const_int32_9 = mvm::jit::constantZero;
+ ConstantInt* const_int32_10 = mvm::jit::constantMinusOne;
+ BinaryOperator* int32_tmpneg = BinaryOperator::create(Instruction::Sub, const_int32_9, args[0], "tmpneg", currentBlock);
+ ICmpInst* int1_abscond = new ICmpInst(ICmpInst::ICMP_SGT, args[0], const_int32_10, "abscond", currentBlock);
+ return new SelectInst(int1_abscond, args[0], int32_tmpneg, "abs", currentBlock);
+ } else if (Ty == Type::Int64Ty) {
+ Constant* const_int64_9 = mvm::jit::constantLongZero;
+ ConstantInt* const_int64_10 = mvm::jit::constantLongMinusOne;
+ BinaryOperator* int64_tmpneg = BinaryOperator::create(Instruction::Sub, const_int64_9, args[0], "tmpneg", currentBlock);
+ ICmpInst* int1_abscond = new ICmpInst(ICmpInst::ICMP_SGT, args[0], const_int64_10, "abscond", currentBlock);
+ return new SelectInst(int1_abscond, args[0], int64_tmpneg, "abs", currentBlock);
+ } else if (Ty == Type::FloatTy) {
+ return new CallInst(mvm::jit::func_llvm_fabs_f32, args[0], "tmp1", currentBlock);
+ } else if (Ty == Type::DoubleTy) {
+ return new CallInst(mvm::jit::func_llvm_fabs_f64, args[0], "tmp1", currentBlock);
+ }
+ } else if (name == Jnjvm::sqrt) {
+ return new CallInst(mvm::jit::func_llvm_sqrt_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::sin) {
+ return new CallInst(mvm::jit::func_llvm_sin_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::cos) {
+ return new CallInst(mvm::jit::func_llvm_cos_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::tan) {
+ return new CallInst(mvm::jit::func_llvm_tan_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::asin) {
+ return new CallInst(mvm::jit::func_llvm_asin_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::acos) {
+ return new CallInst(mvm::jit::func_llvm_acos_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::atan) {
+ return new CallInst(mvm::jit::func_llvm_atan_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::atan2) {
+ return new CallInst(mvm::jit::func_llvm_atan2_f64, args.begin(), args.end(), "tmp1", currentBlock);
+ } else if (name == Jnjvm::exp) {
+ return new CallInst(mvm::jit::func_llvm_exp_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::log) {
+ return new CallInst(mvm::jit::func_llvm_log_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::pow) {
+ return new CallInst(mvm::jit::func_llvm_pow_f64, args.begin(), args.end(), "tmp1", currentBlock);
+ } else if (name == Jnjvm::ceil) {
+ return new CallInst(mvm::jit::func_llvm_ceil_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::floor) {
+ return new CallInst(mvm::jit::func_llvm_floor_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::rint) {
+ return new CallInst(mvm::jit::func_llvm_rint_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::cbrt) {
+ return new CallInst(mvm::jit::func_llvm_cbrt_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::cosh) {
+ return new CallInst(mvm::jit::func_llvm_cosh_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::expm1) {
+ return new CallInst(mvm::jit::func_llvm_expm1_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::hypot) {
+ return new CallInst(mvm::jit::func_llvm_hypot_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::log10) {
+ return new CallInst(mvm::jit::func_llvm_log10_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::log1p) {
+ return new CallInst(mvm::jit::func_llvm_log1p_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::sinh) {
+ return new CallInst(mvm::jit::func_llvm_sinh_f64, args[0], "tmp1", currentBlock);
+ } else if (name == Jnjvm::tanh) {
+ return new CallInst(mvm::jit::func_llvm_tanh_f64, args[0], "tmp1", currentBlock);
+ }
+
+ return 0;
+
+}
+
+
+Instruction* JavaJIT::invokeInline(JavaMethod* meth,
+ std::vector<Value*>& args) {
+ JavaJIT* jit = gc_new(JavaJIT)();
+ jit->compilingClass = meth->classDef;
+ jit->compilingMethod = meth;
+ jit->unifiedUnreachable = unifiedUnreachable;
+ jit->inlineMethods = inlineMethods;
+ jit->inlineMethods[meth] = true;
+ Instruction* ret = jit->inlineCompile(llvmFunction, currentBlock,
+ currentExceptionBlock, args);
+ inlineMethods[meth] = false;
+ return ret;
+}
+
+void JavaJIT::invokeSpecial(uint16 index) {
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ JavaMethod* meth = 0;
+ Signdef* signature = 0;
+ const UTF8* name = 0;
+ const UTF8* cl = 0;
+ ctpInfo->nameOfStaticOrSpecialMethod(index, cl, name, signature);
+ llvm::Instruction* val = 0;
+
+ std::vector<Value*> args;
+ FunctionType::param_iterator it = signature->virtualType->param_end();
+ makeArgs(it, index, args, signature->nbIn + 1);
+ JITVerifyNull(args[0]);
+
+ if (cl == Jnjvm::mathName) {
+ val = lowerMathOps(name, args);
+ }
+
+ if (!val) {
+ Function* func = ctpInfo->infoOfStaticOrSpecialMethod(index, ACC_VIRTUAL,
+ signature, meth);
+
+ if (meth && meth->canBeInlined && meth != compilingMethod &&
+ inlineMethods[meth] == 0) {
+ val = invokeInline(meth, args);
+ } else {
+ val = invoke(func, args, "", currentBlock);
+ }
+ }
+
+ const llvm::Type* retType = signature->virtualType->getReturnType();
+ if (retType != Type::VoidTy) {
+ push(val, signature->ret->funcs);
+ if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ }
+ }
+
+}
+
+void JavaJIT::invokeStatic(uint16 index) {
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ JavaMethod* meth = 0;
+ Signdef* signature = 0;
+ const UTF8* name = 0;
+ const UTF8* cl = 0;
+ ctpInfo->nameOfStaticOrSpecialMethod(index, cl, name, signature);
+ llvm::Instruction* val = 0;
+
+ std::vector<Value*> args; // size = [signature->nbIn + 2];
+ FunctionType::param_iterator it = signature->staticType->param_end();
+ makeArgs(it, index, args, signature->nbIn);
+ ctpInfo->markAsStaticCall(index);
+
+ if (cl == Jnjvm::mathName) {
+ val = lowerMathOps(name, args);
+ }
+
+ if (!val) {
+ Function* func = ctpInfo->infoOfStaticOrSpecialMethod(index, ACC_STATIC,
+ signature, meth);
+
+ if (meth && meth->canBeInlined && meth != compilingMethod &&
+ inlineMethods[meth] == 0) {
+ val = invokeInline(meth, args);
+ } else {
+ val = invoke(func, args, "", currentBlock);
+ }
+ }
+
+ const llvm::Type* retType = signature->staticType->getReturnType();
+ if (retType != Type::VoidTy) {
+ push(val, signature->ret->funcs);
+ if (retType == Type::DoubleTy || retType == Type::Int64Ty) {
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ }
+ }
+}
+
+Value* JavaJIT::getInitializedClass(uint16 index) {
+ const Type* PtrTy = mvm::jit::ptrType;
+ compilingClass->isolate->protectModule->lock();
+ GlobalVariable * gv =
+ new GlobalVariable(PtrTy, false,
+ GlobalValue::ExternalLinkage,
+ mvm::jit::constantPtrNull, "",
+ compilingClass->isolate->module);
+
+ compilingClass->isolate->protectModule->unlock();
+
+ Value* arg1 = new LoadInst(gv, "", false, currentBlock);
+ Value* test = new ICmpInst(ICmpInst::ICMP_EQ, arg1,
+ mvm::jit::constantPtrNull, "", currentBlock);
+
+ BasicBlock* trueCl = createBasicBlock("Cl OK");
+ BasicBlock* falseCl = createBasicBlock("Cl Not OK");
+ PHINode* node = new PHINode(PtrTy, "", trueCl);
+ node->addIncoming(arg1, currentBlock);
+ new BranchInst(falseCl, trueCl, test, currentBlock);
+
+ currentBlock = falseCl;
+
+ std::vector<Value*> Args;
+ Value* v =
+ new LoadInst(compilingClass->llvmVar(compilingClass->isolate->module),
+ "", currentBlock);
+ Args.push_back(v);
+ mvm::jit::protectConstants();
+ ConstantInt* CI = ConstantInt::get(Type::Int32Ty, index);
+ mvm::jit::unprotectConstants();
+ Args.push_back(CI);
+ Args.push_back(gv);
+ Value* res = invoke(newLookupLLVM, Args, "", currentBlock);
+ node->addIncoming(res, currentBlock);
+
+ new BranchInst(trueCl, currentBlock);
+ currentBlock = trueCl;
+
+ return node;
+}
+
+void JavaJIT::invokeNew(uint16 index) {
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ ctpInfo->checkInfoOfClass(index);
+
+ Class* cl = (Class*)(ctpInfo->getMethodClassIfLoaded(index));
+ Value* val = 0;
+ if (!cl || !cl->isReady()) {
+ Value* node = getInitializedClass(index);
+ val = invoke(doNewUnknownLLVM, node, "", currentBlock);
+ } else {
+ Value* load = new LoadInst(cl->llvmVar(compilingClass->isolate->module), "", currentBlock);
+ val = invoke(doNewLLVM, load, "", currentBlock);
+ // give the real type info, escape analysis uses it
+ new BitCastInst(val, cl->virtualType, "", currentBlock);
+ }
+
+ push(val, AssessorDesc::dRef);
+
+}
+
+Value* JavaJIT::arraySize(Value* val) {
+ return new CallInst(arrayLengthLLVM, val, "", currentBlock);
+ /*
+ Value* array = new BitCastInst(val, JavaArray::llvmType, "", currentBlock);
+ std::vector<Value*> args; //size= 2
+ args.push_back(mvm::jit::constantZero);
+ args.push_back(JavaArray::sizeOffset());
+ Value* ptr = new GetElementPtrInst(array, args.begin(), args.end(),
+ "", currentBlock);
+ return new LoadInst(ptr, "", currentBlock);*/
+}
+
+static llvm::Value* fieldGetter(JavaJIT* jit, const Type* type, Value* object,
+ Value* offset) {
+ llvm::Value* objectConvert = new BitCastInst(object, type, "",
+ jit->currentBlock);
+
+ Constant* zero = mvm::jit::constantZero;
+ std::vector<Value*> args; // size = 2
+ args.push_back(zero);
+ args.push_back(offset);
+ llvm::Value* ptr = new GetElementPtrInst(objectConvert, args.begin(),
+ args.end(), "", jit->currentBlock);
+ return ptr;
+}
+
+Value* JavaJIT::ldResolved(uint16 index, bool stat, Value* object,
+ const Type* fieldType, const Type* fieldTypePtr) {
+ JavaCtpInfo* info = compilingClass->ctpInfo;
+
+ JavaField* field = info->lookupField(index, stat);
+ if (field && field->classDef->isReady()) {
+ if (stat) object = new LoadInst(field->classDef->staticVar(compilingClass->isolate->module), "",
+ currentBlock);
+ const Type* type = stat ? field->classDef->staticType :
+ field->classDef->virtualType;
+
+#ifndef SINGLE_VM
+ if (stat && field->classDef->isolate == Jnjvm::bootstrapVM) {
+ object = new CallInst(getStaticInstanceLLVM, object, "", currentBlock);
+ }
+#endif
+ return fieldGetter(this, type, object, field->offset);
+ } else {
+ const Type* Pty = mvm::jit::arrayPtrType;
+ compilingClass->isolate->protectModule->lock();
+ GlobalVariable* gvStaticInstance =
+ new GlobalVariable(mvm::jit::ptrType, false,
+ GlobalValue::ExternalLinkage,
+ mvm::jit::constantPtrNull,
+ "", compilingClass->isolate->module);
+
+
+ Constant* zero = mvm::jit::constantZero;
+ GlobalVariable* gv =
+ new GlobalVariable(Type::Int32Ty, false, GlobalValue::ExternalLinkage,
+ zero, "", compilingClass->isolate->module);
+ compilingClass->isolate->protectModule->unlock();
+
+ // set is volatile
+ Value* val = new LoadInst(gv, "", true, currentBlock);
+ Value * cmp = new ICmpInst(ICmpInst::ICMP_NE, val, zero, "", currentBlock);
+ BasicBlock* ifTrue = createBasicBlock("true ldResolved");
+ BasicBlock* ifFalse = createBasicBlock("false ldResolved");
+ BasicBlock* endBlock = createBasicBlock("end ldResolved");
+ PHINode * node = new PHINode(mvm::jit::ptrType, "", endBlock);
+ new BranchInst(ifTrue, ifFalse, cmp, currentBlock);
+
+ // ---------- In case we already resolved something --------------------- //
+ currentBlock = ifTrue;
+ Value* resPtr = 0;
+ if (object) {
+ Value* ptr = new BitCastInst(object, Pty, "", currentBlock);
+ std::vector<Value*> gepArgs; // size = 1
+ gepArgs.push_back(zero);
+ gepArgs.push_back(val);
+ resPtr = new GetElementPtrInst(ptr, gepArgs.begin(), gepArgs.end(),
+ "", currentBlock);
+
+ } else {
+ resPtr = new LoadInst(gvStaticInstance, "", currentBlock);
+ }
+
+ node->addIncoming(resPtr, currentBlock);
+ new BranchInst(endBlock, currentBlock);
+
+ // ---------- In case we have to resolve -------------------------------- //
+ currentBlock = ifFalse;
+ std::vector<Value*> args;
+ if (object) {
+ args.push_back(object);
+ } else {
+ args.push_back(constantJavaObjectNull);
+ }
+ args.push_back(new LoadInst(compilingClass->llvmVar(compilingClass->isolate->module), "",
+ currentBlock));
+ mvm::jit::protectConstants();//->lock();
+ args.push_back(ConstantInt::get(Type::Int32Ty, index));
+ mvm::jit::unprotectConstants();//->unlock();
+ args.push_back(stat ? mvm::jit::constantOne : mvm::jit::constantZero);
+ args.push_back(gvStaticInstance);
+ args.push_back(gv);
+ Value* tmp = invoke(JavaJIT::fieldLookupLLVM, args, "", currentBlock);
+ node->addIncoming(tmp, currentBlock);
+ new BranchInst(endBlock, currentBlock);
+
+ currentBlock = endBlock;;
+ return new BitCastInst(node, fieldTypePtr, "", currentBlock);
+ }
+}
+
+extern void convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock, bool usign);
+
+
+void JavaJIT::setStaticField(uint16 index) {
+ const AssessorDesc* ass = topFunc();
+ Value* val = pop();
+ Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
+ const Type* type = sign->funcs->llvmType;
+ if (type == Type::Int64Ty || type == Type::DoubleTy) {
+ val = pop();
+ }
+ Value* ptr = ldResolved(index, true, 0, type, sign->funcs->llvmTypePtr);
+
+ if (type != val->getType()) { // int1, int8, int16
+ convertValue(val, type, currentBlock,
+ ass == AssessorDesc::dChar || ass == AssessorDesc::dBool);
+ }
+
+ new StoreInst(val, ptr, false, currentBlock);
+}
+
+void JavaJIT::getStaticField(uint16 index) {
+ Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
+ Value* ptr = ldResolved(index, true, 0, sign->funcs->llvmType,
+ sign->funcs->llvmTypePtr);
+ push(new LoadInst(ptr, "", currentBlock), sign->funcs);
+ const Type* type = sign->funcs->llvmType;
+ if (type == Type::Int64Ty || type == Type::DoubleTy) {
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ }
+}
+
+void JavaJIT::setVirtualField(uint16 index) {
+ const AssessorDesc* ass = topFunc();
+ Value* val = pop();
+ Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
+ const Type* type = sign->funcs->llvmType;
+
+ if (type == Type::Int64Ty || type == Type::DoubleTy) {
+ val = pop();
+ }
+
+ Value* object = pop();
+ JITVerifyNull(object);
+ Value* ptr = ldResolved(index, false, object, type,
+ sign->funcs->llvmTypePtr);
+
+ if (type != val->getType()) { // int1, int8, int16
+ convertValue(val, type, currentBlock,
+ ass == AssessorDesc::dChar || ass == AssessorDesc::dBool);
+ }
+
+ new StoreInst(val, ptr, false, currentBlock);
+}
+
+void JavaJIT::getVirtualField(uint16 index) {
+ Typedef* sign = compilingClass->ctpInfo->infoOfField(index);
+ Value* obj = pop();
+ JITVerifyNull(obj);
+ Value* ptr = ldResolved(index, false, obj, sign->funcs->llvmType,
+ sign->funcs->llvmTypePtr);
+ push(new LoadInst(ptr, "", currentBlock), sign->funcs);
+ const Type* type = sign->funcs->llvmType;
+ if (type == Type::Int64Ty || type == Type::DoubleTy) {
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ }
+}
+
+
+Instruction* JavaJIT::invoke(Value *F, std::vector<llvm::Value*>& args,
+ const char* Name,
+ BasicBlock *InsertAtEnd) {
+
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ return new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
+ args.end(), Name, InsertAtEnd);
+ } else {
+ return new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
+ }
+}
+
+Instruction* JavaJIT::invoke(Value *F, Value* arg1, const char* Name,
+ BasicBlock *InsertAtEnd) {
+
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ std::vector<Value*> arg;
+ arg.push_back(arg1);
+ return new InvokeInst(F, ifNormal, currentExceptionBlock, arg.begin(),
+ arg.end(), Name, InsertAtEnd);
+ } else {
+ return new CallInst(F, arg1, Name, InsertAtEnd);
+ }
+}
+
+Instruction* JavaJIT::invoke(Value *F, Value* arg1, Value* arg2,
+ const char* Name, BasicBlock *InsertAtEnd) {
+
+ std::vector<Value*> args;
+ args.push_back(arg1);
+ args.push_back(arg2);
+
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ return new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
+ args.end(), Name, InsertAtEnd);
+ } else {
+ return new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
+ }
+}
+
+Instruction* JavaJIT::invoke(Value *F, const char* Name,
+ BasicBlock *InsertAtEnd) {
+ // means: is there a handler for me?
+ if (currentExceptionBlock != endExceptionBlock) {
+ BasicBlock* ifNormal = createBasicBlock("no exception block");
+ currentBlock = ifNormal;
+ std::vector<Value*> args;
+ return new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
+ args.end(), Name, InsertAtEnd);
+ } else {
+ return new CallInst(F, Name, InsertAtEnd);
+ }
+}
+
+
diff --git a/vmkit/lib/JnJVM/VMCore/JavaJIT.h b/vmkit/lib/JnJVM/VMCore/JavaJIT.h
new file mode 100644
index 0000000..37c7193
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaJIT.h
@@ -0,0 +1,497 @@
+//===----------- JavaJIT.h - Java just in time compiler -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_JIT_H
+#define JNJVM_JAVA_JIT_H
+
+#include <vector>
+#include <map>
+
+#include "llvm/BasicBlock.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/PassManager.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Value.h"
+
+#include "types.h"
+
+#include "mvm/Object.h"
+
+namespace jnjvm {
+
+class AssessorDesc;
+class CacheNode;
+class Class;
+class JavaField;
+class JavaMethod;
+class JavaObject;
+class JavaString;
+class Jnjvm;
+class JnjvmModuleProvider;
+class Reader;
+class Signdef;
+class UTF8;
+
+class Exception : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ uint32 startpc;
+ uint32 endpc;
+ uint32 handlerpc;
+ uint16 index;
+ Class* catchClass;
+ llvm::BasicBlock* test;
+ llvm::BasicBlock* realTest;
+ llvm::BasicBlock* handler;
+ llvm::PHINode* exceptionPHI;
+ llvm::PHINode* handlerPHI;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+};
+
+class Opinfo : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ llvm::BasicBlock* newBlock;
+ bool reqSuppl;
+ llvm::BasicBlock* exceptionBlock;
+
+ virtual void print(mvm::PrintBuffer* buf) const {
+ buf->write("Opinfo");
+ }
+ virtual void tracer(size_t sz);
+};
+
+class JavaJIT : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ static void invokeOnceVoid(Jnjvm* vm, JavaObject* loader,
+ const char* className,
+ const char* func, const char* sign,
+ int access, ...);
+
+
+ llvm::Function* javaCompile();
+ llvm::Function* nativeCompile(void* natPtr = 0);
+ llvm::Instruction* inlineCompile(llvm::Function* parentFunction,
+ llvm::BasicBlock*& curBB,
+ llvm::BasicBlock* endExBlock,
+ std::vector<llvm::Value*>& args);
+
+ std::map<JavaMethod*, bool> inlineMethods;
+
+ Class* compilingClass;
+ JavaMethod* compilingMethod;
+ llvm::Function* llvmFunction;
+ const llvm::Type* returnType;
+
+ // change into LLVM instructions
+ void compileOpcodes(uint8* bytecodes, uint32 codeLength);
+ // create basic blocks
+ void exploreOpcodes(uint8* bytecodes, uint32 codeLength);
+
+ // load constant
+ void _ldc(uint16 index);
+
+ // float comparisons
+ void compareFP(llvm::Value*, llvm::Value*, const llvm::Type*, bool l);
+
+ // null pointer exception
+ void JITVerifyNull(llvm::Value* obj);
+
+
+ // stack manipulation
+ std::vector< std::pair<llvm::Value*, const AssessorDesc*> > stack;
+ void push(llvm::Value* val, const AssessorDesc* ass);
+ void push(std::pair<llvm::Value*, const AssessorDesc*> pair);
+ llvm::Value* pop();
+ llvm::Value* popAsInt();
+ llvm::Value* top();
+ const AssessorDesc* topFunc();
+ std::pair<llvm::Value*, const AssessorDesc*> popPair();
+ uint32 stackSize();
+
+ // exceptions
+ static llvm::Function* getExceptionLLVM;
+ static llvm::Function* getJavaExceptionLLVM;
+ static llvm::Function* throwExceptionLLVM;
+ static llvm::Function* clearExceptionLLVM;
+ static llvm::Function* compareExceptionLLVM;
+ static llvm::Function* nullPointerExceptionLLVM;
+ static llvm::Function* indexOutOfBoundsExceptionLLVM;
+ static llvm::Function* classCastExceptionLLVM;
+ std::vector<llvm::BasicBlock*> jsrs;
+ // exception local
+ llvm::Value* supplLocal;
+ unsigned readExceptionTable(Reader* reader);
+ std::vector<Exception*> exceptions;
+ llvm::BasicBlock* endExceptionBlock;
+ llvm::BasicBlock* currentExceptionBlock;
+ llvm::BasicBlock* unifiedUnreachable;
+ Opinfo* opcodeInfos;
+
+ // block manipulation
+ llvm::BasicBlock* currentBlock;
+ llvm::BasicBlock* createBasicBlock(const char* name = "");
+ void setCurrentBlock(llvm::BasicBlock* block);
+
+ // branches
+ void branch(llvm::Value* test, llvm::BasicBlock* ifTrue,
+ llvm::BasicBlock* ifFalse, llvm::BasicBlock* insert);
+ void branch(llvm::BasicBlock* where, llvm::BasicBlock* insert);
+
+ // locals
+ std::vector<llvm::Value*> intLocals;
+ std::vector<llvm::Value*> longLocals;
+ std::vector<llvm::Value*> floatLocals;
+ std::vector<llvm::Value*> doubleLocals;
+ std::vector<llvm::Value*> objectLocals;
+
+ // end function
+ llvm::BasicBlock* endBlock;
+ llvm::PHINode* endNode;
+
+ // array manipulation
+ llvm::Value* verifyAndComputePtr(llvm::Value* obj, llvm::Value* index,
+ const llvm::Type* arrayType,
+ bool verif = true);
+ llvm::Value* arraySize(llvm::Value* obj);
+
+
+ // synchronize
+ void beginSynchronize();
+ void endSynchronize();
+
+ // fields invoke
+ void getStaticField(uint16 index);
+ void setStaticField(uint16 index);
+ void getVirtualField(uint16 index);
+ void setVirtualField(uint16 index);
+ llvm::Value* ldResolved(uint16 index, bool stat, llvm::Value* object,
+ const llvm::Type* fieldType,
+ const llvm::Type* fieldTypePtr);
+ llvm::Value* getInitializedClass(uint16 index);
+
+ // methods invoke
+ void makeArgs(llvm::FunctionType::param_iterator it,
+ uint32 index, std::vector<llvm::Value*>& result, uint32 nb);
+ void invokeInterfaceOrVirtual(uint16 index);
+ void invokeSpecial(uint16 index);
+ void invokeStatic(uint16 index);
+ void invokeNew(uint16 index);
+ llvm::Instruction* invokeInline(JavaMethod* meth,
+ std::vector<llvm::Value*>& args);
+ llvm::Instruction* lowerMathOps(const UTF8* name,
+ std::vector<llvm::Value*>& args);
+
+
+ llvm::Instruction* invoke(llvm::Value *F, std::vector<llvm::Value*>&args,
+ const char* Name,
+ llvm::BasicBlock *InsertAtEnd);
+ // Alternate CallInst ctors w/ two actuals, w/ one actual and no
+ // actuals, respectively.
+ llvm::Instruction* invoke(llvm::Value *F, llvm::Value *Actual1,
+ llvm::Value *Actual2, const char* Name,
+ llvm::BasicBlock *InsertAtEnd);
+ llvm::Instruction* invoke(llvm::Value *F, llvm::Value *Actual1,
+ const char* Name, llvm::BasicBlock *InsertAtEnd);
+ llvm::Instruction* invoke(llvm::Value *F, const char* Name,
+ llvm::BasicBlock *InsertAtEnd);
+
+
+ // wide status
+ bool wide;
+ uint32 WREAD_U1(uint8* bytecodes, bool init, uint32 &i);
+ sint32 WREAD_S1(uint8* bytecodes, bool init, uint32 &i);
+ uint32 WCALC(uint32 n);
+
+ uint16 maxStack;
+ uint16 maxLocals;
+ uint32 codeLen;
+
+ static const char* OpcodeNames[256];
+
+ static VirtualTable* makeVT(Class* cl, bool stat);
+
+ static llvm::Function* javaObjectTracerLLVM;
+
+ static void initialise();
+ static void initialiseJITBootstrapVM(Jnjvm* vm);
+ static void initialiseJITIsolateVM(Jnjvm* vm);
+
+
+ static void initField(JavaField* field, JavaObject* obj, uint64 val = 0);
+ static void initField(JavaField* field, JavaObject* obj, JavaObject* val);
+ static void initField(JavaField* field, JavaObject* obj, double val);
+ static void initField(JavaField* field, JavaObject* obj, float val);
+
+ static llvm::Function* getSJLJBufferLLVM;
+ static llvm::Function* virtualLookupLLVM;
+ static llvm::Function* fieldLookupLLVM;
+ static llvm::Function* UTF8AconsLLVM;
+ static llvm::Function* Int8AconsLLVM;
+ static llvm::Function* Int32AconsLLVM;
+ static llvm::Function* Int16AconsLLVM;
+ static llvm::Function* FloatAconsLLVM;
+ static llvm::Function* DoubleAconsLLVM;
+ static llvm::Function* LongAconsLLVM;
+ static llvm::Function* ObjectAconsLLVM;
+ static llvm::Function* printExecutionLLVM;
+ static llvm::Function* printMethodStartLLVM;
+ static llvm::Function* printMethodEndLLVM;
+ static llvm::Function* jniProceedPendingExceptionLLVM;
+ static llvm::Function* doNewLLVM;
+ // this is when the type is not known at compile time (escape analysis)
+ static llvm::Function* doNewUnknownLLVM;
+ static llvm::Function* initialiseObjectLLVM;
+ static llvm::Function* newLookupLLVM;
+ static llvm::Function* instanceOfLLVM;
+ static llvm::Function* aquireObjectLLVM;
+ static llvm::Function* releaseObjectLLVM;
+ static llvm::Function* multiCallNewLLVM;
+ static llvm::Function* runtimeUTF8ToStrLLVM;
+ static llvm::Function* getStaticInstanceLLVM;
+ static llvm::Function* getClassDelegateeLLVM;
+ static llvm::Function* arrayLengthLLVM;
+#ifndef SINGLE_VM
+ static llvm::Function* doNewIsolateLLVM;
+#endif
+ static void runtimeInitialise();
+
+
+ static Class* getCallingClass();
+ static Class* getCallingClassWalker();
+ static JavaObject* getCallingClassLoader();
+ static void printBacktrace();
+
+ static llvm::Function* markAndTraceLLVM;
+ static const llvm::FunctionType* markAndTraceLLVMType;
+ static llvm::Constant* constantJavaObjectNull;
+ static llvm::Constant* constantUTF8Null;
+};
+
+enum Opcode {
+ NOP = 0x00,
+ ACONST_NULL = 0x01,
+ ICONST_M1 = 0x02,
+ ICONST_0 = 0x03,
+ ICONST_1 = 0x04,
+ ICONST_2 = 0x05,
+ ICONST_3 = 0x06,
+ ICONST_4 = 0x07,
+ ICONST_5 = 0x08,
+ LCONST_0 = 0x09,
+ LCONST_1 = 0x0A,
+ FCONST_0 = 0x0B,
+ FCONST_1 = 0x0C,
+ FCONST_2 = 0x0D,
+ DCONST_0 = 0x0E,
+ DCONST_1 = 0x0F,
+ BIPUSH = 0x10,
+ SIPUSH = 0x11,
+ LDC = 0x12,
+ LDC_W = 0x13,
+ LDC2_W = 0x14,
+ ILOAD = 0x15,
+ LLOAD = 0x16,
+ FLOAD = 0x17,
+ DLOAD = 0x18,
+ ALOAD = 0x19,
+ ILOAD_0 = 0x1A,
+ ILOAD_1 = 0x1B,
+ ILOAD_2 = 0x1C,
+ ILOAD_3 = 0x1D,
+ LLOAD_0 = 0x1E,
+ LLOAD_1 = 0x1F,
+ LLOAD_2 = 0x20,
+ LLOAD_3 = 0x21,
+ FLOAD_0 = 0x22,
+ FLOAD_1 = 0x23,
+ FLOAD_2 = 0x24,
+ FLOAD_3 = 0x25,
+ DLOAD_0 = 0x26,
+ DLOAD_1 = 0x27,
+ DLOAD_2 = 0x28,
+ DLOAD_3 = 0x29,
+ ALOAD_0 = 0x2A,
+ ALOAD_1 = 0x2B,
+ ALOAD_2 = 0x2C,
+ ALOAD_3 = 0x2D,
+ IALOAD = 0x2E,
+ LALOAD = 0x2F,
+ FALOAD = 0x30,
+ DALOAD = 0x31,
+ AALOAD = 0x32,
+ BALOAD = 0x33,
+ CALOAD = 0x34,
+ SALOAD = 0x35,
+ ISTORE = 0x36,
+ LSTORE = 0x37,
+ FSTORE = 0x38,
+ DSTORE = 0x39,
+ ASTORE = 0x3A,
+ ISTORE_0 = 0x3B,
+ ISTORE_1 = 0x3C,
+ ISTORE_2 = 0x3D,
+ ISTORE_3 = 0x3E,
+ LSTORE_0 = 0x3F,
+ LSTORE_1 = 0x40,
+ LSTORE_2 = 0x41,
+ LSTORE_3 = 0x42,
+ FSTORE_0 = 0x43,
+ FSTORE_1 = 0x44,
+ FSTORE_2 = 0x45,
+ FSTORE_3 = 0x46,
+ DSTORE_0 = 0x47,
+ DSTORE_1 = 0x48,
+ DSTORE_2 = 0x49,
+ DSTORE_3 = 0x4A,
+ ASTORE_0 = 0x4B,
+ ASTORE_1 = 0x4C,
+ ASTORE_2 = 0x4D,
+ ASTORE_3 = 0x4E,
+ IASTORE = 0x4F,
+ LASTORE = 0x50,
+ FASTORE = 0x51,
+ DASTORE = 0x52,
+ AASTORE = 0x53,
+ BASTORE = 0x54,
+ CASTORE = 0x55,
+ SASTORE = 0x56,
+ POP = 0x57,
+ POP2 = 0x58,
+ DUP = 0x59,
+ DUP_X1 = 0x5A,
+ DUP_X2 = 0x5B,
+ DUP2 = 0x5C,
+ DUP2_X1 = 0x5D,
+ DUP2_X2 = 0x5E,
+ SWAP = 0x5F,
+ IADD = 0x60,
+ LADD = 0x61,
+ FADD = 0x62,
+ DADD = 0x63,
+ ISUB = 0x64,
+ LSUB = 0x65,
+ FSUB = 0x66,
+ DSUB = 0x67,
+ IMUL = 0x68,
+ LMUL = 0x69,
+ FMUL = 0x6A,
+ DMUL = 0x6B,
+ IDIV = 0x6C,
+ LDIV = 0x6D,
+ FDIV = 0x6E,
+ DDIV = 0x6F,
+ IREM = 0x70,
+ LREM = 0x71,
+ FREM = 0x72,
+ DREM = 0x73,
+ INEG = 0x74,
+ LNEG = 0x75,
+ FNEG = 0x76,
+ DNEG = 0x77,
+ ISHL = 0x78,
+ LSHL = 0x79,
+ ISHR = 0x7A,
+ LSHR = 0x7B,
+ IUSHR = 0x7C,
+ LUSHR = 0x7D,
+ IAND = 0x7E,
+ LAND = 0x7F,
+ IOR = 0x80,
+ LOR = 0x81,
+ IXOR = 0x82,
+ LXOR = 0x83,
+ IINC = 0x84,
+ I2L = 0x85,
+ I2F = 0x86,
+ I2D = 0x87,
+ L2I = 0x88,
+ L2F = 0x89,
+ L2D = 0x8A,
+ F2I = 0x8B,
+ F2L = 0x8C,
+ F2D = 0x8D,
+ D2I = 0x8E,
+ D2L = 0x8F,
+ D2F = 0x90,
+ I2B = 0x91,
+ I2C = 0x92,
+ I2S = 0x93,
+ LCMP = 0x94,
+ FCMPL = 0x95,
+ FCMPG = 0x96,
+ DCMPL = 0x97,
+ DCMPG = 0x98,
+ IFEQ = 0x99,
+ IFNE = 0x9A,
+ IFLT = 0x9B,
+ IFGE = 0x9C,
+ IFGT = 0x9D,
+ IFLE = 0x9E,
+ IF_ICMPEQ = 0x9F,
+ IF_ICMPNE = 0xA0,
+ IF_ICMPLT = 0xA1,
+ IF_ICMPGE = 0xA2,
+ IF_ICMPGT = 0xA3,
+ IF_ICMPLE = 0xA4,
+ IF_ACMPEQ = 0xA5,
+ IF_ACMPNE = 0xA6,
+ GOTO = 0xA7,
+ JSR = 0xA8,
+ RET = 0xA9,
+ TABLESWITCH = 0xAA,
+ LOOKUPSWITCH = 0xAB,
+ IRETURN = 0xAC,
+ LRETURN = 0xAD,
+ FRETURN = 0xAE,
+ DRETURN = 0xAF,
+ ARETURN = 0xB0,
+ RETURN = 0xB1,
+ GETSTATIC = 0xB2,
+ PUTSTATIC = 0xB3,
+ GETFIELD = 0xB4,
+ PUTFIELD = 0xB5,
+ INVOKEVIRTUAL = 0xB6,
+ INVOKESPECIAL = 0xB7,
+ INVOKESTATIC = 0xB8,
+ INVOKEINTERFACE = 0xB9,
+ UNUSED = 0xBA,
+ NEW = 0xBB,
+ NEWARRAY = 0xBC,
+ ANEWARRAY = 0xBD,
+ ARRAYLENGTH = 0xBE,
+ ATHROW = 0xBF,
+ CHECKCAST = 0xC0,
+ INSTANCEOF = 0xC1,
+ MONITORENTER = 0xC2,
+ MONITOREXIT = 0xC3,
+ WIDE = 0xC4,
+ MULTIANEWARRAY = 0xC5,
+ IFNULL = 0xC6,
+ IFNONNULL = 0xC7,
+ GOTO_W = 0xC8,
+ JSR_W = 0xC9,
+ BREAKPOINT = 0xCA,
+ IMPDEP1 = 0xFE,
+ IMPDEP2 = 0xFF
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaJITInitialise.cpp b/vmkit/lib/JnJVM/VMCore/JavaJITInitialise.cpp
new file mode 100644
index 0000000..57cd128
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaJITInitialise.cpp
@@ -0,0 +1,665 @@
+//===------JavaJITInitialise.cpp - Initialization of LLVM objects ---------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Type.h>
+#include <llvm/Support/CFG.h>
+#include <llvm/Module.h>
+#include <llvm/Constants.h>
+#include <llvm/Type.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Assembly/PrintModulePass.h>
+#include <llvm/Target/TargetOptions.h>
+#include <llvm/CodeGen/MachineCodeEmitter.h>
+#include <llvm/CodeGen/MachineBasicBlock.h>
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/ParameterAttributes.h"
+#include "llvm/PassManager.h"
+#include "llvm/ValueSymbolTable.h"
+#include "llvm/Analysis/LoadValueNumbering.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/MutexGuard.h"
+
+#include <llvm/Transforms/IPO.h>
+
+#include <setjmp.h>
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+#include "mvm/VMLet.h"
+
+#include "JavaArray.h"
+#include "JavaCache.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+
+using namespace jnjvm;
+using namespace llvm;
+
+void JavaJIT::initialise() {
+ runtimeInitialise();
+}
+
+void JavaJIT::initialiseJITIsolateVM(Jnjvm* vm) {
+ mvm::jit::protectEngine->lock();
+ mvm::jit::executionEngine->addModuleProvider(vm->TheModuleProvider);
+ mvm::jit::protectEngine->unlock();
+}
+
+void JavaJIT::initialiseJITBootstrapVM(Jnjvm* vm) {
+ //llvm::PrintMachineCode = true;
+ Module* module = vm->module;
+ mvm::jit::protectEngine->lock();
+ mvm::jit::executionEngine->addModuleProvider(vm->TheModuleProvider);
+ mvm::jit::protectEngine->unlock();
+
+
+
+ mvm::jit::protectTypes();//->lock();
+ // Create JavaObject::llvmType
+ const llvm::Type* Pty = mvm::jit::ptrType;
+
+ std::vector<const llvm::Type*> objectFields;
+ objectFields.push_back(Pty); // VT
+ objectFields.push_back(Pty); // Class
+ objectFields.push_back(Pty); // Lock
+ JavaObject::llvmType =
+ llvm::PointerType::getUnqual(llvm::StructType::get(objectFields, false));
+
+ // Create JavaArray::llvmType
+ {
+ std::vector<const llvm::Type*> arrayFields;
+ arrayFields.push_back(JavaObject::llvmType->getContainedType(0));
+ arrayFields.push_back(llvm::Type::Int32Ty);
+ JavaArray::llvmType =
+ llvm::PointerType::getUnqual(llvm::StructType::get(arrayFields, false));
+ }
+
+#define ARRAY_TYPE(name, type) \
+ { \
+ std::vector<const Type*> arrayFields; \
+ arrayFields.push_back(JavaObject::llvmType->getContainedType(0)); \
+ arrayFields.push_back(Type::Int32Ty); \
+ arrayFields.push_back(ArrayType::get(type, 0)); \
+ name::llvmType = PointerType::getUnqual(StructType::get(arrayFields, false)); \
+ }
+
+ ARRAY_TYPE(ArrayUInt8, Type::Int8Ty);
+ ARRAY_TYPE(ArraySInt8, Type::Int8Ty);
+ ARRAY_TYPE(ArrayUInt16, Type::Int16Ty);
+ ARRAY_TYPE(ArraySInt16, Type::Int16Ty);
+ ARRAY_TYPE(ArrayUInt32, Type::Int32Ty);
+ ARRAY_TYPE(ArraySInt32, Type::Int32Ty);
+ ARRAY_TYPE(ArrayLong, Type::Int64Ty);
+ ARRAY_TYPE(ArrayDouble, Type::DoubleTy);
+ ARRAY_TYPE(ArrayFloat, Type::FloatTy);
+ ARRAY_TYPE(ArrayObject, JavaObject::llvmType);
+
+#undef ARRAY_TYPE
+
+ // Create UTF8::llvmType
+ {
+ std::vector<const llvm::Type*> arrayFields;
+ arrayFields.push_back(JavaObject::llvmType->getContainedType(0));
+ arrayFields.push_back(llvm::Type::Int32Ty);
+ arrayFields.push_back(llvm::ArrayType::get(llvm::Type::Int16Ty, 0));
+ UTF8::llvmType =
+ llvm::PointerType::getUnqual(llvm::StructType::get(arrayFields, false));
+ }
+
+ // Create CacheNode::llvmType
+ {
+ std::vector<const llvm::Type*> arrayFields;
+ arrayFields.push_back(mvm::jit::ptrType); // VT
+ arrayFields.push_back(mvm::jit::ptrType); // methPtr
+ arrayFields.push_back(mvm::jit::ptrType); // lastCible
+ arrayFields.push_back(mvm::jit::ptrType); // next
+ arrayFields.push_back(mvm::jit::ptrType); // enveloppe
+ CacheNode::llvmType =
+ PointerType::getUnqual(StructType::get(arrayFields, false));
+ }
+
+ // Create Enveloppe::llvmType
+ {
+ std::vector<const llvm::Type*> arrayFields;
+ arrayFields.push_back(mvm::jit::ptrType); // VT
+ arrayFields.push_back(CacheNode::llvmType); // firstCache
+ arrayFields.push_back(mvm::jit::ptrType); // ctpInfo
+ arrayFields.push_back(mvm::jit::ptrType); // cacheLock
+ arrayFields.push_back(Type::Int32Ty); // index
+ Enveloppe::llvmType =
+ PointerType::getUnqual(StructType::get(arrayFields, false));
+ }
+
+
+ // Create javaObjectTracerLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+ javaObjectTracerLLVM = new Function(type,
+ GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaObject6tracerEj",
+ module);
+ }
+
+ // Create virtualLookupLLVM
+ {
+ std::vector<const Type*> args;
+ //args.push_back(JavaObject::llvmType);
+ //args.push_back(mvm::jit::ptrType);
+ //args.push_back(llvm::Type::Int32Ty);
+ args.push_back(CacheNode::llvmType);
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type =
+ FunctionType::get(mvm::jit::ptrType, args, false);
+
+ virtualLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "virtualLookup",
+ module);
+ }
+
+ // Create doNewLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args,
+ false);
+
+ doNewLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm5Class5doNewEv",
+ module);
+ }
+
+ // Create doNewUnknownLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args,
+ false);
+
+ doNewUnknownLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm5Class12doNewUnknownEv",
+ module);
+ }
+
+ // Create initialiseObjectLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args,
+ false);
+
+ initialiseObjectLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm5Class16initialiseObjectEPNS_10JavaObjectE",
+ module);
+ PAListPtr func_toto_PAL;
+ SmallVector<ParamAttrsWithIndex, 4> Attrs;
+ ParamAttrsWithIndex PAWI;
+ PAWI.Index = 0; PAWI.Attrs = 0 | ParamAttr::ReadNone;
+ Attrs.push_back(PAWI);
+ func_toto_PAL = PAListPtr::get(Attrs.begin(), Attrs.end());
+ initialiseObjectLLVM->setParamAttrs(func_toto_PAL);
+ }
+
+ // Create arrayLengthLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type = FunctionType::get(Type::Int32Ty, args, false);
+
+ arrayLengthLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "arrayLength",
+ module);
+ PAListPtr func_toto_PAL;
+ SmallVector<ParamAttrsWithIndex, 4> Attrs;
+ ParamAttrsWithIndex PAWI;
+ PAWI.Index = 0; PAWI.Attrs = 0 | ParamAttr::ReadNone;
+ Attrs.push_back(PAWI);
+ func_toto_PAL = PAListPtr::get(Attrs.begin(), Attrs.end());
+ arrayLengthLLVM->setParamAttrs(func_toto_PAL);
+ }
+
+ // Create newLookupLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ args.push_back(Type::Int32Ty);
+ args.push_back(PointerType::getUnqual(mvm::jit::ptrType));
+ const FunctionType* type = FunctionType::get(mvm::jit::ptrType, args,
+ false);
+
+ newLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "newLookup",
+ module);
+ }
+
+#ifndef SINGLE_VM
+ // Create doNewIsolateLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args,
+ false);
+
+ doNewIsolateLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm5Class12doNewIsolateEv",
+ module);
+ }
+#endif
+
+ // Create fieldLookupLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ args.push_back(mvm::jit::ptrType);
+ args.push_back(llvm::Type::Int32Ty);
+ args.push_back(llvm::Type::Int32Ty);
+ args.push_back(PointerType::getUnqual(mvm::jit::ptrType));
+ args.push_back(PointerType::getUnqual(llvm::Type::Int32Ty));
+ const FunctionType* type =
+ FunctionType::get(mvm::jit::ptrType, args,
+ false);
+
+ fieldLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "fieldLookup",
+ module);
+ }
+
+ // Create nullPointerExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ nullPointerExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "nullPointerException",
+ module);
+ }
+
+ // Create classCastExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ classCastExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "classCastException",
+ module);
+ }
+
+ // Create indexOutOfBoundsExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ args.push_back(Type::Int32Ty);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ indexOutOfBoundsExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "indexOutOfBoundsException",
+ module);
+ }
+
+ // Create proceedPendingExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ jniProceedPendingExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "jniProceedPendingException",
+ module);
+ }
+
+ // Create printExecutionLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(Type::Int32Ty);
+ args.push_back(Type::Int32Ty);
+ args.push_back(Type::Int32Ty);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ printExecutionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "printExecution",
+ module);
+ }
+
+ // Create printMethodStartLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(Type::Int32Ty);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ printMethodStartLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "printMethodStart",
+ module);
+ }
+
+ // Create printMethodEndLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(Type::Int32Ty);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ printMethodEndLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "printMethodEnd",
+ module);
+ }
+
+ // Create throwExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ throwExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaThread14throwExceptionEPNS_10JavaObjectE",
+ module);
+ }
+
+ // Create clearExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ clearExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaThread14clearExceptionEv",
+ module);
+ }
+
+
+
+ // Create getExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ const FunctionType* type = FunctionType::get(mvm::jit::ptrType,
+ args, false);
+
+ getExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaThread12getExceptionEv",
+ module);
+ }
+
+ // Create getJavaExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType,
+ args, false);
+
+ getJavaExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaThread16getJavaExceptionEv",
+ module);
+ }
+
+ // Create compareExceptionLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(Type::Int1Ty, args, false);
+
+ compareExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaThread16compareExceptionEPNS_5ClassE",
+ module);
+ }
+
+ // Create getStaticInstanceLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args, false);
+
+ getStaticInstanceLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "getStaticInstance",
+ module);
+ }
+
+ // Create getClassDelegateeLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args, false);
+
+ getClassDelegateeLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "getClassDelegatee",
+ module);
+ }
+
+ // Create instanceOfLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(Type::Int32Ty, args, false);
+
+ instanceOfLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaObject10instanceOfEPNS_11CommonClassE",
+ module);
+ }
+
+ // Create aquireObjectLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ aquireObjectLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaObject6aquireEv",
+ module);
+ }
+
+ // Create releaseObjectLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+ releaseObjectLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10JavaObject6unlockEv",
+ module);
+ }
+
+ // Create multiCallNewLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(mvm::jit::ptrType);
+ args.push_back(Type::Int32Ty);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args,
+ true);
+
+ multiCallNewLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm9JavaArray12multiCallNewEPNS_10ClassArrayEjz",
+ module);
+ }
+
+
+
+ // Create *AconsLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(Type::Int32Ty);
+ args.push_back(mvm::jit::ptrType);
+ const FunctionType* type = FunctionType::get(JavaObject::llvmType, args,
+ false);
+
+ FloatAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10ArrayFloat5aconsEiPNS_10ClassArrayE",
+ module);
+
+ Int8AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm10ArraySInt85aconsEiPNS_10ClassArrayE",
+ module);
+
+ DoubleAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm11ArrayDouble5aconsEiPNS_10ClassArrayE",
+ module);
+
+ Int16AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm11ArraySInt165aconsEiPNS_10ClassArrayE",
+ module);
+
+ Int32AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm11ArraySInt325aconsEiPNS_10ClassArrayE",
+ module);
+
+ UTF8AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm4UTF85aconsEiPNS_10ClassArrayE",
+ module);
+
+ LongAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm9ArrayLong5aconsEiPNS_10ClassArrayE",
+ module);
+
+ ObjectAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm11ArrayObject5aconsEiPNS_10ClassArrayE",
+ module);
+ }
+
+ {
+ std::vector<const Type*> args;
+ args.push_back(UTF8::llvmType);
+ FunctionType* FuncTy = FunctionType::get(
+ /*Result=*/JavaObject::llvmType,
+ /*Params=*/args,
+ /*isVarArg=*/false);
+ runtimeUTF8ToStrLLVM = new Function(FuncTy, GlobalValue::ExternalLinkage,
+ "runtimeUTF8ToStr", module);
+ }
+
+
+ // Create getSJLJBufferLLVM
+ {
+ std::vector<const Type*> args;
+ const FunctionType* type = FunctionType::get(mvm::jit::ptrType, args,
+ false);
+
+ getSJLJBufferLLVM = new Function(type, GlobalValue::ExternalLinkage,
+ "getSJLJBuffer",
+ module);
+
+ }
+
+
+ // Create markAndTraceLLVM
+ {
+ std::vector<const Type*> args;
+ args.push_back(JavaObject::llvmType);
+ markAndTraceLLVMType = FunctionType::get(llvm::Type::VoidTy, args, false);
+ markAndTraceLLVM = new Function(markAndTraceLLVMType,
+ GlobalValue::ExternalLinkage,
+ "_ZNK2gc12markAndTraceEv",
+ module);
+ }
+ mvm::jit::unprotectTypes();//->unlock();
+ mvm::jit::protectConstants();//->lock();
+ constantUTF8Null = Constant::getNullValue(UTF8::llvmType);
+ constantJavaObjectNull = Constant::getNullValue(JavaObject::llvmType);
+ mvm::jit::unprotectConstants();//->unlock();
+}
+
+llvm::Constant* JavaJIT::constantJavaObjectNull;
+llvm::Constant* JavaJIT::constantUTF8Null;
+
+
+namespace mvm {
+
+llvm::FunctionPass* createEscapeAnalysisPass(llvm::Function*, llvm::Function*);
+llvm::FunctionPass* createLowerArrayLengthPass();
+//llvm::FunctionPass* createArrayChecksPass();
+
+}
+
+static void addPass(FunctionPassManager *PM, Pass *P) {
+ // Add the pass to the pass manager...
+ PM->add(P);
+}
+
+void AddStandardCompilePasses(FunctionPassManager *PM) {
+ llvm::MutexGuard locked(mvm::jit::executionEngine->lock);
+ // LLVM does not allow calling functions from other modules in verifier
+ //PM->add(llvm::createVerifierPass()); // Verify that input is correct
+
+ // do escape analysis first, because the type is given in the first bitcastinst
+ addPass(PM, mvm::createEscapeAnalysisPass(JavaJIT::doNewLLVM, JavaJIT::initialiseObjectLLVM));
+ addPass(PM, llvm::createCFGSimplificationPass()); // Clean up disgusting code
+ addPass(PM, llvm::createScalarReplAggregatesPass());// Kill useless allocas
+ addPass(PM, llvm::createInstructionCombiningPass()); // Clean up after IPCP & DAE
+ addPass(PM, llvm::createCFGSimplificationPass()); // Clean up after IPCP & DAE
+ addPass(PM, llvm::createPromoteMemoryToRegisterPass());// Kill useless allocas
+ addPass(PM, llvm::createInstructionCombiningPass()); // Clean up after IPCP & DAE
+ addPass(PM, llvm::createCFGSimplificationPass()); // Clean up after IPCP & DAE
+
+ addPass(PM, llvm::createTailDuplicationPass()); // Simplify cfg by copying code
+ addPass(PM, llvm::createInstructionCombiningPass()); // Cleanup for scalarrepl.
+ addPass(PM, llvm::createCFGSimplificationPass()); // Merge & remove BBs
+ addPass(PM, llvm::createScalarReplAggregatesPass()); // Break up aggregate allocas
+ addPass(PM, llvm::createInstructionCombiningPass()); // Combine silly seq's
+ addPass(PM, llvm::createCondPropagationPass()); // Propagate conditionals
+
+
+ addPass(PM, llvm::createTailCallEliminationPass()); // Eliminate tail calls
+ addPass(PM, llvm::createCFGSimplificationPass()); // Merge & remove BBs
+ addPass(PM, llvm::createReassociatePass()); // Reassociate expressions
+ addPass(PM, llvm::createLoopRotatePass());
+ addPass(PM, llvm::createLICMPass()); // Hoist loop invariants
+ addPass(PM, llvm::createLoopUnswitchPass()); // Unswitch loops.
+ addPass(PM, llvm::createInstructionCombiningPass()); // Clean up after LICM/reassoc
+ addPass(PM, llvm::createIndVarSimplifyPass()); // Canonicalize indvars
+ addPass(PM, llvm::createLoopUnrollPass()); // Unroll small loops
+ addPass(PM, llvm::createInstructionCombiningPass()); // Clean up after the unroller
+ //addPass(PM, mvm::createArrayChecksPass());
+ addPass(PM, llvm::createGVNPass()); // GVN for load instructions
+ addPass(PM, llvm::createGCSEPass()); // Remove common subexprs
+ addPass(PM, llvm::createSCCPPass()); // Constant prop with SCCP
+ addPass(PM, llvm::createPredicateSimplifierPass());
+
+
+ // Run instcombine after redundancy elimination to exploit opportunities
+ // opened up by them.
+ addPass(PM, llvm::createInstructionCombiningPass());
+ addPass(PM, llvm::createCondPropagationPass()); // Propagate conditionals
+
+ addPass(PM, llvm::createDeadStoreEliminationPass()); // Delete dead stores
+ addPass(PM, llvm::createAggressiveDCEPass()); // SSA based 'Aggressive DCE'
+ addPass(PM, llvm::createCFGSimplificationPass()); // Merge & remove BBs
+ addPass(PM, mvm::createLowerArrayLengthPass());
+}
+
diff --git a/vmkit/lib/JnJVM/VMCore/JavaJITOpcodes.cpp b/vmkit/lib/JnJVM/VMCore/JavaJITOpcodes.cpp
new file mode 100644
index 0000000..9d890d2
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaJITOpcodes.cpp
@@ -0,0 +1,2325 @@
+//===---- JavaJITOpcodes.cpp - Reads and compiles opcodes -----------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG 0
+#define JNJVM_COMPILE 0
+#define JNJVM_EXECUTE 0
+
+#include <string.h>
+
+#include <llvm/Type.h>
+#include <llvm/Module.h>
+#include <llvm/Constants.h>
+#include <llvm/Type.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Assembly/PrintModulePass.h>
+#include <llvm/Target/TargetOptions.h>
+#include <llvm/CodeGen/MachineCodeEmitter.h>
+#include <llvm/CodeGen/MachineBasicBlock.h>
+
+#include <llvm/Transforms/IPO.h>
+
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+
+#include "debug.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaObject.h"
+#include "JavaJIT.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+#include "Reader.h"
+
+#include "OpcodeNames.def"
+
+#include <iostream>
+
+
+
+using namespace jnjvm;
+using namespace llvm;
+
+
+static inline sint8 readS1(uint8* bytecode, uint32& i) {
+ return ((sint8*)bytecode)[++i];
+}
+
+static inline uint8 readU1(uint8* bytecode, uint32& i) {
+ return bytecode[++i];
+}
+
+static inline sint16 readS2(uint8* bytecode, uint32& i) {
+ sint16 val = readS1(bytecode, i) << 8;
+ return val | readU1(bytecode, i);
+}
+
+static inline uint16 readU2(uint8* bytecode, uint32& i) {
+ uint16 val = readU1(bytecode, i) << 8;
+ return val | readU1(bytecode, i);
+}
+
+static inline sint32 readS4(uint8* bytecode, uint32& i) {
+ sint32 val = readU2(bytecode, i) << 16;
+ return val | readU2(bytecode, i);
+}
+
+
+static inline uint32 readU4(uint8* bytecode, uint32& i) {
+ return readS4(bytecode, i);
+}
+
+uint32 JavaJIT::WREAD_U1(uint8* array, bool init, uint32 &i) {
+ if (wide) {
+ wide = init;
+ return readU2(array, i);
+ } else {
+ return readU1(array, i);
+ }
+}
+
+sint32 JavaJIT::WREAD_S1(uint8* array, bool init, uint32 &i) {
+ if (wide) {
+ wide = init;
+ return readS2(array, i);
+ } else {
+ return readS1(array, i);
+ }
+}
+
+uint32 JavaJIT::WCALC(uint32 n) {
+ if (wide) {
+ wide = false;
+ return n << 1;
+ } else {
+ return n;
+ }
+}
+
+void convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock, bool usign) {
+ const Type* t2 = val->getType();
+ if (t1 != t2) {
+ if (t1->isInteger() && t2->isInteger()) {
+ if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) {
+ if (usign) {
+ val = new ZExtInst(val, t1, "", currentBlock);
+ } else {
+ val = new SExtInst(val, t1, "", currentBlock);
+ }
+ } else {
+ val = new TruncInst(val, t1, "", currentBlock);
+ }
+ } else if (t1->isFloatingPoint() && t2->isFloatingPoint()) {
+ if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) {
+ val = new FPExtInst(val, t1, "", currentBlock);
+ } else {
+ val = new FPTruncInst(val, t1, "", currentBlock);
+ }
+ } else if (isa<PointerType>(t1) && isa<PointerType>(t2)) {
+ val = new BitCastInst(val, t1, "", currentBlock);
+ }
+ }
+}
+
+void JavaJIT::compileOpcodes(uint8* bytecodes, uint32 codeLength) {
+ uint32 jsrIndex = 0;
+ for(uint32 i = 0; i < codeLength; ++i) {
+
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i,
+ bytecodes[i]);
+ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "compiling ");
+ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_CYAN, OpcodeNames[bytecodes[i]]);
+ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "\n");
+
+ Opinfo* opinfo = &(opcodeInfos[i]);
+ if (opinfo->newBlock) {
+ if (currentBlock->getTerminator() == 0) {
+ branch(opinfo->newBlock, currentBlock);
+ }
+ setCurrentBlock(opinfo->newBlock);
+ }
+ currentExceptionBlock = opinfo->exceptionBlock;
+ if (currentBlock->getTerminator() != 0) { // To prevent a gcj bug with useless goto
+ currentBlock = createBasicBlock("gcj bug");
+ }
+#if JNJVM_EXECUTE > 1
+ {
+ std::vector<llvm::Value*> args;
+ mvm::jit::protectConstants();//->lock();
+ args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]]));
+ args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)i));
+ args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
+ mvm::jit::unprotectConstants();//->unlock();
+ new CallInst(printExecutionLLVM, args.begin(), args.end(), "", currentBlock);
+ }
+#endif
+
+ if (opinfo->reqSuppl) {
+ push(new LoadInst(supplLocal, "", currentBlock), AssessorDesc::dRef);
+ }
+
+ switch (bytecodes[i]) {
+
+ case ACONST_NULL :
+ push(constantJavaObjectNull, AssessorDesc::dRef);
+ break;
+
+ case ICONST_M1 :
+ push(mvm::jit::constantMinusOne, AssessorDesc::dInt);
+ break;
+
+ case ICONST_0 :
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case ICONST_1 :
+ push(mvm::jit::constantOne, AssessorDesc::dInt);
+ break;
+
+ case ICONST_2 :
+ push(mvm::jit::constantTwo, AssessorDesc::dInt);
+ break;
+
+ case ICONST_3 :
+ push(mvm::jit::constantThree, AssessorDesc::dInt);
+ break;
+
+ case ICONST_4 :
+ push(mvm::jit::constantFour, AssessorDesc::dInt);
+ break;
+
+ case ICONST_5 :
+ push(mvm::jit::constantFive, AssessorDesc::dInt);
+ break;
+
+ case LCONST_0 :
+ push(mvm::jit::constantLongZero, AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case LCONST_1 :
+ push(mvm::jit::constantLongOne, AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case FCONST_0 :
+ push(mvm::jit::constantFloatZero, AssessorDesc::dFloat);
+ break;
+
+ case FCONST_1 :
+ push(mvm::jit::constantFloatOne, AssessorDesc::dFloat);
+ break;
+
+ case FCONST_2 :
+ push(mvm::jit::constantFloatTwo, AssessorDesc::dFloat);
+ break;
+
+ case DCONST_0 :
+ push(mvm::jit::constantDoubleZero, AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case DCONST_1 :
+ push(mvm::jit::constantDoubleOne, AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case BIPUSH :
+ mvm::jit::protectConstants();//->lock();
+ push(ConstantExpr::getSExt(ConstantInt::get(Type::Int8Ty,
+ bytecodes[++i]),
+ Type::Int32Ty), AssessorDesc::dInt);
+ mvm::jit::unprotectConstants();//->unlock();
+ break;
+
+ case SIPUSH :
+ mvm::jit::protectConstants();//->lock();
+ push(ConstantExpr::getSExt(ConstantInt::get(Type::Int16Ty,
+ readS2(bytecodes, i)),
+ Type::Int32Ty), AssessorDesc::dInt);
+ mvm::jit::unprotectConstants();//->unlock();
+ break;
+
+ case LDC :
+ _ldc(bytecodes[++i]);
+ break;
+
+ case LDC_W :
+ _ldc(readS2(bytecodes, i));
+ break;
+
+ case LDC2_W :
+ _ldc(readS2(bytecodes, i));
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case ILOAD :
+ push(new LoadInst(intLocals[WREAD_U1(bytecodes, false, i)], "",
+ currentBlock), AssessorDesc::dInt);
+ break;
+
+ case LLOAD :
+ push(new LoadInst(longLocals[WREAD_U1(bytecodes, false, i)], "",
+ currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case FLOAD :
+ push(new LoadInst(floatLocals[WREAD_U1(bytecodes, false, i)], "",
+ currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case DLOAD :
+ push(new LoadInst(doubleLocals[WREAD_U1(bytecodes, false, i)], "",
+ currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case ALOAD :
+ push(new LoadInst(objectLocals[WREAD_U1(bytecodes, false, i)], "",
+ currentBlock), AssessorDesc::dRef);
+ break;
+
+ case ILOAD_0 :
+ push(new LoadInst(intLocals[0], "", currentBlock), AssessorDesc::dInt);
+ break;
+
+ case ILOAD_1 :
+ push(new LoadInst(intLocals[1], "", currentBlock), AssessorDesc::dInt);
+ break;
+
+ case ILOAD_2 :
+ push(new LoadInst(intLocals[2], "", currentBlock), AssessorDesc::dInt);
+ break;
+
+ case ILOAD_3 :
+ push(new LoadInst(intLocals[3], "", currentBlock), AssessorDesc::dInt);
+ break;
+
+ case LLOAD_0 :
+ push(new LoadInst(longLocals[0], "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case LLOAD_1 :
+ push(new LoadInst(longLocals[1], "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case LLOAD_2 :
+ push(new LoadInst(longLocals[2], "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case LLOAD_3 :
+ push(new LoadInst(longLocals[3], "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case FLOAD_0 :
+ push(new LoadInst(floatLocals[0], "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case FLOAD_1 :
+ push(new LoadInst(floatLocals[1], "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case FLOAD_2 :
+ push(new LoadInst(floatLocals[2], "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case FLOAD_3 :
+ push(new LoadInst(floatLocals[3], "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case DLOAD_0 :
+ push(new LoadInst(doubleLocals[0], "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case DLOAD_1 :
+ push(new LoadInst(doubleLocals[1], "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case DLOAD_2 :
+ push(new LoadInst(doubleLocals[2], "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case DLOAD_3 :
+ push(new LoadInst(doubleLocals[3], "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case ALOAD_0 :
+ push(new LoadInst(objectLocals[0], "", currentBlock), AssessorDesc::dRef);
+ break;
+
+ case ALOAD_1 :
+ push(new LoadInst(objectLocals[1], "", currentBlock), AssessorDesc::dRef);
+ break;
+
+ case ALOAD_2 :
+ push(new LoadInst(objectLocals[2], "", currentBlock), AssessorDesc::dRef);
+ break;
+
+ case ALOAD_3 :
+ push(new LoadInst(objectLocals[3], "", currentBlock), AssessorDesc::dRef);
+ break;
+
+ case IALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType);
+ push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayLong::llvmType);
+ push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayFloat::llvmType);
+ push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dFloat);
+ break;
+ }
+
+ case DALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayDouble::llvmType);
+ push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case AALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayObject::llvmType);
+ push(new LoadInst(ptr, "", currentBlock), AssessorDesc::dRef);
+ break;
+ }
+
+ case BALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArraySInt8::llvmType);
+ Value* val = new LoadInst(ptr, "", currentBlock);
+ push(new SExtInst(val, Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case CALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt16::llvmType);
+ Value* val = new LoadInst(ptr, "", currentBlock);
+ push(new ZExtInst(val, Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case SALOAD : {
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArraySInt16::llvmType);
+ Value* val = new LoadInst(ptr, "", currentBlock);
+ push(new SExtInst(val, Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case ISTORE : {
+ Value* val = popAsInt();
+ new StoreInst(val, intLocals[WREAD_U1(bytecodes, false, i)], false,
+ currentBlock);
+ break;
+ }
+
+ case LSTORE :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), longLocals[WREAD_U1(bytecodes, false, i)], false,
+ currentBlock);
+ break;
+
+ case FSTORE :
+ new StoreInst(pop(), floatLocals[WREAD_U1(bytecodes, false, i)], false,
+ currentBlock);
+ break;
+
+ case DSTORE :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), doubleLocals[WREAD_U1(bytecodes, false, i)], false,
+ currentBlock);
+ break;
+
+ case ASTORE :
+ new StoreInst(pop(), objectLocals[WREAD_U1(bytecodes, false, i)], false,
+ currentBlock);
+ break;
+
+ case ISTORE_0 : {
+ Value* val = pop();
+ if (val->getType() != Type::Int32Ty) // int8 and int16
+ val = new ZExtInst(val, Type::Int32Ty, "", currentBlock);
+ new StoreInst(val, intLocals[0], false, currentBlock);
+ break;
+ }
+
+ case ISTORE_1 : {
+ Value* val = pop();
+ if (val->getType() != Type::Int32Ty) // int8 and int16
+ val = new ZExtInst(val, Type::Int32Ty, "", currentBlock);
+ new StoreInst(val, intLocals[1], false, currentBlock);
+ break;
+ }
+
+ case ISTORE_2 : {
+ Value* val = pop();
+ if (val->getType() != Type::Int32Ty) // int8 and int16
+ val = new ZExtInst(val, Type::Int32Ty, "", currentBlock);
+ new StoreInst(val, intLocals[2], false, currentBlock);
+ break;
+ }
+
+ case ISTORE_3 : {
+ Value* val = pop();
+ if (val->getType() != Type::Int32Ty) // int8 and int16
+ val = new ZExtInst(val, Type::Int32Ty, "", currentBlock);
+ new StoreInst(val, intLocals[3], false, currentBlock);
+ break;
+ }
+
+ case LSTORE_0 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), longLocals[0], false, currentBlock);
+ break;
+
+ case LSTORE_1 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), longLocals[1], false, currentBlock);
+ break;
+
+ case LSTORE_2 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), longLocals[2], false, currentBlock);
+ break;
+
+ case LSTORE_3 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), longLocals[3], false, currentBlock);
+ break;
+
+ case FSTORE_0 :
+ new StoreInst(pop(), floatLocals[0], false, currentBlock);
+ break;
+
+ case FSTORE_1 :
+ new StoreInst(pop(), floatLocals[1], false, currentBlock);
+ break;
+
+ case FSTORE_2 :
+ new StoreInst(pop(), floatLocals[2], false, currentBlock);
+ break;
+
+ case FSTORE_3 :
+ new StoreInst(pop(), floatLocals[3], false, currentBlock);
+ break;
+
+ case DSTORE_0 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), doubleLocals[0], false, currentBlock);
+ break;
+
+ case DSTORE_1 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), doubleLocals[1], false, currentBlock);
+ break;
+
+ case DSTORE_2 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), doubleLocals[2], false, currentBlock);
+ break;
+
+ case DSTORE_3 :
+ pop(); // remove the 0 on the stack
+ new StoreInst(pop(), doubleLocals[3], false, currentBlock);
+ break;
+
+ case ASTORE_0 :
+ new StoreInst(pop(), objectLocals[0], false, currentBlock);
+ break;
+
+ case ASTORE_1 :
+ new StoreInst(pop(), objectLocals[1], false, currentBlock);
+ break;
+
+ case ASTORE_2 :
+ new StoreInst(pop(), objectLocals[2], false, currentBlock);
+ break;
+
+ case ASTORE_3 :
+ new StoreInst(pop(), objectLocals[3], false, currentBlock);
+ break;
+
+ case IASTORE : {
+ Value* val = popAsInt();
+ Value* index = popAsInt();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case LASTORE : {
+ pop(); // remove the 0 on stack
+ Value* val = pop();
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayLong::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case FASTORE : {
+ Value* val = pop();
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayFloat::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case DASTORE : {
+ pop(); // remove the 0 on stack
+ Value* val = pop();
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayDouble::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case AASTORE : {
+ Value* val = pop();
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayObject::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case BASTORE : {
+ Value* val = pop();
+ if (val->getType() != Type::Int8Ty) {
+ val = new TruncInst(val, Type::Int8Ty, "", currentBlock);
+ }
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArraySInt8::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case CASTORE : {
+ const AssessorDesc* ass = topFunc();
+ Value* val = pop();
+ if (ass == AssessorDesc::dInt) {
+ val = new TruncInst(val, Type::Int16Ty, "", currentBlock);
+ } else if (ass == AssessorDesc::dByte || ass == AssessorDesc::dBool) {
+ val = new ZExtInst(val, Type::Int16Ty, "", currentBlock);
+ }
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt16::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case SASTORE : {
+ const AssessorDesc* ass = topFunc();
+ Value* val = pop();
+ if (ass == AssessorDesc::dInt) {
+ val = new TruncInst(val, Type::Int16Ty, "", currentBlock);
+ } else if (ass == AssessorDesc::dByte || ass == AssessorDesc::dBool) {
+ val = new SExtInst(val, Type::Int16Ty, "", currentBlock);
+ }
+ Value* index = pop();
+ Value* obj = pop();
+ Value* ptr = verifyAndComputePtr(obj, index, ArraySInt16::llvmType);
+ new StoreInst(val, ptr, false, currentBlock);
+ break;
+ }
+
+ case POP :
+ pop();
+ break;
+
+ case POP2 :
+ pop(); pop();
+ break;
+
+ case DUP :
+ push(top(), topFunc());
+ break;
+
+ case DUP_X1 : {
+ std::pair<Value*, const AssessorDesc*> one = popPair();
+ std::pair<Value*, const AssessorDesc*> two = popPair();
+ push(one);
+ push(two);
+ push(one);
+ break;
+ }
+
+ case DUP_X2 : {
+ std::pair<Value*, const AssessorDesc*> one = popPair();
+ std::pair<Value*, const AssessorDesc*> two = popPair();
+ std::pair<Value*, const AssessorDesc*> three = popPair();
+ push(one);
+ push(three);
+ push(two);
+ push(one);
+ break;
+ }
+
+ case DUP2 :
+ push(stack[stackSize() - 2]);
+ push(stack[stackSize() - 2]);
+ break;
+
+ case DUP2_X1 : {
+ std::pair<Value*, const AssessorDesc*> one = popPair();
+ std::pair<Value*, const AssessorDesc*> two = popPair();
+ std::pair<Value*, const AssessorDesc*> three = popPair();
+
+ push(two);
+ push(one);
+
+ push(three);
+ push(two);
+ push(one);
+
+ break;
+ }
+
+ case DUP2_X2 : {
+ std::pair<Value*, const AssessorDesc*> one = popPair();
+ std::pair<Value*, const AssessorDesc*> two = popPair();
+ std::pair<Value*, const AssessorDesc*> three = popPair();
+ std::pair<Value*, const AssessorDesc*> four = popPair();
+
+ push(two);
+ push(one);
+
+ push(four);
+ push(three);
+ push(two);
+ push(one);
+
+ break;
+ }
+
+ case SWAP : {
+ std::pair<Value*, const AssessorDesc*> one = popPair();
+ std::pair<Value*, const AssessorDesc*> two = popPair();
+ push(one);
+ push(two);
+ break;
+ }
+
+ case IADD : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LADD : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FADD : {
+ Value* val2 = pop();
+ Value* val1 = pop();
+ push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dFloat);
+ break;
+ }
+
+ case DADD : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createAdd(val1, val2, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case ISUB : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+ case LSUB : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FSUB : {
+ Value* val2 = pop();
+ Value* val1 = pop();
+ push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dFloat);
+ break;
+ }
+
+ case DSUB : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createSub(val1, val2, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IMUL : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LMUL : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FMUL : {
+ Value* val2 = pop();
+ Value* val1 = pop();
+ push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dFloat);
+ break;
+ }
+
+ case DMUL : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createMul(val1, val2, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IDIV : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createSDiv(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LDIV : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createSDiv(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FDIV : {
+ Value* val2 = pop();
+ Value* val1 = pop();
+ push(BinaryOperator::createFDiv(val1, val2, "", currentBlock), AssessorDesc::dFloat);
+ break;
+ }
+
+ case DDIV : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createFDiv(val1, val2, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IREM : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createSRem(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LREM : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createSRem(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FREM : {
+ Value* val2 = pop();
+ Value* val1 = pop();
+ push(BinaryOperator::createFRem(val1, val2, "", currentBlock), AssessorDesc::dFloat);
+ break;
+ }
+
+ case DREM : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+ push(BinaryOperator::createFRem(val1, val2, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case INEG :
+ push(BinaryOperator::createSub(
+ mvm::jit::constantZero,
+ popAsInt(), "", currentBlock), AssessorDesc::dInt);
+ break;
+
+ case LNEG : {
+ pop();
+ push(BinaryOperator::createSub(
+ mvm::jit::constantLongZero,
+ pop(), "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case FNEG :
+ push(BinaryOperator::createSub(
+ mvm::jit::constantFloatMinusZero,
+ pop(), "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case DNEG : {
+ pop();
+ push(BinaryOperator::createSub(
+ mvm::jit::constantDoubleMinusZero,
+ pop(), "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case ISHL : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createShl(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LSHL : {
+ Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock);
+ pop(); // remove the 0 on the stack
+ Value* val1 = pop();
+ push(BinaryOperator::createShl(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case ISHR : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createAShr(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LSHR : {
+ Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock);
+ pop(); // remove the 0 on the stack
+ Value* val1 = pop();
+ push(BinaryOperator::createAShr(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IUSHR : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createLShr(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LUSHR : {
+ Value* val2 = new ZExtInst(pop(), Type::Int64Ty, "", currentBlock);
+ pop(); // remove the 0 on the stack
+ Value* val1 = pop();
+ push(BinaryOperator::createLShr(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IAND : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createAnd(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LAND : {
+ pop();
+ Value* val2 = pop();
+ pop(); // remove the 0 on the stack
+ Value* val1 = pop();
+ push(BinaryOperator::createAnd(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IOR : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createOr(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LOR : {
+ pop();
+ Value* val2 = pop();
+ pop(); // remove the 0 on the stack
+ Value* val1 = pop();
+ push(BinaryOperator::createOr(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IXOR : {
+ Value* val2 = popAsInt();
+ Value* val1 = popAsInt();
+ push(BinaryOperator::createXor(val1, val2, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LXOR : {
+ pop();
+ Value* val2 = pop();
+ pop(); // remove the 0 on the stack
+ Value* val1 = pop();
+ push(BinaryOperator::createXor(val1, val2, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case IINC : {
+ uint16 idx = WREAD_U1(bytecodes, true, i);
+ sint16 val = WREAD_S1(bytecodes, false, i);
+ mvm::jit::protectConstants();//->lock();
+ llvm::Value* add = BinaryOperator::createAdd(
+ new LoadInst(intLocals[idx], "", currentBlock),
+ ConstantInt::get(Type::Int32Ty, val), "",
+ currentBlock);
+ mvm::jit::unprotectConstants();//->unlock();
+ new StoreInst(add, intLocals[idx], false, currentBlock);
+ break;
+ }
+
+ case I2L :
+ push(new SExtInst(pop(), llvm::Type::Int64Ty, "", currentBlock), AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case I2F :
+ push(new SIToFPInst(pop(), llvm::Type::FloatTy, "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case I2D :
+ push(new SIToFPInst(pop(), llvm::Type::DoubleTy, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case L2I :
+ pop();
+ push(new TruncInst(pop(), llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+
+ case L2F :
+ pop();
+ push(new SIToFPInst(pop(), llvm::Type::FloatTy, "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case L2D :
+ pop();
+ push(new SIToFPInst(pop(), llvm::Type::DoubleTy, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case F2I : {
+ llvm::Value* val = pop();
+ llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "",
+ currentBlock);
+
+ BasicBlock* res = createBasicBlock("F2I");
+ PHINode* node = new PHINode(llvm::Type::Int32Ty, "", res);
+ node->addIncoming(mvm::jit::constantZero, currentBlock);
+ BasicBlock* cont = createBasicBlock("F2I");
+
+ new BranchInst(res, cont, test, currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OGE, val,
+ mvm::jit::constantMaxIntFloat,
+ "", currentBlock);
+
+ cont = createBasicBlock("F2I");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMaxInt,
+ currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OLE, val,
+ mvm::jit::constantMinIntFloat,
+ "", currentBlock);
+
+ cont = createBasicBlock("F2I");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMinInt, currentBlock);
+
+ currentBlock = cont;
+ llvm::Value* newVal = new FPToSIInst(val, Type::Int32Ty, "",
+ currentBlock);
+ new BranchInst(res, currentBlock);
+
+ node->addIncoming(newVal, currentBlock);
+
+ currentBlock = res;
+
+ push(node, AssessorDesc::dInt);
+ break;
+ }
+
+ case F2L : {
+ llvm::Value* val = pop();
+ llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "",
+ currentBlock);
+
+ BasicBlock* res = createBasicBlock("F2L");
+ PHINode* node = new PHINode(llvm::Type::Int64Ty, "", res);
+ node->addIncoming(mvm::jit::constantLongZero, currentBlock);
+ BasicBlock* cont = createBasicBlock("F2L");
+
+ new BranchInst(res, cont, test, currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OGE, val,
+ mvm::jit::constantMaxLongFloat,
+ "", currentBlock);
+
+ cont = createBasicBlock("F2L");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMaxLong, currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OLE, val,
+ mvm::jit::constantMinLongFloat, "", currentBlock);
+
+ cont = createBasicBlock("F2L");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMinLong, currentBlock);
+
+ currentBlock = cont;
+ llvm::Value* newVal = new FPToSIInst(val, Type::Int64Ty, "",
+ currentBlock);
+ new BranchInst(res, currentBlock);
+
+ node->addIncoming(newVal, currentBlock);
+
+ currentBlock = res;
+
+ push(node, AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case F2D :
+ push(new FPExtInst(pop(), llvm::Type::DoubleTy, "", currentBlock), AssessorDesc::dDouble);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+
+ case D2I : {
+ pop(); // remove the 0 on the stack
+ llvm::Value* val = pop();
+ llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "",
+ currentBlock);
+
+ BasicBlock* res = createBasicBlock("D2I");
+ PHINode* node = new PHINode(llvm::Type::Int32Ty, "", res);
+ node->addIncoming(mvm::jit::constantZero, currentBlock);
+ BasicBlock* cont = createBasicBlock("D2I");
+
+ new BranchInst(res, cont, test, currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OGE, val, mvm::jit::constantMaxIntDouble,
+ "", currentBlock);
+
+ cont = createBasicBlock("D2I");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMaxInt, currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OLE, val, mvm::jit::constantMinIntDouble,
+ "", currentBlock);
+
+ cont = createBasicBlock("D2I");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMinInt, currentBlock);
+
+ currentBlock = cont;
+ llvm::Value* newVal = new FPToSIInst(val, Type::Int32Ty, "",
+ currentBlock);
+ new BranchInst(res, currentBlock);
+
+ node->addIncoming(newVal, currentBlock);
+
+ currentBlock = res;
+
+ push(node, AssessorDesc::dInt);
+
+ break;
+ }
+
+ case D2L : {
+ pop(); // remove the 0 on the stack
+ llvm::Value* val = pop();
+ llvm::Value* test = new FCmpInst(FCmpInst::FCMP_ONE, val, val, "",
+ currentBlock);
+
+ BasicBlock* res = createBasicBlock("D2L");
+ PHINode* node = new PHINode(llvm::Type::Int64Ty, "", res);
+ node->addIncoming(mvm::jit::constantLongZero, currentBlock);
+ BasicBlock* cont = createBasicBlock("D2L");
+
+ new BranchInst(res, cont, test, currentBlock);
+
+ currentBlock = cont;
+
+ test = new FCmpInst(FCmpInst::FCMP_OGE, val, mvm::jit::constantMaxLongDouble,
+ "", currentBlock);
+
+ cont = createBasicBlock("D2L");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMaxLong, currentBlock);
+
+ currentBlock = cont;
+
+ test =
+ new FCmpInst(FCmpInst::FCMP_OLE, val, mvm::jit::constantMinLongDouble,
+ "", currentBlock);
+
+ cont = createBasicBlock("D2L");
+
+ new BranchInst(res, cont, test, currentBlock);
+ node->addIncoming(mvm::jit::constantMinLong, currentBlock);
+
+ currentBlock = cont;
+ llvm::Value* newVal = new FPToSIInst(val, Type::Int64Ty, "",
+ currentBlock);
+ new BranchInst(res, currentBlock);
+
+ node->addIncoming(newVal, currentBlock);
+
+ currentBlock = res;
+
+ push(node, AssessorDesc::dLong);
+ push(mvm::jit::constantZero, AssessorDesc::dInt);
+ break;
+ }
+
+ case D2F :
+ pop(); // remove the 0 on the stack
+ push(new FPTruncInst(pop(), llvm::Type::FloatTy, "", currentBlock), AssessorDesc::dFloat);
+ break;
+
+ case I2B : {
+ Value* val = pop();
+ if (val->getType() == Type::Int32Ty) {
+ val = new TruncInst(val, llvm::Type::Int8Ty, "", currentBlock);
+ }
+ push(new SExtInst(val, llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case I2C : {
+ Value* val = pop();
+ if (val->getType() == Type::Int32Ty) {
+ val = new TruncInst(val, llvm::Type::Int16Ty, "", currentBlock);
+ }
+ push(new ZExtInst(val, llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case I2S : {
+ Value* val = pop();
+ if (val->getType() == Type::Int32Ty) {
+ val = new TruncInst(val, llvm::Type::Int16Ty, "", currentBlock);
+ }
+ push(new SExtInst(val, llvm::Type::Int32Ty, "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case LCMP : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "",
+ currentBlock);
+
+ BasicBlock* cont = createBasicBlock("LCMP");
+ BasicBlock* res = createBasicBlock("LCMP");
+ PHINode* node = new PHINode(llvm::Type::Int32Ty, "", res);
+ node->addIncoming(mvm::jit::constantZero, currentBlock);
+
+ new BranchInst(res, cont, test, currentBlock);
+ currentBlock = cont;
+
+ test = new ICmpInst(ICmpInst::ICMP_SLT, val1, val2, "", currentBlock);
+ node->addIncoming(mvm::jit::constantMinusOne, currentBlock);
+
+ cont = createBasicBlock("LCMP");
+ new BranchInst(res, cont, test, currentBlock);
+ currentBlock = cont;
+ node->addIncoming(mvm::jit::constantOne, currentBlock);
+ new BranchInst(res, currentBlock);
+ currentBlock = res;
+
+ push(node, AssessorDesc::dInt);
+ break;
+ }
+
+ case FCMPL : {
+ llvm::Value* val2 = pop();
+ llvm::Value* val1 = pop();
+ compareFP(val1, val2, Type::FloatTy, false);
+ break;
+ }
+
+ case FCMPG : {
+ llvm::Value* val2 = pop();
+ llvm::Value* val1 = pop();
+ compareFP(val1, val2, Type::FloatTy, true);
+ break;
+ }
+
+ case DCMPL : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+
+ compareFP(val1, val2, Type::DoubleTy, false);
+ break;
+ }
+
+ case DCMPG : {
+ pop();
+ llvm::Value* val2 = pop();
+ pop();
+ llvm::Value* val1 = pop();
+
+ compareFP(val1, val2, Type::DoubleTy, false);
+ break;
+ }
+
+ case IFEQ : {
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* val = ass->llvmNullConstant;
+ Value* op = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, op, val, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFEQ");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IFNE : {
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* val = ass->llvmNullConstant;
+ Value* op = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, op, val, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFNE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IFLT : {
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* val = ass->llvmNullConstant;
+ Value* op = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLT, op, val, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFLT");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IFGE : {
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* val = ass->llvmNullConstant;
+ Value* op = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGE, op, val, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFGE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IFGT : {
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* val = ass->llvmNullConstant;
+ Value* op = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGT, op, val, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFGT");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IFLE : {
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* val = ass->llvmNullConstant;
+ Value* op = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLE, op, val, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFLE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ICMPEQ : {
+ Value *val2 = popAsInt();
+ Value *val1 = popAsInt();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ICMPEQ");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ICMPNE : {
+ Value *val2 = popAsInt();
+ Value *val1 = popAsInt();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ICMPNE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ICMPLT : {
+ Value *val2 = popAsInt();
+ Value *val1 = popAsInt();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLT, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_IFCMPLT");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ICMPGE : {
+ Value *val2 = popAsInt();
+ Value *val1 = popAsInt();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGE, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ICMPGE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ICMPGT : {
+ Value *val2 = popAsInt();
+ Value *val1 = popAsInt();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SGT, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ICMPGT");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ICMPLE : {
+ Value *val2 = popAsInt();
+ Value *val1 = popAsInt();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_SLE, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ICMPLE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ACMPEQ : {
+ Value *val2 = pop();
+ Value *val1 = pop();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ACMPEQ");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IF_ACMPNE : {
+ Value *val2 = pop();
+ Value *val1 = pop();
+ uint32 tmp = i;
+ BasicBlock* ifTrue = opcodeInfos[tmp + readS2(bytecodes, i)].newBlock;
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val1, val2, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IF_ACMPNE");
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case GOTO : {
+ uint32 tmp = i;
+ branch(opcodeInfos[tmp + readS2(bytecodes, i)].newBlock,
+ currentBlock);
+ break;
+ }
+
+ case JSR : {
+ uint32 tmp = i;
+ mvm::jit::protectConstants();//->lock();
+ Value* expr = ConstantExpr::getIntToPtr(
+ ConstantInt::get(Type::Int64Ty,
+ uint64_t (jsrIndex++)),
+ JavaObject::llvmType);
+ mvm::jit::unprotectConstants();//->unlock();
+
+ new StoreInst(expr, supplLocal, false, currentBlock);
+ new BranchInst(opcodeInfos[tmp + readS2(bytecodes, i)].newBlock,
+ currentBlock);
+ break;
+ }
+
+ case RET : {
+ uint8 local = readU1(bytecodes, i);
+ Value* _val = new LoadInst(objectLocals[local], "", currentBlock);
+ Value* val = new PtrToIntInst(_val, Type::Int32Ty, "", currentBlock);
+ SwitchInst* inst = new SwitchInst(val, jsrs[0], jsrs.size(),
+ currentBlock);
+
+ uint32 index = 0;
+ mvm::jit::protectConstants();//->lock();
+ for (std::vector<BasicBlock*>::iterator i = jsrs.begin(),
+ e = jsrs.end(); i!= e; ++i, ++index) {
+ inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i);
+ }
+ mvm::jit::unprotectConstants();//->unlock();
+
+ break;
+ }
+
+ case TABLESWITCH : {
+ uint32 tmp = i;
+ uint32 reste = (i + 1) & 3;
+ uint32 filled = reste ? (4 - reste) : 0;
+ i += filled;
+ BasicBlock* def = opcodeInfos[tmp + readU4(bytecodes, i)].newBlock;
+
+ uint32 low = readU4(bytecodes, i);
+ uint32 high = readU4(bytecodes, i) + 1;
+
+ Value* index = pop();
+
+ const llvm::Type* type = index->getType();
+ mvm::jit::protectConstants();//->lock();
+ for (uint32 cur = low; cur < high; ++cur) {
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ,
+ ConstantInt::get(type, cur), index,
+ "", currentBlock);
+ BasicBlock* falseBlock = createBasicBlock("continue tableswitch");
+ branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock);
+ currentBlock = falseBlock;
+ }
+ mvm::jit::unprotectConstants();//->unlock();
+
+
+ //Value* cmp = new ICmpInst(ICmpInst::ICMP_SLT, index,
+ // ConstantInt::get(Type::Int32Ty, low), "",
+ // currentBlock);
+ branch(def, currentBlock);
+ i = tmp + 12 + filled + ((high - low) << 2);
+
+ break;
+ }
+
+ case LOOKUPSWITCH : {
+ uint32 tmp = i;
+ uint32 filled = (3 - i) & 3;
+ i += filled;
+ BasicBlock* def = opcodeInfos[tmp + readU4(bytecodes, i)].newBlock;
+ uint32 nbs = readU4(bytecodes, i);
+
+ const AssessorDesc* ass = topFunc();
+ Value* key = pop();
+ if (ass == AssessorDesc::dShort || ass == AssessorDesc::dByte) {
+ key = new SExtInst(key, Type::Int32Ty, "", currentBlock);
+ } else if (ass == AssessorDesc::dChar || ass == AssessorDesc::dBool) {
+ key = new ZExtInst(key, Type::Int32Ty, "", currentBlock);
+ }
+ mvm::jit::protectConstants();//->lock();
+ for (uint32 cur = 0; cur < nbs; ++cur) {
+ Value* val = ConstantInt::get(Type::Int32Ty, readU4(bytecodes, i));
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, val, key, "", currentBlock);
+ BasicBlock* falseBlock = createBasicBlock("continue lookupswitch");
+ branch(cmp, opcodeInfos[tmp + readU4(bytecodes, i)].newBlock, falseBlock, currentBlock);
+ currentBlock = falseBlock;
+ }
+ mvm::jit::unprotectConstants();//->unlock();
+ branch(def, currentBlock);
+ i = tmp + 8 + filled + (nbs << 3);
+ break;
+ }
+ case IRETURN : {
+ const AssessorDesc* ass = topFunc();
+ Value* val = pop();
+ assert(val->getType()->isInteger());
+ convertValue(val, returnType, currentBlock,
+ ass == AssessorDesc::dChar || ass == AssessorDesc::dBool);
+ endNode->addIncoming(val, currentBlock);
+ new BranchInst(endBlock, currentBlock);
+ break;
+ }
+ case LRETURN :
+ pop(); // remove the 0 on the stack
+ endNode->addIncoming(pop(), currentBlock);
+ new BranchInst(endBlock, currentBlock);
+ break;
+
+ case FRETURN :
+ endNode->addIncoming(pop(), currentBlock);
+ new BranchInst(endBlock, currentBlock);
+ break;
+
+ case DRETURN :
+ pop(); // remove the 0 on the stack
+ endNode->addIncoming(pop(), currentBlock);
+ new BranchInst(endBlock, currentBlock);
+ break;
+
+ case ARETURN :
+ endNode->addIncoming(pop(), currentBlock);
+ new BranchInst(endBlock, currentBlock);
+ break;
+
+ case RETURN :
+ new BranchInst(endBlock, currentBlock);
+ break;
+
+ case GETSTATIC : {
+ uint16 index = readU2(bytecodes, i);
+ getStaticField(index);
+ break;
+ }
+
+ case PUTSTATIC : {
+ uint16 index = readU2(bytecodes, i);
+ setStaticField(index);
+ break;
+ }
+
+ case GETFIELD : {
+ uint16 index = readU2(bytecodes, i);
+ getVirtualField(index);
+ break;
+ }
+
+ case PUTFIELD : {
+ uint16 index = readU2(bytecodes, i);
+ setVirtualField(index);
+ break;
+ }
+
+ case INVOKEVIRTUAL : {
+ uint16 index = readU2(bytecodes, i);
+ JavaCtpInfo* ctpInfo = compilingClass->ctpInfo;
+ CommonClass* cl = 0;
+ JavaMethod* meth = 0;
+ ctpInfo->infoOfMethod(index, ACC_VIRTUAL, cl, meth);
+ if ((cl && isFinal(cl->access)) || (meth && isFinal(meth->access)))
+ invokeSpecial(index);
+ else
+ invokeInterfaceOrVirtual(index);
+ break;
+ }
+
+ case INVOKESPECIAL : {
+ uint16 index = readU2(bytecodes, i);
+ invokeSpecial(index);
+ break;
+ }
+
+ case INVOKESTATIC : {
+ uint16 index = readU2(bytecodes, i);
+ invokeStatic(index);
+ break;
+ }
+
+ case INVOKEINTERFACE : {
+ uint16 index = readU2(bytecodes, i);
+ invokeInterfaceOrVirtual(index);
+ i += 2;
+ break;
+ }
+
+ case NEW : {
+ uint16 index = readU2(bytecodes, i);
+ invokeNew(index);
+ break;
+ }
+
+ case NEWARRAY : {
+
+ Jnjvm* vm = compilingClass->isolate;
+ uint8 id = bytecodes[++i];
+ ClassArray* cl = 0;
+ AssessorDesc* ass = 0;
+ Function* ctr = 0;
+ AssessorDesc::arrayType(vm, compilingClass->classLoader, id, cl, ass,
+ ctr);
+
+ llvm::Value* valCl = new LoadInst(cl->llvmVar(vm->module), "", currentBlock);
+ llvm::Value* arg1 = popAsInt();
+
+ push(invoke(ctr, arg1, valCl, "", currentBlock), AssessorDesc::dRef);
+ break;
+ }
+
+ case ANEWARRAY : {
+
+ Jnjvm* vm = compilingClass->isolate;
+ uint16 index = readU2(bytecodes, i);
+ const UTF8* className =
+ compilingClass->ctpInfo->resolveClassName(index);
+
+ const UTF8* arrayName =
+ AssessorDesc::constructArrayName(vm, 0, 1, className);
+
+ ClassArray* dcl =
+ vm->constructArray(arrayName, compilingClass->classLoader);
+
+
+ llvm::Value* valCl = new LoadInst(dcl->llvmVar(vm->module), "", currentBlock);
+ llvm::Value* arg1 = popAsInt();
+
+ push(invoke(ObjectAconsLLVM, arg1, valCl, "", currentBlock), AssessorDesc::dRef);
+ break;
+ }
+
+ case ARRAYLENGTH : {
+ Value* val = pop();
+ JITVerifyNull(val);
+ push(arraySize(val), AssessorDesc::dInt);
+ break;
+ }
+
+ case ATHROW : {
+ llvm::Value* arg = pop();
+ std::vector<Value*> args;
+ args.push_back(arg);
+ if (currentExceptionBlock != endExceptionBlock) {
+ new InvokeInst(throwExceptionLLVM, unifiedUnreachable, currentExceptionBlock, args.begin(), args.end(), "", currentBlock);
+ } else {
+ new CallInst(throwExceptionLLVM, args.begin(), args.end(), "", currentBlock);
+ new UnreachableInst(currentBlock);
+ }
+ break;
+ }
+
+ case CHECKCAST : {
+ uint16 index = readU2(bytecodes, i);
+ CommonClass* dcl =
+ compilingClass->ctpInfo->getMethodClassIfLoaded(index);
+
+ Value* obj = top();
+
+ Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj,
+ constantJavaObjectNull,
+ "", currentBlock);
+
+ BasicBlock* ifTrue = createBasicBlock("null checkcast");
+ BasicBlock* ifFalse = createBasicBlock("non null checkcast");
+
+ new BranchInst(ifTrue, ifFalse, cmp, currentBlock);
+ currentBlock = ifFalse;
+ Value* clVar = 0;
+ if (dcl && dcl->isReady()) {
+ clVar = new LoadInst(dcl->llvmVar(compilingClass->isolate->module), "", ifFalse);
+ } else {
+ clVar = getInitializedClass(index);
+ }
+ std::vector<Value*> args;
+ args.push_back(obj);
+ args.push_back(clVar);
+ Value* call = new CallInst(instanceOfLLVM, args.begin(), args.end(),
+ "", currentBlock);
+
+ cmp = new ICmpInst(ICmpInst::ICMP_EQ, call,
+ mvm::jit::constantZero, "", currentBlock);
+
+ BasicBlock* ex = createBasicBlock("false checkcast");
+ new BranchInst(ex, ifTrue, cmp, currentBlock);
+
+ std::vector<Value*> exArgs;
+ exArgs.push_back(obj);
+ exArgs.push_back(clVar);
+ if (currentExceptionBlock != endExceptionBlock) {
+ new InvokeInst(classCastExceptionLLVM, unifiedUnreachable, currentExceptionBlock, exArgs.begin(), exArgs.end(), "", ex);
+ } else {
+ new CallInst(classCastExceptionLLVM, exArgs.begin(), exArgs.end(), "", ex);
+ new UnreachableInst(ex);
+ }
+
+ currentBlock = ifTrue;
+ break;
+ }
+
+ case INSTANCEOF : {
+ uint16 index = readU2(bytecodes, i);
+ CommonClass* dcl =
+ compilingClass->ctpInfo->getMethodClassIfLoaded(index);
+
+ Value* clVar = 0;
+ if (dcl && dcl->isReady()) {
+ clVar = new LoadInst(dcl->llvmVar(compilingClass->isolate->module), "", currentBlock);
+ } else {
+ clVar = getInitializedClass(index);
+ }
+ std::vector<Value*> args;
+ args.push_back(pop());
+ args.push_back(clVar);
+ push(new CallInst(instanceOfLLVM, args.begin(), args.end(), "", currentBlock), AssessorDesc::dInt);
+ break;
+ }
+
+ case MONITORENTER : {
+ Value* obj = pop();
+ invoke(aquireObjectLLVM, obj, "", currentBlock);
+ break;
+ }
+
+ case MONITOREXIT : {
+ Value* obj = pop();
+ invoke(releaseObjectLLVM, obj, "", currentBlock);
+ break;
+ }
+
+ case MULTIANEWARRAY : {
+ Jnjvm* vm = compilingClass->isolate;
+ uint16 index = readU2(bytecodes, i);
+ uint8 dim = readU1(bytecodes, i);
+
+ const UTF8* className =
+ compilingClass->ctpInfo->resolveClassName(index);
+
+ ClassArray* dcl =
+ vm->constructArray(className, compilingClass->classLoader);
+
+ compilingClass->ctpInfo->loadClass(index);
+
+ Value* valCl = new LoadInst(dcl->llvmVar(vm->module), "", currentBlock);
+ Value* args[dim + 2];
+ args[0] = valCl;
+ mvm::jit::protectConstants();//->lock();
+ args[1] = ConstantInt::get(Type::Int32Ty, dim);
+ mvm::jit::unprotectConstants();//->unlock();
+
+ for (int cur = dim + 1; cur >= 2; --cur)
+ args[cur] = pop();
+
+ std::vector<Value*> Args;
+ for (sint32 v = 0; v < dim + 2; ++v) {
+ Args.push_back(args[v]);
+ }
+ push(invoke(multiCallNewLLVM, Args, "", currentBlock), AssessorDesc::dRef);
+ break;
+ }
+
+ case WIDE :
+ wide = true;
+ break;
+
+ case IFNULL : {
+ uint32 tmp = i;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* nil = ass->llvmNullConstant;
+ llvm::Value* val = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_EQ, val, nil, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("true IFNULL");
+ BasicBlock* ifTrue = opcodeInfos[readS2(bytecodes, i) + tmp].newBlock;
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ case IFNONNULL : {
+ uint32 tmp = i;
+ const AssessorDesc* ass = topFunc();
+ llvm::Value* nil = ass->llvmNullConstant;
+ llvm::Value* val = pop();
+ llvm::Value* test = new ICmpInst(ICmpInst::ICMP_NE, val, nil, "",
+ currentBlock);
+ BasicBlock* ifFalse = createBasicBlock("false IFNONNULL");
+ BasicBlock* ifTrue = opcodeInfos[readS2(bytecodes, i) + tmp].newBlock;
+ branch(test, ifTrue, ifFalse, currentBlock);
+ currentBlock = ifFalse;
+ break;
+ }
+
+ default :
+ JavaThread::get()->isolate->unknownError("unknown bytecode");
+
+ }
+ }
+}
+
+void JavaJIT::exploreOpcodes(uint8* bytecodes, uint32 codeLength) {
+ for(uint32 i = 0; i < codeLength; ++i) {
+
+ PRINT_DEBUG(JNJVM_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i,
+ bytecodes[i]);
+ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "exploring ");
+ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_CYAN, OpcodeNames[bytecodes[i]]);
+ PRINT_DEBUG(JNJVM_COMPILE, 1, LIGHT_BLUE, "\n");
+
+ switch (bytecodes[i]) {
+
+ case ACONST_NULL :
+ case ICONST_M1 :
+ case ICONST_0 :
+ case ICONST_1 :
+ case ICONST_2 :
+ case ICONST_3 :
+ case ICONST_4 :
+ case ICONST_5 :
+ case LCONST_0 :
+ case LCONST_1 :
+ case FCONST_0 :
+ case FCONST_1 :
+ case FCONST_2 :
+ case DCONST_0 :
+ case DCONST_1 : break;
+
+ case BIPUSH : ++i; break;
+
+ case SIPUSH : i += 2; break;
+
+ case LDC : ++i; break;
+
+ case LDC_W :
+ case LDC2_W : i += 2; break;
+
+ case ILOAD :
+ case LLOAD :
+ case FLOAD :
+ case DLOAD :
+ case ALOAD :
+ i += WCALC(1);
+ break;
+
+ case ILOAD_0 :
+ case ILOAD_1 :
+ case ILOAD_2 :
+ case ILOAD_3 :
+ case LLOAD_0 :
+ case LLOAD_1 :
+ case LLOAD_2 :
+ case LLOAD_3 :
+ case FLOAD_0 :
+ case FLOAD_1 :
+ case FLOAD_2 :
+ case FLOAD_3 :
+ case DLOAD_0 :
+ case DLOAD_1 :
+ case DLOAD_2 :
+ case DLOAD_3 :
+ case ALOAD_0 :
+ case ALOAD_1 :
+ case ALOAD_2 :
+ case ALOAD_3 :
+ case IALOAD :
+ case LALOAD :
+ case FALOAD :
+ case DALOAD :
+ case AALOAD :
+ case BALOAD :
+ case CALOAD :
+ case SALOAD : break;
+
+ case ISTORE :
+ case LSTORE :
+ case FSTORE :
+ case DSTORE :
+ case ASTORE :
+ i += WCALC(1);
+ break;
+
+ case ISTORE_0 :
+ case ISTORE_1 :
+ case ISTORE_2 :
+ case ISTORE_3 :
+ case LSTORE_0 :
+ case LSTORE_1 :
+ case LSTORE_2 :
+ case LSTORE_3 :
+ case FSTORE_0 :
+ case FSTORE_1 :
+ case FSTORE_2 :
+ case FSTORE_3 :
+ case DSTORE_0 :
+ case DSTORE_1 :
+ case DSTORE_2 :
+ case DSTORE_3 :
+ case ASTORE_0 :
+ case ASTORE_1 :
+ case ASTORE_2 :
+ case ASTORE_3 :
+ case IASTORE :
+ case LASTORE :
+ case FASTORE :
+ case DASTORE :
+ case AASTORE :
+ case BASTORE :
+ case CASTORE :
+ case SASTORE :
+ case POP :
+ case POP2 :
+ case DUP :
+ case DUP_X1 :
+ case DUP_X2 :
+ case DUP2 :
+ case DUP2_X1 :
+ case DUP2_X2 :
+ case SWAP :
+ case IADD :
+ case LADD :
+ case FADD :
+ case DADD :
+ case ISUB :
+ case LSUB :
+ case FSUB :
+ case DSUB :
+ case IMUL :
+ case LMUL :
+ case FMUL :
+ case DMUL :
+ case IDIV :
+ case LDIV :
+ case FDIV :
+ case DDIV :
+ case IREM :
+ case LREM :
+ case FREM :
+ case DREM :
+ case INEG :
+ case LNEG :
+ case FNEG :
+ case DNEG :
+ case ISHL :
+ case LSHL :
+ case ISHR :
+ case LSHR :
+ case IUSHR :
+ case LUSHR :
+ case IAND :
+ case LAND :
+ case IOR :
+ case LOR :
+ case IXOR :
+ case LXOR : break;
+
+ case IINC :
+ i += WCALC(2);
+ break;
+
+ case I2L :
+ case I2F :
+ case I2D :
+ case L2I :
+ case L2F :
+ case L2D :
+ case F2I :
+ case F2L :
+ case F2D :
+ case D2I :
+ case D2L :
+ case D2F :
+ case I2B :
+ case I2C :
+ case I2S :
+ case LCMP :
+ case FCMPL :
+ case FCMPG :
+ case DCMPL :
+ case DCMPG : break;
+
+ case IFEQ :
+ case IFNE :
+ case IFLT :
+ case IFGE :
+ case IFGT :
+ case IFLE :
+ case IF_ICMPEQ :
+ case IF_ICMPNE :
+ case IF_ICMPLT :
+ case IF_ICMPGE :
+ case IF_ICMPGT :
+ case IF_ICMPLE :
+ case IF_ACMPEQ :
+ case IF_ACMPNE :
+ case GOTO : {
+ uint32 tmp = i;
+ uint16 index = tmp + readU2(bytecodes, i);
+ if (!(opcodeInfos[index].newBlock))
+ opcodeInfos[index].newBlock = createBasicBlock("GOTO or IF*");
+ break;
+ }
+
+ case JSR : {
+ uint32 tmp = i;
+ uint16 index = tmp + readU2(bytecodes, i);
+ if (!(opcodeInfos[index].newBlock)) {
+ BasicBlock* block = createBasicBlock("JSR");
+ opcodeInfos[index].newBlock = block;
+ }
+ if (!(opcodeInfos[tmp + 3].newBlock)) {
+ BasicBlock* block = createBasicBlock("JSR2");
+ jsrs.push_back(block);
+ opcodeInfos[tmp + 3].newBlock = block;
+ } else {
+ jsrs.push_back(opcodeInfos[tmp + 3].newBlock);
+ }
+ opcodeInfos[index].reqSuppl = true;
+ break;
+ }
+
+ case RET : ++i; break;
+
+ case TABLESWITCH : {
+ uint32 tmp = i;
+ uint32 reste = (i + 1) & 3;
+ uint32 filled = reste ? (4 - reste) : 0;
+ i += filled;
+ uint32 index = tmp + readU4(bytecodes, i);
+ if (!(opcodeInfos[index].newBlock)) {
+ BasicBlock* block = createBasicBlock("tableswitch");
+ opcodeInfos[index].newBlock = block;
+ }
+ uint32 low = readU4(bytecodes, i);
+ uint32 high = readU4(bytecodes, i) + 1;
+ uint32 depl = high - low;
+ for (uint32 cur = 0; cur < depl; ++cur) {
+ uint32 index2 = tmp + readU4(bytecodes, i);
+ if (!(opcodeInfos[index2].newBlock)) {
+ BasicBlock* block = createBasicBlock("tableswitch");
+ opcodeInfos[index2].newBlock = block;
+ }
+ }
+ i = tmp + 12 + filled + (depl << 2);
+ break;
+ }
+
+ case LOOKUPSWITCH : {
+ uint32 tmp = i;
+ uint32 filled = (3 - i) & 3;
+ i += filled;
+ uint32 index = tmp + readU4(bytecodes, i);
+ if (!(opcodeInfos[index].newBlock)) {
+ BasicBlock* block = createBasicBlock("tableswitch");
+ opcodeInfos[index].newBlock = block;
+ }
+ uint32 nbs = readU4(bytecodes, i);
+ for (uint32 cur = 0; cur < nbs; ++cur) {
+ i += 4;
+ uint32 index2 = tmp + readU4(bytecodes, i);
+ if (!(opcodeInfos[index2].newBlock)) {
+ BasicBlock* block = createBasicBlock("tableswitch");
+ opcodeInfos[index2].newBlock = block;
+ }
+ }
+
+ i = tmp + 8 + filled + (nbs << 3);
+ break;
+ }
+
+ case IRETURN :
+ case LRETURN :
+ case FRETURN :
+ case DRETURN :
+ case ARETURN :
+ case RETURN : break;
+
+ case GETSTATIC :
+ case PUTSTATIC :
+ case GETFIELD :
+ case PUTFIELD :
+ case INVOKEVIRTUAL :
+ case INVOKESPECIAL :
+ case INVOKESTATIC :
+ i += 2;
+ break;
+
+ case INVOKEINTERFACE :
+ i += 4;
+ break;
+
+ case NEW :
+ i += 2;
+ break;
+
+ case NEWARRAY :
+ ++i;
+ break;
+
+ case ANEWARRAY :
+ i += 2;
+ break;
+
+ case ARRAYLENGTH :
+ case ATHROW : break;
+
+ case CHECKCAST :
+ i += 2;
+ break;
+
+ case INSTANCEOF :
+ i += 2;
+ break;
+
+ case MONITORENTER :
+ break;
+
+ case MONITOREXIT :
+ break;
+
+ case MULTIANEWARRAY :
+ i += 3;
+ break;
+
+ case WIDE :
+ wide = true;
+ break;
+
+ case IFNULL :
+ case IFNONNULL : {
+ uint32 tmp = i;
+ uint16 index = tmp + readU2(bytecodes, i);
+ if (!(opcodeInfos[index].newBlock))
+ opcodeInfos[index].newBlock = createBasicBlock("true IF*NULL");
+ break;
+ }
+
+
+ default :
+ JavaThread::get()->isolate->unknownError("unknown bytecode");
+ }
+ }
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaMetaJIT.cpp b/vmkit/lib/JnJVM/VMCore/JavaMetaJIT.cpp
new file mode 100644
index 0000000..7c4378d
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaMetaJIT.cpp
@@ -0,0 +1,905 @@
+//===---- JavaMetaJIT.cpp - Functions for Java internal objects -----------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include <llvm/Type.h>
+#include <llvm/Support/CFG.h>
+#include <llvm/Module.h>
+#include <llvm/Constants.h>
+#include <llvm/Type.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/ModuleProvider.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Assembly/PrintModulePass.h>
+#include <llvm/Target/TargetOptions.h>
+#include <llvm/CodeGen/MachineCodeEmitter.h>
+#include <llvm/CodeGen/MachineBasicBlock.h>
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/PassManager.h"
+#include "llvm/ValueSymbolTable.h"
+#include "llvm/Analysis/LoadValueNumbering.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/SchedulerRegistry.h"
+#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <llvm/Transforms/IPO.h>
+
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+
+#include "debug.h"
+#include "JavaArray.h"
+#include "JavaCache.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaObject.h"
+#include "JavaJIT.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+#include "NativeUtil.h"
+#include "Reader.h"
+#include "Zip.h"
+
+#include <iostream>
+
+
+using namespace jnjvm;
+using namespace llvm;
+
+#ifndef SINGLE_VM
+GlobalVariable* Class::staticVar(llvm::Module* compilingModule) {
+ if (!_staticVar) {
+ aquire();
+ if (!_staticVar) {
+ if (isolate == Jnjvm::bootstrapVM) {
+ _staticVar = llvmVar(compilingModule);
+ release();
+ return _staticVar;
+ } else {
+ isolate->protectModule->lock();
+ _staticVar = new GlobalVariable(JavaObject::llvmType, false,
+ GlobalValue::ExternalLinkage,
+ JavaJIT::constantJavaObjectNull, "",
+ isolate->module);
+ isolate->protectModule->unlock();
+
+ // TODO: put an initializer in here
+ void* ptr = mvm::jit::executionEngine->getPointerToGlobal(_staticVar);
+ GenericValue Val = GenericValue((void*)staticInstance());
+ llvm::GenericValue * Ptr = (llvm::GenericValue*)ptr;
+ mvm::jit::executionEngine->StoreValueToMemory(Val, Ptr, staticType);
+ }
+ }
+ release();
+ }
+
+ return _staticVar;
+}
+#else
+GlobalVariable* Class::staticVar(llvm::Module* compilingModule) {
+ if (!_staticVar) {
+ aquire();
+ if (!_staticVar) {
+
+ JavaObject* obj = staticInstance();
+ mvm::jit::protectConstants();//->lock();
+ Constant* cons =
+ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (obj)),
+ JavaObject::llvmType);
+ mvm::jit::unprotectConstants();//->unlock();
+
+ isolate->protectModule->lock();
+ _staticVar = new GlobalVariable(JavaObject::llvmType, true,
+ GlobalValue::ExternalLinkage,
+ cons, "",
+ isolate->module);
+ isolate->protectModule->unlock();
+
+ }
+ release();
+ }
+ return _staticVar;
+}
+#endif
+
+GlobalVariable* CommonClass::llvmVar(llvm::Module* compilingModule) {
+ if (!_llvmVar) {
+ aquire();
+ if (!_llvmVar) {
+#ifndef SINGLE_VM
+ if (compilingModule == Jnjvm::bootstrapVM->module && isArray && isolate != Jnjvm::bootstrapVM) {
+ // We know the array class can belong to bootstrap
+ _llvmVar = Jnjvm::bootstrapVM->constructArray(this->name, 0)->llvmVar(compilingModule);
+ release();
+ return _llvmVar;
+ }
+#endif
+ const Type* pty = mvm::jit::ptrType;
+
+ mvm::jit::protectConstants();//->lock();
+ Constant* cons =
+ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)),
+ pty);
+ mvm::jit::unprotectConstants();//->unlock();
+
+ isolate->protectModule->lock();
+ _llvmVar = new GlobalVariable(pty, true,
+ GlobalValue::ExternalLinkage,
+ cons, "",
+ isolate->module);
+ isolate->protectModule->unlock();
+ }
+ release();
+ }
+ return _llvmVar;
+}
+
+#ifdef SINGLE_VM
+GlobalVariable* CommonClass::llvmDelegatee() {
+ if (!_llvmDelegatee) {
+ aquire();
+ if (!_llvmDelegatee) {
+ const Type* pty = JavaObject::llvmType;
+
+ JavaObject* obj = getClassDelegatee();
+ mvm::jit::protectConstants();//->lock();
+ Constant* cons =
+ ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (obj)),
+ pty);
+ mvm::jit::unprotectConstants();//->unlock();
+
+ isolate->protectModule->lock();
+ _llvmDelegatee = new GlobalVariable(pty, true,
+ GlobalValue::ExternalLinkage,
+ cons, "",
+ isolate->module);
+ isolate->protectModule->unlock();
+ }
+ release();
+ }
+ return _llvmDelegatee;
+}
+#endif
+
+ConstantInt* JavaObject::classOffset() {
+ return mvm::jit::constantOne;
+}
+
+ConstantInt* JavaArray::sizeOffset() {
+ return mvm::jit::constantOne;
+}
+
+ConstantInt* JavaArray::elementsOffset() {
+ return mvm::jit::constantTwo;
+}
+
+void JavaJIT::invokeOnceVoid(Jnjvm* vm, JavaObject* loader,
+ char const* className, char const* func,
+ char const* sign, int access, ...) {
+
+ CommonClass* cl = vm->loadName(vm->asciizConstructUTF8(className), loader,
+ true, true, true);
+
+ bool stat = access == ACC_STATIC ? true : false;
+ JavaMethod* method = cl->lookupMethod(vm->asciizConstructUTF8(func),
+ vm->asciizConstructUTF8(sign), stat,
+ true);
+ va_list ap;
+ va_start(ap, access);
+ if (stat) {
+ method->invokeIntStaticAP(ap);
+ } else {
+ JavaObject* obj = va_arg(ap, JavaObject*);
+ method->invokeIntSpecialAP(obj, ap);
+ }
+ va_end(ap);
+}
+
+VirtualTable* JavaJIT::makeVT(Class* cl, bool stat) {
+
+ const Type* type = stat ? cl->staticType : cl->virtualType;
+ std::vector<JavaField*> &fields = stat ? cl->staticFields : cl->virtualFields;
+
+ cl->isolate->protectModule->lock();
+ Function* func = new Function(markAndTraceLLVMType,
+ GlobalValue::ExternalLinkage,
+ "markAndTraceObject",
+ cl->isolate->module);
+ cl->isolate->protectModule->unlock();
+
+ Constant* zero = mvm::jit::constantZero;
+ Argument* arg = func->arg_begin();
+ BasicBlock* block = new BasicBlock("", func);
+ llvm::Value* realArg = new BitCastInst(arg, type, "", block);
+
+ if (stat || cl->super == 0) {
+ new CallInst(javaObjectTracerLLVM, arg, "", block);
+ } else {
+ new CallInst(((Class*)cl->super)->virtualTracer, arg, "", block);
+ }
+
+ for (std::vector<JavaField*>::iterator i = fields.begin(),
+ e = fields.end(); i!= e; ++i) {
+ if ((*i)->signature->funcs->doTrace) {
+ std::vector<Value*> args; //size = 2
+ args.push_back(zero);
+ args.push_back((*i)->offset);
+ Value* ptr = new GetElementPtrInst(realArg, args.begin(), args.end(), "",
+ block);
+ Value* val = new LoadInst(ptr, "", block);
+ Value* valCast = new BitCastInst(val, JavaObject::llvmType, "", block);
+ new CallInst(markAndTraceLLVM, valCast, "", block);
+ }
+ }
+
+ new ReturnInst(block);
+
+ VirtualTable * res = malloc(VT_SIZE);
+ memcpy(res, JavaObject::VT, VT_SIZE);
+ void* codePtr = mvm::jit::executionEngine->getPointerToGlobal(func);
+ ((void**)res)[VT_TRACER_OFFSET] = codePtr;
+
+ if (!stat) {
+ cl->virtualTracer = func;
+ cl->codeVirtualTracer = (mvm::Code*)((unsigned*)codePtr - 1);
+ } else {
+ cl->staticTracer = func;
+ cl->codeStaticTracer = (mvm::Code*)((unsigned*)codePtr - 1);
+ }
+ return res;
+}
+
+
+static void _initField(JavaField* field) {
+ ConstantInt* offset = field->offset;
+ const TargetData* targetData = mvm::jit::executionEngine->getTargetData();
+ bool stat = isStatic(field->access);
+ const Type* clType = stat ? field->classDef->staticType :
+ field->classDef->virtualType;
+
+ const StructLayout* sl =
+ targetData->getStructLayout((StructType*)(clType->getContainedType(0)));
+ uint64 ptrOffset = sl->getElementOffset(offset->getZExtValue());
+
+ field->ptrOffset = ptrOffset;
+}
+
+void JavaJIT::initField(JavaField* field, JavaObject* obj, uint64 val) {
+ _initField(field);
+
+ const AssessorDesc* funcs = field->signature->funcs;
+ if (funcs == AssessorDesc::dLong) {
+ ((sint64*)((uint64)obj + field->ptrOffset))[0] = val;
+ } else if (funcs == AssessorDesc::dInt) {
+ ((sint32*)((uint64)obj + field->ptrOffset))[0] = (sint32)val;
+ } else if (funcs == AssessorDesc::dChar) {
+ ((uint16*)((uint64)obj + field->ptrOffset))[0] = (uint16)val;
+ } else if (funcs == AssessorDesc::dShort) {
+ ((sint16*)((uint64)obj + field->ptrOffset))[0] = (sint16)val;
+ } else if (funcs == AssessorDesc::dByte) {
+ ((sint8*)((uint64)obj + field->ptrOffset))[0] = (sint8)val;
+ } else if (funcs == AssessorDesc::dBool) {
+ ((uint8*)((uint64)obj + field->ptrOffset))[0] = (uint8)val;
+ } else {
+ // 0 value for everything else
+ ((sint32*)((uint64)obj + field->ptrOffset))[0] = (sint32)val;
+ }
+}
+
+void JavaJIT::initField(JavaField* field, JavaObject* obj, JavaObject* val) {
+ _initField(field);
+ ((JavaObject**)((uint64)obj + field->ptrOffset))[0] = val;
+}
+
+void JavaJIT::initField(JavaField* field, JavaObject* obj, double val) {
+ _initField(field);
+ ((double*)((uint64)obj + field->ptrOffset))[0] = val;
+}
+
+void JavaJIT::initField(JavaField* field, JavaObject* obj, float val) {
+ _initField(field);
+ ((float*)((uint64)obj + field->ptrOffset))[0] = val;
+}
+
+JavaObject* Class::operator()() {
+ if (!isReady())
+ isolate->loadName(name, classLoader, true, true, true);
+ return doNew();
+}
+
+void JavaField::operator()(JavaObject* obj, float val) {
+ if (!classDef->isReady())
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
+
+ bool stat = isStatic(access);
+ if (stat) obj = classDef->staticInstance();
+ void* ptr = (void*)((uint64)obj + ptrOffset);
+
+ if (signature->funcs->llvmType == Type::FloatTy) {
+ ((float*)ptr)[0] = val;
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
+ }
+}
+
+void JavaField::operator()(JavaObject* obj, double val) {
+ if (!classDef->isReady())
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
+
+ bool stat = isStatic(access);
+ if (stat) obj = classDef->staticInstance();
+ void* ptr = (void*)((uint64)obj + ptrOffset);
+
+ if (signature->funcs->llvmType == Type::DoubleTy) {
+ ((double*)ptr)[0] = val;
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
+ }
+}
+
+void JavaField::operator()(JavaObject* obj, sint64 val) {
+ if (!classDef->isReady())
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
+
+ bool stat = isStatic(access);
+ if (stat) obj = classDef->staticInstance();
+ void* ptr = (void*)((uint64)obj + ptrOffset);
+
+ if (signature->funcs == AssessorDesc::dLong) {
+ ((uint64*)ptr)[0] = val;
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
+ }
+}
+
+void JavaField::operator()(JavaObject* obj, uint32 val) {
+ if (!classDef->isReady())
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
+
+ bool stat = isStatic(access);
+ if (stat) obj = classDef->staticInstance();
+ void* ptr = (void*)((uint64)obj + ptrOffset);
+
+ if (signature->funcs == AssessorDesc::dInt) {
+ ((sint32*)ptr)[0] = (sint32)val;
+ } else if (signature->funcs == AssessorDesc::dShort) {
+ ((sint16*)ptr)[0] = (sint16)val;
+ } else if (signature->funcs == AssessorDesc::dByte) {
+ ((sint8*)ptr)[0] = (sint8)val;
+ } else if (signature->funcs == AssessorDesc::dBool) {
+ ((uint8*)ptr)[0] = (uint8)val;
+ } else if (signature->funcs == AssessorDesc::dChar) {
+ ((uint16*)ptr)[0] = (uint16)val;
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
+ }
+}
+
+void JavaField::operator()(JavaObject* obj, JavaObject* val) {
+ if (!classDef->isReady())
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
+
+ bool stat = isStatic(access);
+ if (stat) obj = classDef->staticInstance();
+ void* ptr = (void*)((uint64)obj + ptrOffset);
+
+ if (signature->funcs->llvmType == JavaObject::llvmType) {
+ ((JavaObject**)ptr)[0] = val;
+ } else {
+ JavaThread::get()->isolate->illegalArgumentException("wrong type in field assignment");
+ }
+}
+
+GenericValue JavaField::operator()(JavaObject* obj) {
+ if (!classDef->isReady())
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);
+
+ bool stat = isStatic(access);
+ if (stat) {
+ if (obj != 0) {
+ // Assignment to a static var
+ void* ptr = (void*)((uint64)(classDef->staticInstance()) + ptrOffset);
+ ((JavaObject**)ptr)[0] = obj;
+ return GenericValue(0);
+ } else {
+ // Get a static var
+ obj = classDef->staticInstance();
+ }
+ }
+
+ assert(obj && "getting a field from a null value");
+
+ void* ptr = (void*)((uint64)obj + ptrOffset);
+ const Type* type = signature->funcs->llvmType;
+ if (type == Type::Int8Ty) {
+ GenericValue gv;
+ gv.IntVal = APInt(8, ((uint8*)ptr)[0]);
+ return gv;
+ } else if (type == Type::Int16Ty) {
+ GenericValue gv;
+ gv.IntVal = APInt(16, ((uint16*)ptr)[0]);
+ return gv;
+ } else if (type == Type::Int32Ty) {
+ GenericValue gv;
+ gv.IntVal = APInt(32, ((uint32*)ptr)[0]);
+ return gv;
+ } else if (type == Type::Int64Ty) {
+ GenericValue gv;
+ gv.IntVal = APInt(64, ((uint64*)ptr)[0]);
+ return gv;
+ } else if (type == Type::DoubleTy) {
+ GenericValue gv;
+ gv.DoubleVal = ((double*)ptr)[0];
+ return gv;
+ } else if (type == Type::FloatTy) {
+ GenericValue gv;
+ gv.FloatVal = ((float*)ptr)[0];
+ return gv;
+ } else if (type == JavaObject::llvmType) {
+ GenericValue gv(((JavaObject**)ptr)[0]);
+ return gv;
+ } else {
+ assert(0 && "Unknown type!");
+ return GenericValue(0);
+ }
+}
+
+#define readArgs(buf, signature, ap) \
+ for (std::vector<Typedef*>::iterator i = signature->args.begin(), \
+ e = signature->args.end(); i!= e; i++) { \
+ const AssessorDesc* funcs = (*i)->funcs; \
+ if (funcs == AssessorDesc::dLong) { \
+ ((sint64*)buf)[0] = va_arg(ap, sint64); \
+ buf += 2; \
+ } else if (funcs == AssessorDesc::dInt) { \
+ ((sint32*)buf)[0] = va_arg(ap, sint32); \
+ buf++; \
+ } else if (funcs == AssessorDesc::dChar) { \
+ ((uint32*)buf)[0] = va_arg(ap, uint32); \
+ buf++; \
+ } else if (funcs == AssessorDesc::dShort) { \
+ ((uint32*)buf)[0] = va_arg(ap, uint32); \
+ buf++; \
+ } else if (funcs == AssessorDesc::dByte) { \
+ ((uint32*)buf)[0] = va_arg(ap, uint32); \
+ buf++; \
+ } else if (funcs == AssessorDesc::dBool) { \
+ ((uint32*)buf)[0] = va_arg(ap, uint32); \
+ buf++; \
+ } else if (funcs == AssessorDesc::dFloat) { \
+ ((float*)buf)[0] = (float)va_arg(ap, double); \
+ buf++; \
+ } else if (funcs == AssessorDesc::dDouble) { \
+ ((double*)buf)[0] = va_arg(ap, double); \
+ buf += 2; \
+ } else if (funcs == AssessorDesc::dRef || funcs == AssessorDesc::dTab) { \
+ ((JavaObject**)buf)[0] = va_arg(ap, JavaObject*); \
+ buf++; \
+ } else { \
+ assert(0 && "Should not be here"); \
+ } \
+ } \
+
+
+#if 1//defined(__PPC__) && !defined(__MACH__)
+#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(JavaObject* obj, va_list ap) { \
+ if (!classDef->isReady()) \
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true); \
+ \
+ verifyNull(obj); \
+ JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true); \
+ \
+ void** buf = (void**)alloca(meth->signature->args.size() * sizeof(uint64)); \
+ void* _buf = (void*)buf; \
+ readArgs(buf, signature, ap); \
+ void* func = meth->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, _buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(JavaObject* obj, va_list ap) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ verifyNull(obj);\
+ void** buf = (void**)alloca(this->signature->args.size() * sizeof(uint64)); \
+ void* _buf = (void*)buf; \
+ readArgs(buf, signature, ap); \
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, _buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(va_list ap) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ void** buf = (void**)alloca(this->signature->args.size() * sizeof(uint64)); \
+ void* _buf = (void*)buf; \
+ readArgs(buf, signature, ap); \
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_STATIC_BUF)signature->staticCallBuf())(func, _buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualBuf(JavaObject* obj, void* buf) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ verifyNull(obj);\
+ JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true);\
+ \
+ void* func = meth->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialBuf(JavaObject* obj, void* buf) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ verifyNull(obj);\
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticBuf(void* buf) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_STATIC_BUF)signature->staticCallBuf())(func, buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Virtual(JavaObject* obj, ...) { \
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##VirtualAP(obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Special(JavaObject* obj, ...) {\
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##SpecialAP(obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Static(...) {\
+ va_list ap;\
+ va_start(ap, this);\
+ TYPE res = invoke##TYPE_NAME##StaticAP(ap);\
+ va_end(ap); \
+ return res; \
+}\
+
+#else
+
+#define INVOKE(TYPE, TYPE_NAME, FUNC_TYPE_VIRTUAL_AP, FUNC_TYPE_STATIC_AP, FUNC_TYPE_VIRTUAL_BUF, FUNC_TYPE_STATIC_BUF) \
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualAP(JavaObject* obj, va_list ap) { \
+ if (!classDef->isReady()) \
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true); \
+ \
+ verifyNull(obj); \
+ JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true); \
+ \
+ void* func = meth->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_AP)signature->virtualCallAP())(func, obj, ap);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialAP(JavaObject* obj, va_list ap) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ verifyNull(obj);\
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_AP)signature->virtualCallAP())(func, obj, ap);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticAP(va_list ap) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_STATIC_AP)signature->staticCallAP())(func, ap);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##VirtualBuf(JavaObject* obj, void* buf) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ verifyNull(obj);\
+ JavaMethod* meth = obj->classOf->lookupMethod(name, type, false, true);\
+ \
+ void* func = meth->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##SpecialBuf(JavaObject* obj, void* buf) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ verifyNull(obj);\
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_VIRTUAL_BUF)signature->virtualCallBuf())(func, obj, buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##StaticBuf(void* buf) {\
+ if (!classDef->isReady())\
+ classDef->isolate->loadName(classDef->name, classDef->classLoader, true, true, true);\
+ \
+ void* func = this->compiledPtr();\
+ return ((FUNC_TYPE_STATIC_BUF)signature->staticCallBuf())(func, buf);\
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Virtual(JavaObject* obj, ...) { \
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##VirtualAP(obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Special(JavaObject* obj, ...) {\
+ va_list ap;\
+ va_start(ap, obj);\
+ TYPE res = invoke##TYPE_NAME##SpecialAP(obj, ap);\
+ va_end(ap); \
+ return res; \
+}\
+\
+TYPE JavaMethod::invoke##TYPE_NAME##Static(...) {\
+ va_list ap;\
+ va_start(ap, this);\
+ TYPE res = invoke##TYPE_NAME##StaticAP(ap);\
+ va_end(ap); \
+ return res; \
+}\
+
+#endif
+
+typedef uint32 (*uint32_virtual_ap)(void*, JavaObject*, va_list);
+typedef sint64 (*sint64_virtual_ap)(void*, JavaObject*, va_list);
+typedef float (*float_virtual_ap)(void*, JavaObject*, va_list);
+typedef double (*double_virtual_ap)(void*, JavaObject*, va_list);
+typedef JavaObject* (*object_virtual_ap)(void*, JavaObject*, va_list);
+
+typedef uint32 (*uint32_static_ap)(void*, va_list);
+typedef sint64 (*sint64_static_ap)(void*, va_list);
+typedef float (*float_static_ap)(void*, va_list);
+typedef double (*double_static_ap)(void*, va_list);
+typedef JavaObject* (*object_static_ap)(void*, va_list);
+
+typedef uint32 (*uint32_virtual_buf)(void*, JavaObject*, void*);
+typedef sint64 (*sint64_virtual_buf)(void*, JavaObject*, void*);
+typedef float (*float_virtual_buf)(void*, JavaObject*, void*);
+typedef double (*double_virtual_buf)(void*, JavaObject*, void*);
+typedef JavaObject* (*object_virtual_buf)(void*, JavaObject*, void*);
+
+typedef uint32 (*uint32_static_buf)(void*, void*);
+typedef sint64 (*sint64_static_buf)(void*, void*);
+typedef float (*float_static_buf)(void*, void*);
+typedef double (*double_static_buf)(void*, void*);
+typedef JavaObject* (*object_static_buf)(void*, void*);
+
+INVOKE(uint32, Int, uint32_virtual_ap, uint32_static_ap, uint32_virtual_buf, uint32_static_buf)
+INVOKE(sint64, Long, sint64_virtual_ap, sint64_static_ap, sint64_virtual_buf, sint64_static_buf)
+INVOKE(float, Float, float_virtual_ap, float_static_ap, float_virtual_buf, float_static_buf)
+INVOKE(double, Double, double_virtual_ap, double_static_ap, double_virtual_buf, double_static_buf)
+INVOKE(JavaObject*, JavaObject, object_virtual_ap, object_static_ap, object_virtual_buf, object_static_buf)
+
+#undef INVOKE
+
+GenericValue JavaObject::operator()(JavaField* field) {
+ return (*field)(this);
+}
+
+void JavaObject::operator()(JavaField* field, float val) {
+ return (*field)(this, val);
+}
+
+void JavaObject::operator()(JavaField* field, double val) {
+ return (*field)(this, val);
+}
+
+void JavaObject::operator()(JavaField* field, uint32 val) {
+ return (*field)(this, val);
+}
+
+void JavaObject::operator()(JavaField* field, sint64 val) {
+ return (*field)(this, val);
+}
+
+void JavaObject::operator()(JavaField* field, JavaObject* val) {
+ return (*field)(this, val);
+}
+
+void JavaField::operator()(float val) {
+ JavaField * field = this;
+ return (*field)(classDef->virtualInstance, val);
+}
+
+void JavaField::operator()(double val) {
+ JavaField * field = this;
+ return (*field)(classDef->virtualInstance, val);
+}
+
+void JavaField::operator()(sint64 val) {
+ JavaField * field = this;
+ return (*field)(classDef->virtualInstance, val);
+}
+
+void JavaField::operator()(uint32 val) {
+ JavaField * field = this;
+ return (*field)(classDef->virtualInstance, val);
+}
+
+Function* Signdef::createFunctionCallBuf(bool virt) {
+
+ ConstantInt* CI = mvm::jit::constantZero;
+ std::vector<Value*> Args;
+
+ isolate->protectModule->lock();
+ Function* res = new llvm::Function(virt ? virtualBufType : staticBufType,
+ GlobalValue::ExternalLinkage,
+ this->printString(),
+ isolate->module);
+ isolate->protectModule->unlock();
+
+ BasicBlock* currentBlock = new BasicBlock("enter", res);
+ Function::arg_iterator i = res->arg_begin();
+ Value *obj, *ptr, *func;
+ func = i;
+ ++i;
+ if (virt) {
+ obj = i;
+ ++i;
+ Args.push_back(obj);
+ }
+ ptr = i;
+
+ for (std::vector<Typedef*>::iterator i = args.begin(),
+ e = args.end(); i!= e; ++i) {
+
+ const AssessorDesc* funcs = (*i)->funcs;
+ ptr = new GetElementPtrInst(ptr, CI, "", currentBlock);
+ Value* val = new BitCastInst(ptr, funcs->llvmTypePtr, "", currentBlock);
+ Value* arg = new LoadInst(val, "", currentBlock);
+ Args.push_back(arg);
+ if (funcs == AssessorDesc::dLong || funcs == AssessorDesc::dDouble) {
+ CI = mvm::jit::constantTwo;
+ } else {
+ CI = mvm::jit::constantOne;
+ }
+ }
+ Value* val = new CallInst(func, Args.begin(), Args.end(), "", currentBlock);
+ if (ret->funcs != AssessorDesc::dVoid)
+ new ReturnInst(val, currentBlock);
+ else
+ new ReturnInst(currentBlock);
+
+ return res;
+}
+
+Function* Signdef::createFunctionCallAP(bool virt) {
+
+ std::vector<Value*> Args;
+
+ isolate->protectModule->lock();
+ Function* res = new llvm::Function(virt ? virtualBufType : staticBufType,
+ GlobalValue::ExternalLinkage,
+ this->printString(),
+ isolate->module);
+ isolate->protectModule->unlock();
+
+ BasicBlock* currentBlock = new BasicBlock("enter", res);
+ Function::arg_iterator i = res->arg_begin();
+ Value *obj, *ap, *func;
+ func = i;
+ ++i;
+ if (virt) {
+ obj = i;
+ Args.push_back(obj);
+ ++i;
+ }
+ ap = i;
+
+ for (std::vector<Typedef*>::iterator i = args.begin(),
+ e = args.end(); i!= e; i++) {
+
+ Args.push_back(new VAArgInst(ap, (*i)->funcs->llvmType, "", currentBlock));
+ }
+
+ Value* val = new CallInst(func, Args.begin(), Args.end(), "", currentBlock);
+ if (ret->funcs != AssessorDesc::dVoid)
+ new ReturnInst(val, currentBlock);
+ else
+ new ReturnInst(currentBlock);
+
+ return res;
+}
+
+void Signdef::createFuncPtrsCalls() {
+ assert(0 && "do not call me");
+ Function* virtBuf = createFunctionCallBuf(true);
+ Function* statBuf = createFunctionCallBuf(false);
+ Function* virtAP = createFunctionCallAP(true);
+ Function* statAP = createFunctionCallAP(false);
+
+ _staticCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statBuf);
+ _virtualCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtBuf);
+ _staticCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statAP);
+ _virtualCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtAP);
+}
+
+void* Signdef::staticCallBuf() {
+ if (!_staticCallBuf) {
+ Function* statBuf = createFunctionCallBuf(false);
+ _staticCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statBuf);
+ }
+ return _staticCallBuf;
+}
+
+void* Signdef::virtualCallBuf() {
+ if (!_virtualCallBuf) {
+ Function* virtBuf = createFunctionCallBuf(true);
+ _virtualCallBuf = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtBuf);
+ }
+ return _virtualCallBuf;
+}
+
+void* Signdef::staticCallAP() {
+ if (!_staticCallAP) {
+ Function* statAP = createFunctionCallAP(false);
+ _staticCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(statAP);
+ }
+ return _staticCallAP;
+}
+
+void* Signdef::virtualCallAP() {
+ if (!_virtualCallAP) {
+ Function* virtAP = createFunctionCallAP(true);
+ _virtualCallAP = (mvm::Code*)mvm::jit::executionEngine->getPointerToGlobal(virtAP);
+ }
+ return _virtualCallAP;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaObject.cpp b/vmkit/lib/JnJVM/VMCore/JavaObject.cpp
new file mode 100644
index 0000000..5284054
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaObject.cpp
@@ -0,0 +1,217 @@
+//===----------- JavaObject.cpp - Java object definition ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "mvm/Threads/Locks.h"
+
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+
+using namespace jnjvm;
+
+JavaCond* JavaCond::allocate() {
+ return gc_new(JavaCond)();
+}
+
+void JavaCond::notify() {
+ for (std::vector<JavaThread*>::iterator i = threads.begin(),
+ e = threads.end(); i!= e;) {
+ JavaThread* cur = *i;
+ cur->lock->lock();
+ if (cur->interruptFlag != 0) {
+ cur->lock->unlock();
+ ++i;
+ continue;
+ } else if (cur->javaThread != 0) {
+ cur->varcond->signal();
+ cur->lock->unlock();
+ threads.erase(i);
+ break;
+ } else { // dead thread
+ ++i;
+ threads.erase(i - 1);
+ }
+ }
+}
+
+void JavaCond::notifyAll() {
+ for (std::vector<JavaThread*>::iterator i = threads.begin(),
+ e = threads.end(); i!= e; ++i) {
+ JavaThread* cur = *i;
+ cur->lock->lock();
+ cur->varcond->signal();
+ cur->lock->unlock();
+ }
+ threads.clear();
+}
+
+void JavaCond::wait(JavaThread* th) {
+ threads.push_back(th);
+}
+
+void JavaCond::remove(JavaThread* th) {
+ for (std::vector<JavaThread*>::iterator i = threads.begin(),
+ e = threads.end(); i!= e; ++i) {
+ if (*i == th) {
+ threads.erase(i);
+ break;
+ }
+ }
+}
+
+void LockObj::print(mvm::PrintBuffer* buf) const {
+ buf->write("Lock<>");
+}
+
+LockObj* LockObj::allocate() {
+ LockObj* res = gc_new(LockObj)();
+ res->lock = mvm::Lock::allocRecursive();
+ res->varcond = JavaCond::allocate();
+ return res;
+}
+
+void LockObj::aquire() {
+ lock->lock();
+}
+
+void LockObj::release() {
+ lock->unlock();
+}
+
+bool LockObj::owner() {
+ return mvm::Lock::selfOwner(lock);
+}
+
+void JavaObject::print(mvm::PrintBuffer* buf) const {
+ buf->write("JavaObject<");
+ CommonClass::printClassName(classOf->name, buf);
+ buf->write(">");
+}
+
+JavaObject* JavaObject::allocate(CommonClass* cl) {
+ JavaObject* res = gc_new(JavaObject)();
+ res->classOf = cl;
+ return res;
+}
+
+static LockObj* myLock(JavaObject* obj) {
+ verifyNull(obj);
+ if (obj->lockObj == 0) {
+ JavaObject::globalLock->lock();
+ if (obj->lockObj == 0) {
+ obj->lockObj = LockObj::allocate();
+ }
+ JavaObject::globalLock->unlock();
+ }
+ return obj->lockObj;
+}
+
+void JavaObject::aquire() {
+ myLock(this)->aquire();
+}
+
+void JavaObject::unlock() {
+ verifyNull(this);
+ lockObj->release();
+}
+
+void JavaObject::waitIntern(struct timeval* info, bool timed) {
+ LockObj * l = myLock(this);
+ bool owner = l->owner();
+
+ if (owner) {
+ JavaThread* thread = JavaThread::get();
+ mvm::Lock* mutexThread = thread->lock;
+ mvm::Cond* varcondThread = thread->varcond;
+
+ mutexThread->lock();
+ if (thread->interruptFlag != 0) {
+ mutexThread->unlock();
+ thread->interruptFlag = 0;
+ thread->isolate->interruptedException(this);
+ } else {
+ unsigned int recur = mvm::LockRecursive::recursion_count(l->lock);
+ bool timeout = false;
+ mvm::LockRecursive::my_unlock_all(l->lock);
+ l->varcond->wait(thread);
+ thread->state = JavaThread::StateWaiting;
+
+ if (timed) {
+ timeout = varcondThread->timed_wait(mutexThread, info);
+ } else {
+ varcondThread->wait(mutexThread);
+ }
+
+ bool interrupted = (thread->interruptFlag != 0);
+ mutexThread->unlock();
+ mvm::LockRecursive::my_lock_all(l->lock, recur);
+
+ if (interrupted || timeout) {
+ l->varcond->remove(thread);
+ }
+
+ thread->state = JavaThread::StateRunning;
+
+ if (interrupted) {
+ thread->interruptFlag = 0;
+ thread->isolate->interruptedException(this);
+ }
+ }
+ } else {
+ JavaThread::get()->isolate->illegalMonitorStateException(this);
+ }
+}
+
+void JavaObject::wait() {
+ waitIntern(0, false);
+}
+
+void JavaObject::timedWait(struct timeval& info) {
+ waitIntern(&info, true);
+}
+
+void JavaObject::notify() {
+ LockObj* l = myLock(this);
+ if (l->owner()) {
+ l->varcond->notify();
+ } else {
+ JavaThread::get()->isolate->illegalMonitorStateException(this);
+ }
+}
+
+void JavaObject::notifyAll() {
+ LockObj* l = myLock(this);
+ if (l->owner()) {
+ l->varcond->notifyAll();
+ } else {
+ JavaThread::get()->isolate->illegalMonitorStateException(this);
+ }
+}
+
+bool JavaObject::instanceOfString(const UTF8* name) {
+ if (!this) return false;
+ else return this->classOf->isOfTypeName(name);
+}
+
+bool JavaObject::checkCast(const UTF8* Tname) {
+ if (!this || this->classOf->isOfTypeName(Tname)) {
+ return true;
+ } else {
+ JavaThread::get()->isolate->classCastException("checkcast");
+ return false;
+ }
+}
+
+bool JavaObject::instanceOf(CommonClass* cl) {
+ if (!this) return false;
+ else return this->classOf->isAssignableFrom(cl);
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaObject.h b/vmkit/lib/JnJVM/VMCore/JavaObject.h
new file mode 100644
index 0000000..dd90be2
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaObject.h
@@ -0,0 +1,113 @@
+//===----------- JavaObject.h - Java object definition -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_OBJECT_H
+#define JNJVM_JAVA_OBJECT_H
+
+#include <vector>
+
+#include "llvm/Constants.h"
+#include "llvm/Type.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+#include "mvm/Object.h"
+#include "mvm/Threads/Locks.h"
+
+#include "types.h"
+
+namespace jnjvm {
+
+class CommonClass;
+class JavaField;
+class JavaObject;
+class JavaThread;
+class UTF8;
+
+class JavaCond : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ std::vector<JavaThread*> threads;
+
+ static JavaCond* allocate();
+
+ void notify();
+ void notifyAll();
+ void wait(JavaThread* th);
+ void remove(JavaThread* th);
+
+ virtual void tracer(size_t sz);
+};
+
+
+class LockObj : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ mvm::Lock *lock;
+ JavaCond* varcond;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ static LockObj* allocate();
+ void aquire();
+ void release();
+ bool owner();
+};
+
+class JavaObject : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ CommonClass* classOf;
+ LockObj* lockObj;
+
+ static mvm::Lock* globalLock;
+ static const llvm::Type* llvmType;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ static JavaObject* allocate(CommonClass* cl);
+ void aquire();
+ void unlock();
+ void waitIntern(struct timeval *info, bool timed);
+ void wait();
+ void timedWait(struct timeval &info);
+ void notify();
+ void notifyAll();
+ void initialise(CommonClass* cl) {
+ this->classOf = cl;
+ this->lockObj = 0;
+ }
+
+ bool checkCast(const UTF8* name);
+ bool instanceOfString(const UTF8* name);
+ bool instanceOf(CommonClass* cl);
+
+ static llvm::ConstantInt* classOffset();
+
+#ifdef SIGSEGV_THROW_NULL
+ #define verifyNull(obj) {}
+#else
+ #define verifyNull(obj) \
+ if (obj == 0) JavaThread::get()->isolate->nullPointerException("");
+#endif
+
+ llvm::GenericValue operator()(JavaField* field);
+ void operator()(JavaField* field, float val);
+ void operator()(JavaField* field, double val);
+ void operator()(JavaField* field, sint64 val);
+ void operator()(JavaField* field, uint32 val);
+ void operator()(JavaField* field, JavaObject* val);
+
+};
+
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaPrimitive.cpp b/vmkit/lib/JnJVM/VMCore/JavaPrimitive.cpp
new file mode 100644
index 0000000..75d30f3
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaPrimitive.cpp
@@ -0,0 +1,62 @@
+//===--- JavaPrimitive.cpp - Native functions for primitive values --------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include <string.h>
+
+#include "JavaClass.h"
+#include "JavaPrimitive.h"
+#include "JavaTypes.h"
+
+using namespace jnjvm;
+
+void JavaPrimitive::print(mvm::PrintBuffer* buf) {
+ buf->write("Primitive");
+}
+
+JavaPrimitive* JavaPrimitive::byteIdToPrimitive(char id) {
+ for (uint32 i = 0; i < JavaPrimitive::primitives.size(); ++i) {
+ JavaPrimitive* cur = JavaPrimitive::primitives[i];
+ if (cur->funcs->byteId == id) return cur;
+ }
+ return 0;
+}
+
+JavaPrimitive* JavaPrimitive::asciizToPrimitive(char* asciiz) {
+ for (uint32 i = 0; i < JavaPrimitive::primitives.size(); ++i) {
+ JavaPrimitive* cur = JavaPrimitive::primitives[i];
+ if (!(strcmp(asciiz, cur->funcs->asciizName))) return cur;
+ }
+ return 0;
+}
+
+JavaPrimitive* JavaPrimitive::bogusClassToPrimitive(CommonClass* cl) {
+ for (uint32 i = 0; i < JavaPrimitive::primitives.size(); ++i) {
+ JavaPrimitive* cur = JavaPrimitive::primitives[i];
+ if (cur->classType == cl) return cur;
+ }
+ return 0;
+}
+
+JavaPrimitive* JavaPrimitive::classToPrimitive(CommonClass* cl) {
+ for (uint32 i = 0; i < JavaPrimitive::primitives.size(); ++i) {
+ JavaPrimitive* cur = JavaPrimitive::primitives[i];
+ if (cur->className == cl->name) return cur;
+ }
+ return 0;
+}
+
+JavaPrimitive* JavaPrimitive::funcsToPrimitive(AssessorDesc* func) {
+ for (uint32 i = 0; i < JavaPrimitive::primitives.size(); ++i) {
+ JavaPrimitive* cur = JavaPrimitive::primitives[i];
+ if (cur->funcs == func) return cur;
+ }
+ return 0;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaPrimitive.h b/vmkit/lib/JnJVM/VMCore/JavaPrimitive.h
new file mode 100644
index 0000000..1e3efa0
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaPrimitive.h
@@ -0,0 +1,51 @@
+//===--- JavaPrimitive.h - Native functions for primitive values ----------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_PRIMITIVE_H
+#define JNJVM_JAVA_PRIMITIVE_H
+
+#include "llvm/Function.h"
+
+#include "mvm/Object.h"
+
+#include "types.h"
+
+namespace jnjvm {
+
+class AssessorDesc;
+class CommonClass;
+class UTF8;
+
+class JavaPrimitive : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ AssessorDesc* funcs;
+ const UTF8* className;
+ CommonClass* classType;
+ const UTF8* symName;
+ llvm::Function* initer;
+ llvm::Function* getter;
+
+ static std::vector<JavaPrimitive*> primitives;
+
+ static void initialise();
+
+ static JavaPrimitive* byteIdToPrimitive(char id);
+ static JavaPrimitive* asciizToPrimitive(char* asciiz);
+ static JavaPrimitive* bogusClassToPrimitive(CommonClass* cl);
+ static JavaPrimitive* classToPrimitive(CommonClass* cl);
+ static JavaPrimitive* funcsToPrimitive(AssessorDesc* funcs);
+
+ virtual void print(mvm::PrintBuffer* buf);
+ virtual void tracer(size_t sz);
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp b/vmkit/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp
new file mode 100644
index 0000000..92f138e
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp
@@ -0,0 +1,208 @@
+//===-------------------- JavaRuntimeJIT.cpp ------------------------------===//
+//=== ---- Runtime functions called by code compiled by the JIT -----------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Function.h"
+
+#include "mvm/JIT.h"
+#include "mvm/Threads/Thread.h"
+
+#include "JavaArray.h"
+#include "JavaCache.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+#include "LockedMap.h"
+
+using namespace jnjvm;
+
+extern "C" JavaString* runtimeUTF8ToStr(const UTF8* val) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ return vm->UTF8ToStr(val);
+}
+
+extern "C" void* virtualLookup(CacheNode* cache, JavaObject *obj) {
+ Enveloppe* enveloppe = cache->enveloppe;
+ JavaCtpInfo* ctpInfo = enveloppe->ctpInfo;
+ CommonClass* ocl = obj->classOf;
+ CommonClass* cl = 0;
+ const UTF8* utf8 = 0;
+ Signdef* sign = 0;
+ uint32 index = enveloppe->index;
+
+ ctpInfo->resolveInterfaceOrMethod(index, cl, utf8, sign);
+
+ CacheNode* rcache = 0;
+ CacheNode* tmp = enveloppe->firstCache;
+ CacheNode* last = tmp;
+ enveloppe->cacheLock->lock();
+
+ while (tmp) {
+ if (ocl == tmp->lastCible) {
+ rcache = tmp;
+ break;
+ } else {
+ last = tmp;
+ tmp = tmp->next;
+ }
+ }
+
+ if (!rcache) {
+ JavaMethod* dmeth = ocl->lookupMethod(utf8, sign->keyName, false, true);
+ if (cache->methPtr) {
+ rcache = CacheNode::allocate();
+ rcache->enveloppe = enveloppe;
+ } else {
+ rcache = cache;
+ }
+
+ rcache->methPtr = dmeth->compiledPtr();
+ rcache->lastCible = (Class*)ocl;
+
+ }
+
+ if (enveloppe->firstCache != rcache) {
+ CacheNode *f = enveloppe->firstCache;
+ enveloppe->firstCache = rcache;
+ last->next = rcache->next;
+ rcache->next = f;
+ }
+
+ enveloppe->cacheLock->unlock();
+
+ return rcache->methPtr;
+}
+
+extern "C" void* fieldLookup(JavaObject* obj, Class* caller, uint32 index,
+ uint32 stat, void** ifStatic, uint32* offset) {
+ JavaCtpInfo* ctpInfo = caller->ctpInfo;
+ if (ctpInfo->ctpRes[index]) {
+ JavaField* field = (JavaField*)(ctpInfo->ctpRes[index]);
+ field->classDef->initialiseClass();
+ if (stat) obj = field->classDef->staticInstance();
+ void* ptr = (void*)(field->ptrOffset + (uint64)obj);
+ if (stat) *ifStatic = ptr;
+ *offset = (uint32)field->ptrOffset;
+ return ptr;
+ }
+
+ CommonClass* cl = 0;
+ const UTF8* utf8 = 0;
+ Typedef* sign = 0;
+
+ ctpInfo->resolveField(index, cl, utf8, sign);
+
+ JavaField* field = cl->lookupField(utf8, sign->keyName, stat, true);
+ field->classDef->initialiseClass();
+
+ if (stat) obj = ((Class*)cl)->staticInstance();
+ void* ptr = (void*)((uint64)obj + field->ptrOffset);
+
+ ctpInfo->ctpRes[index] = field;
+
+ if (stat) *ifStatic = ptr;
+ *offset = (uint32)field->ptrOffset;
+
+ return ptr;
+}
+
+extern "C" void printMethodStart(JavaMethod* meth) {
+ printf("[%d] executing %s\n", mvm::Thread::self(), meth->printString());
+ fflush(stdout);
+}
+
+extern "C" void printMethodEnd(JavaMethod* meth) {
+ printf("[%d] return from %s\n", mvm::Thread::self(), meth->printString());
+ fflush(stdout);
+}
+
+extern "C" void printExecution(char* opcode, uint32 index, JavaMethod* meth) {
+ printf("[%d] executing %s %s at %d\n", mvm::Thread::self(), meth->printString(),
+ opcode, index);
+ fflush(stdout);
+}
+
+extern "C" void jniProceedPendingException() {
+ JavaThread* th = JavaThread::get();
+ jmp_buf* buf = th->sjlj_buffers.back();
+ th->sjlj_buffers.pop_back();
+ free(buf);
+ if (JavaThread::get()->pendingException) {
+ th->throwPendingException();
+ }
+}
+
+extern "C" void* getSJLJBuffer() {
+ JavaThread* th = JavaThread::get();
+ void** buf = (void**)malloc(sizeof(jmp_buf));
+ th->sjlj_buffers.push_back((jmp_buf*)buf);
+ return (void*)buf;
+}
+
+extern "C" void nullPointerException() {
+ JavaThread::get()->isolate->nullPointerException("null");
+}
+
+extern "C" void classCastException(JavaObject* obj, CommonClass* cl) {
+ JavaThread::get()->isolate->classCastException("");
+}
+
+extern "C" void indexOutOfBoundsException(JavaObject* obj, sint32 index) {
+ JavaThread::get()->isolate->indexOutOfBounds(obj, index);
+}
+
+#ifndef SINGLE_VM
+extern "C" JavaObject* getStaticInstance(Class* cl) {
+ if (cl->isolate == Jnjvm::bootstrapVM) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ std::pair<uint8, JavaObject*>* val = vm->statics->lookup(cl);
+ if (!val) {
+ cl->initialiseClass();
+ val = vm->statics->lookup(cl);
+ }
+ return val->second;
+ } else {
+ return cl->_staticInstance;
+ }
+}
+
+extern "C" JavaObject* getClassDelegatee(CommonClass* cl) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ return vm->getClassDelegatee(cl);
+}
+#endif
+
+void JavaJIT::runtimeInitialise() {
+ void* p;
+ p = (void*)&runtimeUTF8ToStr;
+ p = (void*)&fieldLookup;
+ p = (void*)&virtualLookup;
+ p = (void*)&printExecution;
+ p = (void*)&jniProceedPendingException;
+ p = (void*)&nullPointerException;
+ p = (void*)&classCastException;
+ p = (void*)&indexOutOfBoundsException;
+#ifndef SINGLE_VM
+ p = (void*)&getStaticInstance;
+ p = (void*)&getClassDelegatee;
+#endif
+}
+
+extern "C" Class* newLookup(Class* caller, uint32 index, Class** toAlloc) {
+ JavaCtpInfo* ctpInfo = caller->ctpInfo;
+ Class* cl = (Class*)ctpInfo->loadClass(index);
+ cl->resolveClass(true);
+
+ *toAlloc = cl;
+ return cl;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaString.cpp b/vmkit/lib/JnJVM/VMCore/JavaString.cpp
new file mode 100644
index 0000000..1c12d24
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaString.cpp
@@ -0,0 +1,46 @@
+//===-- JavaString.cpp - Internal correspondance with Java Strings --------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaString.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+
+using namespace jnjvm;
+
+
+JavaString* JavaString::stringDup(const UTF8*& utf8, Jnjvm* vm) {
+ JavaString* res = (JavaString*)(*Classpath::newString)();
+ // no need to call the function
+ // Classpath::initString->run(res, utf8, 0, utf8->size, true);
+ res->value = utf8;
+ res->count = utf8->size;
+ res->offset = 0;
+ res->cachedHashCode = 0;
+ return res;
+}
+
+char* JavaString::strToAsciiz() {
+ mvm::NativeString* buf = mvm::NativeString::alloc(count + 1);
+ for (sint32 i = 0; i < count; ++i) {
+ buf->setAt(i, value->elements[i + offset]);
+ }
+ buf->setAt(count, 0);
+ return buf->cString();
+}
+
+const UTF8* JavaString::strToUTF8(Jnjvm* vm) {
+ const UTF8* utf8 = this->value;
+ if (offset || (offset + count <= utf8->size)) {
+ return utf8->extract(vm, offset, offset + count);
+ } else {
+ return utf8;
+ }
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaString.h b/vmkit/lib/JnJVM/VMCore/JavaString.h
new file mode 100644
index 0000000..7abe4ce
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaString.h
@@ -0,0 +1,43 @@
+//===--- JavaString.h - Internal correspondance with Java Strings ---------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_STRING_H
+#define JNJVM_JAVA_STRING_H
+
+#include "types.h"
+
+#include "JavaObject.h"
+
+namespace jnjvm {
+
+class UTF8;
+class Jnjvm;
+
+class JavaString : public JavaObject {
+public:
+ static VirtualTable* VT;
+ virtual void print(mvm::PrintBuffer* buf) const {
+ buf->write("Java string");
+ }
+ virtual void tracer(size_t sz);
+
+ // CLASSPATH FIELDS!!
+ const UTF8* value;
+ sint32 count;
+ sint32 cachedHashCode;
+ sint32 offset;
+
+ static JavaString* stringDup(const UTF8*& utf8, Jnjvm* vm);
+ char* strToAsciiz();
+ const UTF8* strToUTF8(Jnjvm* vm);
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaThread.cpp b/vmkit/lib/JnJVM/VMCore/JavaThread.cpp
new file mode 100644
index 0000000..ca14c53
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaThread.cpp
@@ -0,0 +1,117 @@
+//===--------- JavaThread.cpp - Java thread description -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Target/TargetData.h"
+
+#include "mvm/JIT.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Key.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Thread.h"
+
+#include "JavaClass.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+#include "JnjvmModuleProvider.h"
+
+using namespace jnjvm;
+
+const unsigned int JavaThread::StateRunning = 0;
+const unsigned int JavaThread::StateWaiting = 1;
+const unsigned int JavaThread::StateInterrupted = 2;
+
+void JavaThread::print(mvm::PrintBuffer* buf) const {
+ buf->write("Thread:");
+ javaThread->print(buf);
+}
+
+void JavaThread::destroyer(size_t sz) {
+ delete perFunctionPasses;
+}
+
+JavaThread* JavaThread::get() {
+ return threadKey->get();
+}
+
+extern void AddStandardCompilePasses(llvm::FunctionPassManager*);
+
+JavaThread* JavaThread::allocate(JavaObject* thread, Jnjvm* isolate) {
+ JavaThread* key = gc_new(JavaThread)();
+ key->javaThread = thread;
+ key->isolate = isolate;
+ key->lock = mvm::Lock::allocNormal();
+ key->varcond = mvm::Cond::allocCond();
+ key->interruptFlag = 0;
+ key->state = StateRunning;
+ key->self = mvm::Thread::self();
+ key->pendingException = 0;
+ key->perFunctionPasses = new llvm::FunctionPassManager(isolate->TheModuleProvider);
+ key->perFunctionPasses->add(new llvm::TargetData(isolate->module));
+ AddStandardCompilePasses(key->perFunctionPasses);
+ return key;
+}
+
+JavaObject* JavaThread::currentThread() {
+ JavaThread* result = get();
+ if (result != 0)
+ return result->javaThread;
+ else
+ return 0;
+}
+
+extern "C" void* __cxa_allocate_exception(unsigned);
+extern "C" void __cxa_throw(void*, void*, void*);
+
+void* JavaThread::getException() {
+ return (void*)((char*)JavaThread::get()->internalPendingException - 8 * sizeof(void*));
+}
+
+JavaObject* JavaThread::getJavaException() {
+ return JavaThread::get()->pendingException;
+}
+
+
+void JavaThread::throwException(JavaObject* obj) {
+ JavaThread* th = JavaThread::get();
+ assert(th->pendingException == 0 && "pending exception already there?");
+ th->pendingException = obj;
+ void* exc = __cxa_allocate_exception(0);
+ th->internalPendingException = exc;
+ __cxa_throw(exc, 0, 0);
+}
+
+void JavaThread::throwPendingException() {
+ JavaThread* th = JavaThread::get();
+ assert(th->pendingException);
+ void* exc = __cxa_allocate_exception(0);
+ th->internalPendingException = exc;
+ __cxa_throw(exc, 0, 0);
+}
+
+void JavaThread::clearException() {
+ JavaThread* th = JavaThread::get();
+ th->pendingException = 0;
+ th->internalPendingException = 0;
+}
+
+bool JavaThread::compareException(Class* cl) {
+ JavaObject* pe = JavaThread::get()->pendingException;
+ assert(pe && "no pending exception?");
+ bool val = pe->classOf->subclassOf(cl);
+ return val;
+}
+
+void JavaThread::returnFromNative() {
+ assert(sjlj_buffers.size());
+ longjmp((__jmp_buf_tag*)sjlj_buffers.back(), 1);
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaThread.h b/vmkit/lib/JnJVM/VMCore/JavaThread.h
new file mode 100644
index 0000000..b5ffc66
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaThread.h
@@ -0,0 +1,70 @@
+//===----------- JavaThread.h - Java thread description -------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_THREAD_H
+#define JNJVM_JAVA_THREAD_H
+
+#include <setjmp.h>
+
+#include "llvm/PassManager.h"
+
+#include "mvm/Object.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Key.h"
+#include "mvm/Threads/Locks.h"
+
+namespace jnjvm {
+
+class Class;
+class JavaObject;
+class Jnjvm;
+
+class JavaThread : public mvm::Object {
+public:
+ static VirtualTable *VT;
+ JavaObject* javaThread;
+ Jnjvm* isolate;
+ mvm::Lock* lock;
+ mvm::Cond* varcond;
+ JavaObject* pendingException;
+ void* internalPendingException;
+ unsigned int self;
+ unsigned int interruptFlag;
+ unsigned int state;
+ llvm::FunctionPassManager* perFunctionPasses;
+ std::vector<jmp_buf*> sjlj_buffers;
+
+ static const unsigned int StateRunning;
+ static const unsigned int StateWaiting;
+ static const unsigned int StateInterrupted;
+
+ JavaObject* cacheObject; // cache for allocations patching
+
+ virtual void print(mvm::PrintBuffer *buf) const;
+ virtual void tracer(size_t sz);
+ virtual void destroyer(size_t sz);
+
+ static mvm::Key<JavaThread>* threadKey;
+
+ static JavaThread* get();
+ static JavaThread* allocate(JavaObject* thread, Jnjvm* isolate);
+ static JavaObject* currentThread();
+
+ static void* getException();
+ static void throwException(JavaObject*);
+ static void throwPendingException();
+ static void clearException();
+ static bool compareException(Class*);
+ static JavaObject* getJavaException();
+ void returnFromNative();
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaTypes.cpp b/vmkit/lib/JnJVM/VMCore/JavaTypes.cpp
new file mode 100644
index 0000000..caadc68
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaTypes.cpp
@@ -0,0 +1,622 @@
+//===------------- JavaTypes.cpp - Java primitives ------------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+
+#include "mvm/JIT.h"
+
+#include "JavaAccess.h"
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+
+
+using namespace jnjvm;
+
+const char AssessorDesc::I_TAB = '[';
+const char AssessorDesc::I_END_REF = ';';
+const char AssessorDesc::I_PARG = '(';
+const char AssessorDesc::I_PARD = ')';
+const char AssessorDesc::I_BYTE = 'B';
+const char AssessorDesc::I_CHAR = 'C';
+const char AssessorDesc::I_DOUBLE = 'D';
+const char AssessorDesc::I_FLOAT = 'F';
+const char AssessorDesc::I_INT = 'I';
+const char AssessorDesc::I_LONG = 'J';
+const char AssessorDesc::I_REF = 'L';
+const char AssessorDesc::I_SHORT = 'S';
+const char AssessorDesc::I_VOID = 'V';
+const char AssessorDesc::I_BOOL = 'Z';
+const char AssessorDesc::I_SEP = '/';
+
+AssessorDesc* AssessorDesc::dParg = 0;
+AssessorDesc* AssessorDesc::dPard = 0;
+AssessorDesc* AssessorDesc::dVoid = 0;
+AssessorDesc* AssessorDesc::dBool = 0;
+AssessorDesc* AssessorDesc::dByte = 0;
+AssessorDesc* AssessorDesc::dChar = 0;
+AssessorDesc* AssessorDesc::dShort = 0;
+AssessorDesc* AssessorDesc::dInt = 0;
+AssessorDesc* AssessorDesc::dFloat = 0;
+AssessorDesc* AssessorDesc::dLong = 0;
+AssessorDesc* AssessorDesc::dDouble = 0;
+AssessorDesc* AssessorDesc::dTab = 0;
+AssessorDesc* AssessorDesc::dRef = 0;
+
+AssessorDesc* AssessorDesc::allocate(bool dt, char bid, uint32 nb, uint32 nw,
+ const char* name, Jnjvm* vm,
+ const llvm::Type* t,
+ const char* assocName, arrayCtor_t ctor) {
+ AssessorDesc* res = gc_new(AssessorDesc)();
+ res->doTrace = dt;
+ res->byteId = bid;
+ res->nbb = nb;
+ res->nbw = nw;
+ res->asciizName = name;
+ res->llvmType = t;
+ if (t && t != llvm::Type::VoidTy) {
+ res->llvmTypePtr = llvm::PointerType::getUnqual(t);
+ res->llvmNullConstant = llvm::Constant::getNullValue(t);
+ }
+ res->arrayCtor = ctor;
+ if (assocName)
+ res->assocClassName = vm->asciizConstructUTF8(assocName);
+ else
+ res->assocClassName = 0;
+
+ if (bid != I_PARG && bid != I_PARD && bid != I_REF && bid != I_TAB) {
+ res->classType = vm->constructClass(vm->asciizConstructUTF8(name),
+ CommonClass::jnjvmClassLoader);
+ res->classType->status = ready;
+ res->classType->access = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC;
+ } else {
+ res->classType = 0;
+ }
+ return res;
+}
+
+void AssessorDesc::initialise(Jnjvm* vm) {
+
+ dParg = AssessorDesc::allocate(false, I_PARG, 0, 0, "(", vm, 0, 0, 0);
+ dPard = AssessorDesc::allocate(false, I_PARD, 0, 0, ")", vm, 0, 0, 0);
+ dVoid = AssessorDesc::allocate(false, I_VOID, 0, 0, "void", vm,
+ llvm::Type::VoidTy, "java/lang/Void", 0);
+ dBool = AssessorDesc::allocate(false, I_BOOL, 1, 1, "boolean", vm,
+ llvm::Type::Int8Ty, "java/lang/Boolean",
+ (arrayCtor_t)ArrayUInt8::acons);
+ dByte = AssessorDesc::allocate(false, I_BYTE, 1, 1, "byte", vm,
+ llvm::Type::Int8Ty, "java/lang/Byte",
+ (arrayCtor_t)ArraySInt8::acons);
+ dChar = AssessorDesc::allocate(false, I_CHAR, 2, 1, "char", vm,
+ llvm::Type::Int16Ty, "java/lang/Character",
+ (arrayCtor_t)ArrayUInt16::acons);
+ dShort = AssessorDesc::allocate(false, I_SHORT, 2, 1, "short", vm,
+ llvm::Type::Int16Ty, "java/lang/Short",
+ (arrayCtor_t)ArraySInt16::acons);
+ dInt = AssessorDesc::allocate(false, I_INT, 4, 1, "int", vm,
+ llvm::Type::Int32Ty, "java/lang/Integer",
+ (arrayCtor_t)ArraySInt32::acons);
+ dFloat = AssessorDesc::allocate(false, I_FLOAT, 4, 1, "float", vm,
+ llvm::Type::FloatTy, "java/lang/Float",
+ (arrayCtor_t)ArrayFloat::acons);
+ dLong = AssessorDesc::allocate(false, I_LONG, 8, 2, "long", vm,
+ llvm::Type::Int64Ty, "java/lang/Long",
+ (arrayCtor_t)ArrayLong::acons);
+ dDouble = AssessorDesc::allocate(false, I_DOUBLE, 8, 2, "double", vm,
+ llvm::Type::DoubleTy, "java/lang/Double",
+ (arrayCtor_t)ArrayDouble::acons);
+ dTab = AssessorDesc::allocate(true, I_TAB, 4, 1, "array", vm,
+ JavaObject::llvmType, 0,
+ (arrayCtor_t)ArrayObject::acons);
+ dRef = AssessorDesc::allocate(true, I_REF, 4, 1, "reference", vm,
+ JavaObject::llvmType, 0,
+ (arrayCtor_t)ArrayObject::acons);
+
+ mvm::Object::pushRoot((mvm::Object*)dParg);
+ mvm::Object::pushRoot((mvm::Object*)dPard);
+ mvm::Object::pushRoot((mvm::Object*)dVoid);
+ mvm::Object::pushRoot((mvm::Object*)dBool);
+ mvm::Object::pushRoot((mvm::Object*)dByte);
+ mvm::Object::pushRoot((mvm::Object*)dChar);
+ mvm::Object::pushRoot((mvm::Object*)dShort);
+ mvm::Object::pushRoot((mvm::Object*)dInt);
+ mvm::Object::pushRoot((mvm::Object*)dFloat);
+ mvm::Object::pushRoot((mvm::Object*)dLong);
+ mvm::Object::pushRoot((mvm::Object*)dDouble);
+ mvm::Object::pushRoot((mvm::Object*)dTab);
+ mvm::Object::pushRoot((mvm::Object*)dRef);
+}
+
+void AssessorDesc::print(mvm::PrintBuffer* buf) const {
+ buf->write("AssessorDescriptor<");
+ buf->write(asciizName);
+ buf->write(">");
+}
+
+static void typeError(const UTF8* name, short int l) {
+ if (l != 0) {
+ JavaThread::get()->isolate->
+ unknownError("wrong type %d in %s", l, name->printString());
+ } else {
+ JavaThread::get()->isolate->
+ unknownError("wrong type %s", name->printString());
+ }
+}
+
+
+void AssessorDesc::analyseIntern(const UTF8* name, uint32 pos,
+ uint32 meth, AssessorDesc*& ass,
+ uint32& ret) {
+ short int cur = name->at(pos);
+ if (cur == I_PARG) {
+ ass = dParg;
+ ret = pos + 1;
+ } else if (cur == I_PARD) {
+ ass = dPard;
+ ret = pos + 1;
+ } else if (cur == I_BOOL) {
+ ass = dBool;
+ ret = pos + 1;
+ } else if (cur == I_BYTE) {
+ ass = dByte;
+ ret = pos + 1;
+ } else if (cur == I_CHAR) {
+ ass = dChar;
+ ret = pos + 1;
+ } else if (cur == I_SHORT) {
+ ass = dShort;
+ ret = pos + 1;
+ } else if (cur == I_INT) {
+ ass = dInt;
+ ret = pos + 1;
+ } else if (cur == I_FLOAT) {
+ ass = dFloat;
+ ret = pos + 1;
+ } else if (cur == I_DOUBLE) {
+ ass = dDouble;
+ ret = pos + 1;
+ } else if (cur == I_LONG) {
+ ass = dLong;
+ ret = pos + 1;
+ } else if (cur == I_VOID) {
+ ass = dVoid;
+ ret = pos + 1;
+ } else if (cur == I_TAB) {
+ if (meth == 1) {
+ pos++;
+ } else {
+ AssessorDesc * typeIntern = dTab;
+ while (name->at(++pos) == I_TAB);
+ analyseIntern(name, pos, 1, typeIntern, pos);
+ }
+ ass = dTab;
+ ret = pos;
+ } else if (cur == I_REF) {
+ if (meth != 2) {
+ while (name->at(++pos) != I_END_REF);
+ }
+ ass = dRef;
+ ret = pos + 1;
+ } else {
+ typeError(name, cur);
+ }
+}
+
+const UTF8* AssessorDesc::constructArrayName(Jnjvm *vm, AssessorDesc* ass,
+ uint32 steps,
+ const UTF8* className) {
+ if (ass) {
+ uint16* buf = (uint16*)alloca((steps + 1) * sizeof(uint16));
+ for (uint32 i = 0; i < steps; i++) {
+ buf[i] = I_TAB;
+ }
+ buf[steps] = ass->byteId;
+ return UTF8::readerConstruct(vm, buf, steps + 1);
+ } else {
+ uint32 len = className->size;
+ uint32 pos = steps;
+ AssessorDesc * funcs = (className->at(0) == I_TAB ? dTab : dRef);
+ uint32 n = steps + len + (funcs == dRef ? 2 : 0);
+ uint16* buf = (uint16*)alloca(n * sizeof(uint16));
+
+ for (uint32 i = 0; i < steps; i++) {
+ buf[i] = I_TAB;
+ }
+
+ if (funcs == dRef) {
+ ++pos;
+ buf[steps] = funcs->byteId;
+ }
+
+ for (uint32 i = 0; i < len; i++) {
+ buf[pos + i] = className->at(i);
+ }
+
+ if (funcs == dRef) {
+ buf[n - 1] = I_END_REF;
+ }
+
+ return UTF8::readerConstruct(vm, buf, n);
+ }
+}
+
+void AssessorDesc::introspectArrayName(Jnjvm *vm, const UTF8* utf8,
+ uint32 start, AssessorDesc*& ass,
+ const UTF8*& res) {
+ uint32 pos = 0;
+ uint32 intern = 0;
+ AssessorDesc* funcs = 0;
+
+ analyseIntern(utf8, start, 1, funcs, intern);
+
+ if (funcs != dTab) {
+ vm->unknownError("%s isn't an array", utf8->printString());
+ }
+
+ analyseIntern(utf8, intern, 0, funcs, pos);
+
+ if (funcs == dRef) {
+ ass = dRef;
+ res = utf8->extract(vm, intern + 1, pos - 1);
+ } else if (funcs == dTab) {
+ ass = dTab;
+ res = utf8->extract(vm, intern, pos);
+ } else {
+ ass = funcs;
+ res = 0;
+ }
+}
+
+void AssessorDesc::introspectArray(Jnjvm *vm, JavaObject* loader,
+ const UTF8* utf8, uint32 start,
+ AssessorDesc*& ass, CommonClass*& res) {
+ uint32 pos = 0;
+ uint32 intern = 0;
+ AssessorDesc* funcs = 0;
+
+ analyseIntern(utf8, start, 1, funcs, intern);
+
+ if (funcs != dTab) {
+ vm->unknownError("%s isn't an array", utf8->printString());
+ }
+
+ analyseIntern(utf8, intern, 0, funcs, pos);
+
+ if (funcs == dRef) {
+ ass = dRef;
+ res = vm->loadName(utf8->extract(vm, intern + 1, pos - 1), loader, false,
+ false, true);
+ } else if (funcs == dTab) {
+ ass = dTab;
+ res = vm->constructArray(utf8->extract(vm, intern, pos), loader);
+ } else {
+ ass = funcs;
+ res = funcs->classType;
+ }
+}
+
+static void _arrayType(Jnjvm *vm, unsigned int t, AssessorDesc*& funcs,
+ llvm::Function*& ctor) {
+ if (t == JavaArray::T_CHAR) {
+ funcs = AssessorDesc::dChar;
+ ctor = JavaJIT::UTF8AconsLLVM;
+ } else if (t == JavaArray::T_BOOLEAN) {
+ funcs = AssessorDesc::dBool;
+ ctor = JavaJIT::Int8AconsLLVM;
+ } else if (t == JavaArray::T_INT) {
+ funcs = AssessorDesc::dInt;
+ ctor = JavaJIT::Int32AconsLLVM;
+ } else if (t == JavaArray::T_SHORT) {
+ funcs = AssessorDesc::dShort;
+ ctor = JavaJIT::Int16AconsLLVM;
+ } else if (t == JavaArray::T_BYTE) {
+ funcs = AssessorDesc::dByte;
+ ctor = JavaJIT::Int8AconsLLVM;
+ } else if (t == JavaArray::T_FLOAT) {
+ funcs = AssessorDesc::dFloat;
+ ctor = JavaJIT::FloatAconsLLVM;
+ } else if (t == JavaArray::T_LONG) {
+ funcs = AssessorDesc::dLong;
+ ctor = JavaJIT::LongAconsLLVM;
+ } else if (t == JavaArray::T_DOUBLE) {
+ funcs = AssessorDesc::dDouble;
+ ctor = JavaJIT::DoubleAconsLLVM;
+ } else {
+ vm->unknownError("unknown array type %d\n", t);
+ }
+}
+
+void AssessorDesc::arrayType(Jnjvm *vm, JavaObject* loader, unsigned int t,
+ ClassArray*& cl, AssessorDesc*& ass,
+ llvm::Function*& ctr) {
+ _arrayType(vm, t, ass, ctr);
+ cl = vm->constructArray(constructArrayName(vm, ass, 1, 0), loader);
+ assert(cl);
+}
+
+void Typedef::tPrintBuf(mvm::PrintBuffer* buf) const {
+ if (pseudoAssocClassName == 0)
+ buf->write(funcs->asciizName);
+ else
+ CommonClass::printClassName(pseudoAssocClassName, buf);
+}
+
+AssessorDesc* AssessorDesc::byteIdToPrimitive(char id) {
+ if (id == I_FLOAT) {
+ return dFloat;
+ } else if (id == I_INT) {
+ return dInt;
+ } else if (id == I_SHORT) {
+ return dShort;
+ } else if (id == I_CHAR) {
+ return dChar;
+ } else if (id == I_DOUBLE) {
+ return dDouble;
+ } else if (id == I_BYTE) {
+ return dByte;
+ } else if (id == I_BOOL) {
+ return dBool;
+ } else if (id == I_LONG) {
+ return dLong;
+ } else if (id == I_VOID) {
+ return dVoid;
+ } else {
+ return 0;
+ }
+}
+
+AssessorDesc* AssessorDesc::classToPrimitive(CommonClass* cl) {
+ const UTF8* name = cl->name;
+ if (name == dFloat->assocClassName) {
+ return dFloat;
+ } else if (name == dInt->assocClassName) {
+ return dInt;
+ } else if (name == dShort->assocClassName) {
+ return dShort;
+ } else if (name == dChar->assocClassName) {
+ return dChar;
+ } else if (name == dDouble->assocClassName) {
+ return dDouble;
+ } else if (name == dByte->assocClassName) {
+ return dByte;
+ } else if (name == dBool->assocClassName) {
+ return dBool;
+ } else if (name == dLong->assocClassName) {
+ return dLong;
+ } else if (name == dVoid->assocClassName) {
+ return dVoid;
+ } else {
+ return 0;
+ }
+}
+
+AssessorDesc* AssessorDesc::bogusClassToPrimitive(CommonClass* cl) {
+ if (cl == dFloat->classType) {
+ return dFloat;
+ } else if (cl == dInt->classType) {
+ return dInt;
+ } else if (cl == dShort->classType) {
+ return dShort;
+ } else if (cl == dChar->classType) {
+ return dChar;
+ } else if (cl == dDouble->classType) {
+ return dDouble;
+ } else if (cl == dByte->classType) {
+ return dByte;
+ } else if (cl == dBool->classType) {
+ return dBool;
+ } else if (cl == dLong->classType) {
+ return dLong;
+ } else if (cl == dVoid->classType) {
+ return dVoid;
+ } else {
+ return 0;
+ }
+}
+
+void Typedef::print(mvm::PrintBuffer* buf) const {
+ buf->write("Type<");
+ tPrintBuf(buf);
+ buf->write(">");
+}
+
+CommonClass* Typedef::assocClass(JavaObject* loader) {
+ if (pseudoAssocClassName == 0) {
+ return funcs->classType;
+ } else if (funcs == AssessorDesc::dRef) {
+ return isolate->loadName(pseudoAssocClassName, loader, false, true, true);
+ } else {
+ return isolate->constructArray(pseudoAssocClassName, loader);
+ }
+}
+
+void Typedef::humanPrintArgs(const std::vector<Typedef*>* args,
+ mvm::PrintBuffer* buf) {
+ buf->write("(");
+ for (uint32 i = 0; i < args->size(); i++) {
+ args->at(i)->tPrintBuf(buf);
+ if (i != args->size() - 1) {
+ buf->write(", ");
+ }
+ }
+ buf->write(")");
+}
+
+void Signdef::print(mvm::PrintBuffer* buf) const {
+ buf->write("Signature<");
+ ret->tPrintBuf(buf);
+ buf->write("...");
+ Typedef::humanPrintArgs(&args, buf);
+ buf->write(">");
+}
+
+const llvm::FunctionType* Signdef::createVirtualType(
+ const std::vector<Typedef*>* args, Typedef* ret) {
+ std::vector<const llvm::Type*> llvmArgs;
+ unsigned int size = args->size();
+
+ llvmArgs.push_back(JavaObject::llvmType);
+
+ for (uint32 i = 0; i < size; ++i) {
+ llvmArgs.push_back(args->at(i)->funcs->llvmType);
+ }
+
+
+ mvm::jit::protectTypes();//->lock();
+ llvm::FunctionType* res = llvm::FunctionType::get(ret->funcs->llvmType,
+ llvmArgs, false);
+ mvm::jit::unprotectTypes();//->unlock();
+
+ return res;
+
+}
+
+const llvm::FunctionType* Signdef::createStaticType(
+ const std::vector<Typedef*>* args, Typedef* ret) {
+ std::vector<const llvm::Type*> llvmArgs;
+ unsigned int size = args->size();
+
+
+ for (uint32 i = 0; i < size; ++i) {
+ llvmArgs.push_back(args->at(i)->funcs->llvmType);
+ }
+
+ mvm::jit::protectTypes();//->lock();
+ llvm::FunctionType* res = llvm::FunctionType::get(ret->funcs->llvmType,
+ llvmArgs, false);
+ mvm::jit::unprotectTypes();//->unlock();
+
+ return res;
+}
+
+const llvm::FunctionType* Signdef::createNativeType(
+ const std::vector<Typedef*>* args, Typedef* ret) {
+ std::vector<const llvm::Type*> llvmArgs;
+ unsigned int size = args->size();
+
+ llvmArgs.push_back(mvm::jit::ptrType); // JNIEnv
+ llvmArgs.push_back(JavaObject::llvmType); // Class
+
+ for (uint32 i = 0; i < size; ++i) {
+ llvmArgs.push_back(args->at(i)->funcs->llvmType);
+ }
+
+
+ mvm::jit::protectTypes();//->lock();
+ llvm::FunctionType* res = llvm::FunctionType::get(ret->funcs->llvmType,
+ llvmArgs, false);
+ mvm::jit::unprotectTypes();//->unlock();
+
+ return res;
+}
+
+void Signdef::printWithSign(CommonClass* cl, const UTF8* name,
+ mvm::PrintBuffer* buf) {
+ ret->tPrintBuf(buf);
+ buf->write(" ");
+ CommonClass::printClassName(cl->name, buf);
+ buf->write("::");
+ name->print(buf);
+ humanPrintArgs(&args, buf);
+}
+
+unsigned int Signdef::nbInWithThis(unsigned int flag) {
+ return args.size() + (isStatic(flag) ? 0 : 1);
+}
+
+Signdef* Signdef::signDup(const UTF8* name, Jnjvm *vm) {
+ std::vector<Typedef*> buf;
+ uint32 len = (uint32)name->size;
+ uint32 pos = 1;
+ uint32 pred = 0;
+ AssessorDesc* funcs = 0;
+
+ while (pos < len) {
+ pred = pos;
+ AssessorDesc::analyseIntern(name, pos, 0, funcs, pos);
+ if (funcs == AssessorDesc::dPard) break;
+ else {
+ buf.push_back(vm->constructType(name->extract(vm, pred, pos)));
+ }
+ }
+
+ if (pos == len) {
+ typeError(name, 0);
+ }
+
+ AssessorDesc::analyseIntern(name, pos, 0, funcs, pred);
+
+ if (pred != len) {
+ typeError(name, 0);
+ }
+
+ Signdef* res = gc_new(Signdef)();
+ res->args = buf;
+ res->ret = vm->constructType(name->extract(vm, pos, pred));
+ res->isolate = vm;
+ res->keyName = name;
+ res->pseudoAssocClassName = name;
+ res->funcs = 0;
+ res->nbIn = buf.size();
+ res->_virtualCallBuf = 0;
+ res->_staticCallBuf = 0;
+ res->_virtualCallAP = 0;
+ res->_staticCallAP = 0;
+ res->staticType = Signdef::createStaticType(&buf, res->ret);
+ res->virtualType = Signdef::createVirtualType(&buf, res->ret);
+ res->nativeType = Signdef::createNativeType(&buf, res->ret);
+ mvm::jit::protectTypes();//->lock();
+ res->staticTypePtr = llvm::PointerType::getUnqual(res->staticType);
+ res->virtualTypePtr = llvm::PointerType::getUnqual(res->virtualType);
+ res->nativeTypePtr = llvm::PointerType::getUnqual(res->nativeType);
+
+ std::vector<const llvm::Type*> Args;
+ Args.push_back(res->staticTypePtr);
+ Args.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
+ res->staticBufType = llvm::FunctionType::get(res->ret->funcs->llvmType, Args, false);
+
+ std::vector<const llvm::Type*> Args2;
+ Args2.push_back(res->virtualTypePtr);
+ Args2.push_back(JavaObject::llvmType);
+ Args2.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
+ res->virtualBufType = llvm::FunctionType::get(res->ret->funcs->llvmType, Args2, false);
+
+ mvm::jit::unprotectTypes();//->unlock();
+ return res;
+
+}
+
+Typedef* Typedef::typeDup(const UTF8* name, Jnjvm *vm) {
+ AssessorDesc* funcs = 0;
+ uint32 next;
+ AssessorDesc::analyseIntern(name, 0, 0, funcs, next);
+
+ if (funcs == AssessorDesc::dParg) {
+ return Signdef::signDup(name, vm);
+ } else {
+ Typedef* res = gc_new(Typedef)();
+ res->isolate = vm;
+ res->keyName = name;
+ res->funcs = funcs;
+ if (funcs == AssessorDesc::dRef) {
+ res->pseudoAssocClassName = name->extract(vm, 1, next - 1);
+ } else if (funcs == AssessorDesc::dTab) {
+ res->pseudoAssocClassName = name;
+ }
+ return res;
+ }
+
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaTypes.h b/vmkit/lib/JnJVM/VMCore/JavaTypes.h
new file mode 100644
index 0000000..73055ee
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaTypes.h
@@ -0,0 +1,181 @@
+//===--------------- JavaTypes.h - Java primitives ------------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_TYPES_H
+#define JNJVM_JAVA_TYPES_H
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+
+#include "mvm/Object.h"
+
+#include "types.h"
+
+#include "JavaArray.h"
+
+namespace jnjvm {
+
+class CommonClass;
+class JavaJIT;
+class JavaObject;
+class Jnjvm;
+class UTF8;
+
+class AssessorDesc : public mvm::Object {
+public:
+ static VirtualTable *VT;
+ static const char I_TAB;
+ static const char I_END_REF;
+ static const char I_PARG;
+ static const char I_PARD;
+ static const char I_BYTE;
+ static const char I_CHAR;
+ static const char I_DOUBLE;
+ static const char I_FLOAT;
+ static const char I_INT;
+ static const char I_LONG;
+ static const char I_REF;
+ static const char I_SHORT;
+ static const char I_VOID;
+ static const char I_BOOL;
+ static const char I_SEP;
+
+ bool doTrace;
+ char byteId;
+ uint32 nbb;
+ uint32 nbw;
+
+ const char* asciizName;
+ CommonClass* classType;
+ const llvm::Type* llvmType;
+ const llvm::Type* llvmTypePtr;
+ llvm::Constant* llvmNullConstant;
+ const UTF8* assocClassName;
+ arrayCtor_t arrayCtor;
+
+ static AssessorDesc* dParg;
+ static AssessorDesc* dPard;
+ static AssessorDesc* dVoid;
+ static AssessorDesc* dBool;
+ static AssessorDesc* dByte;
+ static AssessorDesc* dChar;
+ static AssessorDesc* dShort;
+ static AssessorDesc* dInt;
+ static AssessorDesc* dFloat;
+ static AssessorDesc* dLong;
+ static AssessorDesc* dDouble;
+ static AssessorDesc* dTab;
+ static AssessorDesc* dRef;
+
+ static AssessorDesc* allocate(bool dt, char bid, uint32 nb, uint32 nw,
+ const char* name, Jnjvm* vm,
+ const llvm::Type* type, const char* assocName,
+ arrayCtor_t ctor);
+
+ static void initialise(Jnjvm* vm);
+
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ static void analyseIntern(const UTF8* name, uint32 pos,
+ uint32 meth, AssessorDesc*& ass,
+ uint32& ret);
+
+ static const UTF8* constructArrayName(Jnjvm *vm, AssessorDesc* ass,
+ uint32 steps, const UTF8* className);
+
+ static void introspectArrayName(Jnjvm *vm, const UTF8* utf8, uint32 start,
+ AssessorDesc*& ass, const UTF8*& res);
+
+ static void introspectArray(Jnjvm *vm, JavaObject* loader, const UTF8* utf8,
+ uint32 start, AssessorDesc*& ass,
+ CommonClass*& res);
+
+ static void arrayType(Jnjvm *vm, JavaObject* loader, unsigned int t,
+ ClassArray*& cl, AssessorDesc*& ass,
+ llvm::Function*& ctr);
+
+ static AssessorDesc* byteIdToPrimitive(const char id);
+ static AssessorDesc* classToPrimitive(CommonClass* cl);
+ static AssessorDesc* bogusClassToPrimitive(CommonClass* cl);
+
+};
+
+
+class Typedef : public mvm::Object {
+public:
+ static VirtualTable *VT;
+ const UTF8* keyName;
+ const UTF8* pseudoAssocClassName;
+ const AssessorDesc* funcs;
+ Jnjvm* isolate;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ CommonClass* assocClass(JavaObject* loader);
+ void typePrint(mvm::PrintBuffer* buf);
+ static void humanPrintArgs(const std::vector<Typedef*>*, mvm::PrintBuffer* buf);
+ static Typedef* typeDup(const UTF8* name, Jnjvm* vm);
+ void tPrintBuf(mvm::PrintBuffer* buf) const;
+
+};
+
+class Signdef : public Typedef {
+public:
+ static VirtualTable *VT;
+ std::vector<Typedef*> args;
+ Typedef* ret;
+ const llvm::FunctionType* staticType;
+ const llvm::FunctionType* virtualType;
+ const llvm::FunctionType* nativeType;
+ const llvm::FunctionType* virtualBufType;
+ const llvm::FunctionType* staticBufType;
+ const llvm::PointerType* staticTypePtr;
+ const llvm::PointerType* virtualTypePtr;
+ const llvm::PointerType* nativeTypePtr;
+ mvm::Code* _staticCallBuf;
+ mvm::Code* _virtualCallBuf;
+ mvm::Code* _staticCallAP;
+ mvm::Code* _virtualCallAP;
+ uint32 nbIn;
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+
+ static const llvm::FunctionType* createVirtualType(
+ const std::vector<Typedef*>*, Typedef*);
+
+ static const llvm::FunctionType* createStaticType(
+ const std::vector<Typedef*>*, Typedef*);
+
+ static const llvm::FunctionType* createNativeType(
+ const std::vector<Typedef*>*, Typedef*);
+
+ llvm::Function* createFunctionCallBuf(bool virt);
+ llvm::Function* createFunctionCallAP(bool virt);
+ void createFuncPtrsCalls();
+
+
+
+ void printWithSign(CommonClass* cl, const UTF8* name, mvm::PrintBuffer* buf);
+ unsigned int nbInWithThis(unsigned int flag);
+ static Signdef* signDup(const UTF8* name, Jnjvm* vm);
+
+ void* staticCallBuf();
+ void* virtualCallBuf();
+ void* staticCallAP();
+ void* virtualCallAP();
+
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JavaUpcalls.cpp b/vmkit/lib/JnJVM/VMCore/JavaUpcalls.cpp
new file mode 100644
index 0000000..ae0f44c
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaUpcalls.cpp
@@ -0,0 +1,308 @@
+//===-------- JavaUpcalls.cpp - Upcalls to Java entities ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+
+#include "JavaAccess.h"
+#include "JavaClass.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+
+#define COMPILE_METHODS(cl) \
+ for (std::vector<JavaMethod*>::iterator i = cl->virtualMethods.begin(), \
+ e = cl->virtualMethods.end(); i!= e; ++i) { \
+ (*i)->compiledPtr(); \
+ } \
+ \
+ for (std::vector<JavaMethod*>::iterator i = cl->staticMethods.begin(), \
+ e = cl->staticMethods.end(); i!= e; ++i) { \
+ (*i)->compiledPtr(); \
+ }
+
+
+using namespace jnjvm;
+
+Class* ClasspathThread::newThread;
+Class* ClasspathThread::newVMThread;
+JavaField* ClasspathThread::assocThread;
+JavaField* ClasspathThread::vmdata;
+JavaMethod* ClasspathThread::finaliseCreateInitialThread;
+JavaMethod* ClasspathThread::initVMThread;
+JavaMethod* ClasspathThread::groupAddThread;
+JavaField* ClasspathThread::name;
+JavaField* ClasspathThread::priority;
+JavaField* ClasspathThread::daemon;
+JavaField* ClasspathThread::group;
+JavaField* ClasspathThread::running;
+JavaField* ClasspathThread::rootGroup;
+JavaField* ClasspathThread::vmThread;
+JavaMethod* ClasspathThread::uncaughtException;
+
+JavaMethod* Classpath::setContextClassLoader;
+JavaMethod* Classpath::getSystemClassLoader;
+Class* Classpath::newString;
+Class* Classpath::newClass;
+Class* Classpath::newThrowable;
+Class* Classpath::newException;
+JavaMethod* Classpath::initClass;
+JavaMethod* Classpath::initClassWithProtectionDomain;
+JavaField* Classpath::vmdataClass;
+JavaMethod* Classpath::setProperty;
+JavaMethod* Classpath::initString;
+JavaMethod* Classpath::getCallingClassLoader;
+JavaMethod* Classpath::initConstructor;
+Class* Classpath::newConstructor;
+ClassArray* Classpath::constructorArrayClass;
+JavaField* Classpath::constructorSlot;
+JavaMethod* Classpath::initMethod;
+JavaMethod* Classpath::initField;
+Class* Classpath::newField;
+Class* Classpath::newMethod;
+ClassArray* Classpath::methodArrayClass;
+ClassArray* Classpath::fieldArrayClass;
+JavaField* Classpath::methodSlot;
+JavaField* Classpath::fieldSlot;
+ClassArray* Classpath::classArrayClass;
+JavaMethod* Classpath::loadInClassLoader;
+JavaMethod* Classpath::initVMThrowable;
+JavaField* Classpath::vmDataVMThrowable;
+Class* Classpath::newVMThrowable;
+JavaField* Classpath::bufferAddress;
+JavaField* Classpath::dataPointer32;
+JavaField* Classpath::vmdataClassLoader;
+
+JavaField* Classpath::boolValue;
+JavaField* Classpath::byteValue;
+JavaField* Classpath::shortValue;
+JavaField* Classpath::charValue;
+JavaField* Classpath::intValue;
+JavaField* Classpath::longValue;
+JavaField* Classpath::floatValue;
+JavaField* Classpath::doubleValue;
+
+Class* Classpath::newStackTraceElement;
+JavaMethod* Classpath::initStackTraceElement;
+
+Class* Classpath::voidClass;
+Class* Classpath::boolClass;
+Class* Classpath::byteClass;
+Class* Classpath::shortClass;
+Class* Classpath::charClass;
+Class* Classpath::intClass;
+Class* Classpath::floatClass;
+Class* Classpath::doubleClass;
+Class* Classpath::longClass;
+
+Class* Classpath::vmStackWalker;
+
+void ClasspathThread::initialise(Jnjvm* vm) {
+ newThread = UPCALL_CLASS(vm, "java/lang/Thread");
+ newVMThread = UPCALL_CLASS(vm, "java/lang/VMThread");
+ assocThread = UPCALL_FIELD(vm, "java/lang/VMThread", "thread", "Ljava/lang/Thread;", ACC_VIRTUAL);
+ vmdata = UPCALL_FIELD(vm, "java/lang/VMThread", "vmdata", "Ljava/lang/Object;", ACC_VIRTUAL);
+ finaliseCreateInitialThread = UPCALL_METHOD(vm, "java/lang/InheritableThreadLocal", "newChildThread", "(Ljava/lang/Thread;)V", ACC_STATIC);
+ initVMThread = UPCALL_METHOD(vm, "java/lang/VMThread", "<init>", "(Ljava/lang/Thread;)V", ACC_VIRTUAL);
+ groupAddThread = UPCALL_METHOD(vm, "java/lang/ThreadGroup", "addThread", "(Ljava/lang/Thread;)V", ACC_VIRTUAL);
+ name = UPCALL_FIELD(vm, "java/lang/Thread", "name", "Ljava/lang/String;", ACC_VIRTUAL);
+ priority = UPCALL_FIELD(vm, "java/lang/Thread", "priority", "I", ACC_VIRTUAL);
+ daemon = UPCALL_FIELD(vm, "java/lang/Thread", "daemon", "Z", ACC_VIRTUAL);
+ group = UPCALL_FIELD(vm, "java/lang/Thread", "group", "Ljava/lang/ThreadGroup;", ACC_VIRTUAL);
+ running = UPCALL_FIELD(vm, "java/lang/VMThread", "running", "Z", ACC_VIRTUAL);
+ rootGroup = UPCALL_FIELD(vm, "java/lang/ThreadGroup", "root", "Ljava/lang/ThreadGroup;", ACC_STATIC);
+ vmThread = UPCALL_FIELD(vm, "java/lang/Thread", "vmThread", "Ljava/lang/VMThread;", ACC_VIRTUAL);
+ uncaughtException = UPCALL_METHOD(vm, "java/lang/ThreadGroup", "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V", ACC_VIRTUAL);
+}
+
+void ClasspathThread::createInitialThread(Jnjvm* vm, JavaObject* th) {
+ JavaObject* vmth = (*newVMThread)();
+ (*th)(name, (JavaObject*)vm->asciizToStr("main"));
+ (*th)(priority, (uint32)1);
+ (*th)(daemon, (uint32)0);
+ (*th)(vmThread, vmth);
+ (*vmth)(assocThread, th);
+ (*vmth)(running, (uint32)1);
+ (*rootGroup)();
+ (*th)(group, (JavaObject*)((*rootGroup)().PointerVal));
+ groupAddThread->invokeIntSpecial((JavaObject*)((*rootGroup)().PointerVal), th);
+}
+
+void ClasspathThread::mapInitialThread(Jnjvm* vm) {
+ JavaObject* th = (*newThread)();
+ createInitialThread(vm, th);
+ JavaThread* myth = JavaThread::get();
+ myth->javaThread = th;
+ JavaObject* vmth = (JavaObject*)((*th)(vmThread).PointerVal);
+ (*vmth)(vmdata, (JavaObject*)myth);
+ finaliseCreateInitialThread->invokeIntStatic(th);
+}
+
+void Classpath::initialiseClasspath(Jnjvm* vm) {
+ getSystemClassLoader = UPCALL_METHOD(vm, "java/lang/ClassLoader", "getSystemClassLoader", "()Ljava/lang/ClassLoader;", ACC_STATIC);
+ setContextClassLoader = UPCALL_METHOD(vm, "java/lang/Thread", "setContextClassLoader", "(Ljava/lang/ClassLoader;)V", ACC_VIRTUAL);
+ newString = UPCALL_CLASS(vm, "java/lang/String");
+ newClass = UPCALL_CLASS(vm, "java/lang/Class");
+ newThrowable = UPCALL_CLASS(vm, "java/lang/Throwable");
+ newException = UPCALL_CLASS(vm, "java/lang/Exception");
+ initClass = UPCALL_METHOD(vm, "java/lang/Class", "<init>", "(Ljava/lang/Object;)V", ACC_VIRTUAL);
+ initClassWithProtectionDomain = UPCALL_METHOD(vm, "java/lang/Class", "<init>", "(Ljava/lang/Object;Ljava/security/ProtectionDomain;)V", ACC_VIRTUAL);
+ vmdataClass = UPCALL_FIELD(vm, "java/lang/Class", "vmdata", "Ljava/lang/Object;", ACC_VIRTUAL);
+ setProperty = UPCALL_METHOD(vm, "java/util/Properties", "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;", ACC_VIRTUAL);
+ initString = UPCALL_METHOD(vm, "java/lang/String", "<init>", "([CIIZ)V", ACC_VIRTUAL);
+
+ initConstructor = UPCALL_METHOD(vm, "java/lang/reflect/Constructor", "<init>", "(Ljava/lang/Class;I)V", ACC_VIRTUAL);
+ newConstructor = UPCALL_CLASS(vm, "java/lang/reflect/Constructor");
+ constructorArrayClass = UPCALL_ARRAY_CLASS(vm, "java/lang/reflect/Constructor", 1);
+ constructorSlot = UPCALL_FIELD(vm, "java/lang/reflect/Constructor", "slot", "I", ACC_VIRTUAL);
+
+ initMethod = UPCALL_METHOD(vm, "java/lang/reflect/Method", "<init>", "(Ljava/lang/Class;Ljava/lang/String;I)V", ACC_VIRTUAL);
+ newMethod = UPCALL_CLASS(vm, "java/lang/reflect/Method");
+ methodArrayClass = UPCALL_ARRAY_CLASS(vm, "java/lang/reflect/Method", 1);
+ methodSlot = UPCALL_FIELD(vm, "java/lang/reflect/Method", "slot", "I", ACC_VIRTUAL);
+
+ initField = UPCALL_METHOD(vm, "java/lang/reflect/Field", "<init>", "(Ljava/lang/Class;Ljava/lang/String;I)V", ACC_VIRTUAL);
+ newField = UPCALL_CLASS(vm, "java/lang/reflect/Field");
+ fieldArrayClass = UPCALL_ARRAY_CLASS(vm, "java/lang/reflect/Field", 1);
+ fieldSlot = UPCALL_FIELD(vm, "java/lang/reflect/Field", "slot", "I", ACC_VIRTUAL);
+
+
+ classArrayClass = UPCALL_ARRAY_CLASS(vm, "java/lang/Class", 1);
+ newVMThrowable = UPCALL_CLASS(vm, "java/lang/VMThrowable");
+ initVMThrowable = UPCALL_METHOD(vm, "java/lang/VMThrowable", "<init>", "()V", ACC_VIRTUAL);
+ vmDataVMThrowable = UPCALL_FIELD(vm, "java/lang/VMThrowable", "vmdata", "Ljava/lang/Object;", ACC_VIRTUAL);
+ bufferAddress = UPCALL_FIELD(vm, "java/nio/Buffer", "address", "Lgnu/classpath/Pointer;", ACC_VIRTUAL);
+ dataPointer32 = UPCALL_FIELD(vm, "gnu/classpath/Pointer32", "data", "I", ACC_VIRTUAL);
+ vmdataClassLoader = UPCALL_FIELD(vm, "java/lang/ClassLoader", "vmdata", "Ljava/lang/Object;", ACC_VIRTUAL);
+
+ newStackTraceElement = UPCALL_CLASS(vm, "java/lang/StackTraceElement");
+ initStackTraceElement = UPCALL_METHOD(vm, "java/lang/StackTraceElement", "<init>", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Z)V", ACC_VIRTUAL);
+
+
+ boolValue = UPCALL_FIELD(vm, "java/lang/Boolean", "value", "Z", ACC_VIRTUAL);
+ byteValue = UPCALL_FIELD(vm, "java/lang/Byte", "value", "B", ACC_VIRTUAL);
+ shortValue = UPCALL_FIELD(vm, "java/lang/Short", "value", "S", ACC_VIRTUAL);
+ charValue = UPCALL_FIELD(vm, "java/lang/Character", "value", "C", ACC_VIRTUAL);
+ intValue = UPCALL_FIELD(vm, "java/lang/Integer", "value", "I", ACC_VIRTUAL);
+ longValue = UPCALL_FIELD(vm, "java/lang/Long", "value", "J", ACC_VIRTUAL);
+ floatValue = UPCALL_FIELD(vm, "java/lang/Float", "value", "F", ACC_VIRTUAL);
+ doubleValue = UPCALL_FIELD(vm, "java/lang/Double", "value", "D", ACC_VIRTUAL);
+
+ Classpath::voidClass = UPCALL_CLASS(vm, "java/lang/Void");
+ Classpath::boolClass = UPCALL_CLASS(vm, "java/lang/Boolean");
+ Classpath::byteClass = UPCALL_CLASS(vm, "java/lang/Byte");
+ Classpath::shortClass = UPCALL_CLASS(vm, "java/lang/Short");
+ Classpath::charClass = UPCALL_CLASS(vm, "java/lang/Character");
+ Classpath::intClass = UPCALL_CLASS(vm, "java/lang/Integer");
+ Classpath::floatClass = UPCALL_CLASS(vm, "java/lang/Float");
+ Classpath::doubleClass = UPCALL_CLASS(vm, "java/lang/Double");
+ Classpath::longClass = UPCALL_CLASS(vm, "java/lang/Long");
+
+ vmStackWalker = UPCALL_CLASS(vm, "gnu/classpath/VMStackWalker");
+
+ loadInClassLoader = UPCALL_METHOD(vm, "java/lang/ClassLoader", "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;", ACC_VIRTUAL);
+
+ getCallingClassLoader = UPCALL_METHOD(vm, "gnu/classpath/VMStackWalker", "getCallingClassLoader", "()Ljava/lang/ClassLoader;", ACC_STATIC);
+
+ // Create getCallingClassLoader
+ {
+ std::vector<const llvm::Type*> args;
+ const llvm::FunctionType* type =
+ llvm::FunctionType::get(JavaObject::llvmType, args, false);
+
+ Classpath::getCallingClassLoader->methPtr =
+ new llvm::Function(type, llvm::GlobalValue::ExternalLinkage,
+ "_ZN5jnjvm7JavaJIT21getCallingClassLoaderEv",
+ vm->module);
+ }
+
+ JavaMethod* internString = UPCALL_METHOD(vm, "java/lang/VMString", "intern", "(Ljava/lang/String;)Ljava/lang/String;", ACC_STATIC);
+ // Create intern
+ {
+ std::vector<const llvm::Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const llvm::FunctionType* type =
+ llvm::FunctionType::get(JavaObject::llvmType, args, false);
+
+ internString->methPtr =
+ new llvm::Function(type, llvm::GlobalValue::ExternalLinkage,
+ "internString",
+ vm->module);
+ }
+
+ JavaMethod* isArray = UPCALL_METHOD(vm, "java/lang/Class", "isArray", "()Z", ACC_VIRTUAL);
+ // Create intern
+ {
+ std::vector<const llvm::Type*> args;
+ args.push_back(JavaObject::llvmType);
+ const llvm::FunctionType* type =
+ llvm::FunctionType::get(llvm::Type::Int8Ty, args, false);
+
+ isArray->methPtr =
+ new llvm::Function(type, llvm::GlobalValue::ExternalLinkage,
+ "isArray",
+ vm->module);
+ }
+
+ ClasspathThread::initialise(vm);
+
+ vm->loadName(vm->asciizConstructUTF8("java/lang/String"),
+ CommonClass::jnjvmClassLoader, true,
+ true, false);
+
+ CommonClass* object =
+ vm->loadName(vm->asciizConstructUTF8("java/lang/Object"),
+ CommonClass::jnjvmClassLoader, true,
+ true, false);
+ COMPILE_METHODS(object)
+
+ JavaMethod* getCallingClass = UPCALL_METHOD(vm, "gnu/classpath/VMStackWalker", "getCallingClass", "()Ljava/lang/Object;", ACC_STATIC);
+ {
+ std::vector<const llvm::Type*> args;
+ const llvm::FunctionType* type =
+ llvm::FunctionType::get(JavaObject::llvmType, args, false);
+
+ getCallingClass->methPtr =
+ new llvm::Function(type, llvm::GlobalValue::ExternalLinkage,
+ "getCallingClass",
+ vm->module);
+ }
+
+ JavaMethod* getCallingClassLoader = UPCALL_METHOD(vm, "gnu/classpath/VMStackWalker", "getCallingClassLoader", "()Ljava/lang/Object;", ACC_STATIC);
+ {
+ std::vector<const llvm::Type*> args;
+ const llvm::FunctionType* type =
+ llvm::FunctionType::get(JavaObject::llvmType, args, false);
+
+ getCallingClassLoader->methPtr =
+ new llvm::Function(type, llvm::GlobalValue::ExternalLinkage,
+ "getCallingClassLoader",
+ vm->module);
+ }
+}
+
+extern "C" JavaString* internString(JavaString* obj) {
+ Jnjvm* vm = JavaThread::get()->isolate;
+ const UTF8* utf8 = obj->strToUTF8(vm);
+ return vm->UTF8ToStr(utf8);
+}
+
+extern "C" uint8 isArray(JavaObject* klass) {
+ CommonClass* cl =
+ (CommonClass*)(((*Classpath::vmdataClass)((JavaObject*)klass)).PointerVal);
+
+ return (uint8)cl->isArray;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/JavaUpcalls.h b/vmkit/lib/JnJVM/VMCore/JavaUpcalls.h
new file mode 100644
index 0000000..01004ad
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JavaUpcalls.h
@@ -0,0 +1,129 @@
+//===---------- JavaUpcalls.h - Upcalls to Java entities ------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_UPCALLS_H
+#define JNJVM_JAVA_UPCALLS_H
+
+
+#define UPCALL_CLASS(vm, name) \
+ vm->constructClass(vm->asciizConstructUTF8(name), \
+ CommonClass::jnjvmClassLoader)
+
+#define UPCALL_FIELD(vm, cl, name, type, acc) \
+ vm->constructField(UPCALL_CLASS(vm, cl), vm->asciizConstructUTF8(name), \
+ vm->asciizConstructUTF8(type), acc)
+
+#define UPCALL_METHOD(vm, cl, name, type, acc) \
+ vm->constructMethod(UPCALL_CLASS(vm, cl), vm->asciizConstructUTF8(name), \
+ vm->asciizConstructUTF8(type), acc)
+
+#define UPCALL_ARRAY_CLASS(vm, name, depth) \
+ vm->constructArray( \
+ AssessorDesc::constructArrayName(vm, 0, depth, \
+ vm->asciizConstructUTF8(name)), \
+ CommonClass::jnjvmClassLoader)
+
+
+namespace jnjvm {
+
+class Jnjvm;
+class JavaField;
+class JavaMethod;
+class Class;
+
+class ClasspathThread {
+public:
+ static void initialise(Jnjvm* vm);
+
+ static Class* newThread;
+ static Class* newVMThread;
+ static JavaField* assocThread;
+ static JavaField* vmdata;
+ static JavaMethod* finaliseCreateInitialThread;
+ static JavaMethod* initVMThread;
+ static JavaMethod* groupAddThread;
+ static JavaField* name;
+ static JavaField* priority;
+ static JavaField* daemon;
+ static JavaField* group;
+ static JavaField* running;
+ static JavaField* rootGroup;
+ static JavaField* vmThread;
+ static JavaMethod* uncaughtException;
+
+ static void createInitialThread(Jnjvm* vm, JavaObject* th);
+ static void mapInitialThread(Jnjvm* vm);
+};
+
+class Classpath {
+public:
+ static JavaMethod* getSystemClassLoader;
+ static JavaMethod* setContextClassLoader;
+ static Class* newString;
+ static Class* newClass;
+ static Class* newThrowable;
+ static Class* newException;
+ static JavaMethod* initClass;
+ static JavaMethod* initClassWithProtectionDomain;
+ static JavaField* vmdataClass;
+ static JavaMethod* setProperty;
+ static JavaMethod* initString;
+ static JavaMethod* getCallingClassLoader;
+ static JavaMethod* initConstructor;
+ static ClassArray* constructorArrayClass;
+ static Class* newConstructor;
+ static JavaField* constructorSlot;
+ static JavaMethod* initMethod;
+ static JavaMethod* initField;
+ static ClassArray* methodArrayClass;
+ static ClassArray* fieldArrayClass;
+ static Class* newMethod;
+ static Class* newField;
+ static JavaField* methodSlot;
+ static JavaField* fieldSlot;
+ static ClassArray* classArrayClass;
+ static JavaMethod* loadInClassLoader;
+ static JavaMethod* initVMThrowable;
+ static JavaField* vmDataVMThrowable;
+ static Class* newVMThrowable;
+ static JavaField* bufferAddress;
+ static JavaField* dataPointer32;
+ static JavaField* vmdataClassLoader;
+
+ static JavaField* boolValue;
+ static JavaField* byteValue;
+ static JavaField* shortValue;
+ static JavaField* charValue;
+ static JavaField* intValue;
+ static JavaField* longValue;
+ static JavaField* floatValue;
+ static JavaField* doubleValue;
+
+ static Class* newStackTraceElement;
+ static JavaMethod* initStackTraceElement;
+
+ static void initialiseClasspath(Jnjvm* vm);
+
+ static Class* voidClass;
+ static Class* boolClass;
+ static Class* byteClass;
+ static Class* shortClass;
+ static Class* charClass;
+ static Class* intClass;
+ static Class* floatClass;
+ static Class* doubleClass;
+ static Class* longClass;
+
+ static Class* vmStackWalker;
+};
+
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/Jni.cpp b/vmkit/lib/JnJVM/VMCore/Jni.cpp
new file mode 100644
index 0000000..3824251
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Jni.cpp
@@ -0,0 +1,2478 @@
+//===------------- Jni.cpp - Jni interface for JnJVM ----------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <jni.h>
+
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+
+
+using namespace jnjvm;
+
+extern "C" const struct JNIInvokeInterface JNI_JavaVMTable;
+extern "C" struct JNINativeInterface JNI_JNIEnvTable;
+
+#define BEGIN_EXCEPTION \
+ JavaObject* excp = 0; \
+ try {
+
+#define END_EXCEPTION \
+ } catch(...) { \
+ excp = JavaThread::getJavaException(); \
+ JavaThread::clearException(); \
+ } \
+ if (excp) { \
+ JavaThread* th = JavaThread::get(); \
+ th->pendingException = excp; \
+ th->returnFromNative(); \
+ }
+
+/*
+static void* ptr_jvm = (JavaVM) &JNI_JavaVMTable;
+static void *ptr_env = (void*) &JNI_JNIEnvTable;
+*/
+
+jint GetVersion(JNIEnv *env) {
+ return JNI_VERSION_1_4;
+}
+
+
+jclass DefineClass(JNIEnv *env, const char *name, jobject loader,
+ const jbyte *buf, jsize bufLen) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jclass FindClass(JNIEnv *env, const char *asciiz) {
+
+ BEGIN_EXCEPTION
+
+ Jnjvm *vm = NativeUtil::myVM(env);
+ const UTF8* utf8 = vm->asciizConstructUTF8(asciiz);
+ sint32 len = utf8->size;
+
+ JavaObject* loader = 0;
+ Class* currentClass = JavaJIT::getCallingClass();
+ if (currentClass) loader = currentClass->classLoader;
+
+ CommonClass* cl = vm->lookupClassFromUTF8(utf8, 0, len, loader, true, true,
+ true);
+ return (jclass)(cl->getClassDelegatee());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jmethodID FromReflectedMethod(JNIEnv *env, jobject method) {
+
+ BEGIN_EXCEPTION
+
+ JavaObject* meth = (JavaObject*)method;
+ CommonClass* cl = meth->classOf;
+ if (cl == Classpath::newConstructor) {
+ return (jmethodID)(*Classpath::constructorSlot)(meth).IntVal.getZExtValue();
+ } else if (cl == Classpath::newMethod) {
+ return (jmethodID)(*Classpath::methodSlot)(meth).IntVal.getZExtValue();
+ } else {
+ JavaThread::get()->isolate->unknownError(
+ "%s is not a constructor or a method",
+ meth->printString());
+ }
+
+ END_EXCEPTION
+
+ return 0;
+}
+
+
+jclass GetSuperclass(JNIEnv *env, jclass sub) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup) {
+
+ BEGIN_EXCEPTION
+
+ CommonClass* cl2 = NativeUtil::resolvedImplClass(sup, false);
+ CommonClass* cl1 = NativeUtil::resolvedImplClass(sub, false);
+
+ AssessorDesc* prim = AssessorDesc::bogusClassToPrimitive(cl2);
+ if (prim)
+ return prim == AssessorDesc::bogusClassToPrimitive(cl1);
+ else
+ return cl1->isAssignableFrom(cl2);
+
+ END_EXCEPTION
+
+ return false;
+}
+
+
+jint Throw(JNIEnv *env, jthrowable obj) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) {
+
+ BEGIN_EXCEPTION
+
+ JavaThread* th = JavaThread::get();
+ Jnjvm* vm = th->isolate;
+ CommonClass* cl = NativeUtil::resolvedImplClass(clazz, true);
+ if (cl->isArray) assert(0 && "implement me");
+ JavaObject* res = ((Class*)cl)->doNew();
+ JavaMethod* init =
+ cl->lookupMethod(Jnjvm::initName,
+ vm->asciizConstructUTF8("(Ljava/lang/String;)V"), 0, 1);
+ init->invokeIntSpecial(res, vm->asciizToStr(msg));
+ th->pendingException = res;
+ th->returnFromNative();
+ return 1;
+
+ END_EXCEPTION
+
+ return 0;
+}
+
+
+jthrowable ExceptionOccurred(JNIEnv *env) {
+ return (jthrowable)JavaThread::get()->pendingException;
+}
+
+
+void ExceptionDescribe(JNIEnv *env) {
+ assert(0 && "implement me");
+}
+
+
+void ExceptionClear(JNIEnv *env) {
+ assert(0 && "implement me");
+}
+
+
+void FatalError(JNIEnv *env, const char *msg) {
+ assert(0 && "implement me");
+}
+
+
+jint PushLocalFrame(JNIEnv* env, jint capacity) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+jobject PopLocalFrame(JNIEnv* env, jobject result) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void DeleteLocalRef(JNIEnv *env, jobject localRef) {
+}
+
+
+jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject NewLocalRef(JNIEnv *env, jobject ref) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint EnsureLocalCapacity(JNIEnv* env, jint capacity) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject AllocObject(JNIEnv *env, jclass clazz) {
+
+ BEGIN_EXCEPTION
+
+ CommonClass* cl = NativeUtil::resolvedImplClass(clazz, true);
+ if (cl->isArray) JavaThread::get()->isolate->unknownError("implement me");
+ return (jobject)((Class*)cl)->doNew();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaMethod* meth = (JavaMethod*)methodID;
+ Class* cl = (Class*)NativeUtil::resolvedImplClass(clazz, true);
+ JavaObject* res = cl->doNew();
+ meth->invokeIntSpecialAP(res, ap);
+ va_end(ap);
+ return (jobject)res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jclass GetObjectClass(JNIEnv *env, jobject obj) {
+
+ BEGIN_EXCEPTION
+
+ verifyNull((JavaObject*)obj);
+ return (jclass)((JavaObject*)obj)->classOf->getClassDelegatee();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jfieldID FromReflectedField(JNIEnv* env, jobject field) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
+ jboolean isStatic) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
+ jboolean isStatic) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *aname,
+ const char *atype) {
+
+ BEGIN_EXCEPTION
+
+ Jnjvm* vm = NativeUtil::myVM(env);
+ CommonClass* cl = NativeUtil::resolvedImplClass(clazz, true);
+ const UTF8* name = vm->asciizConstructUTF8(aname);
+ const UTF8* type = vm->asciizConstructUTF8(atype);
+ JavaMethod* meth = cl->lookupMethod(
+ name->javaToInternal(vm, 0, name->size),
+ type->javaToInternal(vm, 0, type->size), false, true);
+
+ return (jmethodID)meth;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* self = (JavaObject*)obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ JavaObject* res = meth->invokeJavaObjectVirtualAP(self, ap);
+ va_end(ap);
+ return (jobject)res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue * args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean CallBooleanMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* self = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ uint32 res = meth->invokeIntVirtualAP(self, ap);
+ va_end(ap);
+ return res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue * args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jint CallIntMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ uint32 res = meth->invokeIntVirtualAP(obj, ap);
+ va_end(ap);
+ return res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jfloat CallFloatMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ jfloat res = meth->invokeFloatVirtualAP(obj, ap);
+ va_end(ap);
+ return res;
+
+ END_EXCEPTION;
+ return 0.0;
+}
+
+
+jfloat CallFloatMethodV(JNIEnv *env, jobject _obj, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jfloat CallFloatMethodA(JNIEnv *env, jobject _obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jdouble CallDoubleMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ jdouble res = meth->invokeDoubleVirtualAP(obj, ap);
+ va_end(ap);
+ return res;
+
+ END_EXCEPTION
+ return 0.0;
+}
+
+
+jdouble CallDoubleMethodV(JNIEnv *env, jobject _obj, jmethodID methodID,
+ va_list args) {
+
+ BEGIN_EXCEPTION
+
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ return meth->invokeDoubleVirtualAP(obj, args);
+
+ END_EXCEPTION
+ return 0.0;
+
+}
+
+
+jdouble CallDoubleMethodA(JNIEnv *env, jobject _obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+void CallVoidMethod(JNIEnv *env, jobject _obj, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ meth->invokeIntVirtualAP(obj, ap);
+ va_end(ap);
+
+ END_EXCEPTION
+}
+
+
+void CallVoidMethodV(JNIEnv *env, jobject _obj, jmethodID methodID,
+ va_list args) {
+
+ BEGIN_EXCEPTION
+
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ meth->invokeIntVirtualAP(obj, args);
+
+ END_EXCEPTION
+}
+
+
+void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+}
+
+
+
+jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+void CallNonvirtualVoidMethod(JNIEnv *env, jobject _obj, jclass clazz,
+ jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaObject* obj = (JavaObject*)_obj;
+ JavaMethod* meth = (JavaMethod*)methodID;
+ meth->invokeIntSpecialAP(obj, ap);
+ va_end(ap);
+
+ END_EXCEPTION
+}
+
+
+void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ assert(0 && "implement me");
+}
+
+
+void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, jvalue * args) {
+ assert(0 && "implement me");
+}
+
+
+jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
+ const char *sig) {
+
+ BEGIN_EXCEPTION
+
+ Jnjvm* vm = NativeUtil::myVM(env);
+ return (jfieldID)
+ NativeUtil::resolvedImplClass(clazz, true)->lookupField(
+ vm->asciizConstructUTF8(name),
+ vm->asciizConstructUTF8(sig), 0, 1);
+
+ END_EXCEPTION
+ return 0;
+
+}
+
+
+jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (jobject)((*field)(o).PointerVal);
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (uint8)((*field)(o).IntVal.getZExtValue());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (sint8)((*field)(o).IntVal.getSExtValue());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (uint16)((*field)(o).IntVal.getZExtValue());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (sint16)((*field)(o).IntVal.getSExtValue());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (sint32)((*field)(o).IntVal.getSExtValue());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (sint64)((*field)(o).IntVal.getSExtValue());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (*field)(o).FloatVal;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ return (*field)(o).DoubleVal;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (JavaObject*)value);
+
+ END_EXCEPTION
+}
+
+
+void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID,
+ jboolean value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (sint64)value);
+
+ END_EXCEPTION
+}
+
+
+void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (float)value);
+
+ END_EXCEPTION
+}
+
+
+void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ JavaObject* o = (JavaObject*)obj;
+ (*field)(o, (double)value);
+
+ END_EXCEPTION
+}
+
+
+jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *aname,
+ const char *atype) {
+
+ BEGIN_EXCEPTION
+
+ Jnjvm* vm = NativeUtil::myVM(env);
+ CommonClass* cl = NativeUtil::resolvedImplClass(clazz, true);
+ const UTF8* name = vm->asciizConstructUTF8(aname);
+ const UTF8* type = vm->asciizConstructUTF8(atype);
+ JavaMethod* meth = cl->lookupMethod(
+ name->javaToInternal(vm, 0, name->size),
+ type->javaToInternal(vm, 0, type->size), true, true);
+
+ return (jmethodID)meth;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
+ ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaMethod* meth = (JavaMethod*)methodID;
+ uint32 res = meth->invokeIntStaticAP(ap);
+ va_end(ap);
+ return res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
+ ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+
+jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
+ ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
+ ...) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue *args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
+
+ BEGIN_EXCEPTION
+
+ va_list ap;
+ va_start(ap, methodID);
+ JavaMethod* meth = (JavaMethod*)methodID;
+ meth->invokeIntStaticAP(ap);
+ va_end(ap);
+
+ END_EXCEPTION
+}
+
+
+void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID,
+ va_list args) {
+
+ BEGIN_EXCEPTION
+
+ JavaMethod* meth = (JavaMethod*)methodID;
+ meth->invokeIntStaticAP(args);
+
+ END_EXCEPTION
+}
+
+
+void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID,
+ jvalue * args) {
+ assert(0 && "implement me");
+}
+
+
+jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
+ const char *sig) {
+
+ BEGIN_EXCEPTION
+
+ Jnjvm* vm = NativeUtil::myVM(env);
+ return (jfieldID)
+ NativeUtil::resolvedImplClass(clazz, true)->lookupField(
+ vm->asciizConstructUTF8(name),
+ vm->asciizConstructUTF8(sig), true, true);
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jobject)res.PointerVal;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jboolean)res.IntVal.getZExtValue();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jbyte)res.IntVal.getSExtValue();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jchar)res.IntVal.getZExtValue();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jshort)res.IntVal.getSExtValue();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jint)res.IntVal.getSExtValue();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jlong)res.IntVal.getZExtValue();
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jfloat)res.FloatVal;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ llvm::GenericValue res = (*field)();
+ return (jdouble)res.DoubleVal;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jobject value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((JavaObject*)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jboolean value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jbyte value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jchar value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jshort value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jint value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((uint32)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jlong value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((sint64)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jfloat value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((float)value);
+
+ END_EXCEPTION
+}
+
+
+void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jdouble value) {
+
+ BEGIN_EXCEPTION
+
+ JavaField* field = (JavaField*)fieldID;
+ (*field)((double)value);
+
+ END_EXCEPTION
+}
+
+
+jstring NewString(JNIEnv *env, const jchar *buf, jsize len) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jsize GetStringLength(JNIEnv *env, jstring str) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars) {
+ assert(0 && "implement me");
+}
+
+
+jstring NewStringUTF(JNIEnv *env, const char *bytes) {
+
+ BEGIN_EXCEPTION
+
+ Jnjvm* vm = NativeUtil::myVM(env);
+ return (jstring)(vm->asciizToStr(bytes));
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jsize GetStringUTFLength (JNIEnv *env, jstring string) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy != 0) (*isCopy) = true;
+ return strdup(((JavaString*)string)->strToAsciiz());
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) {
+ free((void*)utf);
+}
+
+
+jsize GetArrayLength(JNIEnv *env, jarray array) {
+
+ BEGIN_EXCEPTION
+
+ return ((JavaArray*)array)->size;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass,
+ jobject initialElement) {
+ BEGIN_EXCEPTION
+ Jnjvm* vm = NativeUtil::myVM(env);
+ if (length < 0) vm->negativeArraySizeException(length);
+
+ CommonClass* base = NativeUtil::resolvedImplClass(elementClass, true);
+ JavaObject* loader = base->classLoader;
+ const UTF8* name = base->name;
+ const UTF8* arrayName = AssessorDesc::constructArrayName(vm, 0, 1, name);
+ ClassArray* array = vm->constructArray(arrayName, loader);
+ ArrayObject* res = ArrayObject::acons(length, array);
+ if (initialElement) {
+ memset(res->elements, (int)initialElement,
+ length * sizeof(JavaObject*));
+ }
+ return (jobjectArray)res;
+ END_EXCEPTION
+ return 0;
+}
+
+
+jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index,
+ jobject val) {
+
+ BEGIN_EXCEPTION
+
+ ((ArrayObject*)array)->setAt(index, (JavaObject*)val);
+
+ END_EXCEPTION
+}
+
+
+jbooleanArray NewBooleanArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArrayUInt8* res = 0;
+ res = ArrayUInt8::acons(len, JavaArray::ofBool);
+ return (jbooleanArray)res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jbyteArray NewByteArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArraySInt8* res = 0;
+ res = ArraySInt8::acons(len, JavaArray::ofByte);
+ return (jbyteArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jcharArray NewCharArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArrayUInt16* res = 0;
+ res = ArrayUInt16::acons(len, JavaArray::ofChar);
+ return (jcharArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jshortArray NewShortArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArraySInt16* res = 0;
+ res = ArraySInt16::acons(len, JavaArray::ofShort);
+ return (jshortArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jintArray NewIntArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArraySInt32* res = 0;
+ res = ArraySInt32::acons(len, JavaArray::ofInt);
+ return (jintArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jlongArray NewLongArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArrayLong* res = 0;
+ res = ArrayLong::acons(len, JavaArray::ofLong);
+ return (jlongArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jfloatArray NewFloatArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArrayFloat* res = 0;
+ res = ArrayFloat::acons(len, JavaArray::ofFloat);
+ return (jfloatArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jdoubleArray NewDoubleArray(JNIEnv *env, jsize len) {
+
+ BEGIN_EXCEPTION
+
+ ArrayDouble* res = 0;
+ res = ArrayDouble::acons(len, JavaArray::ofDouble);
+ return (jdoubleArray) res;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array,
+ jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return (jboolean*)((ArrayUInt8*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArraySInt8*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArrayUInt16*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jshort *GetShortArrayElements(JNIEnv *env, jshortArray array,
+ jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArraySInt16*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArraySInt32*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArrayLong*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array,
+ jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArrayFloat*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+ jboolean *isCopy) {
+
+ BEGIN_EXCEPTION
+
+ if (isCopy) (*isCopy) = false;
+ return ((ArrayDouble*)array)->elements;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array,
+ jboolean *elems, jint mode) {
+}
+
+
+void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems,
+ jint mode) {
+}
+
+
+void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems,
+ jint mode) {
+}
+
+
+void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems,
+ jint mode) {
+}
+
+
+void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems,
+ jint mode) {
+}
+
+
+void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems,
+ jint mode) {
+}
+
+
+void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems,
+ jint mode) {
+}
+
+
+void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array,
+ jdouble *elems, jint mode) {
+}
+
+
+void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
+ jsize len, jboolean *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
+ jbyte *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
+ jchar *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
+ jsize len, jshort *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
+ jint *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len,
+ jlong *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
+ jsize len, jfloat *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
+ jsize len, jdouble *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start,
+ jsize len, jboolean *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len,
+ jbyte *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len,
+ jchar *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start,
+ jsize len, jshort *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len,
+ jint *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len,
+ jlong *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start,
+ jsize len, jfloat *buf) {
+ assert(0 && "implement me");
+}
+
+
+void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start,
+ jsize len, jdouble *buf) {
+ assert(0 && "implement me");
+}
+
+
+jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint UnregisterNatives(JNIEnv *env, jclass clazz) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint MonitorEnter(JNIEnv *env, jobject obj) {
+
+ BEGIN_EXCEPTION
+
+ ((JavaObject*)obj)->aquire();
+ return 1;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jint MonitorExit(JNIEnv *env, jobject obj) {
+
+ BEGIN_EXCEPTION
+
+ ((JavaObject*)obj)->unlock();
+ return 1;
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
+ BEGIN_EXCEPTION
+ Jnjvm* myvm = JavaThread::get()->isolate;
+ (*vm) = (JavaVM*)(void*)(&(myvm->javavmEnv));
+ return 0;
+ END_EXCEPTION
+ return 0;
+}
+
+
+void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
+ jchar *buf) {
+ assert(0 && "implement me");
+}
+
+
+void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len,
+ char *buf) {
+ assert(0 && "implement me");
+}
+
+
+void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray,
+ jint mode) {
+ assert(0 && "implement me");
+}
+
+
+const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring) {
+ assert(0 && "implement me");
+}
+
+
+jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void DeleteWeakGlobalRef(JNIEnv* env, jweak ref) {
+ assert(0 && "implement me");
+}
+
+
+jobject NewGlobalRef(JNIEnv* env, jobject obj) {
+ Jnjvm* vm = NativeUtil::myVM(env);
+ vm->globalRefsLock->lock();
+ vm->globalRefs.push_back((JavaObject*)obj);
+ vm->globalRefsLock->unlock();
+ return obj;
+}
+
+
+void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
+ Jnjvm* vm = NativeUtil::myVM(env);
+ vm->globalRefsLock->lock();
+ for (std::vector<JavaObject*>::iterator i = vm->globalRefs.begin(),
+ e = vm->globalRefs.end(); i!= e; ++i) {
+ if ((*i) == (JavaObject*)globalRef) {
+ vm->globalRefs.erase(i);
+ break;
+ }
+ }
+ vm->globalRefsLock->unlock();
+}
+
+
+jboolean ExceptionCheck(JNIEnv *env) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+void *GetDirectBufferAddress(JNIEnv *env, jobject _buf) {
+
+ BEGIN_EXCEPTION
+
+ JavaObject* buf = (JavaObject*)_buf;
+ JavaObject* address = (JavaObject*)((*Classpath::bufferAddress)(buf).PointerVal);
+ if (address != 0) {
+ int res = (*Classpath::dataPointer32)(address).IntVal.getZExtValue();
+ return (void*)res;
+ } else {
+ return 0;
+ }
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint DestroyJavaVM(JavaVM *vm) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint DetachCurrentThread(JavaVM *vm) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+jint GetEnv(JavaVM *vm, void **env, jint version) {
+
+ BEGIN_EXCEPTION
+
+ JavaObject* th = JavaThread::currentThread();
+ Jnjvm* myvm = JavaThread::get()->isolate;
+ if (th != 0) {
+ (*env) = &(myvm->jniEnv);
+ return JNI_OK;
+ } else {
+ (*env) = 0;
+ return JNI_EDETACHED;
+ }
+
+ END_EXCEPTION
+ return 0;
+}
+
+
+
+jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2) {
+ assert(0 && "implement me");
+ return 0;
+}
+
+
+const struct JNIInvokeInterface JNI_JavaVMTable = {
+ NULL,
+ NULL,
+ NULL,
+
+ DestroyJavaVM,
+ AttachCurrentThread,
+ DetachCurrentThread,
+ GetEnv,
+ AttachCurrentThreadAsDaemon
+};
+
+
+struct JNINativeInterface JNI_JNIEnvTable = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &GetVersion,
+
+ &DefineClass,
+ &FindClass,
+ &FromReflectedMethod,
+ &FromReflectedField,
+ &ToReflectedMethod,
+ &GetSuperclass,
+ &IsAssignableFrom,
+ &ToReflectedField,
+
+ &Throw,
+ &ThrowNew,
+ &ExceptionOccurred,
+ &ExceptionDescribe,
+ &ExceptionClear,
+ &FatalError,
+ &PushLocalFrame,
+ &PopLocalFrame,
+
+ &NewGlobalRef,
+ &DeleteGlobalRef,
+ &DeleteLocalRef,
+ &IsSameObject,
+ &NewLocalRef,
+ &EnsureLocalCapacity,
+
+ &AllocObject,
+ &NewObject,
+ &NewObjectV,
+ &NewObjectA,
+
+ &GetObjectClass,
+ &IsInstanceOf,
+
+ &GetMethodID,
+
+ &CallObjectMethod,
+ &CallObjectMethodV,
+ &CallObjectMethodA,
+ &CallBooleanMethod,
+ &CallBooleanMethodV,
+ &CallBooleanMethodA,
+ &CallByteMethod,
+ &CallByteMethodV,
+ &CallByteMethodA,
+ &CallCharMethod,
+ &CallCharMethodV,
+ &CallCharMethodA,
+ &CallShortMethod,
+ &CallShortMethodV,
+ &CallShortMethodA,
+ &CallIntMethod,
+ &CallIntMethodV,
+ &CallIntMethodA,
+ &CallLongMethod,
+ &CallLongMethodV,
+ &CallLongMethodA,
+ &CallFloatMethod,
+ &CallFloatMethodV,
+ &CallFloatMethodA,
+ &CallDoubleMethod,
+ &CallDoubleMethodV,
+ &CallDoubleMethodA,
+ &CallVoidMethod,
+ &CallVoidMethodV,
+ &CallVoidMethodA,
+
+ &CallNonvirtualObjectMethod,
+ &CallNonvirtualObjectMethodV,
+ &CallNonvirtualObjectMethodA,
+ &CallNonvirtualBooleanMethod,
+ &CallNonvirtualBooleanMethodV,
+ &CallNonvirtualBooleanMethodA,
+ &CallNonvirtualByteMethod,
+ &CallNonvirtualByteMethodV,
+ &CallNonvirtualByteMethodA,
+ &CallNonvirtualCharMethod,
+ &CallNonvirtualCharMethodV,
+ &CallNonvirtualCharMethodA,
+ &CallNonvirtualShortMethod,
+ &CallNonvirtualShortMethodV,
+ &CallNonvirtualShortMethodA,
+ &CallNonvirtualIntMethod,
+ &CallNonvirtualIntMethodV,
+ &CallNonvirtualIntMethodA,
+ &CallNonvirtualLongMethod,
+ &CallNonvirtualLongMethodV,
+ &CallNonvirtualLongMethodA,
+ &CallNonvirtualFloatMethod,
+ &CallNonvirtualFloatMethodV,
+ &CallNonvirtualFloatMethodA,
+ &CallNonvirtualDoubleMethod,
+ &CallNonvirtualDoubleMethodV,
+ &CallNonvirtualDoubleMethodA,
+ &CallNonvirtualVoidMethod,
+ &CallNonvirtualVoidMethodV,
+ &CallNonvirtualVoidMethodA,
+
+ &GetFieldID,
+
+ &GetObjectField,
+ &GetBooleanField,
+ &GetByteField,
+ &GetCharField,
+ &GetShortField,
+ &GetIntField,
+ &GetLongField,
+ &GetFloatField,
+ &GetDoubleField,
+ &SetObjectField,
+ &SetBooleanField,
+ &SetByteField,
+ &SetCharField,
+ &SetShortField,
+ &SetIntField,
+ &SetLongField,
+ &SetFloatField,
+ &SetDoubleField,
+
+ &GetStaticMethodID,
+
+ &CallStaticObjectMethod,
+ &CallStaticObjectMethodV,
+ &CallStaticObjectMethodA,
+ &CallStaticBooleanMethod,
+ &CallStaticBooleanMethodV,
+ &CallStaticBooleanMethodA,
+ &CallStaticByteMethod,
+ &CallStaticByteMethodV,
+ &CallStaticByteMethodA,
+ &CallStaticCharMethod,
+ &CallStaticCharMethodV,
+ &CallStaticCharMethodA,
+ &CallStaticShortMethod,
+ &CallStaticShortMethodV,
+ &CallStaticShortMethodA,
+ &CallStaticIntMethod,
+ &CallStaticIntMethodV,
+ &CallStaticIntMethodA,
+ &CallStaticLongMethod,
+ &CallStaticLongMethodV,
+ &CallStaticLongMethodA,
+ &CallStaticFloatMethod,
+ &CallStaticFloatMethodV,
+ &CallStaticFloatMethodA,
+ &CallStaticDoubleMethod,
+ &CallStaticDoubleMethodV,
+ &CallStaticDoubleMethodA,
+ &CallStaticVoidMethod,
+ &CallStaticVoidMethodV,
+ &CallStaticVoidMethodA,
+
+ &GetStaticFieldID,
+
+ &GetStaticObjectField,
+ &GetStaticBooleanField,
+ &GetStaticByteField,
+ &GetStaticCharField,
+ &GetStaticShortField,
+ &GetStaticIntField,
+ &GetStaticLongField,
+ &GetStaticFloatField,
+ &GetStaticDoubleField,
+ &SetStaticObjectField,
+ &SetStaticBooleanField,
+ &SetStaticByteField,
+ &SetStaticCharField,
+ &SetStaticShortField,
+ &SetStaticIntField,
+ &SetStaticLongField,
+ &SetStaticFloatField,
+ &SetStaticDoubleField,
+
+ &NewString,
+ &GetStringLength,
+ &GetStringChars,
+ &ReleaseStringChars,
+
+ &NewStringUTF,
+ &GetStringUTFLength,
+ &GetStringUTFChars,
+ &ReleaseStringUTFChars,
+
+ &GetArrayLength,
+
+ &NewObjectArray,
+ &GetObjectArrayElement,
+ &SetObjectArrayElement,
+
+ &NewBooleanArray,
+ &NewByteArray,
+ &NewCharArray,
+ &NewShortArray,
+ &NewIntArray,
+ &NewLongArray,
+ &NewFloatArray,
+ &NewDoubleArray,
+
+ &GetBooleanArrayElements,
+ &GetByteArrayElements,
+ &GetCharArrayElements,
+ &GetShortArrayElements,
+ &GetIntArrayElements,
+ &GetLongArrayElements,
+ &GetFloatArrayElements,
+ &GetDoubleArrayElements,
+
+ &ReleaseBooleanArrayElements,
+ &ReleaseByteArrayElements,
+ &ReleaseCharArrayElements,
+ &ReleaseShortArrayElements,
+ &ReleaseIntArrayElements,
+ &ReleaseLongArrayElements,
+ &ReleaseFloatArrayElements,
+ &ReleaseDoubleArrayElements,
+
+ &GetBooleanArrayRegion,
+ &GetByteArrayRegion,
+ &GetCharArrayRegion,
+ &GetShortArrayRegion,
+ &GetIntArrayRegion,
+ &GetLongArrayRegion,
+ &GetFloatArrayRegion,
+ &GetDoubleArrayRegion,
+ &SetBooleanArrayRegion,
+ &SetByteArrayRegion,
+ &SetCharArrayRegion,
+ &SetShortArrayRegion,
+ &SetIntArrayRegion,
+ &SetLongArrayRegion,
+ &SetFloatArrayRegion,
+ &SetDoubleArrayRegion,
+
+ &RegisterNatives,
+ &UnregisterNatives,
+
+ &MonitorEnter,
+ &MonitorExit,
+
+ &GetJavaVM,
+
+ /* new JNI 1.2 functions */
+
+ &GetStringRegion,
+ &GetStringUTFRegion,
+
+ &GetPrimitiveArrayCritical,
+ &ReleasePrimitiveArrayCritical,
+
+ &GetStringCritical,
+ &ReleaseStringCritical,
+
+ &NewWeakGlobalRef,
+ &DeleteWeakGlobalRef,
+
+ &ExceptionCheck,
+
+ /* new JNI 1.4 functions */
+
+ &NewDirectByteBuffer,
+ &GetDirectBufferAddress,
+ &GetDirectBufferCapacity
+};
diff --git a/vmkit/lib/JnJVM/VMCore/Jnjvm.cpp b/vmkit/lib/JnJVM/VMCore/Jnjvm.cpp
new file mode 100644
index 0000000..3384cfc
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Jnjvm.cpp
@@ -0,0 +1,867 @@
+//===---------- Jnjvm.cpp - Java virtual machine description --------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// realpath
+#include <limits.h>
+#include <stdlib.h>
+
+#include <float.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "debug.h"
+
+#include "mvm/JIT.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "LockedMap.h"
+#include "Reader.h"
+#include "Zip.h"
+
+using namespace jnjvm;
+
+const char* Jnjvm::dirSeparator = "/";
+const char* Jnjvm::envSeparator = ":";
+const unsigned int Jnjvm::Magic = 0xcafebabe;
+
+#define DECLARE_EXCEPTION(EXCP) \
+ const char* Jnjvm::EXCP = "java/lang/"#EXCP
+
+#define DECLARE_REFLECT_EXCEPTION(EXCP) \
+ const char* Jnjvm::EXCP = "java/lang/reflect/"#EXCP
+
+DECLARE_EXCEPTION(ArithmeticException);
+DECLARE_REFLECT_EXCEPTION(InvocationTargetException);
+DECLARE_EXCEPTION(ArrayStoreException);
+DECLARE_EXCEPTION(ClassCastException);
+DECLARE_EXCEPTION(IllegalMonitorStateException);
+DECLARE_EXCEPTION(IllegalArgumentException);
+DECLARE_EXCEPTION(InterruptedException);
+DECLARE_EXCEPTION(IndexOutOfBoundsException);
+DECLARE_EXCEPTION(ArrayIndexOutOfBoundsException);
+DECLARE_EXCEPTION(NegativeArraySizeException);
+DECLARE_EXCEPTION(NullPointerException);
+DECLARE_EXCEPTION(SecurityException);
+DECLARE_EXCEPTION(ClassFormatError);
+DECLARE_EXCEPTION(ClassCircularityError);
+DECLARE_EXCEPTION(NoClassDefFoundError);
+DECLARE_EXCEPTION(UnsupportedClassVersionError);
+DECLARE_EXCEPTION(NoSuchFieldError);
+DECLARE_EXCEPTION(NoSuchMethodError);
+DECLARE_EXCEPTION(InstantiationError);
+DECLARE_EXCEPTION(IllegalAccessError);
+DECLARE_EXCEPTION(IllegalAccessException);
+DECLARE_EXCEPTION(VerifyError);
+DECLARE_EXCEPTION(ExceptionInInitializerError);
+DECLARE_EXCEPTION(LinkageError);
+DECLARE_EXCEPTION(AbstractMethodError);
+DECLARE_EXCEPTION(UnsatisfiedLinkError);
+DECLARE_EXCEPTION(InternalError);
+DECLARE_EXCEPTION(OutOfMemoryError);
+DECLARE_EXCEPTION(StackOverflowError);
+DECLARE_EXCEPTION(UnknownError);
+DECLARE_EXCEPTION(ClassNotFoundException);
+
+
+void Jnjvm::analyseClasspathEnv(const char* str) {
+ if (str != 0) {
+ unsigned int len = strlen(str);
+ char* buf = (char*)alloca(len + 1);
+ const char* cur = str;
+ int top = 0;
+ char* rp = 0;
+ char c = 1;
+ while (c != 0) {
+ while (((c = cur[top]) != 0) && c != envSeparator[0]) {
+ top++;
+ }
+ if (top != 0) {
+ memcpy(buf, cur, top);
+ buf[top] = 0;
+ rp = realpath(buf, rp);
+ if (rp != 0) {
+ struct stat st;
+ stat(rp, &st);
+ if ((st.st_mode & S_IFMT) == S_IFDIR) {
+ unsigned int len = strlen(rp);
+ char* temp = (char*)malloc(len + 2);
+ memcpy(temp, rp, len);
+ temp[len] = dirSeparator[0];
+ temp[len + 1] = 0;
+ bootClasspath.push_back(temp);
+ } else {
+ bootClasspath.push_back(rp);
+ }
+ }
+ }
+ cur = cur + top + 1;
+ top = 0;
+ }
+ }
+}
+
+void Jnjvm::readParents(Class* cl, Reader* reader) {
+ JavaCtpInfo* ctpInfo = cl->ctpInfo;
+ unsigned short int superEntry = reader->readU2();
+ const UTF8* super = superEntry ?
+ ctpInfo->resolveClassName(superEntry) : 0;
+
+ unsigned short int nbI = reader->readU2();
+ cl->superUTF8 = super;
+ for (int i = 0; i < nbI; i++)
+ cl->interfacesUTF8.push_back(ctpInfo->resolveClassName(reader->readU2()));
+
+}
+
+void Jnjvm::loadParents(Class* cl) {
+ const UTF8* super = cl->superUTF8;
+ int nbI = cl->interfacesUTF8.size();
+ JavaObject* classLoader = cl->classLoader;
+ if (super == 0) {
+ cl->depth = 0;
+ cl->display.push_back(cl);
+ } else {
+ cl->super = loadName(super, classLoader, true, false, true);
+ int depth = cl->super->depth;
+ cl->depth = depth + 1;
+ for (uint32 i = 0; i < cl->super->display.size(); ++i) {
+ cl->display.push_back(cl->super->display[i]);
+ }
+ cl->display.push_back(cl);
+ }
+
+ for (int i = 0; i < nbI; i++)
+ cl->interfaces.push_back((Class*)loadName(cl->interfacesUTF8[i],
+ classLoader, true, false, true));
+}
+
+void Jnjvm::readAttributs(Class* cl, Reader* reader,
+ std::vector<Attribut*>& attr) {
+ JavaCtpInfo* ctpInfo = cl->ctpInfo;
+ unsigned short int nba = reader->readU2();
+
+ for (int i = 0; i < nba; i++) {
+ const UTF8* attName = ctpInfo->UTF8At(reader->readU2());
+ unsigned int attLen = reader->readU4();
+ Attribut* att = Attribut::derive(attName, attLen, reader);
+ attr.push_back(att);
+ reader->seek(attLen, Reader::SeekCur);
+ }
+}
+
+void Jnjvm::readFields(Class* cl, Reader* reader) {
+ unsigned short int nbFields = reader->readU2();
+ JavaCtpInfo* ctpInfo = cl->ctpInfo;
+ for (int i = 0; i < nbFields; i++) {
+ unsigned short int access = reader->readU2();
+ const UTF8* name = ctpInfo->UTF8At(reader->readU2());
+ const UTF8* type = ctpInfo->UTF8At(reader->readU2());
+ JavaField* field = constructField(cl, name, type, access);
+ readAttributs(cl, reader, field->attributs);
+ if (isStatic(access)) {
+ cl->staticFields.push_back(field);
+ } else {
+ cl->virtualFields.push_back(field);
+ }
+ }
+}
+
+void Jnjvm::readMethods(Class* cl, Reader* reader) {
+ unsigned short int nbMethods = reader->readU2();
+ JavaCtpInfo* ctpInfo = cl->ctpInfo;
+ for (int i = 0; i < nbMethods; i++) {
+ unsigned short int access = reader->readU2();
+ const UTF8* name = ctpInfo->UTF8At(reader->readU2());
+ const UTF8* type = ctpInfo->UTF8At(reader->readU2());
+ JavaMethod* meth = constructMethod(cl, name, type, access);
+ readAttributs(cl, reader, meth->attributs);
+ if (isStatic(access)) {
+ cl->staticMethods.push_back(meth);
+ } else {
+ cl->virtualMethods.push_back(meth);
+ }
+ }
+}
+
+void Jnjvm::readClass(Class* cl) {
+
+ PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "; ");
+ PRINT_DEBUG(JNJVM_LOAD, 0, LIGHT_GREEN, "reading ");
+ PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "%s::%s\n", printString(),
+ cl->printString());
+
+ Reader* reader = Reader::allocateReader(cl->bytes);
+ uint32 magic = reader->readU4();
+ if (magic != Jnjvm::Magic) {
+ Jnjvm::error(ClassFormatError, "bad magic number %p", magic);
+ }
+ cl->minor = reader->readU2();
+ cl->major = reader->readU2();
+ JavaCtpInfo::read(this, cl, reader);
+ JavaCtpInfo* ctpInfo = cl->ctpInfo;
+ cl->access = reader->readU2();
+
+ const UTF8* thisClassName =
+ ctpInfo->resolveClassName(reader->readU2());
+
+ if (thisClassName != cl->name) {
+ error(ClassFormatError, "try to load %s and found class named %s",
+ cl->printString(), thisClassName->printString());
+ }
+
+ readParents(cl, reader);
+ readFields(cl, reader);
+ readMethods(cl, reader);
+ readAttributs(cl, reader, cl->attributs);
+}
+
+ArrayUInt8* Jnjvm::openName(const UTF8* utf8) {
+ char* asciiz = utf8->UTF8ToAsciiz();
+ uint32 alen = strlen(asciiz);
+ uint32 nbcp = bootClasspath.size();
+ uint32 idx = 0;
+ ArrayUInt8* res = 0;
+
+ while ((res == 0) && (idx < nbcp)) {
+ char* str = bootClasspath[idx];
+ unsigned int strLen = strlen(str);
+ char* buf = (char*)alloca(strLen + alen + 16);
+
+ if (str[strLen - 1] == dirSeparator[0]) {
+ sprintf(buf, "%s%s.class", str, asciiz);
+ res = Reader::openFile(buf);
+ } else {
+ sprintf(buf, "%s.class", asciiz);
+ res = Reader::openZip(str, buf);
+ }
+ idx++;
+ }
+
+ return res;
+}
+
+
+typedef void (*clinit_t)(void);
+
+void Jnjvm::initialiseClass(CommonClass* cl) {
+start:
+ if (!((Class*)cl)->isReady()) {
+ cl->aquire();
+ int status = cl->status;
+#ifdef SINGLE_VM
+ if (status == ready) {
+#else
+ if (((Class*)cl)->isReady()) {
+#endif
+ cl->release();
+ } else if (status >= resolved && status != clinitParent && status != inClinit) {
+ cl->status = clinitParent;
+ cl->release();
+ if (cl->super) {
+ cl->super->initialiseClass();
+ }
+ for (uint32 i = 0; i < cl->interfaces.size(); i++) {
+ cl->interfaces[i]->initialiseClass();
+ }
+ cl->status = inClinit;
+ JavaMethod* meth = cl->lookupMethodDontThrow(clinitName, clinitType, true,
+ false);
+
+ PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "; ");
+ PRINT_DEBUG(JNJVM_LOAD, 0, LIGHT_GREEN, "clinit ");
+ PRINT_DEBUG(JNJVM_LOAD, 0, COLOR_NORMAL, "%s::%s\n", printString(),
+ cl->printString());
+
+#ifndef SINGLE_VM
+ std::pair<uint8, JavaObject*>* val = 0;
+ if (this == bootstrapVM) {
+ JavaObject* staticVar = ((Class*)cl)->createStaticInstance();
+ val = new std::pair<uint8, JavaObject*>(0, staticVar);
+ JavaThread::get()->isolate->statics->hash((Class*)cl, val);
+ }
+#endif
+ if (meth) {
+ JavaObject* exc = 0;
+ try{
+ clinit_t pred = (clinit_t)meth->compiledPtr();
+ pred();
+ } catch(...) {
+ exc = JavaThread::getJavaException();
+ assert(exc && "no exception?");
+ JavaThread::clearException();
+ }
+ if (exc) {
+ if (exc->classOf->isAssignableFrom(Classpath::newException)) {
+ JavaThread::get()->isolate->initializerError(exc);
+ } else {
+ JavaThread::throwException(exc);
+ }
+ }
+ }
+
+ cl->status = ready;
+#ifndef SINGLE_VM
+ if (this == bootstrapVM) {
+ val->first = 1;
+ }
+#endif
+ cl->broadcastClass();
+ } else if (status < resolved) {
+ cl->release();
+ unknownError("try to clinit a not-readed class...");
+ } else {
+ if (!cl->ownerClass()) {
+ while (status < ready) cl->waitClass();
+ cl->release();
+ goto start;
+ }
+ cl->release();
+ }
+ }
+}
+
+void Jnjvm::resolveClass(CommonClass* cl, bool doClinit) {
+ if (cl->status < resolved) {
+ cl->aquire();
+ int status = cl->status;
+ if (status >= resolved) {
+ cl->release();
+ } else if (status < loaded) {
+ cl->release();
+ unknownError("try to resolve a not-readed class");
+ } else if (status == loaded || cl->ownerClass()) {
+ if (cl->isArray) {
+ ClassArray* arrayCl = (ClassArray*)cl;
+ CommonClass* baseClass = arrayCl->baseClass();
+ baseClass->resolveClass(doClinit);
+ cl->access = cl->access | baseClass->access;
+ cl->status = resolved;
+ } else {
+ readClass((Class*)cl);
+ cl->status = readed;
+ cl->release();
+ loadParents((Class*)cl);
+ cl->aquire();
+ cl->status = prepared;
+ ((Class*)cl)->resolveFields();
+ cl->status = resolved;
+ }
+ cl->release();
+ } else {
+ while (status < resolved) {
+ cl->waitClass();
+ }
+ cl->release();
+ }
+ }
+ if (doClinit) cl->initialiseClass();
+}
+
+CommonClass* Jnjvm::loadName(const UTF8* name, JavaObject* loader,
+ bool doResolve, bool doClinit, bool doThrow) {
+
+
+ CommonClass* cl = lookupClass(name, loader);
+ const UTF8* bootstrapName = name;
+#ifndef SINGLE_VM
+ if (!loader) {
+ bootstrapName = bootstrapVM->readerConstructUTF8(name->elements,
+ name->size);
+ if (bootstrapName != name) {
+ JavaThread::get()->isolate->hashUTF8->replace(name, bootstrapName);
+ }
+ cl = lookupClass(bootstrapName, loader);
+ }
+#endif
+
+ if (!cl || cl->status == hashed) {
+ if (!loader) { // I have to load it
+ ArrayUInt8* bytes = openName(name);
+ if (bytes) {
+ if (!cl) cl = bootstrapVM->constructClass(bootstrapName, loader);
+ if (cl->status == hashed) {
+ cl->aquire();
+ if (cl->status == hashed) {
+ cl->status = loaded;
+ ((Class*)cl)->bytes = bytes;
+ }
+ cl->release();
+ }
+ } else {
+ cl = 0;
+ }
+ } else {
+ cl = loadInClassLoader(name->internalToJava(this, 0, name->size), loader);
+ }
+ }
+
+ if (!cl && doThrow) {
+ if (!memcmp(name->UTF8ToAsciiz(), NoClassDefFoundError,
+ strlen(NoClassDefFoundError))) {
+ unknownError("Unable to load NoClassDefFoundError");
+ }
+ Jnjvm::error(NoClassDefFoundError, "unable to load %s", name->printString());
+ }
+
+ if (cl && doResolve) cl->resolveClass(doClinit);
+
+ return cl;
+}
+
+void Jnjvm::errorWithExcp(const char* className, const JavaObject* excp) {
+ Class* cl = (Class*) this->loadName(this->asciizConstructUTF8(className),
+ CommonClass::jnjvmClassLoader,
+ true, true, true);
+ JavaObject* obj = (*cl)();
+ JavaJIT::invokeOnceVoid(this, CommonClass::jnjvmClassLoader, className, "<init>",
+ "(Ljava/lang/Throwable;)V", ACC_VIRTUAL, obj, excp);
+ JavaThread::throwException(obj);
+}
+
+void Jnjvm::error(const char* className, const char* fmt, ...) {
+ char* tmp = (char*)alloca(4096);
+ Class* cl = (Class*) this->loadName(this->asciizConstructUTF8(className),
+ CommonClass::jnjvmClassLoader,
+ true, true, true);
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(tmp, 4096, fmt, ap);
+ va_end(ap);
+
+ JavaObject* obj = (*cl)();
+ JavaJIT::invokeOnceVoid(this, CommonClass::jnjvmClassLoader, className, "<init>",
+ "(Ljava/lang/String;)V", ACC_VIRTUAL, obj,
+ this->asciizToStr(tmp));
+ JavaThread::throwException(obj);
+}
+
+
+void Jnjvm::verror(const char* className, const char* fmt, va_list ap) {
+ char* tmp = (char*)alloca(4096);
+ Class* cl = (Class*) this->loadName(this->asciizConstructUTF8(className),
+ CommonClass::jnjvmClassLoader,
+ true, true, true);
+ vsnprintf(tmp, 4096, fmt, ap);
+ va_end(ap);
+ JavaObject* obj = (*cl)();
+ JavaJIT::invokeOnceVoid(this, CommonClass::jnjvmClassLoader, className, "<init>",
+ "(Ljava/lang/String;)V", ACC_VIRTUAL, obj,
+ this->asciizToStr(tmp));
+
+ JavaThread::throwException(obj);
+}
+
+void Jnjvm::arrayStoreException() {
+ error(ArrayStoreException, "");
+}
+
+void Jnjvm::indexOutOfBounds(const JavaObject* obj, sint32 entry) {
+ error(ArrayIndexOutOfBoundsException, "%d", entry);
+}
+
+void Jnjvm::negativeArraySizeException(sint32 size) {
+ error(NegativeArraySizeException, "%d", size);
+}
+
+void Jnjvm::nullPointerException(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ char* val = va_arg(ap, char*);
+ va_end(ap);
+ error(NullPointerException, fmt, val);
+}
+
+void Jnjvm::illegalAccessException(const char* msg) {
+ error(IllegalAccessException, msg);
+}
+
+void Jnjvm::illegalMonitorStateException(const JavaObject* obj) {
+ error(IllegalMonitorStateException, "");
+}
+
+void Jnjvm::interruptedException(const JavaObject* obj) {
+ error(InterruptedException, "");
+}
+
+
+void Jnjvm::initializerError(const JavaObject* excp) {
+ errorWithExcp(ExceptionInInitializerError, excp);
+}
+
+void Jnjvm::invocationTargetException(const JavaObject* excp) {
+ errorWithExcp(InvocationTargetException, excp);
+}
+
+void Jnjvm::outOfMemoryError(sint32 n) {
+ error(OutOfMemoryError, "");
+}
+
+void Jnjvm::illegalArgumentExceptionForMethod(JavaMethod* meth,
+ CommonClass* required,
+ CommonClass* given) {
+ error(IllegalArgumentException, "for method %s", meth->printString());
+}
+
+void Jnjvm::illegalArgumentExceptionForField(JavaField* field,
+ CommonClass* required,
+ CommonClass* given) {
+ error(IllegalArgumentException, "for field %s", field->printString());
+}
+
+void Jnjvm::illegalArgumentException(const char* msg) {
+ error(IllegalArgumentException, msg);
+}
+
+void Jnjvm::classCastException(const char* msg) {
+ error(ClassCastException, msg);
+}
+
+void Jnjvm::unknownError(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ verror(UnknownError, fmt, ap);
+}
+
+CommonClass* Jnjvm::lookupClassFromUTF8(const UTF8* utf8, unsigned int start,
+ unsigned int len, JavaObject* loader,
+ bool doResolve, bool doClinit,
+ bool doThrow) {
+ uint32 origLen = len;
+ const UTF8* name = utf8->javaToInternal(this, start, len);
+ bool doLoop = true;
+ CommonClass* ret = 0;
+
+ if (len == 0) {
+ return 0;
+ } else if (name->at(0) == AssessorDesc::I_TAB) {
+
+ while (doLoop) {
+ if (len == 0) {
+ doLoop = false;
+ } else {
+ ++start;
+ --len;
+ if (name->at(start) != AssessorDesc::I_TAB) {
+ if (name->at(start) == AssessorDesc::I_REF) {
+ uint32 size = (uint32)name->size;
+ if ((size == (start + 1)) || (size == (start + 2)) ||
+ (name->at(start + 1) == AssessorDesc::I_TAB) ||
+ (utf8->at(origLen - 1) != AssessorDesc::I_END_REF)) {
+ doLoop = false;
+ } else {
+ const UTF8* componentName = utf8->javaToInternal(this, start + 1,
+ len - 2);
+ if (loadName(componentName, loader, doResolve, doClinit,
+ doThrow)) {
+ ret = constructArray(name, loader);
+ if (doResolve) ret->resolveClass(doClinit);
+ doLoop = false;
+ } else {
+ doLoop = false;
+ }
+ }
+ } else {
+ uint16 cur = name->at(start);
+ if ((cur == AssessorDesc::I_BOOL || cur == AssessorDesc::I_BYTE ||
+ cur == AssessorDesc::I_CHAR || cur == AssessorDesc::I_SHORT ||
+ cur == AssessorDesc::I_INT || cur == AssessorDesc::I_FLOAT ||
+ cur == AssessorDesc::I_DOUBLE || cur == AssessorDesc::I_LONG)
+ && ((uint32)name->size) == start + 1) {
+
+ ret = constructArray(name, loader);
+ ret->resolveClass(doClinit);
+ doLoop = false;
+ } else {
+ doLoop = false;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+
+ } else {
+ return loadName(name, loader, doResolve, doClinit, doThrow);
+ }
+}
+
+CommonClass* Jnjvm::lookupClassFromJavaString(JavaString* str,
+ JavaObject* loader,
+ bool doResolve, bool doClinit,
+ bool doThrow) {
+ return lookupClassFromUTF8(str->value, str->offset, str->count, loader,
+ doResolve, doClinit, doThrow);
+}
+
+CommonClass* Jnjvm::lookupClass(const UTF8* utf8, JavaObject* loader) {
+ if (loader) {
+#ifndef SERVICE_VM
+ ClassMap* map =
+ (ClassMap*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
+ if (!map) {
+ map = ClassMap::allocate();
+ (*Classpath::vmdataClassLoader)(loader, (JavaObject*)map);
+ }
+#else
+ ClassMap* map = 0;
+ ServiceDomain* vm =
+ (ServiceDomain*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
+ if (!vm) {
+ vm = ServiceDomain::allocate();
+ (*Classpath::vmdataClassLoader)(loader, (JavaObject*)vm);
+ }
+ map = vm->classes;
+#endif
+ return map->lookup(utf8);
+ } else {
+ return bootstrapClasses->lookup(utf8);
+ }
+}
+
+static CommonClass* arrayDup(const UTF8*& name, Jnjvm *vm) {
+ ClassArray* cl = gc_new(ClassArray)();
+ cl->initialise(vm, true);
+ cl->name = name;
+ cl->classLoader = 0;
+ cl->_funcs = 0;
+ cl->_baseClass = 0;
+ cl->super = ClassArray::SuperArray;
+ cl->interfaces = ClassArray::InterfacesArray;
+ cl->virtualMethods = ClassArray::VirtualMethodsArray;
+ cl->staticMethods = ClassArray::StaticMethodsArray;
+ cl->virtualFields = ClassArray::VirtualFieldsArray;
+ cl->staticFields = ClassArray::StaticFieldsArray;
+ cl->depth = 1;
+ cl->display.push_back(ClassArray::SuperArray);
+ cl->display.push_back(cl);
+ cl->access = ACC_FINAL | ACC_ABSTRACT;
+ cl->status = loaded;
+ return cl;
+}
+
+ClassArray* Jnjvm::constructArray(const UTF8* name, JavaObject* loader) {
+ if (loader != 0)
+ loader = ClassArray::arrayLoader(this, name, loader, 1, name->size - 1);
+
+ if (loader) {
+#ifndef SERVICE_VM
+ ClassMap* map =
+ (ClassMap*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
+ if (!map) {
+ map = ClassMap::allocate();
+ (*Classpath::vmdataClassLoader)(loader, (JavaObject*)map);
+ }
+ ClassArray* res = (ClassArray*)map->lookupOrCreate(name, this, arrayDup);
+#else
+ ClassMap* map = 0;
+ ServiceDomain* vm =
+ (ServiceDomain*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
+ if (!vm) {
+ vm = ServiceDomain::allocate();
+ (*Classpath::vmdataClassLoader)(loader, (JavaObject*)vm);
+ }
+ map = vm->classes;
+ ClassArray* res = (ClassArray*)map->lookupOrCreate(name, vm, arrayDup);
+#endif
+ if (!res->classLoader) res->classLoader = loader;
+ return res;
+ } else {
+ return (ClassArray*)bootstrapClasses->lookupOrCreate(name, this, arrayDup);
+ }
+}
+
+
+static CommonClass* classDup(const UTF8*& name, Jnjvm *vm) {
+ Class* cl = gc_new(Class)();
+ cl->initialise(vm, false);
+ cl->name = name;
+ cl->classLoader = 0;
+ cl->bytes = 0;
+ cl->_staticInstance = 0;
+ cl->virtualInstance = 0;
+ cl->super = 0;
+ cl->ctpInfo = 0;
+ return cl;
+}
+
+Class* Jnjvm::constructClass(const UTF8* name, JavaObject* loader) {
+ if (loader) {
+#ifndef SERVICE_VM
+ ClassMap* map =
+ (ClassMap*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
+ if (!map) {
+ map = ClassMap::allocate();
+ (*Classpath::vmdataClassLoader)(loader, (JavaObject*)map);
+ }
+ Class* res = (Class*)map->lookupOrCreate(name, this, classDup);
+#else
+ ClassMap* map = 0;
+ ServiceDomain* vm =
+ (ServiceDomain*)(*Classpath::vmdataClassLoader)(loader).PointerVal;
+ if (!vm) {
+ vm = ServiceDomain::allocate();
+ (*Classpath::vmdataClassLoader)(loader, (JavaObject*)vm);
+ }
+ map = vm->classes;
+ Class* res = (Class*)map->lookupOrCreate(name, vm, classDup);
+#endif
+ if (!res->classLoader) res->classLoader = loader;
+ return res;
+ } else {
+ return (Class*)bootstrapClasses->lookupOrCreate(name, this, classDup);
+ }
+}
+
+static JavaField* fieldDup(FieldCmp & cmp, Jnjvm *vm) {
+ JavaField* field = gc_new(JavaField)();
+ field->name = cmp.name;
+ field->type = cmp.type;
+ field->classDef = (Class*)cmp.classDef;
+ field->signature = vm->constructType(field->type);
+ field->ptrOffset = 0;
+ return field;
+}
+
+JavaField* Jnjvm::constructField(Class* cl, const UTF8* name, const UTF8* type,
+ uint32 access){
+ FieldCmp CC(name, cl, type);
+ JavaField* f = loadedFields->lookupOrCreate(CC, this, fieldDup);
+ f->access = access;
+ f->offset = 0;
+ return f;
+}
+
+JavaField* Jnjvm::lookupField(CommonClass* cl, const UTF8* name,
+ const UTF8* type) {
+ FieldCmp CC(name, cl, type);
+ JavaField* f = loadedFields->lookup(CC);
+ return f;
+}
+
+static JavaMethod* methodDup(FieldCmp & cmp, Jnjvm *vm) {
+ JavaMethod* method = gc_new(JavaMethod)();
+ method->name = cmp.name;
+ method->type = cmp.type;
+ method->classDef = (Class*)cmp.classDef;
+ method->signature = (Signdef*)vm->constructType(method->type);
+ method->methPtr = 0;
+ method->code = 0;
+ return method;
+}
+
+JavaMethod* Jnjvm::constructMethod(Class* cl, const UTF8* name,
+ const UTF8* type, uint32 access) {
+ FieldCmp CC(name, cl, type);
+ JavaMethod* f = loadedMethods->lookupOrCreate(CC, this, methodDup);
+ f->access = access;
+ return f;
+}
+
+const UTF8* Jnjvm::asciizConstructUTF8(const char* asciiz) {
+#ifndef SINGLE_VM
+ if (this != bootstrapVM) {
+ const UTF8* existing = bootstrapVM->hashUTF8->lookupAsciiz(asciiz);
+ if (existing) return existing;
+ }
+#endif
+ return hashUTF8->lookupOrCreateAsciiz(asciiz);
+}
+
+const UTF8* Jnjvm::readerConstructUTF8(const uint16* buf, uint32 size) {
+#ifndef SINGLE_VM
+ if (this != bootstrapVM) {
+ const UTF8* existing = bootstrapVM->hashUTF8->lookupReader(buf, size);
+ if (existing) return existing;
+ }
+#endif
+ return hashUTF8->lookupOrCreateReader(buf, size);
+}
+
+Typedef* Jnjvm::constructType(const UTF8* name) {
+ Typedef* res = javaTypes->lookup(name);
+ if (res == 0) {
+ res = Typedef::typeDup(name, this);
+ javaTypes->lock->lock();
+ Typedef* tmp = javaTypes->lookup(name);
+ if (tmp == 0) javaTypes->hash(name, res);
+ else res = tmp;
+ javaTypes->lock->unlock();
+ }
+ return res;
+}
+
+CommonClass* Jnjvm::loadInClassLoader(const UTF8* name, JavaObject* loader) {
+ JavaObject* obj = (JavaObject*)
+ Classpath::loadInClassLoader->invokeJavaObjectVirtual(loader, this->UTF8ToStr(name));
+ return (CommonClass*)((*Classpath::vmdataClass)(obj).PointerVal);
+}
+
+JavaString* Jnjvm::UTF8ToStr(const UTF8* utf8) {
+#ifndef SINGLE_VM
+ if (this != bootstrapVM) {
+ JavaString* existing = bootstrapVM->hashStr->lookup(utf8);
+ if (existing) return existing;
+ }
+#endif
+ JavaString* res = hashStr->lookupOrCreate(utf8, this, JavaString::stringDup);
+ return res;
+}
+
+JavaString* Jnjvm::asciizToStr(const char* asciiz) {
+ const UTF8* var = asciizConstructUTF8(asciiz);
+ return UTF8ToStr(var);
+}
+
+void Jnjvm::addProperty(char* key, char* value) {
+ postProperties.push_back(std::make_pair(key, value));
+}
+
+#ifdef SINGLE_VM
+JavaObject* Jnjvm::getClassDelegatee(CommonClass* cl) {
+ if (!(cl->delegatee)) {
+ JavaObject* delegatee = (*Classpath::newClass)();
+ cl->delegatee = delegatee;
+ Classpath::initClass->invokeIntSpecial(delegatee, cl);
+ } else if (cl->delegatee->classOf != Classpath::newClass) {
+ JavaObject* pd = cl->delegatee;
+ JavaObject* delegatee = (*Classpath::newClass)();
+ cl->delegatee = delegatee;;
+ Classpath::initClassWithProtectionDomain->invokeIntSpecial(delegatee, cl, pd);
+ }
+ return cl->delegatee;
+}
+#else
+JavaObject* Jnjvm::getClassDelegatee(CommonClass* cl) {
+ JavaObject* val = delegatees->lookup(cl);
+ if (!val) {
+ val = (*Classpath::newClass)();
+ delegatees->hash(cl, val);
+ Classpath::initClass->invokeIntSpecial(val, cl);
+ } else if (val->classOf != Classpath::newClass) {
+ JavaObject* pd = val;
+ val = (*Classpath::newClass)();
+ delegatees->hash(cl, val);
+ Classpath::initClassWithProtectionDomain->invokeIntSpecial(val, cl, pd);
+ }
+ return val;
+}
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/Jnjvm.h b/vmkit/lib/JnJVM/VMCore/Jnjvm.h
new file mode 100644
index 0000000..0416cb4
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Jnjvm.h
@@ -0,0 +1,258 @@
+//===---------- Jnjvm.h - Java virtual machine description ---------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_JAVA_VM_H
+#define JNJVM_JAVA_VM_H
+
+#include <vector>
+
+#include "llvm/Function.h"
+#include "llvm/PassManager.h"
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+
+#include "types.h"
+
+namespace jnjvm {
+
+class ArrayUInt8;
+class Attribut;
+class Class;
+class ClassArray;
+class CommonClass;
+class JavaField;
+class JavaMethod;
+class JavaObject;
+class JavaString;
+class JnjvmModuleProvider;
+class Reader;
+class Typedef;
+class UTF8;
+class UTF8Map;
+class ClassMap;
+class DelegateeMap;
+class FieldMap;
+class MethodMap;
+class StaticInstanceMap;
+class StringMap;
+class TypeMap;
+class FunctionMap;
+class FunctionDefMap;
+class AllocationMap;
+
+
+class Jnjvm : public mvm::Object{
+public:
+ static VirtualTable* VT;
+ static Jnjvm* bootstrapVM;
+
+ static const char* dirSeparator;
+ static const char* envSeparator;
+ static const unsigned int Magic;
+
+ // Misc constants
+ static const double MaxDouble;
+ static const double MinDouble;
+ static const double MaxLongDouble;
+ static const double MinLongDouble;
+ static const double MaxIntDouble;
+ static const double MinIntDouble;
+ static const uint64 MaxLong;
+ static const uint64 MinLong;
+ static const uint32 MaxInt;
+ static const uint32 MinInt;
+ static const float MaxFloat;
+ static const float MinFloat;
+ static const float MaxIntFloat;
+ static const float MinIntFloat;
+ static const float MaxLongFloat;
+ static const float MinLongFloat;
+ static const float NaNFloat;
+ static const double NaNDouble;
+
+ // Exceptions name
+ static const char* ArithmeticException;
+ static const char* ClassNotFoundException;
+ static const char* InvocationTargetException;
+ static const char* ArrayStoreException;
+ static const char* ClassCastException;
+ static const char* IllegalMonitorStateException;
+ static const char* IllegalArgumentException;
+ static const char* InterruptedException;
+ static const char* IndexOutOfBoundsException;
+ static const char* ArrayIndexOutOfBoundsException;
+ static const char* NegativeArraySizeException;
+ static const char* NullPointerException;
+ static const char* SecurityException;
+ static const char* ClassFormatError;
+ static const char* ClassCircularityError;
+ static const char* NoClassDefFoundError;
+ static const char* UnsupportedClassVersionError;
+ static const char* NoSuchFieldError;
+ static const char* NoSuchMethodError;
+ static const char* InstantiationError;
+ static const char* IllegalAccessError;
+ static const char* IllegalAccessException;
+ static const char* VerifyError;
+ static const char* ExceptionInInitializerError;
+ static const char* LinkageError;
+ static const char* AbstractMethodError;
+ static const char* UnsatisfiedLinkError;
+ static const char* InternalError;
+ static const char* OutOfMemoryError;
+ static const char* StackOverflowError;
+ static const char* UnknownError;
+
+
+ // Exceptions
+ void arrayStoreException();
+ void indexOutOfBounds(const JavaObject* obj, sint32 entry);
+ void negativeArraySizeException(int size);
+ void nullPointerException(const char* fmt, ...);
+ void illegalAccessException(const char* msg);
+ void illegalMonitorStateException(const JavaObject* obj);
+ void interruptedException(const JavaObject* obj);
+ void initializerError(const JavaObject* excp);
+ void invocationTargetException(const JavaObject* obj);
+ void outOfMemoryError(sint32 n);
+ void illegalArgumentExceptionForMethod(JavaMethod* meth, CommonClass* required,
+ CommonClass* given);
+ void illegalArgumentExceptionForField(JavaField* field, CommonClass* required,
+ CommonClass* given);
+ void illegalArgumentException(const char* msg);
+ void classCastException(const char* msg);
+ void unknownError(const char* fmt, ...);
+ void error(const char* className, const char* fmt, ...);
+ void verror(const char* className, const char* fmt, va_list ap);
+ void errorWithExcp(const char* className, const JavaObject* excp);
+
+
+ static const UTF8* initName;
+ static const UTF8* clinitName;
+ static const UTF8* clinitType;
+ static const UTF8* runName;
+ static const UTF8* prelib;
+ static const UTF8* postlib;
+ static const UTF8* mathName;
+ static const UTF8* abs;
+ static const UTF8* sqrt;
+ static const UTF8* sin;
+ static const UTF8* cos;
+ static const UTF8* tan;
+ static const UTF8* asin;
+ static const UTF8* acos;
+ static const UTF8* atan;
+ static const UTF8* atan2;
+ static const UTF8* exp;
+ static const UTF8* log;
+ static const UTF8* pow;
+ static const UTF8* ceil;
+ static const UTF8* floor;
+ static const UTF8* rint;
+ static const UTF8* cbrt;
+ static const UTF8* cosh;
+ static const UTF8* expm1;
+ static const UTF8* hypot;
+ static const UTF8* log10;
+ static const UTF8* log1p;
+ static const UTF8* sinh;
+ static const UTF8* tanh;
+
+
+ void analyseClasspathEnv(const char*);
+
+ // Loads a Class
+ CommonClass* loadName(const UTF8* name, JavaObject* loader, bool doResolve,
+ bool doClinit, bool doThrow);
+
+ // Class lookup
+ CommonClass* lookupClassFromUTF8(const UTF8* utf8, unsigned int start,
+ unsigned int len, JavaObject* loader,
+ bool doResolve, bool doClinit, bool doThrow);
+ CommonClass* lookupClassFromJavaString(JavaString* str, JavaObject* loader,
+ bool doResolve, bool doClinit,
+ bool doThrow);
+
+ void readParents(Class* cl, Reader* reader);
+ void loadParents(Class* cl);
+ void readAttributs(Class* cl, Reader* reader, std::vector<Attribut*> & attr);
+ void readFields(Class* cl, Reader* reader);
+ void readMethods(Class* cl, Reader* reader);
+ void readClass(Class* cl);
+ void initialiseClass(CommonClass* cl);
+ void resolveClass(CommonClass* cl, bool doClinit);
+ ArrayUInt8* openName(const UTF8* utf8);
+
+ CommonClass* lookupClass(const UTF8* utf8, JavaObject* loader);
+ JavaField* lookupField(CommonClass* cl, const UTF8* name, const UTF8* type);
+
+ ClassArray* constructArray(const UTF8* name, JavaObject* loader);
+ Class* constructClass(const UTF8* name, JavaObject* loader);
+ JavaField* constructField(Class* cl, const UTF8* name, const UTF8* type,
+ uint32 access);
+ JavaMethod* constructMethod(Class* cl, const UTF8* name, const UTF8* type,
+ uint32 access);
+ const UTF8* asciizConstructUTF8(const char* asciiz);
+ const UTF8* readerConstructUTF8(const uint16* buf, uint32 len);
+ JavaString* asciizToStr(const char* asciiz);
+ JavaString* UTF8ToStr(const UTF8* utf8);
+ Typedef* constructType(const UTF8 * name);
+
+
+ JavaObject* getClassDelegatee(CommonClass*);
+ CommonClass* loadInClassLoader(const UTF8* utf8, JavaObject* loader);
+
+ virtual void tracer(size_t sz);
+ virtual void print(mvm::PrintBuffer* buf) const {
+ buf->write("Jnjvm<>");
+ }
+
+ void addProperty(char* key, char* value);
+
+ void* jniEnv;
+ const void* javavmEnv;
+ std::vector< std::pair<char*, char*> > postProperties;
+ std::vector<char*> bootClasspath;
+ std::vector<void*> nativeLibs;
+ const char* classpath;
+ const char* libClasspathEnv;
+ const char* bootClasspathEnv;
+ std::vector<JavaObject*> globalRefs;
+ mvm::Lock* globalRefsLock;
+
+ void setClasspath(char* cp) {
+ classpath = cp;
+ }
+
+ const char* name;
+ JavaObject* appClassLoader;
+ UTF8Map * hashUTF8;
+ StringMap * hashStr;
+ ClassMap* bootstrapClasses;
+ MethodMap* loadedMethods;
+ FieldMap* loadedFields;
+ TypeMap* javaTypes;
+#ifndef SINGLE_VM
+ StaticInstanceMap* statics;
+ DelegateeMap* delegatees;
+#endif
+
+
+ mvm::Lock* protectModule;
+ llvm::Module* module;
+ JnjvmModuleProvider* TheModuleProvider;
+ FunctionMap* functions;
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp b/vmkit/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp
new file mode 100644
index 0000000..3442d7c
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp
@@ -0,0 +1,68 @@
+//===--- JnjvmModuleProvider.cpp - LLVM Module Provider for Jnjvm ---------===//
+//
+// Jnjvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Module.h>
+#include <llvm/ModuleProvider.h>
+
+#include "mvm/JIT.h"
+
+#include "JnjvmModuleProvider.h"
+
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaJIT.h"
+#include "JavaThread.h"
+#include "Jnjvm.h"
+
+using namespace llvm;
+using namespace jnjvm;
+#include <iostream>
+
+static JavaMethod* staticLookup(Class* caller, uint32 index) {
+ JavaCtpInfo* ctpInfo = caller->ctpInfo;
+
+
+ bool isStatic = ctpInfo->isAStaticCall(index);
+
+ CommonClass* cl = 0;
+ const UTF8* utf8 = 0;
+ Signdef* sign = 0;
+
+ ctpInfo->resolveInterfaceOrMethod(index, cl, utf8, sign);
+
+ JavaMethod* meth = cl->lookupMethod(utf8, sign->keyName, isStatic, true);
+
+ meth->compiledPtr();
+
+ ctpInfo->ctpRes[index] = meth->methPtr;
+
+ return meth;
+}
+
+
+bool JnjvmModuleProvider::materializeFunction(Function *F,
+ std::string *ErrInfo) {
+ std::pair<Class*, uint32> * p = functions->lookup(F);
+ if (!p) {
+ // VT methods
+ return false;
+ } else {
+ if (mvm::jit::executionEngine->getPointerToGlobalIfAvailable(F)) {
+ return false;
+ } else {
+ JavaMethod* meth = staticLookup(p->first, p->second);
+ void* val = meth->compiledPtr();
+ if (!(mvm::jit::executionEngine->getPointerToGlobalIfAvailable(F)))
+ mvm::jit::executionEngine->updateGlobalMapping(F, val);
+ return false;
+ }
+
+ }
+}
+
diff --git a/vmkit/lib/JnJVM/VMCore/JnjvmModuleProvider.h b/vmkit/lib/JnJVM/VMCore/JnjvmModuleProvider.h
new file mode 100644
index 0000000..0069c9c
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/JnjvmModuleProvider.h
@@ -0,0 +1,36 @@
+//===----- JnjvmModuleProvider.h - LLVM Module Provider for Jnjvm ---------===//
+//
+// Jnjvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_MODULE_PROVIDER_H
+#define JNJVM_MODULE_PROVIDER_H
+
+#include <llvm/ModuleProvider.h>
+
+#include "LockedMap.h"
+
+using namespace llvm;
+
+namespace jnjvm {
+
+class JnjvmModuleProvider : public ModuleProvider {
+public:
+ FunctionMap* functions;
+ JnjvmModuleProvider(Module *m, FunctionMap* fm) {
+ TheModule = m;
+ functions = fm;
+ }
+
+ bool materializeFunction(Function *F, std::string *ErrInfo = 0);
+
+ Module* materializeModule(std::string *ErrInfo = 0) { return TheModule; }
+};
+
+} // End jnjvm namespace
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/LockedMap.cpp b/vmkit/lib/JnJVM/VMCore/LockedMap.cpp
new file mode 100644
index 0000000..707ff48
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/LockedMap.cpp
@@ -0,0 +1,168 @@
+//===------- LockedMap.cpp - Implementation of the UTF8 map ---------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaString.h"
+#include "JavaTypes.h"
+#include "LockedMap.h"
+#include "Zip.h"
+
+#include <string.h>
+
+using namespace jnjvm;
+
+
+static uint32 asciizHasher(const char* asciiz, sint32 size) {
+ uint32 r0 = 0, r1 = 0;
+ for (sint32 i = 0; i < size; i++) {
+ char c = asciiz[i];
+ r0 += c;
+ r1 ^= c;
+ }
+ return (r1 & 255) + ((r0 & 255) << 8);
+}
+
+static uint32 readerHasher(const uint16* buf, sint32 size) {
+ uint32 r0 = 0, r1 = 0;
+ for (sint32 i = 0; i < size; i++) {
+ uint16 c = buf[i];
+ r0 += c;
+ r1 ^= c;
+ }
+ return (r1 & 255) + ((r0 & 255) << 8);
+}
+
+static bool asciizEqual(const UTF8* val, const char* asciiz, sint32 size) {
+ sint32 len = val->size;
+ if (len != size) return false;
+ else {
+ for (sint32 i = 0; i < len; i++) {
+ if (asciiz[i] != val->at(i)) return false;
+ }
+ return true;
+ }
+}
+
+static bool readerEqual(const UTF8* val, const uint16* buf, sint32 size) {
+ sint32 len = val->size;
+ if (len != size) return false;
+ else return !(memcmp(val->elements, buf, len * sizeof(uint16)));
+}
+
+void UTF8Map::replace(const UTF8* oldUTF8, const UTF8* newUTF8) {
+ lock->lock();
+ uint32 key = readerHasher(oldUTF8->elements, oldUTF8->size);
+ std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key);
+
+ for (UTF8Map::iterator i = p.first; i != p.second; i++) {
+ if (i->second == oldUTF8) {
+ map.erase(i);
+ break;
+ }
+ }
+ map.insert(std::make_pair(key, newUTF8));
+ lock->unlock();
+
+}
+
+const UTF8* UTF8Map::lookupOrCreateAsciiz(const char* asciiz) {
+ sint32 size = strlen(asciiz);
+ uint32 key = asciizHasher(asciiz, size);
+ const UTF8* res = 0;
+ lock->lock();
+
+ std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key);
+
+ for (UTF8Map::iterator i = p.first; i != p.second; i++) {
+ if (asciizEqual(i->second, asciiz, size)) {
+ res = i->second;
+ break;
+ }
+ }
+
+ if (res == 0) {
+ UTF8* tmp = UTF8::acons(size, JavaArray::ofChar);
+ for (sint32 i = 0; i < size; i++) {
+ tmp->setAt(i, asciiz[i]);
+ }
+ res = (const UTF8*)tmp;
+ map.insert(std::make_pair(key, res));
+ }
+
+ lock->unlock();
+ return res;
+}
+
+const UTF8* UTF8Map::lookupOrCreateReader(const uint16* buf, uint32 len) {
+ sint32 size = (sint32)len;
+ uint32 key = readerHasher(buf, size);
+ const UTF8* res = 0;
+ lock->lock();
+
+ std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key);
+
+ for (UTF8Map::iterator i = p.first; i != p.second; i++) {
+ if (readerEqual(i->second, buf, size)) {
+ res = i->second;
+ break;
+ }
+ }
+
+ if (res == 0) {
+ UTF8* tmp = UTF8::acons(size, JavaArray::ofChar);
+ memcpy(tmp->elements, buf, len * sizeof(uint16));
+ res = (const UTF8*)tmp;
+ map.insert(std::make_pair(key, res));
+ }
+
+ lock->unlock();
+ return res;
+}
+
+const UTF8* UTF8Map::lookupAsciiz(const char* asciiz) {
+ sint32 size = strlen(asciiz);
+ uint32 key = asciizHasher(asciiz, size);
+ const UTF8* res = 0;
+ lock->lock();
+
+ std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key);
+
+ for (UTF8Map::iterator i = p.first; i != p.second; i++) {
+ if (asciizEqual(i->second, asciiz, size)) {
+ res = i->second;
+ break;
+ }
+ }
+
+ lock->unlock();
+ return res;
+}
+
+const UTF8* UTF8Map::lookupReader(const uint16* buf, uint32 len) {
+ sint32 size = (sint32)len;
+ uint32 key = readerHasher(buf, size);
+ const UTF8* res = 0;
+ lock->lock();
+
+ std::pair<UTF8Map::iterator, UTF8Map::iterator> p = map.equal_range(key);
+
+ for (UTF8Map::iterator i = p.first; i != p.second; i++) {
+ if (readerEqual(i->second, buf, size)) {
+ res = i->second;
+ break;
+ }
+ }
+
+ lock->unlock();
+ return res;
+}
+
diff --git a/vmkit/lib/JnJVM/VMCore/LockedMap.h b/vmkit/lib/JnJVM/VMCore/LockedMap.h
new file mode 100644
index 0000000..9f29fca
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/LockedMap.h
@@ -0,0 +1,346 @@
+//===------- LockedMap.h - A thread-safe map implementation ---------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_LOCKED_MAP_H
+#define JNJVM_LOCKED_MAP_H
+
+#include <map>
+
+#include <string.h>
+
+#include "types.h"
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaTypes.h"
+#include "JavaString.h"
+#include "Zip.h"
+
+namespace jnjvm {
+
+class JavaObject;
+class Jnjvm;
+class llvm::Function;
+class llvm::GlobalVariable;
+
+template<class Key, class Container, class Compare>
+class LockedMap : public mvm::Object {
+public:
+ typedef typename std::map<Key, Container, Compare>::iterator iterator;
+ typedef Container (*funcCreate)(Key& V, Jnjvm *vm);
+
+ mvm::Lock* lock;
+ std::map<Key, Container, Compare> map;
+
+ inline Container lookupOrCreate(Key& V, Jnjvm *vm, funcCreate func) {
+ lock->lock();
+ iterator End = map.end();
+ iterator I = map.find(V);
+ if (I == End) {
+ Container res = func(V, vm);
+ map.insert(std::make_pair(V, res));
+ lock->unlock();
+ return res;
+ } else {
+ lock->unlock();
+ return ((Container)(I->second));
+ }
+ }
+
+ inline Container lookup(Key V) {
+ lock->lock();
+ iterator End = map.end();
+ iterator I = map.find(V);
+ lock->unlock();
+ return I != End ? ((Container)(I->second)) : 0;
+ }
+
+ inline void hash(Key k, Container c) {
+ lock->lock();
+ map.insert(std::make_pair(k, c));
+ lock->unlock();
+ }
+
+
+ virtual void print(mvm::PrintBuffer* buf) {
+ buf->write("Hashtable<>");
+ }
+
+};
+
+class UTF8Map : public mvm::Object {
+public:
+ typedef std::multimap<uint32, const UTF8*>::iterator iterator;
+
+ mvm::Lock* lock;
+ std::multimap<uint32, const UTF8*> map;
+ static VirtualTable* VT;
+ const UTF8* lookupOrCreateAsciiz(const char* asciiz);
+ const UTF8* lookupOrCreateReader(const uint16* buf, uint32 size);
+ const UTF8* lookupAsciiz(const char* asciiz);
+ const UTF8* lookupReader(const uint16* buf, uint32 size);
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+
+ virtual void print(mvm::PrintBuffer* buf) {
+ buf->write("UTF8 Hashtable<>");
+ }
+
+ static UTF8Map* allocate() {
+ UTF8Map* map = gc_new(UTF8Map)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ UTF8Map* copy() {
+ UTF8Map* newMap = allocate();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ newMap->map.insert(*i);
+ }
+ return newMap;
+ }
+
+ void replace(const UTF8* oldUTF8, const UTF8* newUTF8);
+ void insert(const UTF8* val);
+};
+
+class FieldCmp {
+public:
+ const UTF8* name;
+ CommonClass* classDef;
+ const UTF8* type;
+
+ FieldCmp(const UTF8* n, CommonClass* c, const UTF8* t) : name(n), classDef(c),
+ type(t) {}
+
+ inline bool operator<(const FieldCmp &cmp) const {
+ if (name < cmp.name) return true;
+ else if (name > cmp.name) return false;
+ else if (classDef < cmp.classDef) return true;
+ else if (classDef > cmp.classDef) return false;
+ else return type < cmp.type;
+ }
+};
+
+class ClassMap :
+ public LockedMap<const UTF8*, CommonClass*, std::less<const UTF8*> > {
+public:
+ static VirtualTable* VT;
+ static ClassMap* allocate() {
+ ClassMap* map = gc_new(ClassMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+};
+
+class FieldMap :
+ public LockedMap<FieldCmp, JavaField*, std::less<FieldCmp> > {
+public:
+ static VirtualTable* VT;
+ static FieldMap* allocate() {
+ FieldMap* map = gc_new(FieldMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+};
+
+class MethodMap :
+ public LockedMap<FieldCmp, JavaMethod*, std::less<FieldCmp> > {
+public:
+ static VirtualTable* VT;
+ static MethodMap* allocate() {
+ MethodMap* map = gc_new(MethodMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+};
+
+struct ltstr
+{
+ bool operator()(const char* s1, const char* s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+class ZipFileMap : public LockedMap<const char*, ZipFile*, ltstr> {
+public:
+ static VirtualTable* VT;
+ static ZipFileMap* allocate() {
+ ZipFileMap* map = gc_new(ZipFileMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+};
+
+class StringMap :
+ public LockedMap<const UTF8*, JavaString*, std::less<const UTF8*> > {
+public:
+ static VirtualTable* VT;
+ static StringMap* allocate() {
+ StringMap* map = gc_new(StringMap)();
+ map->lock = mvm::Lock::allocRecursive();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+};
+
+class FunctionMap :
+ public LockedMap<llvm::Function*, std::pair<Class*, uint32>*, std::less<llvm::Function*> > {
+public:
+ static VirtualTable* VT;
+ static FunctionMap* allocate() {
+ FunctionMap* map = gc_new(FunctionMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->first->markAndTrace();
+ }
+ }
+};
+
+class FunctionDefMap :
+ public LockedMap<llvm::Function*, JavaMethod*, std::less<llvm::Function*> > {
+public:
+ static VirtualTable* VT;
+ static FunctionDefMap* allocate() {
+ FunctionDefMap* map = gc_new(FunctionDefMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+};
+
+class TypeMap :
+ public LockedMap<const UTF8*, Typedef*, std::less<const UTF8*> > {
+public:
+ static VirtualTable* VT;
+
+ inline Typedef* lookupOrCreate(const UTF8*& V, Jnjvm *vm, funcCreate func) {
+ assert(0);
+ return 0;
+ }
+
+ static TypeMap* allocate() {
+ TypeMap* map = gc_new(TypeMap)();
+ map->lock = mvm::Lock::allocRecursive();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->second->markAndTrace();
+ }
+ }
+
+};
+
+class StaticInstanceMap :
+ public LockedMap<Class*, std::pair<uint8, JavaObject*>*, std::less<Class*> > {
+public:
+ static VirtualTable* VT;
+
+ static StaticInstanceMap* allocate() {
+ StaticInstanceMap* map = gc_new(StaticInstanceMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->first->markAndTrace();
+ i->second->second->markAndTrace();
+ }
+ }
+
+ virtual void destroyer(size_t sz) {
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ delete i->second;
+ }
+ }
+};
+
+class DelegateeMap :
+ public LockedMap<CommonClass*, JavaObject*, std::less<CommonClass*> > {
+public:
+ static VirtualTable* VT;
+
+ static DelegateeMap* allocate() {
+ DelegateeMap* map = gc_new(DelegateeMap)();
+ map->lock = mvm::Lock::allocNormal();
+ return map;
+ }
+
+ virtual void tracer(size_t sz) {
+ //lock->markAndTrace();
+ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) {
+ i->first->markAndTrace();
+ i->second->markAndTrace();
+ }
+ }
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/LowerArrayLength.cpp b/vmkit/lib/JnJVM/VMCore/LowerArrayLength.cpp
new file mode 100644
index 0000000..54a9ade
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/LowerArrayLength.cpp
@@ -0,0 +1,72 @@
+//===----- LowerArrayLength.cpp - Changes arrayLength calls --------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "llvm/Pass.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+
+#include "mvm/JIT.h"
+
+#include "JavaArray.h"
+#include "JavaJIT.h"
+
+using namespace llvm;
+
+namespace {
+
+ class VISIBILITY_HIDDEN LowerArrayLength : public FunctionPass {
+ public:
+ static char ID;
+ LowerArrayLength() : FunctionPass((intptr_t)&ID) { }
+
+ virtual bool runOnFunction(Function &F);
+ private:
+ };
+ char LowerArrayLength::ID = 0;
+ RegisterPass<LowerArrayLength> X("LowerArrayLength", "Lower Array length");
+}
+
+bool LowerArrayLength::runOnFunction(Function& F) {
+ bool Changed = false;
+ for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) {
+ BasicBlock *Cur = BI;
+
+ for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;
+ II++) {
+ Instruction *I = II;
+ if (CallInst *CI = dyn_cast<CallInst>(I)) {
+ if (CI->getOperand(0) == jnjvm::JavaJIT::arrayLengthLLVM) {
+ Changed = true;
+ Value* val = CI->getOperand(1); // get the array
+ Value* array = new BitCastInst(val, jnjvm::JavaArray::llvmType, "", CI);
+ std::vector<Value*> args; //size= 2
+ args.push_back(mvm::jit::constantZero);
+ args.push_back(jnjvm::JavaArray::sizeOffset());
+ Value* ptr = new GetElementPtrInst(array, args.begin(), args.end(),
+ "", CI);
+ Value* load = new LoadInst(ptr, "", CI);
+ CI->replaceAllUsesWith(load);
+ CI->eraseFromParent();
+ }
+ }
+ }
+ }
+ return Changed;
+}
+
+namespace mvm {
+
+LowerArrayLength* createLowerArrayLengthPass() {
+ return new LowerArrayLength();
+}
+
+}
diff --git a/vmkit/lib/JnJVM/VMCore/Makefile.am b/vmkit/lib/JnJVM/VMCore/Makefile.am
new file mode 100644
index 0000000..c4706db
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Makefile.am
@@ -0,0 +1,24 @@
+# $Id: Makefile.am,v 1.7 2008/03/21 11:12:38 varth Exp $
+EXTRA_DIST = OpcodeNames.def
+lib_LTLIBRARIES = libJnJVM.la
+
+THREADDIR=../../Mvm/CommonThread
+ALLOCDIR=../../Mvm/Allocator
+GCDIR=../../Mvm/GCMmap2
+INCLUDEDIRS=-I@srcdir@/$(THREADDIR) -I@srcdir@/$(ALLOCDIR) -I@srcdir@/$(GCDIR)
+
+PREFIX=@prefix@
+
+libJnJVM_la_SOURCES = \
+ JavaAccess.h JavaArray.cpp JavaArray.h JavaClass.cpp JavaClass.h \
+ JavaConstantPool.cpp JavaConstantPool.h JavaJIT.cpp JavaJIT.h JavaObject.cpp \
+ JavaObject.h JavaThread.cpp JavaThread.h \
+ JavaTypes.cpp JavaTypes.h Jnjvm.cpp Jnjvm.h Reader.cpp Reader.h \
+ Zip.h Zip.cpp types.h debug.h VirtualTables.cpp LockedMap.h LockedMap.cpp \
+ JavaIsolate.h JavaIsolate.cpp JavaString.h JavaString.cpp JavaInitialise.cpp JavaJITOpcodes.cpp \
+ JavaBacktrace.cpp NativeUtil.h NativeUtil.cpp Jni.cpp \
+ JavaCache.h JavaCache.cpp JavaUpcalls.h JavaUpcalls.cpp \
+ JnjvmModuleProvider.h JnjvmModuleProvider.cpp JavaRuntimeJIT.cpp JavaMetaJIT.cpp JavaJITInitialise.cpp \
+ LowerArrayLength.cpp
+
+libJnJVM_la_CXXFLAGS =$(INCLUDEDIRS) -DPREFIX=\"$(PREFIX)\" -W -Wall -ansi -Wno-unused-parameter -Wno-long-long -Wno-unused-function -fno-omit-frame-pointer -g -DSINGLE_VM -Werror -O2
diff --git a/vmkit/lib/JnJVM/VMCore/NativeUtil.cpp b/vmkit/lib/JnJVM/VMCore/NativeUtil.cpp
new file mode 100644
index 0000000..f34d90f
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/NativeUtil.cpp
@@ -0,0 +1,481 @@
+//===------ NativeUtil.cpp - Methods to call native functions -------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/GenericValue.h"
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "JavaUpcalls.h"
+#include "Jnjvm.h"
+#include "NativeUtil.h"
+#include "Reader.h"
+
+using namespace jnjvm;
+
+Jnjvm* NativeUtil::myVM(JNIEnv* env) {
+ return JavaThread::get()->isolate;
+}
+
+#define PRE "Java_"
+#define PRE_LEN 5
+
+static char* jniConsFromMeth(CommonClass* cl, JavaMethod* meth) {
+ const UTF8* jniConsClName = cl->name;
+ const UTF8* jniConsName = meth->name;
+ const UTF8* jniConsType = meth->type;
+ sint32 clen = jniConsClName->size;
+ sint32 mnlen = jniConsName->size;
+ sint32 mtlen = jniConsType->size;
+
+ char* buf = (char*)malloc(3 + PRE_LEN + mnlen + clen + (mtlen << 1));
+ uint32 cur = 0;
+ char* ptr = &(buf[PRE_LEN]);
+
+ memcpy(buf, PRE, PRE_LEN);
+
+ for (sint32 i =0; i < clen; ++i) {
+ cur = jniConsClName->at(i);
+ if (cur == '/') ptr[0] = '_';
+ else ptr[0] = (uint8)cur;
+ ++ptr;
+ }
+
+ ptr[0] = '_';
+ ++ptr;
+
+ for (sint32 i =0; i < mnlen; ++i) {
+ cur = jniConsName->at(i);
+ if (cur == '/') ptr[0] = '_';
+ else ptr[0] = (uint8)cur;
+ ++ptr;
+ }
+
+ ptr[0] = 0;
+
+ return buf;
+
+}
+
+static char* jniConsFromMeth2(CommonClass* cl, JavaMethod* meth) {
+ const UTF8* jniConsClName = cl->name;
+ const UTF8* jniConsName = meth->name;
+ const UTF8* jniConsType = meth->type;
+ sint32 clen = jniConsClName->size;
+ sint32 mnlen = jniConsName->size;
+ sint32 mtlen = jniConsType->size;
+
+ char* buf = (char*)malloc(3 + PRE_LEN + mnlen + clen + (mtlen << 1));
+ uint32 cur = 0;
+ char* ptr = &(buf[PRE_LEN]);
+
+ memcpy(buf, PRE, PRE_LEN);
+
+ for (sint32 i =0; i < clen; ++i) {
+ cur = jniConsClName->at(i);
+ if (cur == '/') ptr[0] = '_';
+ else ptr[0] = (uint8)cur;
+ ++ptr;
+ }
+
+ ptr[0] = '_';
+ ++ptr;
+
+ for (sint32 i =0; i < mnlen; ++i) {
+ cur = jniConsName->at(i);
+ if (cur == '/') ptr[0] = '_';
+ else if (cur == '_') {
+ ptr[0] = '_';
+ ptr[1] = '1';
+ ++ptr;
+ }
+ else ptr[0] = (uint8)cur;
+ ++ptr;
+ }
+
+ ptr[0] = 0;
+
+ return buf;
+
+}
+
+static char* jniConsFromMeth3(CommonClass* cl, JavaMethod* meth) {
+ const UTF8* jniConsClName = cl->name;
+ const UTF8* jniConsName = meth->name;
+ const UTF8* jniConsType = meth->type;
+ sint32 clen = jniConsClName->size;
+ sint32 mnlen = jniConsName->size;
+ sint32 mtlen = jniConsType->size;
+
+ char* buf = (char*)malloc(3 + PRE_LEN + mnlen + clen + (mtlen << 1));
+ uint32 cur = 0;
+ char* ptr = &(buf[PRE_LEN]);
+
+ memcpy(buf, PRE, PRE_LEN);
+
+ for (sint32 i =0; i < clen; ++i) {
+ cur = jniConsClName->at(i);
+ if (cur == '/') ptr[0] = '_';
+ else ptr[0] = (uint8)cur;
+ ++ptr;
+ }
+
+ ptr[0] = '_';
+ ++ptr;
+
+ for (sint32 i =0; i < mnlen; ++i) {
+ cur = jniConsName->at(i);
+ if (cur == '/') ptr[0] = '_';
+ else ptr[0] = (uint8)cur;
+ ++ptr;
+ }
+
+ sint32 i = 0;
+ while (i < jniConsType->size) {
+ char c = jniConsType->at(i++);
+ if (c == AssessorDesc::I_PARG) {
+ ptr[0] = '_';
+ ptr[1] = '_';
+ ptr += 2;
+ } else if (c == '/') {
+ ptr[0] = '_';
+ ++ptr;
+ } else if (c == '_') {
+ ptr[0] = '_';
+ ptr[1] = '1';
+ ptr += 2;
+ } else if (c == AssessorDesc::I_END_REF) {
+ ptr[0] = '_';
+ ptr[1] = '2';
+ ptr += 2;
+ } else if (c == AssessorDesc::I_TAB) {
+ ptr[0] = '_';
+ ptr[1] = '3';
+ ptr += 2;
+ } else if (c == AssessorDesc::I_PARD) {
+ break;
+ } else {
+ ptr[0] = c;
+ ++ptr;
+ }
+ }
+
+ ptr[0] = 0;
+
+ return buf;
+
+}
+#undef PRE_LEN
+
+static void* loadName(char* buf, bool& jnjvm) {
+ void* res = dlsym(0, buf);
+ if (!res) {
+ Jnjvm *vm = JavaThread::get()->isolate;
+ for (std::vector<void*>::iterator i = vm->nativeLibs.begin(),
+ e = vm->nativeLibs.end(); i!= e; ++i) {
+ res = dlsym((*i), buf);
+ if (res) break;
+ }
+ } else {
+ jnjvm = true;
+ }
+ return res;
+}
+
+void* NativeUtil::nativeLookup(CommonClass* cl, JavaMethod* meth, bool& jnjvm) {
+ char* buf = jniConsFromMeth(cl, meth);
+ void* res = loadName(buf, jnjvm);
+ if (!res) {
+ buf = jniConsFromMeth2(cl, meth);
+ res = loadName(buf, jnjvm);
+ if (!res) {
+ buf = jniConsFromMeth3(cl, meth);
+ res = loadName(buf, jnjvm);
+ if (!res) {
+ printf("error for %s\n", meth->printString());
+ JavaThread::get()->isolate->unknownError("can not find native method %s",
+ meth->printString());
+ }
+ }
+ }
+ free(buf);
+ return res;
+}
+
+CommonClass* NativeUtil::resolvedImplClass(jclass clazz, bool doClinit) {
+ JavaObject *Cl = (JavaObject*)clazz;
+ CommonClass* cl = (CommonClass*)((*Cl)(Classpath::vmdataClass).PointerVal);
+ cl->resolveClass(doClinit);
+ return cl;
+}
+
+void NativeUtil::decapsulePrimitive(Jnjvm *vm, void** &buf,
+ JavaObject* obj,
+ Typedef* signature) {
+ const AssessorDesc* funcs = signature->funcs;
+
+ if (funcs == AssessorDesc::dRef || funcs == AssessorDesc::dTab) {
+ if (obj && !(obj->classOf->isOfTypeName(signature->pseudoAssocClassName))) {
+ vm->illegalArgumentException("wrong type argument");
+ }
+ ((JavaObject**)buf)[0] = obj;
+ buf++;
+ return;
+ } else if (obj == 0) {
+ vm->illegalArgumentException("");
+ } else {
+ CommonClass* cl = obj->classOf;
+ AssessorDesc* value = AssessorDesc::classToPrimitive(cl);
+
+ if (value == 0) {
+ vm->illegalArgumentException("");
+ }
+
+ if (funcs == AssessorDesc::dShort) {
+ if (value == AssessorDesc::dShort) {
+ llvm::GenericValue val = (*Classpath::shortValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getSExtValue();
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dByte) {
+ llvm::GenericValue val = (*Classpath::shortValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getSExtValue();
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dByte) {
+ if (value == AssessorDesc::dByte) {
+ llvm::GenericValue val = (*Classpath::byteValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getSExtValue();
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dBool) {
+ if (value == AssessorDesc::dBool) {
+ llvm::GenericValue val = (*Classpath::boolValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getZExtValue();
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dInt) {
+ if (value == AssessorDesc::dInt) {
+ llvm::GenericValue val = (*Classpath::intValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getSExtValue();
+ buf++;
+ } else if (value == AssessorDesc::dByte) {
+ llvm::GenericValue val = (*Classpath::byteValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getSExtValue();
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dChar) {
+ llvm::GenericValue val = (*Classpath::charValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getZExtValue();
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dShort) {
+ llvm::GenericValue val = (*Classpath::shortValue)(obj);
+ ((uint32*)buf)[0] = val.IntVal.getSExtValue();
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dChar) {
+ if (value == AssessorDesc::dChar) {
+ llvm::GenericValue val = (*Classpath::charValue)(obj);
+ ((uint32*)buf)[0] = (uint32)val.IntVal.getZExtValue();
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dFloat) {
+ if (value == AssessorDesc::dFloat) {
+ llvm::GenericValue val = (*Classpath::floatValue)(obj);
+ ((float*)buf)[0] = val.FloatVal;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dByte) {
+ llvm::GenericValue val = (*Classpath::byteValue)(obj);
+ float res = (float)(val.IntVal.getSExtValue());
+ ((float*)buf)[0] = res;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dChar) {
+ llvm::GenericValue val = (*Classpath::charValue)(obj);
+ float res = (float)(val.IntVal.getZExtValue());
+ ((float*)buf)[0] = res;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dShort) {
+ llvm::GenericValue val = (*Classpath::shortValue)(obj);
+ float res = (float)(val.IntVal.getSExtValue());
+ ((float*)buf)[0] = res;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dInt) {
+ llvm::GenericValue val = (*Classpath::intValue)(obj);
+ float res = (float)(val.IntVal.getSExtValue());
+ ((float*)buf)[0] = res;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dLong) {
+ llvm::GenericValue val = (*Classpath::longValue)(obj);
+ float res = (float)(val.IntVal.getSExtValue());
+ ((float*)buf)[0] = res;
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dDouble) {
+ if (value == AssessorDesc::dDouble) {
+ llvm::GenericValue gv = (*Classpath::doubleValue)(obj);
+ ((double*)buf)[0] = gv.DoubleVal;
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dFloat) {
+ llvm::GenericValue val = (*Classpath::floatValue)(obj);
+ double res = (double)(val.FloatVal);
+ ((double*)buf)[0] = res;
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dByte) {
+ llvm::GenericValue val = (*Classpath::byteValue)(obj);
+ double res = (double)(val.IntVal.getSExtValue());
+ ((double*)buf)[0] = res;
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dChar) {
+ llvm::GenericValue val = (*Classpath::charValue)(obj);
+ double res = (double)(val.IntVal.getZExtValue());
+ ((double*)buf)[0] = res;
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dShort) {
+ llvm::GenericValue val = (*Classpath::shortValue)(obj);
+ double res = (double)(val.IntVal.getSExtValue());
+ ((double*)buf)[0] = res;
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dInt) {
+ llvm::GenericValue val = (*Classpath::intValue)(obj);
+ double res = (double)(val.IntVal.getSExtValue());
+ ((double*)buf)[0] = res;
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dLong) {
+ llvm::GenericValue val = (*Classpath::longValue)(obj);
+ double res = (double)(val.IntVal.getSExtValue());
+ ((double*)buf)[0] = res;
+ buf++;
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ } else if (funcs == AssessorDesc::dLong) {
+ if (value == AssessorDesc::dByte) {
+ llvm::GenericValue val = (*Classpath::byteValue)(obj);
+ ((uint64*)buf)[0] = val.IntVal.getSExtValue();
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dChar) {
+ llvm::GenericValue val = (*Classpath::charValue)(obj);
+ ((uint64*)buf)[0] = val.IntVal.getZExtValue();
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dShort) {
+ llvm::GenericValue val = (*Classpath::shortValue)(obj);
+ ((uint64*)buf)[0] = val.IntVal.getSExtValue();
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dInt) {
+ llvm::GenericValue val = (*Classpath::intValue)(obj);
+ ((uint64*)buf)[0] = val.IntVal.getSExtValue();
+ buf++;
+ buf++;
+ return;
+ } else if (value == AssessorDesc::dLong) {
+ llvm::GenericValue val = (*Classpath::longValue)(obj);
+ ((uint64*)buf)[0] = val.IntVal.getSExtValue();
+ buf++;
+ buf++;
+ return;
+ } else {
+ vm->illegalArgumentException("");
+ }
+ }
+ }
+ // can not be here
+ return;
+}
+
+JavaObject* NativeUtil::getClassType(JavaObject* loader, Typedef* type) {
+ CommonClass* res = type->assocClass(loader);
+ return res->getClassDelegatee();
+}
+
+ArrayObject* NativeUtil::getParameterTypes(JavaObject* loader, JavaMethod* meth) {
+ std::vector<Typedef*>& args = meth->signature->args;
+ ArrayObject* res = ArrayObject::acons(args.size(), Classpath::classArrayClass);
+
+ sint32 index = 0;
+ for (std::vector<Typedef*>::iterator i = args.begin(), e = args.end();
+ i != e; ++i, ++index) {
+ res->setAt(index, getClassType(loader, (*i)));
+ }
+
+ return res;
+
+}
+
+ArrayObject* NativeUtil::getExceptionTypes(JavaMethod* meth) {
+ Attribut* exceptionAtt = Attribut::lookup(&meth->attributs,
+ Attribut::exceptionsAttribut);
+ if (exceptionAtt == 0) {
+ return ArrayObject::acons(0, Classpath::classArrayClass);
+ } else {
+ Class* cl = meth->classDef;
+ JavaCtpInfo* ctp = cl->ctpInfo;
+ Reader* reader = exceptionAtt->toReader(cl->bytes, exceptionAtt);
+ uint16 nbe = reader->readU2();
+ ArrayObject* res = ArrayObject::acons(nbe, Classpath::classArrayClass);
+
+ for (uint16 i = 0; i < nbe; ++i) {
+ uint16 idx = reader->readU2();
+ CommonClass* cl = ctp->loadClass(idx);
+ cl->resolveClass(false);
+ JavaObject* obj = cl->getClassDelegatee();
+ res->elements[i] = obj;
+ }
+ return res;
+ }
+}
diff --git a/vmkit/lib/JnJVM/VMCore/NativeUtil.h b/vmkit/lib/JnJVM/VMCore/NativeUtil.h
new file mode 100644
index 0000000..d58d32f
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/NativeUtil.h
@@ -0,0 +1,46 @@
+//===------- NativeUtil.h - Methods to call native functions --------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_NATIVE_UTIL_H
+#define JNJVM_NATIVE_UTIL_H
+
+#include <jni.h>
+
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+
+
+namespace jnjvm {
+
+class ArrayObject;
+class CommonClass;
+class JavaMethod;
+class JavaObject;
+class Jnjvm;
+class Signdef;
+class Typedef;
+
+
+class NativeUtil {
+public:
+
+ static Jnjvm* myVM(JNIEnv* env);
+ static void* nativeLookup(CommonClass* cl, JavaMethod* meth, bool& jnjvm);
+ static CommonClass* resolvedImplClass(jclass clazz, bool doClinit);
+ static void decapsulePrimitive(Jnjvm *vm, void**&buf, JavaObject* obj,
+ Typedef* signature);
+
+ static JavaObject* getClassType(JavaObject* loader, Typedef* type);
+ static ArrayObject* getParameterTypes(JavaObject* loader, JavaMethod* meth);
+ static ArrayObject* getExceptionTypes(JavaMethod* meth);
+
+};
+
+}
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/OpcodeNames.def b/vmkit/lib/JnJVM/VMCore/OpcodeNames.def
new file mode 100644
index 0000000..6737d64
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/OpcodeNames.def
@@ -0,0 +1,221 @@
+//===-------------- OpcodeNames.def - Name of opcodes ---------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPCODE_NAMES_DEF
+#define OPCODE_NAMES_DEF
+
+const char* jnjvm::JavaJIT::OpcodeNames[256] = {
+ "NOP",
+ "ACONST_NULL",
+ "ICONST_M1",
+ "ICONST_0",
+ "ICONST_1",
+ "ICONST_2",
+ "ICONST_3",
+ "ICONST_4",
+ "ICONST_5",
+ "LCONST_0",
+ "LCONST_1",
+ "FCONST_0",
+ "FCONST_1",
+ "FCONST_2",
+ "DCONST_0",
+ "DCONST_1",
+ "BIPUSH",
+ "SIPUSH",
+ "LDC",
+ "LDC_W",
+ "LDC2_W",
+ "ILOAD",
+ "LLOAD",
+ "FLOAD",
+ "DLOAD",
+ "ALOAD",
+ "ILOAD_0",
+ "ILOAD_1",
+ "ILOAD_2",
+ "ILOAD_3",
+ "LLOAD_0",
+ "LLOAD_1",
+ "LLOAD_2",
+ "LLOAD_3",
+ "FLOAD_0",
+ "FLOAD_1",
+ "FLOAD_2",
+ "FLOAD_3",
+ "DLOAD_0",
+ "DLOAD_1",
+ "DLOAD_2",
+ "DLOAD_3",
+ "ALOAD_0",
+ "ALOAD_1",
+ "ALOAD_2",
+ "ALOAD_3",
+ "IALOAD",
+ "LALOAD",
+ "FALOAD",
+ "DALOAD",
+ "AALOAD",
+ "BALOAD",
+ "CALOAD",
+ "SALOAD",
+ "ISTORE",
+ "LSTORE",
+ "FSTORE",
+ "DSTORE",
+ "ASTORE",
+ "ISTORE_0",
+ "ISTORE_1",
+ "ISTORE_2",
+ "ISTORE_3",
+ "LSTORE_0",
+ "LSTORE_1",
+ "LSTORE_2",
+ "LSTORE_3",
+ "FSTORE_0",
+ "FSTORE_1",
+ "FSTORE_2",
+ "FSTORE_3",
+ "DSTORE_0",
+ "DSTORE_1",
+ "DSTORE_2",
+ "DSTORE_3",
+ "ASTORE_0",
+ "ASTORE_1",
+ "ASTORE_2",
+ "ASTORE_3",
+ "IASTORE",
+ "LASTORE",
+ "FASTORE",
+ "DASTORE",
+ "AASTORE",
+ "BASTORE",
+ "CASTORE",
+ "SASTORE",
+ "POP",
+ "POP2",
+ "DUP",
+ "DUP_X1",
+ "DUP_X2",
+ "DUP2",
+ "DUP2_X1",
+ "DUP2_X2",
+ "SWAP",
+ "IADD",
+ "LADD",
+ "FADD",
+ "DADD",
+ "ISUB",
+ "LSUB",
+ "FSUB",
+ "DSUB",
+ "IMUL",
+ "LMUL",
+ "FMUL",
+ "DMUL",
+ "IDIV",
+ "LDIV",
+ "FDIV",
+ "DDIV",
+ "IREM",
+ "LREM",
+ "FREM",
+ "DREM",
+ "INEG",
+ "LNEG",
+ "FNEG",
+ "DNEG",
+ "ISHL",
+ "LSHL",
+ "ISHR",
+ "LSHR",
+ "IUSHR",
+ "LUSHR",
+ "IAND",
+ "LAND",
+ "IOR",
+ "LOR",
+ "IXOR",
+ "LXOR",
+ "IINC",
+ "I2L",
+ "I2F",
+ "I2D",
+ "L2I",
+ "L2F",
+ "L2D",
+ "F2I",
+ "F2L",
+ "F2D",
+ "D2I",
+ "D2L",
+ "D2F",
+ "I2B",
+ "I2C",
+ "I2S",
+ "LCMP",
+ "FCMPL",
+ "FCMPG",
+ "DCMPL",
+ "DCMPG",
+ "IFEQ",
+ "IFNE",
+ "IFLT",
+ "IFGE",
+ "IFGT",
+ "IFLE",
+ "IF_ICMPEQ",
+ "IF_ICMPNE",
+ "IF_ICMPLT",
+ "IF_ICMPGE",
+ "IF_ICMPGT",
+ "IF_ICMPLE",
+ "IF_ACMPEQ",
+ "IF_ACMPNE",
+ "GOTO",
+ "JSR",
+ "RET",
+ "TABLESWITCH",
+ "LOOKUPSWITCH",
+ "IRETURN",
+ "LRETURN",
+ "FRETURN",
+ "DRETURN",
+ "ARETURN",
+ "RETURN",
+ "GETSTATIC",
+ "PUTSTATIC",
+ "GETFIELD",
+ "PUTFIELD",
+ "INVOKEVIRTUAL",
+ "INVOKESPECIAL",
+ "INVOKESTATIC",
+ "INVOKEINTERFACE",
+ "UNUSED",
+ "NEW",
+ "NEWARRAY",
+ "ANEWARRAY",
+ "ARRAYLENGTH",
+ "ATHROW",
+ "CHECKCAST",
+ "INSTANCEOF",
+ "MONITORENTER",
+ "MONITOREXIT",
+ "WIDE",
+ "MULTIANEWARRAY",
+ "IFNULL",
+ "IFNONNULL",
+ "GOTO_W",
+ "JSR_W",
+ "BREAKPOINT",
+ "IMPDEP1",
+ "IMPDEP2"
+};
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/Reader.cpp b/vmkit/lib/JnJVM/VMCore/Reader.cpp
new file mode 100644
index 0000000..64dede8
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Reader.cpp
@@ -0,0 +1,160 @@
+//===--------------- Reader.cpp - Open and read files ---------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#include <string.h>
+
+#include "types.h"
+
+#include "Jnjvm.h"
+#include "JavaArray.h"
+#include "JavaThread.h"
+#include "Reader.h"
+#include "Zip.h"
+
+using namespace jnjvm;
+
+double Reader::readDouble(int first, int second) {
+ int values[2];
+ double res[1];
+#if defined(__PPC__)
+ values[0] = second;
+ values[1] = first;
+#else
+ values[0] = first;
+ values[1] = second;
+#endif
+ memcpy(res, values, 8);
+ return res[0];
+}
+
+sint64 Reader::readLong(int first, int second) {
+ int values[2];
+ sint64 res[1];
+#if defined(__PPC__)
+ values[0] = second;
+ values[1] = first;
+#else
+ values[0] = first;
+ values[1] = second;
+#endif
+ memcpy(res, values, 8);
+ return res[0];
+}
+
+const int Reader::SeekSet = SEEK_SET;
+const int Reader::SeekCur = SEEK_CUR;
+const int Reader::SeekEnd = SEEK_END;
+
+ArrayUInt8* Reader::openFile(char* path) {
+ FILE* fp = fopen(path, "r");
+ ArrayUInt8* res = 0;
+ if (fp != 0) {
+ fseek(fp, 0, SeekEnd);
+ long nbb = ftell(fp);
+ fseek(fp, 0, SeekSet);
+ res = ArrayUInt8::acons(nbb, JavaArray::ofByte);
+ fread(res->elements, nbb, 1, fp);
+ fclose(fp);
+ }
+ return res;
+}
+
+ArrayUInt8* Reader::openZip(char* zipname, char* filename) {
+ ZipArchive* archive = ZipArchive::hashedArchive(zipname);
+ ArrayUInt8* ret = 0;
+ if (archive != 0) {
+ ZipFile* file = archive->getFile(filename);
+ if (file != 0) {
+ ArrayUInt8* res = ArrayUInt8::acons(file->ucsize, JavaArray::ofByte);
+ if (archive->readFile(res, file) != 0) {
+ ret = res;
+ }
+ }
+ }
+ return ret;
+}
+
+uint8 Reader::readU1() {
+ return bytes->at(cursor++);
+}
+
+sint8 Reader::readS1() {
+ return readU1();
+}
+
+uint16 Reader::readU2() {
+ uint16 tmp = ((uint16)(readU1())) << 8;
+ return tmp | ((uint16)(readU1()));
+}
+
+sint16 Reader::readS2() {
+ sint16 tmp = ((sint16)(readS1())) << 8;
+ return tmp | ((sint16)(readS1()));
+}
+
+uint32 Reader::readU4() {
+ uint32 tmp = ((uint32)(readU2())) << 16;
+ return tmp | ((uint32)(readU2()));
+}
+
+sint32 Reader::readS4() {
+ sint32 tmp = ((sint32)(readS2())) << 16;
+ return tmp | ((sint32)(readS2()));
+}
+
+uint64 Reader::readU8() {
+ uint64 tmp = ((uint64)(readU4())) << 32;
+ return tmp | ((uint64)(readU4()));
+}
+
+sint64 Reader::readS8() {
+ sint64 tmp = ((sint64)(readS8())) << 32;
+ return tmp | ((sint64)(readS8()));
+}
+
+Reader* Reader::allocateReader(ArrayUInt8* array, uint32 start,
+ uint32 end) {
+ Reader* reader = gc_new(Reader)();
+ if (!end) end = array->size;
+ reader->bytes = array;
+ reader->cursor = start;
+ reader->min = start;
+ reader->max = start + end;
+ return reader;
+
+}
+
+unsigned int Reader::tell() {
+ return cursor - min;
+}
+
+Reader* Reader::derive(uint32 nbb) {
+ return allocateReader(bytes, cursor, nbb);
+}
+
+void Reader::seek(uint32 pos, int from) {
+ uint32 n = 0;
+ uint32 start = min;
+ uint32 end = max;
+
+ if (from == SeekCur) n = cursor + pos;
+ else if (from == SeekSet) n = start + pos;
+ else if (from == SeekEnd) n = end + pos;
+
+
+ if ((n < start) || (n > end))
+ JavaThread::get()->isolate->unknownError("out of range %d %d", n, end);
+
+ cursor = n;
+}
+
+void Reader::print(mvm::PrintBuffer* buf) const {
+ buf->write("Reader<>");
+}
diff --git a/vmkit/lib/JnJVM/VMCore/Reader.h b/vmkit/lib/JnJVM/VMCore/Reader.h
new file mode 100644
index 0000000..d6911a4
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Reader.h
@@ -0,0 +1,58 @@
+//===----------------- Reader.h - Open and read files ---------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_READER_H
+#define JNJVM_READER_H
+
+#include "mvm/Object.h"
+
+#include "types.h"
+
+namespace jnjvm {
+
+class ArrayUInt8;
+
+class Reader : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ ArrayUInt8* bytes;
+ uint32 min;
+ uint32 cursor;
+ uint32 max;
+
+ static double readDouble(int first, int second);
+ static sint64 readLong(int first, int second);
+
+ static const int SeekSet;
+ static const int SeekCur;
+ static const int SeekEnd;
+
+ static ArrayUInt8* openFile(char* path);
+ static ArrayUInt8* openZip(char* zipname, char* filename);
+ uint8 readU1();
+ sint8 readS1();
+ uint16 readU2();
+ sint16 readS2();
+ uint32 readU4();
+ sint32 readS4();
+ uint64 readU8();
+ sint64 readS8();
+ static Reader* allocateReader(ArrayUInt8* array, uint32 start = 0,
+ uint32 end = 0);
+ unsigned int tell();
+ Reader* derive(uint32 nbb);
+ void seek(uint32 pos, int from);
+
+ virtual void print(mvm::PrintBuffer* buf) const;
+ virtual void tracer(size_t sz);
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/JnJVM/VMCore/VirtualTables.cpp b/vmkit/lib/JnJVM/VMCore/VirtualTables.cpp
new file mode 100644
index 0000000..6dc8d7a
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/VirtualTables.cpp
@@ -0,0 +1,299 @@
+//===--- VirtualTables.cpp - Virtual methods for JnJVM objects ------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/Object.h"
+
+#include "JavaArray.h"
+#include "JavaCache.h"
+#include "JavaClass.h"
+#include "JavaConstantPool.h"
+#include "JavaIsolate.h"
+#include "JavaJIT.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+#include "JavaTypes.h"
+#include "Jnjvm.h"
+#include "LockedMap.h"
+#include "Reader.h"
+#include "Zip.h"
+
+using namespace jnjvm;
+
+#define INIT(X) VirtualTable* X::VT = 0
+
+ INIT(JavaArray);
+ INIT(ArrayUInt8);
+ INIT(ArraySInt8);
+ INIT(ArrayUInt16);
+ INIT(ArraySInt16);
+ INIT(ArrayUInt32);
+ INIT(ArraySInt32);
+ INIT(ArrayLong);
+ INIT(ArrayFloat);
+ INIT(ArrayDouble);
+ INIT(ArrayObject);
+ INIT(UTF8);
+ INIT(Attribut);
+ INIT(CommonClass);
+ INIT(Class);
+ INIT(ClassArray);
+ INIT(JavaMethod);
+ INIT(JavaField);
+ INIT(JavaCtpInfo);
+ INIT(Exception);
+ INIT(JavaJIT);
+ INIT(JavaCond);
+ INIT(LockObj);
+ INIT(JavaObject);
+ INIT(JavaThread);
+ INIT(AssessorDesc);
+ INIT(Typedef);
+ INIT(Signdef);
+ INIT(ThreadSystem);
+ INIT(Jnjvm);
+ INIT(Reader);
+ INIT(ZipFile);
+ INIT(ZipArchive);
+ INIT(UTF8Map);
+ INIT(ClassMap);
+ INIT(FieldMap);
+ INIT(MethodMap);
+ INIT(ZipFileMap);
+ INIT(StringMap);
+ INIT(TypeMap);
+ INIT(StaticInstanceMap);
+ INIT(FunctionMap);
+ INIT(FunctionDefMap);
+ INIT(JavaIsolate);
+ INIT(JavaString);
+ INIT(Opinfo);
+ INIT(CacheNode);
+ INIT(Enveloppe);
+ INIT(DelegateeMap);
+
+#undef INIT
+
+void JavaArray::tracer(size_t sz) {
+ JavaObject::tracer(sz);
+}
+
+void ArrayObject::tracer(size_t sz) {
+ JavaObject::tracer(sz);
+ for (sint32 i = 0; i < size; i++) {
+ elements[i]->markAndTrace();
+ }
+}
+
+#define ARRAYTRACER(name) \
+ void name::tracer(size_t sz) { \
+ JavaObject::tracer(sz); \
+ }
+
+
+ARRAYTRACER(ArrayUInt8);
+ARRAYTRACER(ArraySInt8);
+ARRAYTRACER(ArrayUInt16);
+ARRAYTRACER(ArraySInt16);
+ARRAYTRACER(ArrayUInt32);
+ARRAYTRACER(ArraySInt32);
+ARRAYTRACER(ArrayLong);
+ARRAYTRACER(ArrayFloat);
+ARRAYTRACER(ArrayDouble);
+
+#undef ARRAYTRACER
+
+
+void Attribut::tracer(size_t sz) {
+ name->markAndTrace();
+}
+
+#define TRACE_VECTOR(type,name) { \
+ for (std::vector<type>::iterator i = name.begin(), e = name.end(); \
+ i!= e; ++i) { \
+ (*i)->markAndTrace(); }}
+
+void CommonClass::tracer(size_t sz) {
+ name->markAndTrace();
+ super->markAndTrace();
+ superUTF8->markAndTrace();
+ TRACE_VECTOR(const UTF8*, interfacesUTF8);
+ TRACE_VECTOR(Class*, interfaces);
+ //lockVar->markAndTrace();
+ //condVar->markAndTrace();
+ TRACE_VECTOR(JavaMethod*, virtualMethods);
+ TRACE_VECTOR(JavaMethod*, staticMethods);
+ TRACE_VECTOR(JavaField*, virtualFields);
+ TRACE_VECTOR(JavaField*, staticFields);
+ classLoader->markAndTrace();
+#ifdef SINGLE_VM
+ delegatee->markAndTrace();
+#endif
+ TRACE_VECTOR(CommonClass*, display);
+ isolate->markAndTrace();
+}
+
+void Class::tracer(size_t sz) {
+ CommonClass::tracer(sz);
+ bytes->markAndTrace();
+ _staticInstance->markAndTrace();
+ virtualInstance->markAndTrace();
+ ctpInfo->markAndTrace();
+ TRACE_VECTOR(Attribut*, attributs);
+ TRACE_VECTOR(Class*, innerClasses);
+ outerClass->markAndTrace();
+ codeStaticTracer->markAndTrace();
+ codeVirtualTracer->markAndTrace();
+}
+
+void ClassArray::tracer(size_t sz) {
+ CommonClass::tracer(sz);
+ _baseClass->markAndTrace();
+ _funcs->markAndTrace();
+
+}
+
+void JavaMethod::tracer(size_t sz) {
+ signature->markAndTrace();
+ TRACE_VECTOR(Attribut*, attributs);
+ TRACE_VECTOR(Enveloppe*, caches);
+ classDef->markAndTrace();
+ name->markAndTrace();
+ type->markAndTrace();
+ code->markAndTrace();
+}
+
+void JavaField::tracer(size_t sz) {
+ name->markAndTrace();
+ signature->markAndTrace();
+ type->markAndTrace();
+ TRACE_VECTOR(Attribut*, attributs);
+ classDef->markAndTrace();
+}
+
+void JavaCtpInfo::tracer(size_t sz) {
+ classDef->markAndTrace();
+ // Everything is hashed in the constant pool,
+ // do not trace them here
+}
+
+void Exception::tracer(size_t sz) {
+ catchClass->markAndTrace();
+}
+
+void Opinfo::tracer(size_t sz) {
+}
+
+void JavaJIT::tracer(size_t sz) {
+ compilingClass->markAndTrace();
+ compilingMethod->markAndTrace();
+ TRACE_VECTOR(Exception*, exceptions);
+
+ // Do not trace opinfos: they are allocated in stack
+}
+
+void JavaCond::tracer(size_t sz) {
+ TRACE_VECTOR(JavaThread*, threads);
+}
+
+void LockObj::tracer(size_t sz) {
+ //lock->markAndTrace();
+ varcond->markAndTrace();
+}
+
+void JavaObject::tracer(size_t sz) {
+ classOf->markAndTrace();
+ lockObj->markAndTrace();
+}
+
+void JavaThread::tracer(size_t sz) {
+ javaThread->markAndTrace();
+ isolate->markAndTrace();
+ //lock->markAndTrace();
+ //varcond->markAndTrace();
+ pendingException->markAndTrace();
+}
+
+void AssessorDesc::tracer(size_t sz) {
+ classType->markAndTrace();
+}
+
+void Typedef::tracer(size_t sz) {
+ keyName->markAndTrace();
+ pseudoAssocClassName->markAndTrace();
+ funcs->markAndTrace();
+ isolate->markAndTrace();
+}
+
+void Signdef::tracer(size_t sz) {
+ Typedef::tracer(sz);
+ TRACE_VECTOR(Typedef*, args);
+ ret->markAndTrace();
+ _staticCallBuf->markAndTrace();
+ _virtualCallBuf->markAndTrace();
+ _staticCallAP->markAndTrace();
+ _virtualCallAP->markAndTrace();
+}
+
+void ThreadSystem::tracer(size_t sz) {
+ //nonDaemonLock->markAndTrace();
+ //nonDaemonVar->markAndTrace();
+}
+
+void Jnjvm::tracer(size_t sz) {
+ appClassLoader->markAndTrace();
+ hashUTF8->markAndTrace();
+ hashStr->markAndTrace();
+ bootstrapClasses->markAndTrace();
+ loadedMethods->markAndTrace();
+ loadedFields->markAndTrace();
+ javaTypes->markAndTrace();
+ TRACE_VECTOR(JavaObject*, globalRefs);
+ //globalRefsLock->markAndTrace();
+ functions->markAndTrace();
+#ifndef SINGLE_VM
+ statics->markAndTrace();
+ delegatees->markAndTrace();
+#endif
+ //protectModule->markAndTrace();
+}
+
+void Reader::tracer(size_t sz) {
+ bytes->markAndTrace();
+}
+
+void ZipFile::tracer(size_t sz) {
+}
+
+void ZipArchive::tracer(size_t sz) {
+ reader->markAndTrace();
+ filetable->markAndTrace();
+}
+
+void JavaIsolate::tracer(size_t sz) {
+ Jnjvm::tracer(sz);
+ threadSystem->markAndTrace();
+ bootstrapThread->markAndTrace();
+}
+
+void JavaString::tracer(size_t sz) {
+}
+
+void CacheNode::tracer(size_t sz) {
+ ((mvm::Object*)methPtr)->markAndTrace();
+ lastCible->markAndTrace();
+ next->markAndTrace();
+ enveloppe->markAndTrace();
+}
+
+void Enveloppe::tracer(size_t sz) {
+ firstCache->markAndTrace();
+ ctpInfo->markAndTrace();
+ //cacheLock->markAndTrace();
+}
diff --git a/vmkit/lib/JnJVM/VMCore/Zip.cpp b/vmkit/lib/JnJVM/VMCore/Zip.cpp
new file mode 100644
index 0000000..a4a80c4
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Zip.cpp
@@ -0,0 +1,245 @@
+//===----------------- Zip.cpp - Interface with zlib ----------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <zlib.h>
+
+#include "JavaArray.h"
+#include "LockedMap.h"
+#include "Reader.h"
+#include "Zip.h"
+
+using namespace jnjvm;
+
+ZipArchive* ZipArchive::hashedArchive(char* archname) {
+ assert(0 && "implement hashedArchive");
+ return 0;
+}
+
+ZipArchive* ZipArchive::singleArchive(char* archname) {
+ ZipArchive* ar = gc_new(ZipArchive)();
+ ar->name = archname;
+ ArrayUInt8* bytes = Reader::openFile(archname);
+ if (bytes != 0) {
+ ar->reader = Reader::allocateReader(bytes);
+ ar->findOfscd();
+ if (ar->ofscd > -1) {
+ ar->filetable = ZipFileMap::allocate();
+ ar->addFiles();
+ return ar;
+ }
+ }
+ return 0;
+}
+
+ZipFile* ZipArchive::getFile(char* filename) {
+ ZipFile* res = filetable->lookup(filename);
+ return res;
+}
+
+
+void ZipArchive::remove() {}
+
+#define END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE 18
+#define CENTRAL_DIRECTORY_FILE_HEADER_SIZE 42
+#define LOCAL_FILE_HEADER_SIZE 26
+
+#define C_FILENAME_LENGTH 24
+#define C_UCSIZE 20
+#define C_CSIZE 16
+#define C_EXTRA_FIELD_LENGTH 26
+#define C_FILE_COMMENT_LENGTH 28
+#define C_ROLH 38
+#define C_COMPRESSION_METHOD 6
+
+#define L_FILENAME_LENGTH 22
+#define L_EXTRA_FIELD_LENGTH 24
+
+#define E_OFFSET_START_CENTRAL_DIRECTORY 12
+#define HDR_ENDCENTRAL "PK\005\006"
+#define HDR_CENTRAL "PK\001\002"
+#define HDR_LOCAL "PK\003\004"
+#define PATH_SEPARATOR '/'
+#define ZIP_STORE 0
+#define ZIP_DEFLATE 8
+#define DEF_WBITS 15
+
+static uint32 readEndianDep4(Reader* reader) {
+ uint8 one = reader->readU1();
+ uint8 two = reader->readU1();
+ uint8 three = reader->readU1();
+ uint8 four = reader->readU1();
+ return (one + (two << 8) + (three << 16) + (four << 24));
+}
+
+static uint16 readEndianDep2(Reader* reader) {
+ uint8 one = reader->readU1();
+ uint8 two = reader->readU1();
+ return (one + (two << 8));
+}
+
+void ZipArchive::findOfscd() {
+ sint32 curOffs = 0;
+ sint32 minOffs = 0;
+ sint32 st = END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE + 4;
+
+ curOffs = reader->max;
+ if (curOffs >= (65535 + END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE + 4)) {
+ minOffs = curOffs - (65535 + END_CENTRAL_DIRECTORY_FILE_HEADER_SIZE + 4);
+ } else {
+ minOffs = 0;
+ }
+
+ while (curOffs > minOffs) {
+ sint32 searchPos = 0;
+ if (curOffs >= (1024 - st)) {
+ curOffs = curOffs - (1024 - st);
+ } else {
+ curOffs = 0;
+ }
+ reader->cursor += curOffs;
+
+ sint32 diff = reader->max - reader->cursor;
+ sint32 temp = reader->cursor;
+ if (diff > 1024) {
+ searchPos = 1024;
+ reader->cursor += 1024;
+ } else {
+ searchPos = diff;
+ reader->cursor = reader->max;
+ }
+
+ if (searchPos >= st) {
+ sint32 searchPtr = temp + (searchPos - st);
+ while (searchPtr > temp) {
+ if (reader->bytes->elements[searchPtr] == 'P' && !(memcmp(&(reader->bytes->elements[searchPtr]), HDR_ENDCENTRAL, 4))) {
+ sint32 offset = searchPtr + 4 + E_OFFSET_START_CENTRAL_DIRECTORY;
+ reader->cursor = offset;
+ this->ofscd = readEndianDep4(reader);
+ return;
+ }
+ }
+ }
+ }
+ this->ofscd = -1;
+}
+
+void ZipArchive::addFiles() {
+ sint32 temp = ofscd;
+
+ reader->cursor = temp;
+
+ while (true) {
+ if (memcmp(&(reader->bytes->elements[temp]), HDR_CENTRAL, 4)) return;
+ ZipFile* ptr = gc_new(ZipFile)();
+ reader->cursor = temp + 4 + C_COMPRESSION_METHOD;
+ ptr->compressionMethod = readEndianDep2(reader);
+
+ reader->cursor = temp + 4 + C_CSIZE;
+
+ ptr->csize = readEndianDep4(reader);
+ ptr->ucsize = readEndianDep4(reader);
+ ptr->filenameLength = readEndianDep2(reader);
+ ptr->extraFieldLength = readEndianDep2(reader);
+ ptr->fileCommentLength = readEndianDep2(reader);
+
+ reader->cursor = temp + 4 + C_ROLH;
+ ptr->rolh = readEndianDep4(reader);
+
+ temp = temp + 4 + CENTRAL_DIRECTORY_FILE_HEADER_SIZE;
+
+ if ((ptr->filenameLength > 1024) || (reader->max - temp) < ptr->filenameLength)
+ return;
+
+ ptr->filename = (char*)malloc(ptr->filenameLength + 1);
+ memcpy(ptr->filename, &(reader->bytes->elements[temp]), ptr->filenameLength);
+ ptr->filename[ptr->filenameLength] = 0;
+
+ if (ptr->filename[ptr->filenameLength - 1] != PATH_SEPARATOR) {
+ filetable->hash(ptr->filename, ptr);
+ }
+
+ temp = temp + ptr->filenameLength + ptr->extraFieldLength + ptr->fileCommentLength;
+ }
+}
+
+sint32 ZipArchive::readFile(ArrayUInt8* array, const ZipFile* file) {
+ uint32 bytesLeft = 0;
+ uint32 filenameLength = 0;
+ uint32 extraFieldLength = 0;
+ char* ptr = (char*)array->elements;
+ uint32 temp = 0;
+
+ reader->cursor = file->rolh;
+
+ if (!(memcmp(&(reader->bytes->elements[file->rolh]), HDR_LOCAL, 4))) {
+ reader->cursor += 4;
+ temp = reader->cursor;
+ reader->cursor += L_FILENAME_LENGTH;
+ filenameLength = readEndianDep2(reader);
+ extraFieldLength = readEndianDep2(reader);
+
+ reader->cursor = temp + extraFieldLength + filenameLength + LOCAL_FILE_HEADER_SIZE;
+
+ if (file->compressionMethod == ZIP_STORE) {
+ memcpy(ptr, &(reader->bytes->elements[reader->cursor]), file->ucsize);
+ } else if (file->compressionMethod == ZIP_DEFLATE) {
+ z_stream stre;
+ sint32 err = 0;
+
+ bytesLeft = file->csize;
+ stre.next_out = (Bytef*)ptr;
+ stre.avail_out = file->ucsize;
+ stre.zalloc = 0;
+ stre.zfree = 0;
+
+ err = inflateInit2_(&stre, - DEF_WBITS, zlib_version, sizeof(z_stream));
+
+ if (err != Z_OK) {
+ return 0;
+ }
+
+ while (bytesLeft) {
+ uint32 size = 0;
+ stre.next_in = &(reader->bytes->elements[reader->cursor]);
+ if (bytesLeft > 1024) size = 1024;
+ else size = bytesLeft;
+
+ uint32 diff = reader->max - reader->cursor;
+ if (diff < size) {
+ stre.avail_in = diff;
+ reader->cursor = reader->max;
+ } else {
+ stre.avail_in = size;
+ reader->cursor += size;
+ }
+
+ if (bytesLeft > size) {
+ err = inflate(&stre, Z_PARTIAL_FLUSH);
+ } else {
+ err = inflate(&stre, Z_FINISH);
+ }
+
+ bytesLeft = bytesLeft - size;
+ }
+
+ inflateEnd(&stre);
+
+ if ((err != Z_STREAM_END) && (bytesLeft || err != Z_BUF_ERROR || stre.avail_out)) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ return 0;
+}
diff --git a/vmkit/lib/JnJVM/VMCore/Zip.h b/vmkit/lib/JnJVM/VMCore/Zip.h
new file mode 100644
index 0000000..94e1d71
--- /dev/null
+++ b/vmkit/lib/JnJVM/VMCore/Zip.h
@@ -0,0 +1,73 @@
+//===----------------- Zip.h - Interface with zlib ------------------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef JNJVM_ZIP_H
+#define JNJVM_ZIP_H
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+
+
+namespace jnjvm {
+
+class ArrayUInt8;
+class Reader;
+class ZipFileMap;
+
+
+class ZipFile : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ char* filename;
+ int ucsize;
+ int csize;
+ uint32 filenameLength;
+ uint32 extraFieldLength;
+ uint32 fileCommentLength;
+ int rolh;
+ int compressionMethod;
+
+
+ virtual void print(mvm::PrintBuffer* buf) const {
+ buf->write("ZipFile<");
+ buf->write(filename);
+ buf->write(">");
+ }
+ virtual void tracer(size_t sz);
+};
+
+class ZipArchive : public mvm::Object {
+public:
+ static VirtualTable* VT;
+ int ofscd;
+ ZipFileMap* filetable;
+ char* name;
+ Reader* reader;
+
+ virtual void print(mvm::PrintBuffer* buf) const {
+ buf->write("ZipArchive<");
+ buf->write(name);
+ buf->write(">");
+ }
+ virtual void tracer(size_t sz);
+
+ static ZipArchive* hashedArchive(char* archname);
+ static ZipArchive* singleArchive(char* archname);
+ ZipFile* getFile(char* filename);
+ int readFile(ArrayUInt8* array, const ZipFile* file);
+ void remove();
+
+private:
+ void findOfscd();
+ void addFiles();
+};
+
+} // end namespace jnjvm
+
+#endif