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