Initial repository layout

llvm-svn: 48661
diff --git a/vmkit/AUTHORS b/vmkit/AUTHORS
new file mode 100644
index 0000000..807d476
--- /dev/null
+++ b/vmkit/AUTHORS
@@ -0,0 +1,29 @@
+This file is a partial list of people who have contributed to the VMKit
+project.  If you have contributed a patch or made some other contribution to
+VMKit, please submit a patch to this file to add yourself, and it will be 
+done!
+
+The list is sorted by name and formatted to allow easy grepping and
+beautification by scripts.  The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Bertil Folliot
+E: bertil.folliot@lip6.fr
+W: http://www-src.lip6.fr/homepages/Bertil.Folliot/
+D: Provider of much wisdom
+
+N: Nicolas Geoffray
+E: nicolas.geoffray@lip6.fr
+W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/
+D: Port of JnJVM to LLVM
+D: Architect of N3
+
+N: Gael Thomas
+E: gael.thomas@lip6.fr
+W: http://www-src.lip6.fr/homepages/Gael.Thomas/
+D: Primary architect of JnJVM
+
+N: Sylvain Marechal
+E: sylvain.marechal@lip6.fr
+D: Original autoconf support
diff --git a/vmkit/ChangeLog b/vmkit/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vmkit/ChangeLog
diff --git a/vmkit/LICENSE.TXT b/vmkit/LICENSE.TXT
new file mode 100644
index 0000000..303c58e
--- /dev/null
+++ b/vmkit/LICENSE.TXT
@@ -0,0 +1,44 @@
+==============================================================================
+VMKit Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2008 University of Pierre et Marie Curie.
+All rights reserved.
+
+Developed by:
+
+    VVM Team
+
+    University of Pierre et Marie Curie, Paris
+
+    http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimers.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimers in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the names of the LLVM Team, the VVM Team, University of Illinois 
+      at Urbana-Champaign, University of Pierre et Marie Curie, nor the names 
+      of its contributors may be used to endorse or promote products derived 
+      from this Software without specific prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
diff --git a/vmkit/Makefile.am b/vmkit/Makefile.am
new file mode 100644
index 0000000..a1f7233
--- /dev/null
+++ b/vmkit/Makefile.am
@@ -0,0 +1,4 @@
+# $Id: Makefile.am,v 1.3 2008/03/21 11:25:06 varth Exp $
+SUBDIRS = lib/Mvm lib/JnJVM lib/N3
+DIST_SUBDIRS = lib/Mvm lib/JnJVM lib/N3
+EXTRA_DIST = 
diff --git a/vmkit/NEWS b/vmkit/NEWS
new file mode 100644
index 0000000..7c454acd
--- /dev/null
+++ b/vmkit/NEWS
@@ -0,0 +1,4 @@
+(March 21, 2008)
+
+* VMKit goes public!
+* Usage of the University of Illinois Open source License
diff --git a/vmkit/README b/vmkit/README
new file mode 100644
index 0000000..56725a2
--- /dev/null
+++ b/vmkit/README
@@ -0,0 +1,83 @@
+//===---------------------------------------------------------------------===//
+// General notes
+//===---------------------------------------------------------------------===//
+
+VMKit is the composition of three libraries:
+1) MVM: mostly a garbage collector
+2) JnJVM: a Java Virtual Machine implemented with MVM and LLVM
+3) N3: a CLI implementation with MVM and LLVM
+
+
+You must first patch llvm with vmkit-llvm-svn.patch if you're with SVN, or
+vmkit-llvm-2.2.patch if you're with 2.2. 
+
+
+JnJVM and N3 work on Linux/x86 (note that you may have to disable SSE on some 
+architecture), and mostly work on Linux/PPC (there are some errors with
+floating points). Portage to Darwin has been done some time ago, so it should
+not be too hard.
+
+JnJVM and N3 use GCC's unwinding library (libgcc_s.so).
+
+There are mainly two options in the ./configure script
+--with-gnu-classpath-local-prefix: the local build of GNU classpath
+--with-llvm: the local build of LLVM
+
+Running make on the root tree will produce three executables:
+1) lib/Mvm/main: a command line tool to load virtual machines dynamically
+2) lib/JnJVM/main: running the JnJVM like any other JVM
+3) lib/N3/main: running N3 like CLR
+
+JnJVM and N3 have their own README notes. N3 requires to patch pnet-0.7.4.
+
+
+//===---------------------------------------------------------------------===//
+// LLVM patch
+//===---------------------------------------------------------------------===//
+
+The patched files are:
+- include/llvm/Target/TargetOptions.h: new option SizedMemoryCode to know
+  before emitting the size of the code
+- include/llvm/CodeGen/SizeEmitter.h: new file
+- include/llvm/CodeGen/MachineCodeEmitter.h: uses virtual methods to implement
+  SizeEmitter
+- lib/CodeGen/LLVMTargetMachine.cpp: enables SizeEmitter if SiedMemoryCode is 
+  true
+- lib/CogeGen/SizeEmitter.cpp: new file
+- lib/Target/PowerPC/PPCInstrInfo.td: being able to load extern symbols (probably
+  a bug fix in LLVM)
+- lib/Target/PowerPC/PPCJITInfo.cpp: adds Dwarf debugging output to callbacks,
+  and makes the patching code thread-safe
+- lib/Target/PowerPC/PPCISelLowering.cpp: lowers external symbol, and comments
+  double word alignment (TODO in TOT)
+- lib/ExecutionEngine/JIT/JITEmitter.cpp: helpers for SizedMemoryCode, make the
+  JIT more thread-safe wrt Java (which can execute code when looking for a 
+  class)
+- lib/ExecutionEngine/ExecutionEngine.cpp: Don't check existing mappings (check
+  if TOT is correct)
+- lib/VMCore/AsmWriter.cpp: enables printing of Ghost functions
+  (for debugging purposes)
+- lib/Target/X86/X86JITInfo.cpp: enables Dwarf debugging output to callbacks
+
+//===---------------------------------------------------------------------===//
+// TODOs
+//===---------------------------------------------------------------------===//
+
+- Merge LLVM patch with TOT
+- A compiler/system dependency interface
+- A better autoconf support
+- Remove old, historical references and files
+- Currently old object are allocated by MVM'GC. Make some classes 
+  hand-allocated.
+- Port to Darwin
+- Improve exception handling performance: it's currently ugly and inefficient
+
+//===---------------------------------------------------------------------===//
+// Disclaimer
+//===---------------------------------------------------------------------===//
+
+JnJVM, N3 and MVM were developed with "having functional virtual machines as 
+quick as possible" in mind. The usage of mixed  C/C++ and the absence of clean 
+interfaces, is due to the initial developers lazyness. But now that the VMs
+run, things should go better.
+
diff --git a/vmkit/autogen.sh b/vmkit/autogen.sh
new file mode 100755
index 0000000..a55a246
--- /dev/null
+++ b/vmkit/autogen.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# autogen processing
+function do_autogen()
+{
+  autoreconf -vfi
+  #aclocal
+  #libtoolize --force
+  #autoheader
+  #automake -a
+  #autoconf
+}
+
+do_autogen
+
+#autoreconf
+
+
diff --git a/vmkit/configure.ac b/vmkit/configure.ac
new file mode 100644
index 0000000..9ed2663
--- /dev/null
+++ b/vmkit/configure.ac
@@ -0,0 +1,250 @@
+dnl Process this file with autoconf to produce a configure script
+
+AC_INIT([micro-vm],[0.0.1])
+AC_PREREQ([2.59])
+AC_CONFIG_SRCDIR([lib/Mvm/Main.cc])
+
+
+dnl **************************************************************************
+dnl configure date, in version.cc.in
+dnl **************************************************************************
+configure_date=`date '+%Y-%m-%d %H:%M:%S'`
+AC_SUBST([configure_date])
+
+dnl **************************************************************************
+dnl Initialize target_cpu, target_os etc ...
+dnl **************************************************************************
+AC_CANONICAL_TARGET
+
+dnl **************************************************************************
+dnl Add some vars
+dnl **************************************************************************
+AM_CONDITIONAL(ARCH_IS_PPC,   [test x"$target_cpu" = xpowerpc])
+AM_CONDITIONAL(ARCH_IS_I686,  [test x"$target_cpu" = xi686])
+
+case $host in
+        *linux*) is_linux=true;;
+        *) is_linux=false;;
+esac
+AM_CONDITIONAL(IS_LINUX,      [test x$is_linux = xtrue])
+
+echo $host
+dnl **************************************************************************
+dnl Check system name
+dnl **************************************************************************
+case $host in
+	*linux*) dlsyms_name='dlsyms';;
+	*darwin*) dlsyms_name='dlsyms';;
+	*) dlsyms_name='dlsyms-unknow';;
+esac
+AC_SUBST([dlsyms_name])
+
+dnl **************************************************************************
+dnl Initialize automake with a package version 
+dnl **************************************************************************
+AM_INIT_AUTOMAKE
+
+dnl Use config.h instad of -D macros
+AM_CONFIG_HEADER(config.h)
+
+dnl **************************************************************************
+dnl LLVM Installation Prefix 
+dnl **************************************************************************
+AC_ARG_WITH(llvm,
+       [AS_HELP_STRING(--with-llvm=something,
+           [LLVM installation  prefix (default is /usr/local/)])],
+       [[llvmprefix=$withval]],
+       [[ echo Using /usr/local/ as llvm installation prefix.
+        	llvmprefix=/usr/local/
+       ]]
+)
+LLVMDYLIB="`$llvmprefix/Release/bin/llvm-config --ldflags all` `$llvmprefix/Release/bin/llvm-config --libs all`"
+
+dnl Force some compilation flags
+CXXFLAGS="$CXXFLAGS -fsigned-char -felide-constructors -fno-keep-static-consts -D_REENTRANT -I$PWD/include -I$llvmprefix/include  -D__STDC_LIMIT_MACROS -rdynamic"
+CFLAGS="$CFLAGS -D_REENTRANT"
+
+
+dnl **************************************************************************
+dnl Checks for programs.
+dnl **************************************************************************
+AC_PROG_CXX
+AM_PROG_CC_C_O
+
+dnl **************************************************************************
+dnl check for lex and yacc or bison 
+dnl **************************************************************************
+AM_PROG_LEX
+AC_PROG_YACC
+
+dnl **************************************************************************
+dnl check for as
+dnl **************************************************************************
+AM_PROG_AS
+
+dnl **************************************************************************
+dnl Checks for header files.
+dnl **************************************************************************
+AC_HEADER_STDC
+
+AC_ARG_WITH(readline,
+  [AS_HELP_STRING([--without-readline],
+    [disable readline support])],
+    [with_readline=$enableval],[with_readline=yes]
+)
+
+AS_IF([test "x$with_readline" = xyes],
+  [AC_CHECK_HEADER([readline/readline.h],
+	  [AC_DEFINE(HAVE_READLINE_H,1,[readline found])],
+	  [AC_MSG_WARN(readline NOT found)])
+    AC_CHECK_LIB(readline, history_truncate_file, [],
+     [AC_MSG_ERROR([You need to install readline version 5.])])
+    ]
+)
+
+AC_ARG_WITH(bare,
+  [AS_HELP_STRING([--with-bare], [bare VVMos support])],
+    [with_bare=$enableval],[with_bare=no]
+)
+
+bare_header=""
+AM_CONDITIONAL([BARE], [test "x$vvmthreadtype" != "xno"])
+if test "x$with_bare" != xno; then
+  AC_DEFINE([BARE], [1], [bare VVMos support])
+  bare_header=-I$PWD/../bare/include/
+fi
+
+AC_SUBST([bare_header])
+AC_SUBST([mksyms])
+AC_SUBST([rdynamic])
+AC_SUBST([LLVMDYLIB])
+
+
+dnl **************************************************************************
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl **************************************************************************
+AC_C_CONST
+
+dnl **************************************************************************
+dnl
+dnl **************************************************************************
+AC_LIBTOOL_DLOPEN
+AM_PROG_LIBTOOL
+
+
+dnl **************************************************************************
+dnl VVM thread type
+dnl **************************************************************************
+AC_ARG_WITH(vvm-thread-type,
+       [AS_HELP_STRING(--with-vvm-thread-type=something,
+           [VVM Thread type ('common' or 'no')])],
+       [vvmthreadtype=$withval],[vvmthreadtype=common]
+)
+
+AS_IF([test "x$vvmthreadtype" != "xno"],
+  [AC_CHECK_HEADER([pthread.h],,
+    [AC_MSG_WARN(phtread include NOT found)])
+  AC_CHECK_LIB(pthread, pthread_create, [],
+     [AC_MSG_ERROR([pthread library not found])])
+  ]
+)
+
+AM_CONDITIONAL([HAVE_PTHREAD], [test "x$vvmthreadtype" != "xno"])
+if test "x$vvmthreadtype" = xcommon; then
+  AC_DEFINE([HAVE_PTHREAD], [1], [Using pthread library])
+fi
+
+AC_SUBST([vvmthreadtype])
+GCTHREAD_SUBDIRS="$GCTHREAD_SUBDIRS $vvmthreadtype-thread"
+
+dnl **************************************************************************
+dnl VVM GC type 
+dnl **************************************************************************
+AC_ARG_WITH(vvm-gc-type,
+       [AS_HELP_STRING(--with-vvm-gc-type=something,
+           [VVM GC type ('gen2', 'mmap2' or 'simple2')])],
+       [[vvmgctype=$withval]],
+       [[ echo Using mmap2 as vvm gc type.
+        	vvmgctype=mmap2
+       ]]
+)
+AC_SUBST([vvmgctype])
+GCTHREAD_SUBDIRS="$GCTHREAD_SUBDIRS gc-$vvmgctype"
+AC_SUBST([GCTHREAD_SUBDIRS])
+
+GC_DEFINE=""
+GC_LIBS=""
+
+dnl TODO find the libgc.a
+if test "x$vvmgctype" = "xboehm";  then
+  GC_DEFINE="-DGC_BOEHM"
+  GC_LIBS="/usr/lib/libgc.a"
+fi
+
+AC_SUBST([GC_DEFINE])
+AC_SUBST([GC_LIBS])
+
+dnl **************************************************************************
+dnl GNU CLASSPATH version
+dnl **************************************************************************
+AC_ARG_WITH(gnu-classpath-version,
+       [AS_HELP_STRING(--with-gnu-classpath-version=something,
+           [GNU CLASSPATH VERSION (default is '0.93')])],
+       [[gnuclasspathversion=$withval]],
+       [[       echo Using '0.93' as GNU CLASSPATH version.    
+                                gnuclasspathversion=0.93
+       ]]
+)
+gnuclasspathversionuvm=`echo $gnuclasspathversion | $SED s/\\\./-/`
+AC_SUBST([gnuclasspathversion])
+AC_SUBST([gnuclasspathversionuvm])
+
+dnl **************************************************************************
+dnl GNU CLASSPATH installation prefix
+dnl **************************************************************************
+AC_ARG_WITH(gnu-classpath-local-prefix,
+       [AS_HELP_STRING(--with-gnu-classpath-local-prefix=something,
+           [GNU CLASSPATH local prefix (no default)])],
+       [[gnuclasspathlocalprefix=$withval]],
+       [[       echo Not using GNU CLASSPATH local prefix.    
+                                gnuclasspathlocalprefix=''
+       ]]
+)
+
+AC_ARG_WITH(gnu-classpath-installation-prefix,
+       [AS_HELP_STRING(--with-gnu-classpath-installation-prefix=something,
+           [GNU CLASSPATH installation prefix (default is '/usr/local/classpath')])],
+       [[gnuclasspathinstallationprefix=$withval]],
+       [[gnuclasspathinstallationprefix=/usr/local/classpath]]
+)
+
+if test "x${gnuclasspathlocalprefix}" = x; then
+  echo Using ${gnuclasspathinstallationprefix} as GNU CLASSPATH installation prefix;
+  classpathglibj=${gnuclasspathinstallationprefix}/share/classpath/glibj.zip;
+  classpathlibs=${gnuclasspathinstallationprefix}/lib/classpath/;
+else
+  echo Using ${gnuclasspathlocalprefix} as GNU CLASSPATH local prefix;
+  classpathglibj=${gnuclasspathlocalprefix}/lib/;
+  classpathlibs=${gnuclasspathlocalprefix}/lib/;
+fi
+
+
+AC_SUBST([classpathglibj])
+AC_SUBST([classpathlibs])
+
+
+
+AC_CONFIG_FILES([
+  Makefile
+  lib/N3/Makefile
+  lib/N3/VMCore/Makefile
+  lib/JnJVM/Makefile
+  lib/JnJVM/Classpath/Makefile
+  lib/JnJVM/VMCore/Makefile
+  lib/JnJVM/Classpath/Classpath.h
+  lib/Mvm/Makefile
+  lib/Mvm/GCMmap2/Makefile
+  lib/Mvm/CommonThread/Makefile
+  lib/Mvm/Allocator/Makefile
+])
+AC_OUTPUT
diff --git a/vmkit/include/debug.h b/vmkit/include/debug.h
new file mode 100644
index 0000000..d6284cf
--- /dev/null
+++ b/vmkit/include/debug.h
@@ -0,0 +1,70 @@
+//===----------------- debug.h - Debug facilities -------------------------===//
+//
+//                               Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#define ESC "\033["
+#define COLOR_NORMAL ""
+#define END "m"
+
+#define _BLACK "00"
+#define _RED "01"
+#define _GREEN "02"
+#define _YELLOW "03"
+#define _BLUE "04"
+#define _MAGENTA "05"
+#define _CYAN "06"
+#define _WHITE "07"
+
+#define _NORMAL "00"
+#define _BOLD "01"
+#define _SOULIGNE "04"
+
+#define MK_COLOR(type, bg, fg) type";"bg";"fg
+
+#define WHITE MK_COLOR(_NORMAL, _BLACK, _BLACK)
+
+#define DARK_MAGENTA MK_COLOR(_NORMAL, _BLACK, _MAGENTA)
+#define DARK_YELLOW MK_COLOR(_NORMAL, _BLACK, _YELLOW)
+#define DARK_CYAN MK_COLOR(_NORMAL, _BLACK, _CYAN)
+#define DARK_BLUE MK_COLOR(_NORMAL, _BLACK, _BLUE)
+#define DARK_GREEN MK_COLOR(_NORMAL, _BLACK, _GREEN)
+
+#define LIGHT_MAGENTA MK_COLOR(_BOLD, _BLACK, _MAGENTA)
+#define LIGHT_YELLOW MK_COLOR(_BOLD, _BLACK, _YELLOW)
+#define LIGHT_CYAN MK_COLOR(_BOLD, _BLACK, _CYAN)
+#define LIGHT_BLUE MK_COLOR(_BOLD, _BLACK, _BLUE)
+#define LIGHT_GREEN MK_COLOR(_BOLD, _BLACK, _GREEN)
+#define LIGHT_RED MK_COLOR(_BOLD, _BLACK, _RED)
+
+#if DEBUG > 0
+
+  #ifdef WITH_COLOR
+    #define PRINT_DEBUG(symb, level, color, fmt, args...) \
+      if (symb > level) { \
+          sys_printf("%s%s%s", ESC, color, END); \
+          sys_printf(fmt, ##args); \
+          sys_printf("%s%s%s", ESC, COLOR_NORMAL, END); \
+          sys_fflush(stdout); \
+      }
+  #else
+    #define PRINT_DEBUG(symb, level, color, fmt, args...) \
+      if (symb > level) { \
+        sys_printf(fmt, ##args); \
+        sys_fflush(stdout); \
+      }
+  #endif
+
+#else
+#define PRINT_DEBUG(symb, level, color, fmt, args...)
+#endif
+
+
+#endif
diff --git a/vmkit/include/mvm/CollectableArea.h b/vmkit/include/mvm/CollectableArea.h
new file mode 100644
index 0000000..1395b6d
--- /dev/null
+++ b/vmkit/include/mvm/CollectableArea.h
@@ -0,0 +1,75 @@
+//===----------- CollectableArea.h - Collectable memory -------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_COLLECTABLE_AREA_H
+#define MVM_COLLECTABLE_AREA_H
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+
+namespace mvm {
+
+template <class T>
+class CollectableArea : public Object {
+public:
+  
+  static VirtualTable* VT;
+  unsigned int firstIndex;
+  unsigned int lastIndex;
+  unsigned int capacity;
+
+  inline T **elements() { return (T **)(this + 1); }
+
+  inline T *setAt(T *o, unsigned int idx) { 
+    return (T *)gcset(elements() + idx, o); 
+  }
+  
+  inline T *getAt(unsigned int idx) { return elements()[idx]; }
+
+  static inline CollectableArea *alloc(size_t cap, size_t st, size_t e) {
+    CollectableArea *res = 
+      (CollectableArea *)Object::gcmalloc(sizeof(CollectableArea) + cap<<2, VT);
+    res->firstIndex = st;
+    res->lastIndex = e;
+    res->capacity = cap;
+    return res;
+  }
+
+  inline CollectableArea *realloc(size_t new_cap) {
+    CollectableArea *res = 
+      (CollectableArea *)gc::realloc(sizeof(CollectableArea) + new_cap<<2);
+    res->capacity = new_cap;
+    return res;
+  }
+
+  virtual void print(PrintBuffer *buf) {
+     CollectableArea *const self= (CollectableArea *)this;
+     buf->write("");
+    for (size_t idx= self->firstIndex; idx < self->lastIndex; ++idx) {   
+      if (idx > self->firstIndex)
+        buf->write(" ");
+      buf->writeObj(self->getAt(idx));
+    }   
+  }
+
+
+  virtual void tracer(size_t sz) {
+    CollectableArea *const self= (CollectableArea *)this;
+    register T **e = self->elements();
+    size_t lim= self->lastIndex;
+    size_t idx= self->firstIndex;
+    lim = ((lim << 2) < sz) ? lim : 0;
+    idx = ((idx << 2) < sz) ? idx : (sz >> 2); 
+    for (; idx < lim; ++idx)
+      e[idx]->markAndTrace();
+  }
+};
+
+} // end namespace mvm
+#endif // MVM_COLLECTABLE_AREA_H
diff --git a/vmkit/include/mvm/GC/GC.h b/vmkit/include/mvm/GC/GC.h
new file mode 100644
index 0000000..03523dc
--- /dev/null
+++ b/vmkit/include/mvm/GC/GC.h
@@ -0,0 +1,75 @@
+//===----------- GC.h - Garbage Collection Interface -----------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef MVM_GC_H
+#define MVM_GC_H
+
+#include <sys/types.h>
+
+typedef void (*gc_lock_recovery_fct_t)(int, int, int, int, int, int, int, int);
+
+class gc;
+
+typedef void VirtualTable;
+#define  gc_new(Class)  __gc_new(Class::VT) Class
+
+class gc_header {
+public:
+  VirtualTable *_XXX_vt;
+	inline gc *_2gc() { return (gc *)this; }
+};
+
+class gc {
+public:
+
+	typedef void (*markerFn)(void);
+	inline gc() {}
+	virtual ~gc() {}
+
+	static void	initialise(markerFn mark, void *base_sp);
+	static void	destroy();
+  void setVT(VirtualTable* VT) {
+    ((void**)this)[0] = VT;
+  }
+
+	void	markAndTrace() const;
+	size_t	objectSize() const;
+	void *  operator new(size_t sz, VirtualTable *VT);
+	void    operator delete(void *);
+	void *  realloc(size_t n);
+
+	static void           die_if_sigsegv_occured_during_collection(void *addr);
+	static int            isStable(gc_lock_recovery_fct_t, int, int, int, int,
+                                 int, int, int, int);
+	static unsigned int   enable(unsigned int n);
+	static void	          gcStats(size_t &no, size_t &nbb);
+	static void	          maybeCollect();
+	static void	          collect(void);
+	static void           inject_my_thread(void *sp);
+	static void           remove_my_thread();
+
+	static gc             *begOf(const void *o);
+	static int            byteOffset(void *o);
+	inline static bool    isObject(const void *o) { return begOf((void*)o); }
+        static void     applyFunc(void (*func)(gc *o, void *data), void *data);
+        static void     registerMemoryError(void (*func)(unsigned int));
+        static int      getMaxMemory(void);
+        static int      getFreeMemory(void);
+        static int      getTotalMemory(void);
+        static void     setMaxMemory(size_t);
+        static void     setMinMemory(size_t);
+	
+  virtual void					destroyer(size_t sz) {} ;
+	virtual void					tracer(size_t sz) {};
+};
+
+#define __gc_new new
+
+#endif
diff --git a/vmkit/include/mvm/JIT.h b/vmkit/include/mvm/JIT.h
new file mode 100644
index 0000000..93e2320
--- /dev/null
+++ b/vmkit/include/mvm/JIT.h
@@ -0,0 +1,165 @@
+//===------------------ JIT.h - JIT facilities ----------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_JIT_H
+#define MVM_JIT_H
+
+#include <float.h>
+
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/PassManager.h"
+#include "llvm/Type.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Target/TargetData.h"
+
+#include "types.h"
+
+#include "mvm/Threads/Locks.h"
+
+namespace mvm {
+
+namespace jit {
+
+const double MaxDouble = +INFINITY; //1.0 / 0.0;
+const double MinDouble = -INFINITY;//-1.0 / 0.0;
+const double MaxLongDouble =  9223372036854775807.0;
+const double MinLongDouble = -9223372036854775808.0;
+const double MaxIntDouble = 2147483647.0;
+const double MinIntDouble = -2147483648.0;
+const uint64 MaxLong = 9223372036854775807LL;
+const uint64 MinLong = -9223372036854775808ULL;
+const uint32 MaxInt =  2147483647;
+const uint32 MinInt =  -2147483648U;
+const float MaxFloat = +INFINITY; //(float)(((float)1.0) / (float)0.0);
+const float MinFloat = -INFINITY; //(float)(((float)-1.0) / (float)0.0);
+const float MaxLongFloat = (float)9223372036854775807.0;
+const float MinLongFloat = (float)-9223372036854775808.0;
+const float MaxIntFloat = (float)2147483647.0;
+const float MinIntFloat = (float)-2147483648.0;
+const float NaNFloat = NAN; //(float)(((float)0.0) / (float)0.0);
+const double NaNDouble = NAN; //0.0 / 0.0;
+
+extern llvm::Function* exceptionEndCatch;
+extern llvm::Function* exceptionBeginCatch;
+extern llvm::Function* unwindResume;
+extern llvm::Function* exceptionSelector;
+extern llvm::Function* personality;
+extern llvm::Function* llvmGetException;
+
+extern llvm::Function* printFloatLLVM;
+extern llvm::Function* printDoubleLLVM;
+extern llvm::Function* printLongLLVM;
+extern llvm::Function* printIntLLVM;
+extern llvm::Function* printObjectLLVM;
+
+extern llvm::Function* setjmpLLVM;
+
+extern llvm::Function* func_llvm_fabs_f32;
+extern llvm::Function* func_llvm_fabs_f64;
+extern llvm::Function* func_llvm_sqrt_f64;
+extern llvm::Function* func_llvm_sin_f64;
+extern llvm::Function* func_llvm_cos_f64;
+extern llvm::Function* func_llvm_tan_f64;
+extern llvm::Function* func_llvm_asin_f64;
+extern llvm::Function* func_llvm_acos_f64;
+extern llvm::Function* func_llvm_atan_f64;
+extern llvm::Function* func_llvm_atan2_f64;
+extern llvm::Function* func_llvm_exp_f64;
+extern llvm::Function* func_llvm_log_f64;
+extern llvm::Function* func_llvm_pow_f64;
+extern llvm::Function* func_llvm_ceil_f64;
+extern llvm::Function* func_llvm_floor_f64;
+extern llvm::Function* func_llvm_rint_f64;
+extern llvm::Function* func_llvm_cbrt_f64;
+extern llvm::Function* func_llvm_cosh_f64;
+extern llvm::Function* func_llvm_expm1_f64;
+extern llvm::Function* func_llvm_hypot_f64;
+extern llvm::Function* func_llvm_log10_f64;
+extern llvm::Function* func_llvm_log1p_f64;
+extern llvm::Function* func_llvm_sinh_f64;
+extern llvm::Function* func_llvm_tanh_f64;
+
+extern llvm::Function* llvm_memcpy_i32;
+extern llvm::Function* llvm_memset_i32;
+
+extern llvm::ExecutionEngine* executionEngine;
+
+extern uint64 getTypeSize(const llvm::Type* type);
+
+extern void AddStandardCompilePasses(llvm::FunctionPassManager*);
+
+extern void runPasses(llvm::Function* func, llvm::FunctionPassManager*);
+extern void* runCompilation(llvm::Function*);
+
+//extern mvm::Lock* protectTypes;
+//extern mvm::Lock* protectConstants;
+extern mvm::Lock* protectEngine;
+extern llvm::ConstantInt* constantInt8Zero;
+extern llvm::ConstantInt* constantZero;
+extern llvm::ConstantInt* constantOne;
+extern llvm::ConstantInt* constantTwo;
+extern llvm::ConstantInt* constantThree;
+extern llvm::ConstantInt* constantFour;
+extern llvm::ConstantInt* constantFive;
+extern llvm::ConstantInt* constantSix;
+extern llvm::ConstantInt* constantSeven;
+extern llvm::ConstantInt* constantEight;
+extern llvm::ConstantInt* constantMinusOne;
+extern llvm::ConstantInt* constantLongMinusOne;
+extern llvm::ConstantInt* constantLongZero;
+extern llvm::ConstantInt* constantLongOne;
+extern llvm::ConstantInt* constantMinInt;
+extern llvm::ConstantInt* constantMaxInt;
+extern llvm::ConstantInt* constantMinLong;
+extern llvm::ConstantInt* constantMaxLong;
+extern llvm::ConstantFP*  constantFloatZero;
+extern llvm::ConstantFP*  constantFloatOne;
+extern llvm::ConstantFP*  constantFloatTwo;
+extern llvm::ConstantFP*  constantDoubleZero;
+extern llvm::ConstantFP*  constantDoubleOne;
+extern llvm::ConstantFP*  constantMaxIntFloat;
+extern llvm::ConstantFP*  constantMinIntFloat;
+extern llvm::ConstantFP*  constantMinLongFloat;
+extern llvm::ConstantFP*  constantMinLongDouble;
+extern llvm::ConstantFP*  constantMaxLongFloat;
+extern llvm::ConstantFP*  constantMaxIntDouble;
+extern llvm::ConstantFP*  constantMinIntDouble;
+extern llvm::ConstantFP*  constantMaxLongDouble;
+extern llvm::ConstantFP*  constantDoubleInfinity;
+extern llvm::ConstantFP*  constantDoubleMinusInfinity;
+extern llvm::ConstantFP*  constantFloatInfinity;
+extern llvm::ConstantFP*  constantFloatMinusInfinity;
+extern llvm::ConstantFP*  constantFloatMinusZero;
+extern llvm::ConstantFP*  constantDoubleMinusZero;
+extern llvm::Constant*    constantPtrNull;
+extern const llvm::PointerType* ptrType;
+extern const llvm::Type* arrayPtrType;
+
+
+extern llvm::Module *globalModule;
+extern llvm::ExistingModuleProvider *globalModuleProvider;
+extern llvm::JITMemoryManager *memoryManager;
+
+extern void protectTypes();
+extern void unprotectTypes();
+
+extern void protectConstants();
+extern void unprotectConstants();
+
+
+} // end namespace jit
+
+} // end namespace mvm
+
+#endif // MVM_JIT_H
diff --git a/vmkit/include/mvm/Method.h b/vmkit/include/mvm/Method.h
new file mode 100644
index 0000000..1248b7b
--- /dev/null
+++ b/vmkit/include/mvm/Method.h
@@ -0,0 +1,87 @@
+//===-------------- Method.h - Collectable methods ------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_METHOD_H
+#define MVM_METHOD_H
+
+#include "mvm/Object.h"
+
+namespace mvm {
+
+class Code;
+class ExceptionTable;
+
+class Method : public Object {
+public:
+  inline Method() {}
+  static VirtualTable* VT;
+  GC_defass(Object, name);
+  GC_defass(Code, code);
+  GC_defass(Object, definition);
+  GC_defass(Object, literals);
+  GC_defass(ExceptionTable, exceptionTable);
+  size_t  codeSize;
+
+  /* use this constructor to map a function which is compiled by llvm  */
+  inline Method(Code *c, size_t sz) {
+    code(c);
+    codeSize = sz;
+  }
+
+  virtual void print(PrintBuffer *buf) const;
+  virtual void tracer(size_t sz);
+};
+
+
+class Code : public Object {
+public:
+  inline Code() {}
+  static VirtualTable* VT;
+  static void *allocate(size_t _nbb, void* metaInfo);
+
+  inline Method *method(Method *m, size_t nbb) {
+    return 
+      (Method *)gcset((gc **)((unsigned int)this + nbb + 4 - sizeof(Method *)), m);
+  }
+
+  inline Method *method(size_t nbb) {
+    return ((Method **)((unsigned int)this + nbb + 4 - sizeof(Method *)))[0];
+  }
+    
+  inline Method *method(Method *m) { return method(m, objectSize()); }
+  inline Method *method() { return method(objectSize()); }
+
+  virtual void print(PrintBuffer *buf) const;
+  virtual void tracer(size_t sz);
+};
+
+class ExceptionTable : public Object {
+public:
+  inline ExceptionTable() {}
+  static VirtualTable* VT;
+
+  inline void *frameRegister(void *m, size_t nbb) {
+    return 
+      (void *)gcset((gc **)((unsigned int)this + nbb + 4 - sizeof(void *)), 
+                            (Object*)m);
+  }
+
+  inline void *frameRegister(size_t nbb) {
+    return ((void **)((unsigned int)this + nbb + 4 - sizeof(void *)))[0];
+  }
+    
+  inline void *frameRegister(void *m) { return frameRegister(m, objectSize()); }
+  inline void *frameRegister() { return frameRegister(objectSize()); }
+  
+  virtual void destroyer(size_t sz);
+};
+
+} // end namespace mvm
+
+#endif // MVM_METHOD_H
diff --git a/vmkit/include/mvm/Object.h b/vmkit/include/mvm/Object.h
new file mode 100644
index 0000000..60305f3
--- /dev/null
+++ b/vmkit/include/mvm/Object.h
@@ -0,0 +1,97 @@
+//===---------- Object.h - Common layout for all objects ------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_OBJECT_H
+#define MVM_OBJECT_H
+
+#include <assert.h>
+
+#include "mvm/GC/GC.h"
+
+namespace mvm {
+
+
+#define VT_DESTRUCTOR_OFFSET 0
+#define VT_GC_DESTRUCTOR_OFFSET 1
+#define VT_DESTROYER_OFFSET 2
+#define VT_TRACER_OFFSET 3
+#define VT_PRINT_OFFSET 4
+#define VT_HASHCODE_OFFSET 5
+#define VT_SIZE 24
+
+
+#define GC_defass(TYPE, name)                                  \
+  TYPE    *_hidden_##name;                                     \
+	inline TYPE    *name()        { return _hidden_##name; }     \
+	inline TYPE    *name(TYPE *v) { return _hidden_##name = v; }
+
+class PrintBuffer;
+class Object;
+
+class Object : public gc {
+public:
+  static VirtualTable* VT; 
+  bool    isObject() const;
+  Object *begOf() const;
+  size_t  objectSize() const;
+  VirtualTable* getVirtualTable() {
+    return ((VirtualTable**)(this))[0];
+  }
+
+  char *printString(void) const;
+  static char * printStatic(const Object *); 
+
+#if !defined(GC_GEN)
+  inline gc *gcset(void *ptr, gc *src) { return *((gc **)ptr) = src; }
+#endif
+  
+
+
+  virtual void    destroyer(size_t) {}
+  virtual void    tracer(size_t) {}
+  virtual void    print(PrintBuffer *buf) const;
+  virtual int     hashCode(){ return (int)this;}
+
+protected:
+  static Object **rootTable;
+  static int	   rootTableSize, rootTableLimit;
+
+  static void growRootTable(void);
+
+public:
+  
+  inline static void pushRoot(Object *obj) {
+    if (rootTableSize >= rootTableLimit)
+      growRootTable();
+    rootTable[rootTableSize++]= obj;
+  }
+
+  inline static void pushRoot(Object &var) {
+    pushRoot(var);
+  }
+
+  inline static Object *popRoots(size_t nRoots) {
+    rootTableSize-= nRoots;
+    assert(rootTableSize >= 0);
+    return rootTable[rootTableSize];
+  }
+
+  inline static Object *popRoot(void) {
+    return popRoots(1);
+  }
+
+  static void markAndTraceRoots(void);
+  static Object *gcmalloc(size_t sz, VirtualTable* VT);
+  static void initialise(void *sp);
+
+};
+
+} // end namespace mvm
+
+#endif // MVM_OBJECT_H
diff --git a/vmkit/include/mvm/PrintBuffer.h b/vmkit/include/mvm/PrintBuffer.h
new file mode 100644
index 0000000..fb78a38
--- /dev/null
+++ b/vmkit/include/mvm/PrintBuffer.h
@@ -0,0 +1,147 @@
+//===--------------- PrintBuffer.h - Printing objects ----------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_PRINTBUFFER_H
+#define MVM_PRINTBUFFER_H
+
+#include <stdio.h>
+#include <string.h>
+
+#include "types.h"
+#include "mvm/Object.h"
+
+namespace mvm {
+
+class NativeString : public Object {
+public:
+  
+  static VirtualTable* VT;
+
+	inline char *cString() { return (char *)(this + 1); }
+
+  inline static NativeString *readString(char *cStr) {
+		size_t nbb = strlen(cStr);
+		NativeString * res = alloc(nbb + 1);
+		memcpy(res->cString(), cStr, nbb + 1);
+		return res;
+	}
+
+	static inline NativeString *alloc(size_t len) {
+		return (NativeString *)Object::gcmalloc(len, VT);
+	}
+
+	inline NativeString *realloc(size_t len) {
+		return (NativeString *)gc::realloc(len);
+	}
+
+  inline void setAt(int pos, char c) {
+    cString()[pos] = c;
+  }
+
+public:
+  virtual void print(PrintBuffer *buf) const;
+
+  inline bool compare(char *str) {
+    return !strcmp(cString(), str);
+  }
+
+  inline bool compare(char *str, int len) {
+    return ((int)strlen(cString()) == len) && !strncmp(cString(), str, len);
+  }
+};
+
+
+class PrintBuffer : public Object {
+public:
+  static VirtualTable* VT;
+  size_t  capacity;
+  size_t  writePosition;
+  GC_defass(NativeString, contents);
+
+public:
+
+  static inline PrintBuffer* allocPrintBuffer(void) {
+    PrintBuffer* pbf = gc_new(PrintBuffer)();
+    pbf->capacity= 32;
+    pbf->writePosition= 0;
+		pbf->contents(NativeString::alloc(pbf->capacity));
+    return pbf;
+  }
+
+  inline PrintBuffer *write(const char *string) {
+    size_t len= strlen(string);
+    if ((writePosition + len + 1) >= capacity) {
+		  while ((writePosition + len + 1) >= capacity)
+				capacity*= 4;
+			contents(contents()->realloc(capacity));
+    }
+    strcpy(contents()->cString() + writePosition, string);
+    writePosition+= len;
+    return this;
+  }
+  
+  inline PrintBuffer *writeChar(char v) {
+    char buf[32];
+    sprintf(buf, "%c", v);
+    return write(buf);
+  }
+  
+
+  inline PrintBuffer *writeS4(int v) {
+    char buf[32];
+    sprintf(buf, "%d", v);
+    return write(buf);
+  }
+  
+  inline PrintBuffer *writeS8(sint64 v) {
+    char buf[32];
+    sprintf(buf, "%lld", v);
+    return write(buf);
+  }
+  
+  inline PrintBuffer *writeFP(double v) {
+    char buf[32];
+    sprintf(buf, "%f", v);
+    return write(buf);
+  }
+
+  inline PrintBuffer *writePtr(void *p) {
+    char buf[32];
+    sprintf(buf, "%08x", (int)p);
+    return write(buf);
+  }
+
+  inline PrintBuffer *writeBytes(unsigned char *bytes, size_t len) {
+    write("[");
+    for (size_t idx= 0; idx < len; ++idx) {
+		  if (idx > 0)
+			  write(" ");
+			char buf[32];
+			sprintf(buf, "%d", bytes[idx]);
+			write(buf);
+    }
+    write("]");
+    return this;
+  }
+
+	PrintBuffer *writeObj(const Object *);
+
+	NativeString      *getContents();
+  
+  static PrintBuffer *write_static(PrintBuffer*, char *);
+
+public:
+  static PrintBuffer *alloc(void);
+
+  virtual void tracer(size_t sz);
+};
+
+} // end namespace mvm
+
+#endif // MVM_PRINTBUFFER_H
diff --git a/vmkit/include/mvm/Sigsegv.h b/vmkit/include/mvm/Sigsegv.h
new file mode 100644
index 0000000..05c41da
--- /dev/null
+++ b/vmkit/include/mvm/Sigsegv.h
@@ -0,0 +1,28 @@
+//===------------ Sigsegv.h - Sgsegv handler for mvm  ---------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef MVM_SIGSEGV_H
+#define MVM_SIGSEGV_H
+
+#include <sys/types.h>
+
+namespace mvm {
+
+__BEGIN_DECLS
+
+void register_sigsegv_handler(void (*fct)(int, void *));
+
+__END_DECLS
+
+} // end namespace mvm;
+
+#endif //MVM_SIGSEGV_H
+
+
diff --git a/vmkit/include/mvm/Threads/Cond.h b/vmkit/include/mvm/Threads/Cond.h
new file mode 100644
index 0000000..80b7a30
--- /dev/null
+++ b/vmkit/include/mvm/Threads/Cond.h
@@ -0,0 +1,36 @@
+//===---------------- Cond.h - Threads conditions -------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_COND_H
+#define MVM_COND_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mvm/GC/GC.h"
+#include "mvm/Threads/Locks.h"
+
+namespace mvm {
+
+class Cond {
+  unsigned int    no_barrier;
+  unsigned int    go; 
+  unsigned int    n_wait;
+public:
+  static Cond *allocCond(void);
+  void broadcast(void);
+  void wait(Lock *l);
+  int timed_wait(Lock *l, struct timeval *tv);
+  void signal(void);
+};
+
+} // end namespace mvm
+
+#endif // MVM_COND_H
diff --git a/vmkit/include/mvm/Threads/Key.h b/vmkit/include/mvm/Threads/Key.h
new file mode 100644
index 0000000..fd0764f
--- /dev/null
+++ b/vmkit/include/mvm/Threads/Key.h
@@ -0,0 +1,54 @@
+//===---------------- Key.h - Private thread keys -------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_KEY_H
+#define MVM_KEY_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mvm/GC/GC.h"
+
+namespace mvm {
+
+class ThreadKey {
+public:
+  void * val;
+  
+  ThreadKey(void (*_destr)(void *));
+  ThreadKey();
+  void* get();
+  void set(void*);
+  void initialise();
+
+};
+
+template <class T>
+class Key {
+public:
+  ThreadKey key;
+  
+  Key() {
+    initialise();
+  }
+
+  void initialise() {
+    key.initialise();
+  }
+
+  T*   get() { return (T*)key.get(); }
+  void set(T *v) { key.set(v); }
+  
+};
+
+
+} // end namespace mvm
+
+#endif // MVM_KEY_H
diff --git a/vmkit/include/mvm/Threads/Locks.h b/vmkit/include/mvm/Threads/Locks.h
new file mode 100644
index 0000000..a6702af
--- /dev/null
+++ b/vmkit/include/mvm/Threads/Locks.h
@@ -0,0 +1,104 @@
+//===------------------ Locks.h - Thread locks ----------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_LOCKS_H
+#define MVM_LOCKS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mvm/GC/GC.h"
+
+namespace mvm {
+
+class SpinLock {
+ 	unsigned int value;
+public:
+  static VirtualTable *VT; 
+ 	SpinLock() { value = 0; }
+	
+ 	void slock();
+ 	void sunlock() {
+ 		value = 0;
+ 	}
+};
+
+class Lock : public SpinLock {
+protected:
+	void		(*xlock)(Lock *);
+	void		(*xunlock)(Lock *);
+	int			(*xtrylock)(Lock *);
+
+	int			_owner;
+
+public:
+	inline Lock() { _owner = 0; }
+	inline int	owner() { return _owner; }
+	inline void owner(int o) { _owner = o; }
+
+	void lock() { 
+		xlock(this); 
+	}
+
+	void unlock() { 
+		xunlock(this);
+	}
+
+	int trylock() { 
+		int res = xtrylock(this); 
+		return res;
+	}
+
+	static Lock *allocNormal();
+	static Lock *allocRecursive();
+	static void destroy(Lock *);
+
+	static bool selfOwner(Lock *);
+	static int getOwner(Lock *);
+  
+};
+
+class LockNormal : public Lock {
+	static void		my_lock(Lock *);
+	static void		my_unlock(Lock *);
+	static int		my_trylock(Lock *);
+public:
+	LockNormal() {
+    xlock = my_lock; xunlock = my_unlock; xtrylock = my_trylock;
+  }
+
+  void initialise() {
+    xlock = my_lock; xunlock = my_unlock; xtrylock = my_trylock;
+  }
+};
+	
+class LockRecursive : public Lock {
+	int n;
+
+	static void		my_lock(Lock *);
+	static void		my_unlock(Lock *);
+	static int		my_trylock(Lock *);
+public:
+	LockRecursive() {
+    xlock = my_lock; xunlock = my_unlock; xtrylock = my_trylock; n = 0;
+  }
+  
+  void initialise() {
+    xlock = my_lock; xunlock = my_unlock; xtrylock = my_trylock; n = 0;
+  }
+  
+  static int recursion_count(Lock *);
+  static int my_unlock_all(Lock *);
+  static void my_lock_all(Lock *, int count);
+};
+
+} // end namespace mvm
+
+#endif // MVM_LOCKS_H
diff --git a/vmkit/include/mvm/Threads/Thread.h b/vmkit/include/mvm/Threads/Thread.h
new file mode 100644
index 0000000..4f005ac
--- /dev/null
+++ b/vmkit/include/mvm/Threads/Thread.h
@@ -0,0 +1,30 @@
+//===---------------- Threads.h - Micro-vm threads ------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_THREAD_H
+#define MVM_THREAD_H
+
+#include "mvm/GC/GC.h"
+
+namespace mvm {
+class Thread {
+public:
+  static void yield(void);
+  static void yield(unsigned int *);
+  static int self(void);
+  static void initialise(void);
+  static int kill(int tid, int signo);
+  static void exit(int value);
+  static int start(int *tid, int (*fct)(void *), void *arg);
+
+};
+
+
+} // end namespace mvm
+#endif // MVM_THREAD_H
diff --git a/vmkit/include/mvm/VMLet.h b/vmkit/include/mvm/VMLet.h
new file mode 100644
index 0000000..1871823
--- /dev/null
+++ b/vmkit/include/mvm/VMLet.h
@@ -0,0 +1,38 @@
+//===--------------- VMLet.h - Definition of VMLets -----------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MVM_VMLET_H
+#define MVM_VMLET_H
+
+#include "mvm/Object.h"
+#include "mvm/Threads/Key.h"
+
+namespace llvm {
+  class Module;
+  class ExistingModuleProvider;
+  class ExecutionEngine;
+  class FunctionPassManager;
+  class JITMemoryManager;
+}
+
+namespace mvm {
+
+class VMLet : public Object {
+public:
+  static VirtualTable *VT;
+  //GC_defass(String, name);
+
+  static void register_sigsegv_handler(void (*fct)(int, void *));
+
+  static void initialise();
+};
+
+} // end namespace mvm
+
+#endif // MVM_VMLET_H
diff --git a/vmkit/include/types.h b/vmkit/include/types.h
new file mode 100644
index 0000000..b3ef05b
--- /dev/null
+++ b/vmkit/include/types.h
@@ -0,0 +1,24 @@
+//===------------------- types.h - bitsized types -------------------------===//
+//
+//                              MVM
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPES_H
+#define TYPES_H
+
+#include <stdint.h>
+
+typedef uint8_t uint8;
+typedef int8_t sint8;
+typedef uint16_t uint16;
+typedef int16_t sint16;
+typedef uint32_t uint32;
+typedef int32_t sint32;
+typedef uint64_t uint64;
+typedef int64_t sint64;
+
+#endif
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
diff --git a/vmkit/lib/Mvm/Allocator/.cvsignore b/vmkit/lib/Mvm/Allocator/.cvsignore
new file mode 100644
index 0000000..eefb2a0
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/.cvsignore
@@ -0,0 +1,14 @@
+allocator
+*.d
+Makefile
+Makefile.in
+.deps
+.libs
+*.a
+*.o
+*.la
+*.lo
+*.class
+*.stamp
+
+mainuvm_alloc
diff --git a/vmkit/lib/Mvm/Allocator/Makefile.am b/vmkit/lib/Mvm/Allocator/Makefile.am
new file mode 100644
index 0000000..3c79965
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/Makefile.am
@@ -0,0 +1,12 @@
+# $Id: Makefile.am,v 1.2 2008/03/21 11:12:38 varth Exp $
+noinst_LIBRARIES = libuvm_alloc.a
+noinst_PROGRAMS = mainuvm_alloc
+
+libuvm_alloc_a_SOURCES = gcalloc.cc gcalloc.h gcchunk.cc gcchunk.h gcerror.cc gcerror.h gcmapper.cc gcmapper.h osdep.h
+libuvm_alloc_a_CXXFLAGS = -O2
+
+mainuvm_alloc_SOURCES = main.cc
+mainuvm_alloc_CXXFLAGS =
+mainuvm_alloc_LDADD = libuvm_alloc.a
+
+CLEANFILES = *~ *.bak .*.sw?
diff --git a/vmkit/lib/Mvm/Allocator/README b/vmkit/lib/Mvm/Allocator/README
new file mode 100644
index 0000000..6983f52
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/README
@@ -0,0 +1,130 @@
+##############################################################################
+#
+# Micro-VM Allocator
+# by Charles Clément, corrected by Gaël Thomas.
+#
+##############################################################################
+
+
+I Memory layout
+  1 Exponantial area
+  2 Linear area
+  3 Mmap area
+II Structure
+  1 Referencing memory chunks
+  2 Harsh tables
+III Internal memory management
+
+I Memory layout
+#--------------
+
+Based on the size of the objects to allocate, the allocator chooses between
+three distincts area.
+i) The exponantial area for objects less than max_exp bytes
+ii) The linear area for x in max_exp < x < max_lin bytes
+iii) The mmap area for LIN bytes < x
+
+Max_exp and max_lin are actually defined to 32 and 8192 bytes.
+
+I.1 Exponantial area:
+Objects stored in that area are allocated 2^n bytes, the smallest power of two
+in which the object can fit.
+
+-------------------------------------
+| Size to allocate | reserved space |
+-------------------------------------
+ 1                  2
+ 2                  2
+ 3                  4
+ 4                  4
+ {5,6,7,8}          8
+ {9-16}             16
+ {17-32}            32
+
+-> Size of allocated chunk in this area grows exponantially.
+With max_exp = 32 bytes
+
+I.2 Linear area:
+In the linear area, the size needed to be allocated is rounded to the next
+max_exp multiple. This is to reduce memory loss, as otherwise, with the
+previous technique allocating 260 bytes would induce to occupy a 512 bytes
+area.
+
+   ------------------------------------
+  |  32  |   64   |  96  |  128  |  ...
+   ------------------------------------
+
+max_exp*1    *2      *3      *4
+
+-> Size of allocated chunk in this area grows linearly.
+
+I.3 Mmap area:
+For objects larger than 2^13 (8192) bytes, a number of physical page is
+associated, thus a multiplier of 4096 bytes.
+
+
+II Descriptors
+#-------------
+
+II.1 Hash tables:
+
+In order to keep track of allocated memory adresses, we need to store the
+adresses that we allocated. This is a requirement for the garbage collector, as
+the compatibility with the C ABI implies that a memory reference is
+indistinguishable from a value. Hence, every page descriptor is inserted in a
+hash table when allocated.
+This has a limitation, as it is not possible to make the difference between a
+value in the heap that would point to an actual allocated space in memory if
+translated into a pointer.
+
+
+II.2 Referencing memory chunks:
+Here is the representation of an adress in memory :
+
+          ----------------------------------------------------------
+Pointer: |    Table Entry     |  Page Descriptor  |       Index     |
+          ----------------------------------------------------------
+             |     __                    |                   |
+             |    |  |                   |                   |
+             |    |__|                   |                   |
+             |    |  |    GCHashSet     \|/                  |
+             |    |__|       __ __ __ __ __ __               |
+              --->|  |----->|__|__|__|__|__|__|              |
+                  |__|                    |                  |
+                  |  |                    |    GCPage       \|/
+                  |__|                    |      __ __ __ __ __ __
+           GCHash                          ---->|__|__|__|__|__|__| Headers
+
+
+Memory is separated in spaces. Each space contains memory chunk of the same
+size. When the allocator needs to allocate n bytes, it choose a memory space
+in an exponential, linear or mmaped space and round n to the size of this
+space. This technique is used to construct a performant hashtable of all
+allocated memory chunks, which is used to identify pointer during a collection
+(the garbage collector is only conservative).
+
+The first bits of a memory chunk pointer reference an entry in GCHash, and
+the next bits reference an entry in GCHashSet. Each entry in GCHashSet is a
+GCPage structure, which describes a set of contiguous pages (a memory space).
+
+The GCPage Class holds a field (GCChunkNode*)_headers containing the list to
+all headers of free chunks of the space. It also holds the size of the space
+in _chunk_nbb. This size is the rounded size (exp or linear) of all memory
+chunks managed in this space.
+
+_Note_:
+This is not the case for space allocated in the mmap area, whose page
+descriptor holds directly the header itself.
+
+A header is described by the class GCChunkNode. It holds the size _nbb_mark of
+memory chunks in the last 29 bits (the 3 last ones are used by the garbage
+collector to set the *color* of the chunk). GCChunkNode are stored in a
+circular double linked list.
+
+
+III Internal memory management
+#-----------------------------
+
+The allocator has to allocate its memmory structures itself. It is responsible
+to allocate the memory for the micro-vm and the structures needed to manage
+and access the allocated areas.
diff --git a/vmkit/lib/Mvm/Allocator/gcalloc.cc b/vmkit/lib/Mvm/Allocator/gcalloc.cc
new file mode 100644
index 0000000..22355e2
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcalloc.cc
@@ -0,0 +1,134 @@
+//===--------------- gcalloc.cc - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gcalloc.h"
+
+GCChunkNode *GCAllocator::alloc_headers(size_t headers_nbb, void *base, size_t depl, size_t filled) {
+	GCChunkNode *headers;
+	size_t rounded = GCMappedArea::round(headers_nbb);
+	
+	if(headers_nbb == rounded)
+		headers = (GCChunkNode *)(new GCMappedArea(&headers_area, rounded))->area();
+	else {
+		headers = used_headers;
+		used_headers = (GCChunkNode *)((unsigned int)used_headers + headers_nbb);
+		if(used_headers >= max_headers) {
+			headers = (GCChunkNode *)(new GCMappedArea(&headers_area, used_headers_nbb))->area();
+			used_headers = (GCChunkNode *)((unsigned int)headers + headers_nbb);
+			max_headers = (GCChunkNode *)((unsigned int)headers + used_headers_nbb);
+		}
+	}
+
+	register GCChunkNode *cur = headers;
+	register GCChunkNode *lim = (GCChunkNode *)((unsigned int)headers + headers_nbb);
+	register GCChunkNode *max = lim - (1 + filled);
+	for(;cur<max; cur++) {
+		cur->initialise(cur+1, base);
+		base = (void *)((unsigned int)base + depl);
+	}
+	for(;cur<lim; cur++) {
+ 		cur->initialise(0, base);
+		base = (void *)((unsigned int)base + depl);
+ 	}
+	return headers;
+}
+
+GCChunkNode	*GCAllocator::alloc_list(GCFreeList *fl, size_t n) {
+ 	GCChunkNode	  *headers;
+ 	size_t				area_nbb;
+ 	void          *area_ptr;
+ 	GCPage       	*page;
+
+	if(GCFreeListFinder::isMmaped(n)) {
+ 		area_nbb = GCMappedArea::round(n);
+
+ 		/* on alloue un Descripteur */
+ 		page = new GCDescriptorMappedChunk(&normal_area, area_nbb, area_nbb);
+  		area_ptr = page->area();
+
+ 		headers = page->headers();
+  	} else {
+  		size_t chunk_nbb = fl->chunk_nbb();
+
+			/* on alloue un Descripteur */
+			page = new GCPage(&normal_area, area_nbb = fl->area_nbb(), chunk_nbb);
+
+			area_ptr = page->area();
+
+			/* on alloue des headers */
+			headers = alloc_headers(fl->headers_nbb(), area_ptr, chunk_nbb, fl->filled());
+
+  		page->headers(headers);
+  	}
+
+ 	/* on hash notre nouveau chunk */
+ 	GCHash::hash_unprotected(page, area_ptr, area_nbb, area_nbb);
+	
+	fl->list(headers);
+	return headers;
+}
+
+#define min(a, b)   ((a) < (b) ? (a) : (b))
+#define max(a, b)   ((a) < (b) ? (b) : (a))
+
+GCFreeListFinder::GCFreeListFinder() {
+ 	unsigned int	i, j, m;
+ 	GCFreeList		*cur;
+
+ 	for(i=0; i<=min_exp; i++)
+ 		exp_lists[i] = _exp_lists;
+ 	_exp_lists[0].initialise(min_exp, 128*min_exp);
+
+ 	for(i=min_exp_log, cur=_exp_lists+1; i<max_exp_log; i++, cur++) {
+ 		m = 1 << (i + 1);
+ 		cur->initialise(m, 512*m);
+ 		for(j=1<<i; j<m; j++)
+ 			exp_lists[j+1] = cur;
+ 	}
+
+ 	for(i=0;i<nb_lin; i++) {
+ 		m = ((i+1)<<lin_step_log) + max_exp;
+ 		lin_lists[i].initialise(m, min(128*m, 65536));
+ 	}
+
+ 	//	for(i=0; i<max_lin+2; i++)
+ 	//		printf("%d => %d\n", i, find(i)->chunk_nbb());
+}
+
+
+GCAllocator::GCAllocator() {
+ 	used_headers = 0;
+ 	max_headers = 0;
+ 	GCHash::initialise();
+}
+
+GCAllocator::~GCAllocator() {
+ 	GCMappedArea *cur;
+
+ 	for(cur=normal_area.next(); cur!=&normal_area; cur=cur->next())
+ 		delete cur->munmap();
+
+ 	for(cur=headers_area.next(); cur!=&headers_area; cur=cur->next())
+ 		delete cur->munmap();
+
+ 	for(cur=mapped_area.next(); cur!=&mapped_area; cur=cur->next())
+ 		delete cur->munmap();
+	GCHash::unlink();
+}
+
+void *GCAllocator::operator new(size_t req) {
+	size_t nbb = GCMappedArea::round(req);
+	GCAllocator *res = (GCAllocator *)GCMappedArea::do_mmap(nbb);
+	res->my_size = nbb;
+	return res;
+}
+
+void GCAllocator::operator delete(void *ptr) {
+	GCMappedArea::do_munmap(ptr, ((GCAllocator *)ptr)->my_size);
+}
diff --git a/vmkit/lib/Mvm/Allocator/gcalloc.h b/vmkit/lib/Mvm/Allocator/gcalloc.h
new file mode 100644
index 0000000..8d96628
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcalloc.h
@@ -0,0 +1,202 @@
+//===---------------- gcalloc.h - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GC_ALLOC_H_
+#define _GC_ALLOC_H_
+
+#include <string.h> /* memset */
+
+#include "gcchunk.h"
+
+class GCFreeList {
+ 	GCChunkNode 	 *_list;
+ 	size_t					_chunk_nbb;
+ 	size_t					_area_nbb;
+ 	size_t					_nb_chunks;
+ 	size_t					_headers_nbb;
+ 	size_t          _filled;
+public:
+ 	inline GCFreeList() { _chunk_nbb = 0; _nb_chunks = 1; }
+
+ 	inline void			initialise(size_t n, size_t area) {
+ 		_list					= 0;
+ 		_chunk_nbb		= n; 
+ 		_area_nbb			= GCMappedArea::round(area); /* taille en pages utilisée pour une free-list */
+ 		_nb_chunks		= _area_nbb/_chunk_nbb;      /* nombre de type que je peux caser la dedans  */
+ 		/* est-ce qu'il reste de la place derière ? */
+ 		_filled = (_nb_chunks * _chunk_nbb) == _area_nbb ? 0 : 1;
+ 		/* j'utilise un "faux header" à 0 pour completer ce truc */
+ 		_headers_nbb	= (_nb_chunks + _filled)*sizeof(GCChunkNode);
+ 	}
+
+ 	inline GCChunkNode    *list() { return _list; }
+ 	inline void						list(GCChunkNode *l) { _list = l; }
+ 	inline size_t					nb_chunks()		{ return _nb_chunks; }
+ 	inline size_t					chunk_nbb()		{ return _chunk_nbb; }
+ 	inline size_t					area_nbb()		{ return _area_nbb; }
+ 	inline size_t					headers_nbb() { return _headers_nbb; }
+ 	inline size_t         filled()      { return _filled; }
+
+ 	inline void reject(GCChunkNode *header) {
+ 		header->next(_list);
+ 		_list = header;
+ 	}
+};
+
+class GCFreeListFinder {
+ 	/* trois zones distinctes: exponentielle/lineaire/mmap */
+ 	static const unsigned int min_exp_log = 0;						/* 0  -> 4 => 4 */
+ 	static const unsigned int max_exp_log = 5;						/* 4  -> 32 en exponentielle */
+ 	static const unsigned int max_lin_log = 13;						/* 32 -> 128 en linéaire */
+ 	static const unsigned int lin_step_log = 4;						/* par pas de 4 */
+ 	static const unsigned int min_exp = 1 << min_exp_log;
+ 	static const unsigned int max_exp = 1 << max_exp_log;
+ 	static const unsigned int max_lin = 1 << max_lin_log;
+ 	static const unsigned int	nb_exp = max_exp_log - min_exp_log + 1;
+ 	static const unsigned int nb_lin = (max_lin - max_exp)>>lin_step_log;
+
+ 	GCFreeList		_exp_lists[nb_exp];
+ 	GCFreeList		*exp_lists[max_exp+1];
+ 	GCFreeList		lin_lists[nb_lin];
+ 	GCFreeList		mmap_list;
+
+ 	inline size_t linEntry(size_t n) { return (n - max_exp - 1)>>lin_step_log; }
+public:
+ 	GCFreeListFinder();
+
+ 	static inline bool		isMmaped(size_t n) { return n>max_lin; }
+
+ 	inline GCFreeList *find(size_t n) {
+ 		return isMmaped(n) ? &mmap_list : (n>max_exp) ? lin_lists + linEntry(n) : exp_lists[n]; 
+ 	}
+};
+
+class GCAllocator {
+ 	static const unsigned int		used_headers_nbb = (PAGE_SIZE + (4096*sizeof(GCChunkNode)) - 1) & -PAGE_SIZE;
+
+	size_t    my_size;
+ 	GCFreeListFinder	undefined_finder;
+ 	GCFreeListFinder	zero_filled_finder;
+
+	GCMappedArea		normal_area;    /* area pour les petit chunk */
+	GCMappedArea		mapped_area;    /* pour les gros */
+	GCMappedArea		headers_area;   /* liste des mmap des headers */
+	GCChunkNode		  *used_headers;  /* une liste de headers pour les prochaines alloc_list */
+	GCChunkNode		  *max_headers;   /* la limite */
+
+	GCChunkNode     *alloc_headers(size_t, void *, size_t, size_t);
+	GCChunkNode     *alloc_list(GCFreeList *, size_t);
+public:
+	GCAllocator();
+ 	~GCAllocator();
+
+	void *operator new(size_t);
+	void operator delete(void *);
+
+ 	inline GCPage        *o2page(void *ptr) { return GCHash::get(ptr); }
+
+ 	inline GCChunkNode *alloc_chunk(size_t n, bool isCol, unsigned int m) {
+		GCFreeList			     *fl = undefined_finder.find(n);
+		register GCChunkNode *res = fl->list();
+		
+		if(!res)
+			res = alloc_list(fl, n);
+		
+		fl->list(res->next());
+		res->nbb(n, isCol, m);
+
+		return res;
+ 	}
+	
+ 	inline void reject_chunk(GCPage *page, GCChunkNode *header) {
+ 		GCFreeList *fl = undefined_finder.find(page->chunk_nbb());
+		
+ 		if(fl->chunk_nbb()) {
+			//			printf("0 Filled %p with %d bytes\n", header->chunk(), header->nbb());
+			memset(header->chunk(), 0, header->nbb());
+			header->free();
+ 			fl->reject(header);
+		} else {
+			GCHash::hash_unprotected(page, page->area(), page->nbb(), 0);
+			page->reject();
+			delete (GCPage *)(page->munmap());
+ 		}
+ 	}
+	
+ 	inline void reject_chunk(GCChunkNode *header) {
+ 		reject_chunk(o2page(header->chunk()), header);
+ 	}
+	
+ 	inline GCChunkNode *stupid_realloc_chunk(GCChunkNode *old_header, size_t new_nbb) {
+ 		GCChunkNode *new_header = alloc_chunk(new_nbb, old_header->isCollectable(), old_header->mark());
+ 		size_t old = old_header->nbb();
+ 		size_t nbb = old < new_nbb ? old : new_nbb;
+ 		memcpy(new_header->chunk(), old_header->chunk(), nbb);
+ 		return new_header;
+ 	}
+	
+ 	inline GCChunkNode *realloc_chunk(GCPage *page, GCChunkNode *old_header, size_t new_nbb) {
+ 		GCChunkNode *new_header = old_header;
+ 		size_t	     max_nbb = page->chunk_nbb();
+		
+ 		if(GCFreeListFinder::isMmaped(max_nbb))
+ 			if(GCFreeListFinder::isMmaped(new_nbb)) {
+ 				/* le plus compliqué, on essaye de faire un mremap d'un petit bout... */
+ 				size_t							rounded = GCMappedArea::round(new_nbb);
+				size_t              old_nbb = page->nbb();
+ 				signed int					depl = rounded - page->nbb();
+ 				if(depl)
+ 					if(page->mremap(rounded) == -1) /* perdu */
+ 						return new_header = stupid_realloc_chunk(old_header, new_nbb);
+ 					else {
+ 						if(depl > 0)
+ 							GCHash::hash_unprotected(page, (void *)((unsigned int)page->area() + old_nbb), depl, depl);
+ 						else
+ 							GCHash::hash_unprotected(page, (void *)((unsigned int)page->area() + rounded), -depl, 0);
+ 					}
+				page->chunk_nbb(rounded);
+ 				old_header->nbb(new_nbb);
+ 			} else
+ 				new_header = stupid_realloc_chunk(old_header, new_nbb);
+ 		else
+ 			if(new_nbb <= max_nbb)
+ 				old_header->nbb(new_nbb);
+ 			else
+ 				new_header = stupid_realloc_chunk(old_header, new_nbb);
+ 		return new_header;
+ 	}
+
+ 	inline void *alloc(size_t sz) { return alloc_chunk(sz, 0, 0)->chunk(); }
+	
+ 	inline void free(void *ptr) {
+ 		GCPage     	*page = o2page(ptr);
+ 		GCChunkNode	*header = page->o2node(ptr, GCChunkNode::maskNotCollectable);
+
+ 		if(!header)
+ 			gcfatal("%p isn't an object", ptr);
+		
+ 		reject_chunk(page, header);
+ 	}
+
+ 	inline void *realloc(void *ptr, size_t nbb) {
+ 		GCPage      	*page = o2page(ptr);
+ 		GCChunkNode   *header = page->o2node(ptr, GCChunkNode::maskNotCollectable);
+		
+ 		if(!header)
+ 			gcfatal("%p isn't an object", header);
+		
+ 		register GCChunkNode *new_header = realloc_chunk(page, header, nbb);
+ 		if(new_header != header)
+ 			reject_chunk(page, header);
+
+ 		return new_header->chunk();
+ 	}
+};
+
+#endif
diff --git a/vmkit/lib/Mvm/Allocator/gcchunk.cc b/vmkit/lib/Mvm/Allocator/gcchunk.cc
new file mode 100644
index 0000000..1fd960a
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcchunk.cc
@@ -0,0 +1,114 @@
+//===---------------- gcchunk.cc - Mvm allocator --------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gcchunk.h"
+
+
+GCHashSet		  	*GCHash::sets[GCHashConst::nb_set_per_hash];
+unsigned int  	GCHash::used[GCHashConst::nb_set_per_hash];
+GCHashSet       GCHash::empty;
+bool            GCHash::inited = 0;
+size_t          GCHash::nb_link = 0;
+
+GCChunkNode     GCPage::empty;
+
+GCPage          GCHashSet::empty;
+
+void GCHashSet::hash(GCPage *d, void *base, size_t nbb, size_t nbb_map, unsigned int *c) {
+ 	register unsigned int entry = GCHashConst::desc_entry(base);
+ 	register unsigned int pbase = entry << PAGE_SHIFT;
+ 	register unsigned int top_del = (pbase + nbb) >> PAGE_SHIFT;
+ 	register unsigned int top_add = (pbase + nbb_map) >> PAGE_SHIFT;
+
+	//	printf("   %p Hash from %d to %d and to %d\n", this, entry, top_add, top_del);
+ 	for(; entry<top_add; entry++) {
+ 		pages[entry] = d;
+ 		(*c)++;
+ 	}
+ 	for(; entry<top_del; entry++) {
+ 		pages[entry] = &empty;
+ 		(*c)--;
+ 	}
+}
+
+void GCHash::hash_unprotected(GCPage *desc, void *base, unsigned int nbb, unsigned int nbb_map) {
+ 	unsigned int	entry = GCHashConst::set_entry(base);
+ 	unsigned int	cur_sz = GCHashConst::set_entry_2_ptr(entry + 1) - (unsigned int)base;	/* taille restante */
+ 	cur_sz = ((cur_sz < nbb) ? cur_sz : nbb);													/* on prends le min avec nbb   */
+	
+	//	printf("Hash %p (%p %p %d) in entry %d with %d/%d\n", desc, desc->area(), base, desc->nbb(), entry, cur_sz, nbb_map);
+	while(cur_sz) {
+		if(sets[entry] == &empty)
+			sets[entry] = new GCHashSet();
+		
+		sets[entry]->hash(desc, base, cur_sz, (nbb_map > cur_sz) ? cur_sz : nbb_map, used + entry);
+		
+		if(!used[entry]) {
+			delete sets[entry];
+			sets[entry] = &empty;
+		}
+		entry++;
+		base = (void *)((unsigned int)base + cur_sz);
+		nbb -= cur_sz;
+		nbb_map = (nbb_map < cur_sz) ? 0 : nbb_map - cur_sz;
+		cur_sz = (nbb < GCHashConst::set_nbb) ? nbb : GCHashConst::set_nbb;
+	}
+}
+
+void GCPage::initialise() {
+ 	empty.initialise(0, 0);
+}
+
+GCHashSet::GCHashSet() {
+ 	unsigned int i;
+	
+ 	for(i=0; i<GCHashConst::nb_desc_per_set; i++)
+ 		pages[i] = &empty;
+}
+
+void GCHash::initialise() {
+	if(!inited) {
+		inited = 1;
+		GCMinAlloc::initialise();
+		
+		unsigned int i;
+		
+		for(i=0; i<GCHashConst::nb_set_per_hash; i++) {
+			sets[i] = &empty;
+			used[i] = 0;
+		}
+		GCPage::initialise();
+	}
+	nb_link++;
+}
+
+void GCHash::destroy() {
+	if(inited) {
+		if(nb_link)
+			gcwarning("Can't destroy GC hash map: you have clients connected on it\n");
+		else {
+			inited = 0;
+			unsigned int i;
+	
+			for(i=0; i<GCHashConst::nb_set_per_hash; i++)
+				if(sets[i] != &empty)
+					delete sets[i];
+
+			GCMinAlloc::destroy();
+		}
+	}
+}
+
+void *GCHashSet::operator new(size_t sz) {
+	return (void *)GCMappedArea::do_mmap(sz);
+}
+
+void GCHashSet::operator delete(void *ptr, size_t sz) {
+	GCMappedArea::do_munmap(ptr, sz);
+}
diff --git a/vmkit/lib/Mvm/Allocator/gcchunk.h b/vmkit/lib/Mvm/Allocator/gcchunk.h
new file mode 100644
index 0000000..dabb03b
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcchunk.h
@@ -0,0 +1,201 @@
+//===---------------- gcchunk.h - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GC_CHUNK_H_
+#define _GC_CHUNK_H_
+
+#include "gcmapper.h"
+
+class gc;        /* object collectable */
+class gc_header; /* entete locale */
+
+/* description d'un bout de mémoire */
+class GCChunkNode {
+ 	GCChunkNode *_prev;     /* bit 0-1: l'age, les autres: le previous */
+ 	GCChunkNode	*_next;
+ 	void *       _chunk;
+ 	size_t			 _nbb_mark;	/* nbb = 0 <=> ce chunk est libre */
+	                        /* bit 0-2: la marque */
+	                        /* bit 3: est-on collectable */
+
+public:
+ 	static const signed int maskCollectable    = 8;
+ 	static const signed int maskNotCollectable = 0;
+
+ 	inline GCChunkNode() {}
+ 	inline ~GCChunkNode() {}
+
+ 	inline gc_header	 *	chunk()                { return (gc_header *)_chunk; }
+
+ 	inline GCChunkNode *	next()                 { return _next; }
+ 	inline void						next(GCChunkNode *n)   { _next = n; }
+
+ 	inline GCChunkNode *	prev()                 { return _prev; }
+ 	inline GCChunkNode *  prev(GCChunkNode *p)   { return _prev = p; }
+
+ 	inline void						free() { _nbb_mark = 0; }
+
+ 	inline void						nbb(size_t n, bool isCol, int m) { _nbb_mark = (n << 4) | ((isCol & 0x1) << 3) | m; }
+ 	inline void						nbb(size_t n)					        	 { _nbb_mark = (n << 4) | (_nbb_mark & 0xf); }
+ 	inline size_t					nbb()                            { return _nbb_mark >> 4; }
+
+	/* pas de verification de debordement!!!! */
+ 	inline void						_mark(unsigned int m)             { _nbb_mark = m | (_nbb_mark & -8); }
+ 	inline unsigned int		mark()                           { return _nbb_mark & 7; }
+
+ 	inline signed int      isCollectable() { return _nbb_mark & 8; }
+
+ 	inline void initialise(GCChunkNode *n, void *c) {
+ 		_chunk = c;
+ 		_next = n;
+ 		_nbb_mark = 0;
+ 	}
+
+	/* pour faire une amorce de liste */
+ 	inline void alone() { _prev = _next = this; }
+
+	/* ajoute this à p */
+ 	inline void append(GCChunkNode *p) {
+ 		_prev = p;
+ 		_next = p->_next;
+ 		p->_next = this;
+ 		_next->_prev = this;
+ 	}
+
+	/* enleve this de sa liste */
+ 	inline void remove() {
+ 		_next->_prev = _prev;
+ 		_prev->_next = _next;
+ 	}
+
+	/* place la liste de p dans this. Ecrase celle de p */
+	inline void attrape(GCChunkNode *l)	{
+		if(l == l->_next)
+			alone();
+		else {
+			(_next = l->_next)->_prev = this;
+			(_prev = l->_prev)->_next = this;
+			l->alone();
+		}
+	}
+
+	/* ajoute la liste de l dans this */
+ 	inline void eat(GCChunkNode *l) {
+ 		if(l != l->_next) {
+ 			(_next->_prev = l->_prev)->_next = _next;
+ 			(_next = l->_next)->_prev = this;
+ 			l->alone();
+ 		}
+ 	}
+};
+
+/* entete de description de zone mémoire */
+/* une zone est un ensemble de bouts de mémoire de même taille, contigues, aligné sur des pages */
+class GCPage : public GCMappedArea {
+ 	static GCChunkNode empty;
+
+ 	GCChunkNode	*_headers;
+ 	size_t			 _chunk_nbb;
+public:
+ 	static void initialise();
+
+ 	inline GCPage() {
+ 		GCMappedArea::initialise(0, 0);
+ 		_headers = &empty;
+ 		_chunk_nbb = ((unsigned int)-1) >> 1;		/* on évite le /0 */
+ 	}
+
+ 	inline GCPage(GCMappedArea *p, size_t mapped_nbb, size_t cnbb)
+ 		: GCMappedArea(p, mapped_nbb) {
+ 		_chunk_nbb = cnbb;
+ 	}
+
+ 	inline ~GCPage() {}     /* FAIRE LE UNMAP A LA MAIN!!!!! */
+
+ 	inline size_t					chunk_nbb()		        { return _chunk_nbb; }
+ 	inline void 					chunk_nbb(size_t n)		{ _chunk_nbb = n; }
+ 	inline GCChunkNode   *headers()			        { return _headers; }
+ 	inline void headers(GCChunkNode *h)         { _headers = h;; }
+
+ 	inline GCChunkNode *o2node(void *ptr, signed int mask) {
+ 		register unsigned int entry = ((unsigned int)ptr - (unsigned int)area())/_chunk_nbb;
+ 		register GCChunkNode *res = _headers + entry;
+ 		return ((unsigned int)ptr - (unsigned int)res->chunk() < res->nbb())
+ 			&& (res->isCollectable() == mask)
+ 			? res : 0;
+ 	}
+	
+ 	inline gc_header *o2header(void *ptr, signed int mask) {
+ 		register unsigned int entry = ((unsigned int)ptr - (unsigned int)area())/_chunk_nbb;
+ 		register GCChunkNode *res = _headers + entry;
+ 		return ((unsigned int)ptr - (unsigned int)res->chunk() < res->nbb())
+ 			&& (res->isCollectable() == mask)
+ 			? res->chunk() : 0;
+ 	}
+};
+
+class GCDescriptorMappedChunk : public GCPage {
+	GCChunkNode	header;
+public:
+	inline GCDescriptorMappedChunk(GCMappedArea *p, size_t mapped_nbb, size_t cnbb) 
+		: GCPage(p, mapped_nbb, cnbb) {
+		header.initialise(0, area());
+		headers(&header);
+	}
+};
+
+class GCHashConst {
+public:
+ 	static const unsigned int		desc_bits = PAGE_SHIFT;
+ 	static const unsigned int		set_bits = 10;
+ 	static const unsigned int		hash_bits = (32 - set_bits - desc_bits);
+ 	static const unsigned int		nb_desc_per_set = 1 << set_bits;
+ 	static const unsigned int		nb_set_per_hash = 1 << hash_bits;
+ 	static const unsigned int		set_nbb = 1 << (set_bits + desc_bits);
+
+ 	static unsigned int	desc_entry(void * ptr) { return ((unsigned int)ptr >> desc_bits) & (( 1 << set_bits) - 1); }
+ 	static unsigned int	set_entry(void *ptr) { return (unsigned int)ptr >> (set_bits + desc_bits); }
+ 	static unsigned int	set_entry_2_ptr(unsigned int entry) { return entry << (set_bits + desc_bits); }
+};
+
+class GCHashSet {
+ 	static GCPage empty;
+
+ 	GCPage		*pages[GCHashConst::nb_desc_per_set];
+public:
+ 	void *operator new(size_t);
+ 	void operator delete(void *, size_t);
+	
+ 	GCHashSet();
+
+ 	void hash(GCPage *, void *, size_t, size_t, unsigned int *);
+
+ 	inline GCPage *get(void *ptr) { return pages[GCHashConst::desc_entry(ptr)]; }
+};
+
+class GCHash {
+ 	static GCHashSet			*sets[GCHashConst::nb_set_per_hash];
+ 	static unsigned int		used[GCHashConst::nb_set_per_hash];
+ 	static GCHashSet	    empty;
+	static bool           inited;
+	static size_t         nb_link;
+
+public:
+	static void unlink() { nb_link--; }
+ 	static void initialise();
+ 	static void destroy();
+
+ 	static void hash_unprotected(GCPage *p, void *base, unsigned int nbb, unsigned int nbb_map);
+ 	//void hash(GCPage *p) { hash(p, p->area(), p->nbb(), p->nbb()); }
+ 	//void unhash(GCPage *p) { hash(p, p->area(), p->nbb(), 0); }
+
+ 	static inline GCPage *get(void *ptr) { return sets[GCHashConst::set_entry(ptr)]->get(ptr); }
+};
+
+#endif
diff --git a/vmkit/lib/Mvm/Allocator/gcerror.cc b/vmkit/lib/Mvm/Allocator/gcerror.cc
new file mode 100644
index 0000000..56a7635
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcerror.cc
@@ -0,0 +1,36 @@
+//===--------------- gcerror.cc - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gcerror.h"
+#include <stdarg.h>
+#include "osdep.h"
+
+static void __gcfatal(const char *file, unsigned int l, const char *func, const char *msg, ...)
+{
+  va_list va;
+  va_start(va, msg);
+  fprintf(stderr, "GC[error] in %s line %d (function %s)\n", file, l, func);
+  vfprintf(stderr, msg, va);
+  fprintf(stderr, "\n");
+  va_end(va);
+  exit(0);
+}
+
+static void _on_fatal() {}
+
+void (*_gcfatal)(const char *, unsigned int l, const char *, const char *, ...) = __gcfatal;
+void (*on_fatal)(void) = _on_fatal;
+
+static void _defaultOnMemoryError(unsigned int sz)
+{
+  fprintf(stderr, "GC[error] out of memory for %d bytes\n", sz);
+  exit(0);
+}
+
+void (*onMemoryError)(unsigned int) = _defaultOnMemoryError;
diff --git a/vmkit/lib/Mvm/Allocator/gcerror.h b/vmkit/lib/Mvm/Allocator/gcerror.h
new file mode 100644
index 0000000..65a345d
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcerror.h
@@ -0,0 +1,32 @@
+//===---------------- gcerror.h - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GC_ERROR_H_
+#define _GC_ERROR_H_
+
+
+extern void (*_gcfatal)(const char *, unsigned int l, const char *, const char *, ...);
+
+extern void (*on_fatal)(void);
+
+extern void (*onMemoryError)(unsigned int sz);
+
+#define gcfatal(msg, args...) do { \
+															  on_fatal(); \
+                                (*_gcfatal)(__FILE__, __LINE__, __PRETTY_FUNCTION__, msg, ##args); \
+															} while(0)
+
+#define gcwarning(msg, args...) do { \
+                                  printf("In %s (%s line %d):\n\t", __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+                                  printf(msg, ##args); \
+                                } while(0)
+
+#endif
+
+
diff --git a/vmkit/lib/Mvm/Allocator/gcmapper.cc b/vmkit/lib/Mvm/Allocator/gcmapper.cc
new file mode 100644
index 0000000..064d0ab
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcmapper.cc
@@ -0,0 +1,137 @@
+//===--------------- gcmapper.cc - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gcmapper.h"
+#include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+GCMinAllocStack GCMinAlloc::_stacks[GCMinAlloc::max_min_alloc >> log_step];
+GCMinAllocStack *GCMinAlloc::stacks[GCMinAlloc::max_min_alloc+1];
+GCMappedArea    GCMinAlloc::base_area;
+
+
+
+#if defined(__MACH__)
+#define DO_MMAP(sz)					mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)
+#else
+#define DO_MMAP(sz)					mmap(0, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0)
+#endif
+
+#define DO_MUNMAP(ptr, sz)	munmap(ptr, sz)
+
+#if defined(__MACH__)
+static inline void* manual_mremap(void * addr, int old_size, int new_size, int flags)
+{
+  void * res = addr;
+  if (new_size < old_size)
+    DO_MUNMAP((void*)((int)addr + new_size), old_size - new_size);
+  else if (new_size > old_size)
+    // Use of MAP_FIXED is discouraged...
+    // res = mmap(addr, new_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, MAP_FIXED);
+    res=(void*)-1;
+  
+  return res;
+}
+#endif
+
+static inline void *do_mmap(size_t sz) {
+	void *res = DO_MMAP(sz);
+	//printf("mmap %d bytes at %d\n", sz, res);
+	if(res == MAP_FAILED)
+		if (errno == ENOMEM)
+      (*onMemoryError)(sz);
+    else
+      {
+        gcfatal("unable to mmap %d bytes", sz);
+      }
+	return res;
+}
+
+static inline void do_munmap(void *ptr, size_t sz) {
+	//	printf("munmap %d bytes at %p\n", sz, ptr);
+	DO_MUNMAP(ptr, sz);
+}
+
+void *GCMappedArea::do_mmap(size_t sz) { return ::do_mmap(sz); }
+void GCMappedArea::do_munmap(void *ptr, size_t sz) { ::do_munmap(ptr, sz); }
+
+GCMappedArea *GCMappedArea::munmap() {
+	::do_munmap(_mapped_area, _mapped_nbb);
+	return this;
+}
+
+GCMappedArea *GCMappedArea::mmap(size_t n) {
+	_mapped_area = ::do_mmap(_mapped_nbb = n);
+	return this;
+}
+
+int GCMappedArea::mremap(size_t n) {
+#if defined(__MACH__)
+	void *res = manual_mremap(_mapped_area, _mapped_nbb, n, 0);
+#else
+	void *res = ::mremap(_mapped_area, _mapped_nbb, n, 0);
+#endif
+  
+	if((int)res == -1)
+		return -1;
+	_mapped_area = res;
+	_mapped_nbb = n;
+	return 0;
+}
+
+void *GCMinAlloc::alloc_area(GCMinAllocStack *s) {
+	GCMinAllocStack	*area_stack = stacks[sizeof(GCMappedArea)];
+	GCMappedArea		*area = (GCMappedArea *)area_stack->alloc();
+
+	if(!area) {
+		/* pbm : on n'a vraiment plus rien :) */
+		area = (GCMappedArea *)::do_mmap(PAGE_SIZE);
+		area->initialise(area, PAGE_SIZE);
+		area_stack->fill((unsigned int)(area + 1), PAGE_SIZE - sizeof(GCMappedArea));
+		area->append(&base_area);
+		area = (GCMappedArea *)area_stack->alloc();
+	}
+	area->mmap(PAGE_SIZE);
+	area->append(&base_area);
+	s->fill((unsigned int)area->area(), area->nbb());
+
+	return s->alloc();
+}
+
+void GCMinAlloc::initialise() {
+	unsigned int i, j, m;
+	size_t nb_stacks = max_min_alloc >> log_step;
+	
+	stacks[0] = _stacks;
+	for(i=0; i<nb_stacks; i++) {
+		m = i<<log_step;
+		_stacks[i].initialise(m + (1<<log_step));
+		for(j=0; j<(1<<log_step); j++)
+			stacks[m+j+1] = _stacks + i;
+	}
+}
+
+void GCMinAlloc::destroy() {
+ 	unsigned int nb_area, i;
+ 	GCMappedArea *cur;
+
+ 	for(nb_area=0, cur=base_area.next(); cur!=&base_area; cur=cur->next(), nb_area++);
+
+ 	GCMappedArea	areas[nb_area];
+
+ 	for(i=0, cur=base_area.next(); cur!=&base_area; cur=cur->next(), i++)
+ 		areas[i] = *cur;
+
+ 	for(i=0; i<nb_area; i++)
+ 		areas[i].munmap();
+}
diff --git a/vmkit/lib/Mvm/Allocator/gcmapper.h b/vmkit/lib/Mvm/Allocator/gcmapper.h
new file mode 100644
index 0000000..bd9174b
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/gcmapper.h
@@ -0,0 +1,146 @@
+//===--------------- gcmapper.h - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GC_MAPPER_H_
+#define _GC_MAPPER_H_
+
+#include "gcerror.h"
+#include "osdep.h"
+
+class GCMinAlloc;
+
+class GCMin {
+public:
+	inline GCMin() {}
+	inline ~GCMin() {}
+	inline void *operator new(size_t);
+	inline void operator delete(void *, size_t);
+};
+
+class GCMappedArea : public GCMin {
+ 	GCMappedArea	*_prev;
+ 	GCMappedArea	*_next;
+ 	void					*_mapped_area;
+ 	size_t				_mapped_nbb;
+
+public:
+ 	static size_t round(size_t n) { return (n + PAGE_SIZE - 1) & -PAGE_SIZE; }
+
+ 	GCMappedArea	*prev() { return _prev; }
+ 	GCMappedArea	*next() { return _next; }
+	
+ 	inline GCMappedArea() { _prev = _next = this; }
+ 	inline GCMappedArea(size_t n) { _prev = _next = this; mmap(n); }
+ 	inline GCMappedArea(GCMappedArea *p, size_t n) { append(p); mmap(n); }
+
+ 	inline void		initialise(void *p, size_t n) { _mapped_area = p; _mapped_nbb = n; }
+ 	inline size_t nbb() const { return _mapped_nbb; }
+ 	inline void		*area() { return _mapped_area; }
+
+ 	inline void append(GCMappedArea *p) {
+ 		_prev = p;
+ 		_next = p->_next;
+ 		p->_next = this;
+ 		_next->_prev = this;
+ 	}
+
+ 	inline void reject() {
+ 		_prev->_next = _next;
+ 		_next->_prev = _prev;
+ 	}
+	
+ 	GCMappedArea *	munmap();
+ 	GCMappedArea *	mmap(size_t sz);
+ 	int							mremap(size_t sz);
+	
+ 	static void *do_mmap(size_t sz);
+ 	static void  do_munmap(void *, size_t sz);
+};
+
+class GCMinAllocStack {
+ 	unsigned int		current;
+ 	unsigned int		max;
+ 	unsigned int		*free_list;
+ 	unsigned short	nbb;
+	
+public:
+ 	inline void initialise(size_t n) { nbb = n; current = max = 0; free_list = 0; }
+
+	inline void fill(unsigned int st, size_t n) {
+		current = st;
+		max = st + n;
+	}
+	
+ 	inline void inject_free(void *ptr) {
+ 		*((unsigned int **)ptr) = free_list;
+ 		free_list = (unsigned int *)ptr;
+ 	}
+
+ 	inline void *alloc() {
+ 		register unsigned int res;
+ 		if(free_list) {
+ 			res = (unsigned int)free_list;
+ 			free_list = *((unsigned int **)res);
+ 		} else {
+ 			res = current;
+ 			current += nbb;
+ 			if(current > max)
+ 				return 0;
+ 		}
+		
+ 		return (void *)res;
+ 	}
+};
+
+class GCMinAlloc {
+ 	static const size_t	log_max_min_alloc = 6;											/* 64 octets */
+ 	static const size_t	max_min_alloc = (1 << log_max_min_alloc);
+ 	static const size_t log_step = 2;
+	
+ 	/* piles d'allocations */
+ 	static GCMinAllocStack			_stacks[max_min_alloc >> log_step];
+ 	static GCMinAllocStack			*stacks[max_min_alloc+1];
+
+	static GCMappedArea         base_area;
+
+ 	static void *alloc_area(GCMinAllocStack *s);
+
+	inline GCMinAlloc() {} /* pas d'instance de ce truc */
+public:
+	static void initialise();
+	static void destroy();
+	
+ 	static inline void *minalloc(size_t);
+ 	static inline void minfree(void *, size_t);
+};
+
+inline void *GCMinAlloc::minalloc(size_t nbb) {
+ 	GCMinAllocStack *s = stacks[nbb];
+ 	void *res = s->alloc();
+
+ 	if(!res)
+ 		res = alloc_area(s);
+ 	return res;
+}
+
+inline void GCMinAlloc::minfree(void *ptr, size_t nbb) {
+ 	stacks[nbb]->inject_free(ptr);
+}
+
+inline void *GCMin::operator new(size_t nbb) { 
+ 	return GCMinAlloc::minalloc(nbb);
+}
+
+inline void GCMin::operator delete(void *ptr, size_t nbb) { 
+	GCMinAlloc::minfree(ptr, nbb);
+}
+
+
+
+#endif
diff --git a/vmkit/lib/Mvm/Allocator/main.cc b/vmkit/lib/Mvm/Allocator/main.cc
new file mode 100644
index 0000000..fc469f5
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/main.cc
@@ -0,0 +1,123 @@
+//===------------------ main.cc - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gcalloc.h"
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sys/time.h>
+
+unsigned int rand(unsigned int min, unsigned int max) {
+	return (unsigned int)nearbyint((((double)(max - min))*::rand())/(RAND_MAX + 1.0)) + min;
+}
+
+void tire(size_t n, size_t *vals, size_t *reallocs, size_t *frees) {
+	for(size_t i=0; i<n; i++) {
+		if(rand(0, 20))
+			vals[i] = rand(1, 256);
+		else
+			vals[i] = rand(256, 65536);
+		if(!rand(0, 10)) /* un chance sur 10 de réallouer */
+			if(rand(0, 20))
+				reallocs[i] = rand(1, 256);
+			else
+				reallocs[i] = rand(256, 65536);
+		else
+			reallocs[i] = 0;
+		if(rand(0, 10)) /* un chance sur 10 de ne pas libérer */
+			frees[i] = 1;
+		else
+			frees[i] = 0;
+	}
+}
+
+void printMesure(size_t n, size_t *vals, size_t *reallocs, size_t *frees, struct timeval *start, struct timeval *end) {
+	size_t   totAllocated = 0;
+	size_t   curAllocated = 0;
+	size_t   na = 0;
+	size_t   nr = 0;
+	size_t   nf = 0;
+	size_t   no = 0;
+
+	for(size_t i=0; i<n; i++) {
+		size_t here = vals[i] + reallocs[i];
+		if(reallocs[i]) {
+			na++;
+			nr++;
+		}
+		na++;
+		totAllocated += here;
+		if(!frees[i]) {
+			curAllocated += here;
+			no++;
+		} else
+			nf++;
+	}
+
+	printf("; %d allocations (%d reallocations, %d free, %d chunks)\n", na, nr, nf, no);
+	printf(";   Allocated: %d bytes, current %d bytes\n", totAllocated, curAllocated);
+	
+	struct timeval diff;
+	timersub(end, start, &diff);
+	double f = (double)diff.tv_sec + ((double)diff.tv_usec / 1000000.0);
+	printf(";   time consumed: %fs\n", f);
+}
+
+void mesureAllocateur() {
+	size_t n = 512*1024;
+	size_t vals[n];
+	size_t reallocs[n];
+	size_t frees[n];
+
+	printf("Tire une sequence d'allocations alléatoire\n");
+	tire(n, vals, reallocs, frees);
+
+	printf("test\n");
+	struct timeval start;
+	struct timeval end;
+	GCAllocator *a = new GCAllocator();
+
+	gettimeofday(&start, 0);
+	for(size_t i=0; i<n; i++) {
+		void *p = a->alloc(vals[i]);
+		if(reallocs[i])
+			p = a->realloc(p, reallocs[i]);
+		if(frees[i])
+			a->free(p);
+	}
+	gettimeofday(&end, 0);
+	delete a;
+
+	printMesure(n, vals, reallocs, frees, &start, &end);
+	printf("Press a key...\n");
+	getchar();
+
+	gettimeofday(&start, 0);
+	for(size_t i=0; i<n; i++) {
+		void *p = malloc(vals[i]);
+		((char *)p)[0] = 1;
+		if(reallocs[i])
+			p = realloc(p, reallocs[i]);
+		if(frees[i])
+			free(p);
+	}
+	gettimeofday(&end, 0);
+	printMesure(n, vals, reallocs, frees, &start, &end);
+	printf("Press a key...\n");
+	getchar();
+
+}
+
+int main(int argc, char **argv) {
+	mesureAllocateur();
+
+	GCHash::destroy();
+	return 0;
+}
diff --git a/vmkit/lib/Mvm/Allocator/osdep.h b/vmkit/lib/Mvm/Allocator/osdep.h
new file mode 100644
index 0000000..0047e81
--- /dev/null
+++ b/vmkit/lib/Mvm/Allocator/osdep.h
@@ -0,0 +1,40 @@
+//===------------------ osdep.h - Mvm allocator ---------------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __OSDEP_H_
+#define __OSDEP_H_
+
+#include <sys/types.h>
+#include <stdarg.h>
+
+/* sys/pages.h ?? */
+#define PAGE_SHIFT		12
+#define PAGE_SIZE			(1 << PAGE_SHIFT)
+
+/* stdio.h */
+#include <stdio.h>
+
+__BEGIN_DECLS
+
+/* stdio.h */
+extern int   printf(const char *, ...);
+extern int   fprintf(FILE *, const char *, ...);
+extern int   vfprintf(FILE *, const char *, va_list);
+
+
+/* stdlib.h */
+extern void exit(int) throw ();
+
+/* string.h */
+extern void *memcpy(void *, const void *, size_t) throw ();
+//extern void  bzero(void *, size_t);
+
+__END_DECLS
+
+#endif
diff --git a/vmkit/lib/Mvm/CommandLine.cpp b/vmkit/lib/Mvm/CommandLine.cpp
new file mode 100644
index 0000000..f9a61c7
--- /dev/null
+++ b/vmkit/lib/Mvm/CommandLine.cpp
@@ -0,0 +1,157 @@
+//===------- CommandLine.cpp - Parses the command line --------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include "CommandLine.h"
+#include "mvm/GC/GC.h"
+#include "mvm/Threads/Thread.h"
+
+using namespace mvm;
+
+typedef struct thread_arg_t {
+  int argc;
+  char** argv;
+  vmlet_main_t func;
+};
+
+typedef int (*boot_t)();
+
+
+CommandLine::CommandLine() {
+  resetString();
+  resetArgv();
+}
+
+void CommandLine::appendChar(char c) {
+  assert(_yytext);
+  _yytext[_yylen++]= c;
+  if (_yylen == _yylenMax) {
+    _yylenMax *= 2;
+    _yytext= (char *)realloc(_yytext, _yylenMax);
+  }
+}
+
+void CommandLine::appendString(char* str) {
+  assert(argv);
+  appendChar(0);
+  argv[argc++] = str;
+  if (argc == argcMax) {
+    argcMax *= 2;
+    argv = (char **)realloc(argv, argcMax * sizeof(char*));
+  }
+}
+
+void CommandLine::resetString() {
+  _yytext = (char *)malloc(_yylenMax= 32);
+  _yylen = 0;
+}
+
+void CommandLine::resetArgv() {
+  argv = (char **)malloc(sizeof(char*) * (argcMax= 10));
+  argc = 0;
+}
+
+
+void CommandLine::start() {
+  printf("> ");
+  _yyChar = getc(stdin);
+  
+  while (true) {
+    switch(_yyChar) {
+      case ' ' : 
+        do { _yyChar = getc(stdin); } while (_yyChar == ' ');
+        if (_yylen != 0) {
+          appendString(_yytext);
+          resetString();
+        }
+        break;
+      
+      case '\n' :
+        if (_yylen != 0) {
+          appendString(_yytext);
+          resetString();
+        }
+        if (argc > 1) {
+          executeInstr();
+          resetArgv();
+          printf("> ");
+        }
+        _yyChar = getc(stdin);
+        break;
+
+      case EOF :
+        printf("\n");
+        return;
+
+      default :
+        appendChar(_yyChar);
+        _yyChar = getc(stdin);
+    }
+  } 
+}
+
+extern "C" int startApp(thread_arg_t* arg) {
+  int argc = arg->argc;
+  char** argv = arg->argv;
+  vmlet_main_t func = arg->func;
+  free(arg);
+  gc::inject_my_thread(&argc);
+  func(argc, argv);
+  gc::remove_my_thread();
+  gc::collect();
+  return 0;
+}
+
+void CommandLine::executeInstr() {
+  if (!strcmp(argv[0], "load")) {
+    char* buf = (char*)alloca(sizeof(argv[1]) + 7);
+    sprintf(buf, "lib%s.so", argv[1]);
+    void* handle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
+    if (handle == 0) {
+      fprintf(stderr, "\t Unable to load %s\n", argv[1]);
+      printf("\t error = %s\n", dlerror());
+      return;
+    }
+    
+    boot_t func = (boot_t)dlsym(handle, "boot");
+    
+    if (func == 0) {
+      fprintf(stderr, "\t Unable to find %s boot method\n", argv[1]);
+      dlclose(handle);
+      return;
+    }
+    func();
+    
+    vmlet_main_t vmlet = (vmlet_main_t)dlsym(handle, "start_app");
+
+    vmlets[argv[1]] = vmlet;
+
+  } else {
+    vmlet_main_t func = vmlets[argv[0]];
+    if (!func) {
+      fprintf(stderr, "\t Unknown vmlet %s\n", argv[0]);
+    } else {
+#if 0
+      thread_arg_t* thread_arg = (thread_arg_t*)malloc(sizeof (thread_arg_t));
+      thread_arg->argc = argc;
+      thread_arg->argv = argv;
+      thread_arg->func = func;
+      int tid = 0;
+      Thread::start(&tid, (int (*)(void *))startApp, thread_arg);
+#else
+      func(argc, argv);
+      gc::collect();
+#endif
+    }
+  }
+}
diff --git a/vmkit/lib/Mvm/CommandLine.h b/vmkit/lib/Mvm/CommandLine.h
new file mode 100644
index 0000000..e6915a3
--- /dev/null
+++ b/vmkit/lib/Mvm/CommandLine.h
@@ -0,0 +1,57 @@
+//===--------- CommandLine.h - Parses the command line --------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef COMMAND_LINE_H
+#define COMMAND_LINE_H
+
+#include <map>
+
+#include <string.h>
+
+namespace mvm {
+
+typedef int (*vmlet_main_t)(int argc, char** argv);
+
+struct ltstr
+{
+  bool operator()(const char* s1, const char* s2) const
+  {
+    return strcmp(s1, s2) < 0;
+  }
+};
+
+class CommandLine {
+public:
+  char** argv;
+  unsigned argc;
+  unsigned argcMax;
+
+  char* _yytext;
+  unsigned _yylen;
+  unsigned _yylenMax;
+  char _yyChar;
+  
+  std::map<const char*, vmlet_main_t, ltstr> vmlets;
+
+  CommandLine();
+  
+  void appendChar(char c);
+  void appendString(char* str);
+
+  void start();
+  void executeInstr();
+
+  void resetArgv();
+  void resetString();
+
+};
+
+} // end namespace mvm
+
+#endif // COMMAND_LINE_H
diff --git a/vmkit/lib/Mvm/CommonThread/Makefile.am b/vmkit/lib/Mvm/CommonThread/Makefile.am
new file mode 100644
index 0000000..820de4a
--- /dev/null
+++ b/vmkit/lib/Mvm/CommonThread/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LIBRARIES = libuvm_common_thread.a
+
+GCDIR = ../GCMmap2
+GCLIBS = $(GCDIR)/libuvm_gc_mmap2.a
+ALLOCDIR = ../Allocator
+ALLOCLIBS = $(ALLOCDIR)/libuvm_alloc.a
+
+libuvm_common_thread_a_SOURCES = cterror.h ctthread.cc cterror.cc ctlock.cc
+libuvm_common_thread_a_CXXFLAGS = -frepo -O2
+
+CLEANFILES = *~ *.bak .*.sw?
diff --git a/vmkit/lib/Mvm/CommonThread/cterror.cc b/vmkit/lib/Mvm/CommonThread/cterror.cc
new file mode 100644
index 0000000..c2ca384
--- /dev/null
+++ b/vmkit/lib/Mvm/CommonThread/cterror.cc
@@ -0,0 +1,35 @@
+//===-------------- cterror.cc - Mvm common threads -----------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "cterror.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+void (*pgcdomsgf)(const char *, unsigned int l, const char *, const char *, ...) = _gcdomsgf;
+void (**gcdomsgf)(const char *, unsigned int l, const char *, const char *, ...)	= &pgcdomsgf;
+
+const char *ctperror() {
+	return strerror(errno);
+}
+
+void _gcdomsgf(const char *file, unsigned int l, const char *func, const char *msg, ...)
+{
+  va_list va;
+  va_start(va, msg);
+  fprintf(stderr, "GC[error] in %s line %d (function %s)\n", file, l, func);
+  vfprintf(stderr, msg, va);
+  fprintf(stderr, "\n");
+  va_end(va);
+  exit(0);
+}
+
+
diff --git a/vmkit/lib/Mvm/CommonThread/cterror.h b/vmkit/lib/Mvm/CommonThread/cterror.h
new file mode 100644
index 0000000..ffc0f84
--- /dev/null
+++ b/vmkit/lib/Mvm/CommonThread/cterror.h
@@ -0,0 +1,22 @@
+//===---------------- cterror.h - Mvm common threads ----------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _CT_ERROR_H_
+#define _CT_ERROR_H_
+
+extern const char *ctperror();
+extern void	_gcdomsgf(const char *file, unsigned int l, const char *func, const char *msg, ...);
+extern void (*pgcdomsgf)(const char *, unsigned int l, const char *, const char *, ...);
+extern void (**gcdomsgf)(const char *, unsigned int l, const char *, const char *, ...);
+
+#define ctfatal(msg, args...) (*gcdomsgf)(__FILE__, __LINE__, __PRETTY_FUNCTION__, msg, ##args)
+
+#endif
+
+
diff --git a/vmkit/lib/Mvm/CommonThread/ctlock.cc b/vmkit/lib/Mvm/CommonThread/ctlock.cc
new file mode 100644
index 0000000..133e34c
--- /dev/null
+++ b/vmkit/lib/Mvm/CommonThread/ctlock.cc
@@ -0,0 +1,237 @@
+//===--- ctlock.cc - Common threads implementation of locks ---------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Thread.h"
+#include "cterror.h"
+#include <sys/time.h>
+
+
+using namespace mvm;
+
+inline int atomic_test_and_pass(unsigned int *ptr) {
+
+#if defined(__ppc__) || defined(__powerpc__)
+  int result;
+# if defined(__MACH__)
+  const int val=1;
+
+  asm volatile("1:\n"
+#if 0
+      "  lwz    %0,0(%1)\n"  /* result <- ptr[0] */
+      "  cmpwi  %0,0\n"
+      "  bne    1b\n"
+#endif
+      "  lwarx  %0,0,%1\n"   /* result <- ptr[0] */
+      "  cmpwi  %0,0\n"
+      "  bne    1b\n"
+      "  stwcx. %2,0,%1\n"  /* ptr[0] <- 1 (si pas d'autre accès) */
+      "  bne-   1b\n"
+      "  isync\n"           /* empeche toute execution d'instruction après le lock!!! */
+      :"=&r"(result): "r"(ptr), "r"(val): "cr0", "memory");
+  /* le & empeche gcc d'utiliser le même register pour result et les entrées... */
+# else
+  const int val=1;
+
+  asm volatile("1:\n"
+      "  lwarx  %0,0,%1\n"   /* result <- ptr[0] */
+      "  cmpwi  %0,0\n"
+      "  bne    1b\n"
+      "  stwcx. %2,0,%1\n"  /* ptr[0] <- 1 (si pas d'autre accès) */
+      "  bne-   1b\n"
+      "  isync\n"           /* empeche toute execution d'instruction après le lock!!! */
+      :"=&r"(result): "r"(ptr), "r"(val): "cr0", "memory");
+  /* le & empeche gcc d'utiliser le même register pour result et les entrées... */
+# endif
+
+  return result;
+#else
+	// asm ("bts $1, %1; sbbl %0, %0":"=r" (result):"m" (*ptr):"memory");
+	unsigned int old;
+	int c=0;
+	do {
+		asm volatile("movl   $1,%0;"
+								 "xchgl  %0, %1" : "=&r"(old) : "m"(*ptr));
+		if(!old)
+			return 0;
+		if(!(++c & 0xf))
+			Thread::yield();
+	} while(1);
+#endif
+}
+
+Lock *Lock::allocRecursive() {
+  return new LockRecursive();
+}
+
+Lock *Lock::allocNormal() {
+  return new LockNormal();
+}
+
+void Lock::destroy(Lock *l) {
+}
+
+bool Lock::selfOwner(Lock *l) {
+  return l->owner() == Thread::self();
+}
+
+int Lock::getOwner(Lock *l) {
+  return l->owner();
+}
+
+void SpinLock::slock() {
+  atomic_test_and_pass(&value);
+}
+
+void LockNormal::my_lock(Lock *l) {
+  unsigned int c = 0;
+
+  l->slock();
+
+  while(l->owner()) {
+    l->sunlock();
+    Thread::yield(&c);
+    l->slock();
+  }
+  l->owner(Thread::self());
+  l->sunlock();
+}
+
+void LockNormal::my_unlock(Lock *l) { 
+  l->owner(0); 
+}
+
+int LockNormal::my_trylock(Lock *) {
+  ctfatal("not implemented");
+  return -1;
+}
+
+void LockRecursive::my_lock(Lock *l) {
+  unsigned int c = 0;
+
+  int self = Thread::self();
+
+  l->slock();
+  while(l->owner() && (l->owner() != self)) {
+    l->sunlock();
+    Thread::yield(&c);
+    l->slock();
+  }
+  l->owner(self);
+  ((LockRecursive *)l)->n++;
+  l->sunlock();
+}
+
+  void LockRecursive::my_unlock(Lock *l) { 
+    if(!--((LockRecursive *)l)->n)
+      l->owner(0); 
+  }
+
+int LockRecursive::my_trylock(Lock *) {
+  ctfatal("not implemented");
+  return -1;
+}
+
+int LockRecursive::recursion_count(Lock *l){
+  return ((LockRecursive*)l)->n;
+}
+
+int LockRecursive::my_unlock_all(Lock *l){
+  int count = ((LockRecursive*)l)->n;
+  ((LockRecursive*)l)->n = 0;
+  l->owner(0);
+  return count;
+}
+
+void LockRecursive::my_lock_all(Lock *l, int count){
+  LockRecursive::my_lock(l);
+  ((LockRecursive*)l)->n = count;
+}
+
+
+
+
+void Cond::wait(Lock *l) {
+  unsigned int n=0;
+  unsigned int my_barrier = no_barrier;
+
+  n_wait++;			/* un attente de plus */
+  while(1) {
+    if(no_barrier == my_barrier)			/* pas de broadcast */
+      if(go) {												/* un signal? */
+        n_wait--;											/* pus une attente en moins */
+        go--;													/* pour le pochain */
+        return;
+      } else {												/* à l'ouest rien de nouveau */
+        l->unlock();									/* je rend gentillement le lock */
+        Thread::yield(&n); 				/* j'attends qu'on me libère... */
+        l->lock();										/* je reprends mon lock */
+      }
+      else															/* on a eu un broadcast */
+        return;
+  }
+}
+
+int Cond::timed_wait(Lock *l, struct timeval *ref) {
+  unsigned int		n=0;
+  unsigned int		my_barrier = no_barrier;
+  struct timeval	max, cur;
+
+  gettimeofday(&max, 0);
+  timeradd(&max, ref, &max);
+
+  n_wait++;
+  while(1) {
+    if(no_barrier == my_barrier)			/* pas de broadcast */
+      if(go) {												/* un signal? */
+        n_wait--;											/* puis une attente en moins */
+        go--;													/* pour le pochain */
+        return 0;
+      } else {												/* à l'ouest rien de nouveau */
+        gettimeofday(&cur, 0);
+        if(timercmp(&cur, &max, >=)) {/* timesout écoulé */
+          n_wait--;										/* on n'attend plus */
+          return 1;										/* c'est nif */
+        }
+
+        l->unlock();
+        timersub(&max, &cur, &cur);		/* le reste */
+        if(!cur.tv_sec && (cur.tv_usec <= 2))
+          Thread::yield();				/* j'attends qu'on me libère... */
+        else
+          Thread::yield(&n);			/* j'attends qu'on me libère... */
+        l->lock();										/* je reprends mon lock */
+      }
+      else															/* on a eu un broadcast */
+        return 0;
+  }
+}
+
+void Cond::broadcast() {
+  no_barrier++;
+  n_wait = 0;
+}
+
+void Cond::signal() {
+  if(n_wait>go) go++;
+}
+
+
+extern "C" void lock_C(Lock* l) {
+  return l->lock();
+}
+
+extern "C" void unlock_C(Lock* l) {
+  return l->unlock();
+}
+
+Cond* Cond::allocCond() {
+  return new Cond();
+}
diff --git a/vmkit/lib/Mvm/CommonThread/ctthread.cc b/vmkit/lib/Mvm/CommonThread/ctthread.cc
new file mode 100644
index 0000000..f6e999f
--- /dev/null
+++ b/vmkit/lib/Mvm/CommonThread/ctthread.cc
@@ -0,0 +1,75 @@
+//===-------------- ctthread.cc - Mvm common threads ----------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/Threads/Key.h"
+#include "mvm/Threads/Thread.h"
+
+#include <pthread.h>
+#include <signal.h>
+#include <time.h>
+
+using namespace mvm;
+
+void Thread::yield() {
+  sched_yield();
+}
+
+int Thread::self() {
+  return (int)pthread_self();
+}
+
+void Thread::yield(unsigned int *c) {
+  if(++(*c) & 3)
+    sched_yield();
+  else {
+    struct timespec ts; 
+    ts.tv_sec = 0;
+    ts.tv_nsec = 2000;
+    nanosleep(&ts, 0); 
+  }
+}
+
+int Thread::kill(int tid, int signo) {
+  return pthread_kill((pthread_t)tid, signo);
+}
+
+void Thread::exit(int value) {
+  pthread_exit((void*)value);
+}
+
+void* ThreadKey::get()        { 
+  pthread_key_t k = (pthread_key_t)val;
+  return (void *)pthread_getspecific(k);
+}
+
+void  ThreadKey::set(void *v) {
+  pthread_key_t k = (pthread_key_t)val;
+  pthread_setspecific(k, v);
+}
+
+ThreadKey::ThreadKey(void (*_destr)(void *)) {
+  pthread_key_create((pthread_key_t*)&val, _destr);
+}
+
+ThreadKey::ThreadKey() {
+  pthread_key_create((pthread_key_t*)&val, NULL);
+}
+
+void ThreadKey::initialise() {
+  pthread_key_create((pthread_key_t*)&val, NULL);
+}
+
+void Thread::initialise() {
+}
+
+int Thread::start(int *tid, int (*fct)(void *), void *arg) {
+  int res = pthread_create((pthread_t *)tid, 0, (void * (*)(void *))fct, arg);
+  pthread_detach(*(pthread_t *)tid);
+  return res;
+}
diff --git a/vmkit/lib/Mvm/CommonThread/main.cc b/vmkit/lib/Mvm/CommonThread/main.cc
new file mode 100644
index 0000000..9a99628
--- /dev/null
+++ b/vmkit/lib/Mvm/CommonThread/main.cc
@@ -0,0 +1,94 @@
+//===----------------- main.cc - Mvm common threads -----------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ctthread.h"
+#include <stdio.h>
+#include <sys/time.h>
+
+LockReccursive	* l;
+Cond						* c;
+int go=0;
+
+extern "C" int getchar(void);
+
+int f(void *arg) {
+	struct timeval tv;
+	tv.tv_sec = 2;
+	tv.tv_usec = 0;
+	l->lock();
+	while(!go) {
+		printf("Wait %d\n", Thread::self());
+		c->timed_wait(l, &tv);
+	}
+	l->unlock();
+	printf("Salut\n");
+	return 0;
+}
+
+void pre(void *a) {
+	printf("Pré %p\n", a);
+}
+
+void post(void *a) {
+	printf("Post %p\n", a);
+}
+
+class Zop {
+public:
+	static Key<Zop>		* k;
+	static void initialise_Key(void *pk) {
+		printf("Init %p %p\n", pk, &k);
+		((Key<Zop>*)pk)->set(new Zop());
+		printf("GOOD\n");
+	}
+
+	static void duplicate_for_thread(void *, void *z) {
+		printf("Dup %p\n", z);
+		k->set(new Zop());
+	}
+
+	static void destroy_Key(void *z) {
+		printf("************ Del %p\n", z);
+		delete (Zop *)z;
+	}
+};
+
+Key<Zop>*	Zop::k;
+
+int main(int argc, char **argv) {
+	printf("START\n");
+  ctthread_t tid;
+  
+  printf("Initialise thread...\n");
+	Thread::initialise();
+  printf("Create Key...\n");
+  
+  Zop::k = new Key<Zop>();
+  l = new LockReccursive();
+  c = new Cond();
+  printf("OK\n");
+
+	Thread::register_handler(pre, post, (void *)0x1000);
+	Thread::remove_handler(Thread::register_handler(pre, post, (void *)0x1000));
+
+	Thread::start(&tid, f, (void *)22);
+	Thread::start(&tid, f, (void *)33);
+
+	getchar();
+	l->lock();
+	go = 1;
+	c->broadcast();
+	l->unlock();
+
+	printf("On est passé\n");
+
+	getchar();
+	Thread::exit(22);
+}
+
diff --git a/vmkit/lib/Mvm/EscapeAnalysis.cpp b/vmkit/lib/Mvm/EscapeAnalysis.cpp
new file mode 100644
index 0000000..1e33f87
--- /dev/null
+++ b/vmkit/lib/Mvm/EscapeAnalysis.cpp
@@ -0,0 +1,142 @@
+//===------EscapeAnalysis.cpp - Simple LLVM escape analysis ---------------===//
+//
+//                     The Micro Virtual Machine
+//
+// 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"
+
+using namespace llvm;
+
+namespace {
+
+  class VISIBILITY_HIDDEN EscapeAnalysis : public FunctionPass {
+  public:
+    static char ID;
+    EscapeAnalysis(Function* alloc = 0, Function* init = 0) : 
+      FunctionPass((intptr_t)&ID) {
+      Allocator = alloc;
+      Initialize = init;
+    }
+
+    virtual bool runOnFunction(Function &F);
+  private:
+    Function* Allocator;
+    Function* Initialize;
+    bool processMalloc(Instruction* I);
+  };
+  char EscapeAnalysis::ID = 0;
+  RegisterPass<EscapeAnalysis> X("EscapeAnalysis", "Escape Analysis Pass");
+}
+
+bool EscapeAnalysis::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) == Allocator) {
+          Changed |= processMalloc(CI);
+        }
+      } else if (InvokeInst *CI = dyn_cast<InvokeInst>(I)) {
+        if (CI->getOperand(0) == Allocator) {
+          Changed |= processMalloc(CI);
+        }
+      }
+    }
+  }
+  return Changed;
+}
+
+namespace mvm {
+
+EscapeAnalysis* createEscapeAnalysisPass(Function* alloc, Function* init) {
+  return new EscapeAnalysis(alloc, init);
+}
+
+}
+
+static bool escapes(Instruction* Ins, std::map<AllocaInst*, bool>& visited) {
+  for (Value::use_iterator I = Ins->use_begin(), E = Ins->use_end(); 
+       I != E; ++I) {
+    if (Instruction* II = dyn_cast<Instruction>(I)) {
+      if (dyn_cast<CallInst>(II)) return true;
+      else if (dyn_cast<InvokeInst>(II)) return true;
+      else if (dyn_cast<BitCastInst>(II)) {
+        if (escapes(II, visited)) return true;
+      }
+      else if (StoreInst* SI = dyn_cast<StoreInst>(II)) {
+        if (AllocaInst * AI = dyn_cast<AllocaInst>(SI->getOperand(1))) {
+          if (!visited[AI]) {
+            visited[AI] = true;
+            if (escapes(AI, visited)) return true;
+          }
+        } else if (SI->getOperand(0) == Ins) {
+          return true;
+        }
+      }
+      else if (dyn_cast<LoadInst>(II)) {
+        if (isa<PointerType>(II->getType())) {
+          if (escapes(II, visited)) return true; // allocas
+        }
+      }
+      else if (dyn_cast<GetElementPtrInst>(II)) {
+        if (escapes(II, visited)) return true;
+      }
+      else if (dyn_cast<ReturnInst>(II)) return true;
+      else if (dyn_cast<PHINode>(II)) {
+        if (escapes(II, visited)) return true;
+      }
+    } else {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool EscapeAnalysis::processMalloc(Instruction* I) {
+  Instruction* Alloc = I;
+  Value::use_iterator UI = I->use_begin(), UE = I->use_end(), Last = I->use_begin();
+  while (UI != UE) { Last = UI; UI++;}
+  
+  if (BitCastInst *BCI = dyn_cast<BitCastInst>(Last)) {
+    I = BCI;
+  } 
+  
+  std::map<AllocaInst*, bool> visited;
+  if (!(escapes(Alloc, visited))) {
+    AllocaInst* AI = new AllocaInst(I->getType()->getContainedType(0), "", Alloc);
+    BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc);
+    std::vector<Value*> Args;
+    if (isa<CallInst>(Alloc)) {
+      Args.push_back(Alloc->getOperand(1));
+    } else {
+      Args.push_back(Alloc->getOperand(3)); // skip unwind and normal BB
+    }
+    Args.push_back(BI);
+    Instruction* CI;
+    if (isa<CallInst>(Alloc)) {
+      CI = new CallInst(Initialize, Args.begin(), Args.end(), "", Alloc);
+    } else {
+      CI = new InvokeInst(Initialize, ((InvokeInst*)Alloc)->getNormalDest(), 
+                          ((InvokeInst*)Alloc)->getUnwindDest(), Args.begin(), 
+                          Args.end(), "", Alloc->getParent());
+    }
+    DOUT << "escape" << Alloc->getParent()->getParent()->getName() << "\n";
+    Alloc->replaceAllUsesWith(CI);
+    Alloc->eraseFromParent();
+    return true;
+  }
+  return false;
+}
diff --git a/vmkit/lib/Mvm/GCMmap2/Makefile.am b/vmkit/lib/Mvm/GCMmap2/Makefile.am
new file mode 100644
index 0000000..1f4f06b
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/Makefile.am
@@ -0,0 +1,23 @@
+# $Id: Makefile.am,v 1.3 2008/03/21 16:25:31 varth Exp $
+noinst_LIBRARIES = libuvm_gc_mmap2.a
+noinst_PROGRAMS = mainuvm_gc_mmap2
+
+THREADDIR=../CommonThread
+ALLOCDIR=../Allocator
+INCLUDEDIRS=-I@srcdir@/$(THREADDIR) -I@srcdir@/$(ALLOCDIR)
+
+LIBTHREAD=$(THREADDIR)/libuvm_@vvmthreadtype@_thread.a
+LIBALLOC=$(ALLOCDIR)/libuvm_alloc.a
+
+libuvm_gc_mmap2_a_SOURCES = gc.cc gccollector.cc gcinit.cc gccollector.h
+if HAVE_PTHREAD
+libuvm_gc_mmap2_a_SOURCES += gcthread.cc
+endif
+libuvm_gc_mmap2_a_CXXFLAGS =$(INCLUDEDIRS) -O2
+
+mainuvm_gc_mmap2_SOURCES = main.cc
+mainuvm_gc_mmap2_CXXFLAGS = -O2
+mainuvm_gc_mmap2_LDADD = libuvm_gc_mmap2.a $(LIBTHREAD) $(LIBALLOC)
+mainuvm_gc_mmap2_LDFLAGS =
+
+CLEANFILES = *~ *.bak .*.sw?
diff --git a/vmkit/lib/Mvm/GCMmap2/ctcircular.h b/vmkit/lib/Mvm/GCMmap2/ctcircular.h
new file mode 100644
index 0000000..05e8388
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/ctcircular.h
@@ -0,0 +1,57 @@
+//===------------- ctcircular.h - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _CT_CIRCULAR_H_
+#define _CT_CIRCULAR_H_
+
+#include "ctosdep.h"
+
+
+class CircularBase {
+	CircularBase	*_next;
+	CircularBase	*_prev;
+public:
+	inline CircularBase *next() { return _next; }
+	inline CircularBase *prev() { return _prev; }
+
+	inline void next(CircularBase *n) { _next = n; }
+	inline void prev(CircularBase *p) { _prev = p; }
+
+	inline CircularBase() { alone(); }
+	inline CircularBase(CircularBase *p) { append(p); }
+
+	inline void remove() { 
+		_prev->_next = _next; 
+		_next->_prev = _prev;
+		alone();
+	}
+
+	inline void append(CircularBase *p) { 
+		_prev = p;
+		_next = p->_next;
+		_next->_prev = this;
+		_prev->_next = this;
+	}
+
+	inline void alone() { _prev = _next = this; }
+};
+
+class Circular : public CircularBase, public TObj {
+public:
+	inline Circular() : CircularBase() {}
+	inline Circular(Circular *p) : CircularBase(p) {}
+	inline ~Circular() {
+		if(prev() != this) {
+			next()->prev(prev());
+			delete next();
+		}
+	}
+};
+
+#endif
diff --git a/vmkit/lib/Mvm/GCMmap2/ctosdep.h b/vmkit/lib/Mvm/GCMmap2/ctosdep.h
new file mode 100644
index 0000000..63674bd
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/ctosdep.h
@@ -0,0 +1,32 @@
+//===---------------- ctosdep.h - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _CT_OSDEP_H_
+#define _CT_OSDEP_H_
+
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+extern void *				malloc(size_t);
+extern void					free(void *);
+extern int 					printf(const char *, ...);
+
+__END_DECLS
+
+#define tmalloc					malloc
+#define tfree						free
+
+class TObj {
+public:
+	void *operator new(size_t sz) { return tmalloc(sz); }
+	void operator delete(void *ptr, size_t sz) { return tfree(ptr); }
+};
+
+#endif
diff --git a/vmkit/lib/Mvm/GCMmap2/gc.cc b/vmkit/lib/Mvm/GCMmap2/gc.cc
new file mode 100644
index 0000000..d877ad7
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/gc.cc
@@ -0,0 +1,129 @@
+//===---------------- gc.cc - Mvm Garbage Collector -----------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/GC/GC.h"
+#include "gccollector.h"
+#include "gcerror.h"
+
+using namespace mvm;
+
+typedef void (*memoryError_t)(unsigned int);
+
+memoryError_t GCCollector::internMemoryError;
+
+void gc::markAndTrace() const {
+ 	GCCollector::markAndTrace((void*)this);
+}
+
+size_t gc::objectSize() const {
+ 	return GCCollector::objectSize((gc*)this);
+}
+
+void *gc::operator new(size_t sz, VirtualTable *vt) {
+ 	return GCCollector::gcmalloc(vt, sz);
+}
+
+void gc::operator delete(void *) { 
+	gcfatal(0, "never call directly a destructor....."); 
+}
+
+
+void *gc::realloc(size_t n) {
+ 	return GCCollector::gcrealloc(this, n);
+}
+
+unsigned int gc::enable(unsigned int n) {
+ 	return GCCollector::enable(n);
+}
+
+int gc::isStable(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
+	return GCCollector::isStable(fct, a0, a1, a2, a3, a4, a5, a6, a7);
+}
+
+void gc::die_if_sigsegv_occured_during_collection(void *addr) {
+	GCCollector::die_if_sigsegv_occured_during_collection(addr);
+}
+
+void gc::gcStats(size_t &no, size_t &nbb) {
+	GCCollector::gcStats(&no, &nbb);
+}
+
+void gc::initialise(markerFn marker, void *base_sp) {
+#ifdef HAVE_PTHREAD
+	Thread::initialise();
+#endif
+	GCCollector::initialise(marker);
+#ifdef HAVE_PTHREAD
+	GCCollector::inject_my_thread(base_sp);
+#endif
+}
+
+void gc::destroy() {
+	GCCollector::destroy();
+}
+
+void gc::inject_my_thread(void *base_sp) {
+#ifdef HAVE_PTHREAD
+	GCCollector::inject_my_thread(base_sp);
+#endif
+}
+
+void gc::maybeCollect() {
+ 	GCCollector::maybeCollect();
+}
+
+void gc::collect(void) {
+ 	GCCollector::collect();
+}
+
+gc *gc::begOf(const void *obj) {
+	return GCCollector::begOf((void*)obj);
+}
+
+int gc::byteOffset(void *obj) {
+	int beg = (int)GCCollector::begOf(obj);
+  int off = (int)obj;
+  return (off-beg);
+}
+
+
+void gc::applyFunc(void (*func)(gc *o, void *data), void *data){
+  return GCCollector::applyFunc(func, data);
+}
+
+int gc::getMaxMemory(void){
+  return 0;
+}
+
+int gc::getFreeMemory(void){
+  return 0;
+}
+
+int gc::getTotalMemory(void){
+  return 0;
+}
+
+void gc::setMaxMemory(size_t sz){
+}
+
+void gc::setMinMemory(size_t sz){
+}
+
+void gc::registerMemoryError(void (*func)(unsigned int)){
+  GCCollector::internMemoryError = func;
+  onMemoryError = &GCCollector::defaultMemoryError;
+  
+}
+
+void gc::remove_my_thread() {
+#ifdef HAVE_PTHREAD
+  GCCollector::remove_thread(GCCollector::threads->myloc());
+#endif
+}
+
diff --git a/vmkit/lib/Mvm/GCMmap2/gccollector.cc b/vmkit/lib/Mvm/GCMmap2/gccollector.cc
new file mode 100644
index 0000000..4b166cb
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/gccollector.cc
@@ -0,0 +1,158 @@
+//===----------- gccollector.cc - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gccollector.h"
+#include <setjmp.h>
+
+using namespace mvm;
+
+GCAllocator   *GCCollector::allocator = 0;
+#ifdef HAVE_PTHREAD
+GCThread      *GCCollector::threads;
+#endif
+
+gc::markerFn   GCCollector::_marker;
+
+int  GCCollector::_collect_freq_auto;
+int  GCCollector::_collect_freq_maybe;
+int  GCCollector::_since_last_collection;
+
+bool GCCollector::_enable_auto;
+bool GCCollector::_enable_maybe;
+bool GCCollector::_enable_collection;
+
+int					  GCCollector::status;
+
+GCChunkNode    *GCCollector::used_nodes;
+GCChunkNode    *GCCollector::unused_nodes;
+
+unsigned int   GCCollector::current_mark;
+
+#ifdef HAVE_PTHREAD
+void GCCollector::siggc_handler(int) {
+ 	GCThreadCollector     *loc = threads->myloc();
+ 	register unsigned int cm = current_mark;
+	//	jmp_buf buf;
+
+	//	setjmp(buf);
+
+	threads->stackLock();
+	
+ 	if(!loc) /* arrive lorsqu'on est en train de détruire une clé */		
+ 		threads->another_mark();
+ 	else if(loc->current_mark() != cm) {
+ 		register unsigned int	**cur = (unsigned int **)&cur;
+ 		register unsigned int	**max = loc->base_sp();
+		
+ 		GCChunkNode *node;
+		
+ 		for(; cur<max; cur++) {
+ 			if((node = o2node(*cur)) && (!isMarked(node))) {
+ 				node->remove();
+ 				node->append(used_nodes);
+ 				mark(node);
+ 			}
+ 		}
+		
+ 		loc->current_mark(cm);
+ 		threads->another_mark();
+		
+		threads->waitCollection();
+	}
+	threads->stackUnlock();
+}
+#endif
+
+void GCCollector::do_collect() {
+	//printf("----- do collect -----\n");
+	jmp_buf   buf;
+	setjmp(buf);
+ 	GCChunkNode	*cur;
+ 	_since_last_collection = _collect_freq_auto;
+
+ 	current_mark++;
+
+ 	unused_nodes->attrape(used_nodes);
+
+#ifdef HAVE_PTHREAD
+	threads->synchronize();
+#endif
+
+ 	for(cur=used_nodes->next(); cur!=used_nodes; cur=cur->next())
+ 		trace(cur);
+
+ 	if(_marker)
+ 		_marker();
+
+ 	status = stat_finalize;
+
+ 	/* finalize */
+ 	GCChunkNode	finalizable;
+ 	finalizable.attrape(unused_nodes);
+
+ 	status = stat_alloc;
+#ifdef HAVE_PTHREAD
+	threads->collectionFinished();
+#endif
+	
+ 	/* on tue tout le monde */
+ 	GCChunkNode *next;
+
+ 	for(cur=finalizable.next(); cur!=&finalizable; cur=next) {
+ 		register gc_header *c = cur->chunk();
+ 		next = cur->next();
+		
+ 		c->_2gc()->destroyer(real_nbb(cur));
+		
+		//printf("    !!!! reject %p [%p]\n", cur->chunk()->_2gc(), cur);
+ 		allocator->reject_chunk(cur);
+ 	}
+
+	//	printf(" collection finished\n");
+// 	/* voilà, c'est fini :) */
+// 	stacklock_fini.broadcast();
+// 	//	printf("---- End collect\n");
+}
+
+void GCCollector::collect_unprotect() {
+ 	if(_enable_collection && (status == stat_alloc)) {
+ 		status = stat_collect;
+ 		do_collect();
+ 	}
+}
+
+#ifdef HAVE_PTHREAD
+void GCCollector::die_if_sigsegv_occured_during_collection(void *addr) {
+	if(!isStable(0, 0, 0, 0, 0, 0, 0, 0, 0)) {
+		printf("; ****************************************************** ;\n");
+		printf(";         SIGSEGV occured during a collection            ;\n");
+		printf(";   I'm trying to let the allocator in a coherent stat   ;\n");
+		printf("; but the collector is DEAD and will never collect again ;\n");
+		printf("; ****************************************************** ;\n");
+		
+		status = stat_broken;               /* indique que la collection est terminée + empeche toute nouvelle collection */
+		threads->cancel();                   /* emule une collection complete pour débloquer (synchro) les mutateurs */
+		used_nodes->eat(unused_nodes);      /* tous les noeuds sont utilisés... Domage pour les finalize, ils seront perdus! */
+		unlock_dont_recovery();             /* débloque le sémaphore du gc */
+		//gcfatal("SIGSEGV occured during collection at %p", addr);
+	}
+}
+#endif /* HAVE_PTHREAD */
+
+void GCCollector::gcStats(size_t *_no, size_t *_nbb) {
+ 	register unsigned int n, tot;
+ 	register GCChunkNode *cur;
+ 	lock();
+ 	for(n=0, tot=0, cur=used_nodes->next(); cur!=used_nodes; cur=cur->next(), n++)
+ 		tot += cur->nbb();
+ 	unlock();
+ 	*_no = n;
+ 	*_nbb = tot;
+}
+
diff --git a/vmkit/lib/Mvm/GCMmap2/gccollector.h b/vmkit/lib/Mvm/GCMmap2/gccollector.h
new file mode 100644
index 0000000..df754e4
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/gccollector.h
@@ -0,0 +1,214 @@
+//===------------ gccollector.h - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GC_COLLECTOR_H_
+#define _GC_COLLECTOR_H_
+
+#include "config.h"
+#include "gcalloc.h"
+#ifdef HAVE_PTHREAD
+#include "gcthread.h"
+#endif
+#include "mvm/GC/GC.h"
+
+namespace mvm {
+
+class GCCollector {
+#ifdef HAVE_PTHREAD
+	friend class GCThread;
+
+#endif
+	static GCAllocator  *allocator;      /* la machine à allouer de la mémoire */
+
+ 	static gc::markerFn  _marker;        /* la fonction qui marque les racines */
+
+ 	static GCChunkNode  *used_nodes;     /* les noeuds mémoires utilisés */
+	static GCChunkNode  *unused_nodes;   /* les noeuds inutilisés */
+
+ 	static unsigned int	 current_mark;
+
+ 	static int	_collect_freq_auto;     /* fréquence de collection automatique (lors des gcmalloc/gcrealloc) */
+ 	static int	_collect_freq_maybe;    /* fréquence de collection lors de l'appel à maybeCollect() */
+	static int	_since_last_collection; /* nombre d'octets restants depuis la dernière collection */
+ 	static bool	_enable_auto;           /* collection automatique? */
+	static bool	_enable_maybe;          /* collection lors des maybeCollect()? */
+	static bool	_enable_collection;     /* collection autorisée? */
+	static int	status;
+
+ 	enum { stat_collect, stat_finalize, stat_alloc, stat_broken };
+
+#ifdef HAVE_PTHREAD
+	static void	siggc_handler(int);
+	static inline void  lock()   { threads->lock(); }
+	static inline void  unlock() { threads->unlock(); }
+#else
+	static void	siggc_handler(int) { }
+	static inline void  lock()   { }
+	static inline void  unlock() { }
+#endif
+
+	static void         collect_unprotect();    /* interface pour la collection, verifie le enable_collect */
+	static void         do_collect();           /* la collection proprement dite */
+
+	static inline GCChunkNode *o2node(void *p)
+        {
+                return GCHash::get(p)->o2node(p, GCChunkNode::maskCollectable);
+        }
+
+	static inline size_t real_nbb(GCChunkNode *n) { return n->nbb() - sizeof(gc_header); }
+public:
+	static GCThread     *threads;        /* le gestionnaire de thread et de synchro */
+         static void         (*internMemoryError)(unsigned int);
+
+#ifdef HAVE_PTHREAD
+        static inline void  unlock_dont_recovery() { threads->unlock_dont_recovery(); }
+	static        void  die_if_sigsegv_occured_during_collection(void *addr);
+#else
+	static        void  die_if_sigsegv_occured_during_collection(void *addr) { }
+#endif
+
+       static void defaultMemoryError(unsigned int sz){
+            unlock();
+               internMemoryError(sz);
+    lock();
+  }
+
+	static void	initialise(gc::markerFn marker);
+	static void	destroy();
+
+	static int	siggc();
+
+#ifdef HAVE_PTHREAD
+	static void	        inject_my_thread(void *base_sp);
+	static inline void	remove_thread(GCThreadCollector *loc) { threads->remove(loc); }
+	static inline int       isStable(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
+		return threads->isStable(fct, a0, a1, a2, a3, a4, a5, a6, a7);
+	}
+#else
+	static inline int       isStable(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
+		return 0;
+	}
+#endif
+
+	static inline void  *allocate_unprotected(size_t sz) { return allocator->alloc(sz); }
+	static inline void  free_unprotected(void *ptr) { allocator->free(ptr); }
+
+	static inline gc *begOf(void *p) {
+		GCChunkNode *node = o2node(p);
+		if(node)
+			return node->chunk()->_2gc();
+		else
+			return 0;
+	}
+
+	static void gcStats(size_t *no, size_t *nbb);
+
+	static inline size_t objectSize(void *ptr) {
+		GCChunkNode *node = o2node(ptr);
+		return node ? real_nbb(node) : 0;
+	}
+
+ 	static inline void collect() {
+ 		lock();
+ 		collect_unprotect();
+ 		unlock();
+ 	}
+
+ 	static inline void maybeCollect() {
+ 		if(_enable_auto && (_since_last_collection <= (_collect_freq_auto - _collect_freq_maybe)))
+ 			collect(); 
+ 	}
+
+ 	static inline gc *gcmalloc(VirtualTable *vt, size_t n) {
+ 		lock();
+ 		register GCChunkNode *header = allocator->alloc_chunk(n + sizeof(gc_header), 1, current_mark & 1);
+		
+ 		header->append(used_nodes);
+		//printf("Allocate %d bytes at %p [%p] %d %d\n", n, header->chunk()->_2gc(), header, header->nbb(), real_nbb(header));
+		
+ 		register struct gc_header *p = header->chunk();
+ 		p->_XXX_vt = vt;
+
+ 		_since_last_collection -= n;
+ 		if(_enable_auto && (_since_last_collection <= 0))
+ 			collect_unprotect();
+
+ 		unlock();
+ 		return p->_2gc();
+ 	}
+
+ 	static inline gc *gcrealloc(void *ptr, size_t n) {
+ 		lock();
+
+ 		GCPage    	*desc = GCHash::get(ptr);
+ 		GCChunkNode	*node = desc->o2node(ptr, GCChunkNode::maskCollectable);
+
+		if(!node)
+			gcfatal("%p isn't a avalid object", ptr);
+
+ 		size_t			old_sz = node->nbb();
+ 		GCChunkNode	*res = allocator->realloc_chunk(desc, node, n+sizeof(gc_header));
+
+ 		if(res != node) {
+ 			res->append(used_nodes);
+ 			mark(res);
+ 		}
+
+		gc_header *obj = res->chunk();
+ 		_since_last_collection -= (n - old_sz);
+
+ 		if(_enable_auto && (_since_last_collection <= 0))
+ 			collect_unprotect();
+
+ 		unlock();
+ 		return obj->_2gc();
+ 	}
+
+	static inline unsigned int enable(unsigned int n)  {
+ 		register unsigned int old = _enable_collection;
+ 		_enable_collection = n; 
+ 		return old;
+ 	}
+
+ 	static inline bool isMarked(GCChunkNode *node) { return node->mark() == (current_mark & 1); }
+	static inline void mark(GCChunkNode *node) { node->_mark(current_mark & 1); }
+
+ 	static inline void trace(GCChunkNode *node) {
+ 		gc_header *o = node->chunk();
+    o->_2gc()->tracer(real_nbb(node));
+    markAndTrace(o);
+ 	}
+
+ 	static inline void markAndTrace(void *ptr) {
+ 		GCChunkNode *node = o2node(ptr);
+
+ 		if(node && !isMarked(node)) {
+ 			mark(node);
+			node->remove();
+ 			node->append(used_nodes);
+ 			trace(node);
+ 		}
+ 	}
+
+  static inline void applyFunc(void (*func)(gc *o, void *data), void *data){
+    lock(); /* on s'assure que personne n'alloue ou ne collect */
+    status = stat_collect; /* empeche les collections */
+    GCChunkNode *cur=used_nodes->next(); /* reccupère l'amorce */
+    unlock(); /* on peut allouer autant qu'on veut maintenant */ 
+
+    for(; cur!=used_nodes; cur=cur->next())
+      func(cur->chunk()->_2gc(), data);
+    
+    /* pas besoin de lock ! */
+    status = stat_alloc; 
+  }
+};
+
+}
+#endif
diff --git a/vmkit/lib/Mvm/GCMmap2/gcinit.cc b/vmkit/lib/Mvm/GCMmap2/gcinit.cc
new file mode 100644
index 0000000..dc41a60
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/gcinit.cc
@@ -0,0 +1,112 @@
+//===--------------- gcinit.cc - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <signal.h>
+#include "gccollector.h"
+
+using namespace mvm;
+
+static const size_t	def_collect_freq_auto = 4*1024*1024;
+static const size_t def_collect_freq_maybe = 512*1024;
+
+#if defined(__MACH__)
+# define SIGGC	SIGXCPU
+#else
+# define SIGGC	SIGPWR
+#endif
+
+int GCCollector::siggc() {
+	return SIGGC;
+}
+
+void GCCollector::initialise(gc::markerFn marker) {
+	
+  used_nodes = new GCChunkNode();
+  unused_nodes = new GCChunkNode();
+#ifdef HAVE_PTHREAD
+  threads = new GCThread();
+#endif
+  
+  struct sigaction sa;
+	sigset_t mask;
+
+#ifdef HAVE_PTHREAD
+	on_fatal = unlock_dont_recovery;
+#endif
+
+	sigaction(SIGGC, 0, &sa);
+	sigfillset(&mask);
+	sa.sa_mask = mask;
+	sa.sa_handler = siggc_handler;
+	sa.sa_flags |= SA_RESTART;
+	sigaction(SIGGC, &sa, 0);
+
+	allocator = new GCAllocator();
+// GCCollector::GCCollector(void (*marker)(void *)) {
+ 	
+	_marker = marker;
+
+ 	used_nodes->alone();
+
+ 	current_mark = 0;
+
+ 	_collect_freq_auto = def_collect_freq_auto;
+ 	_collect_freq_maybe = def_collect_freq_maybe;
+	
+ 	_since_last_collection = _collect_freq_auto;
+
+ 	_enable_auto = 1;
+ 	_enable_collection = 1;
+ 	_enable_maybe = 1;
+
+ 	status = stat_alloc;
+}
+
+void GCCollector::destroy() {
+	delete allocator;
+	allocator = 0;
+}
+
+
+static void *get_curr_fp(void)
+{
+	register void *fp;
+	asm(
+#  if defined(__ppc__) || defined(__PPC__)
+#   if defined(__MACH__)
+			"		mr	%0, r1		"
+#   else
+			"		mr	%0, 1		"
+#   endif
+#  elif defined(__i386__)
+			"		movl	%%ebp, %0	"
+#  else
+#   error:
+#   error: I do not know how to read the frame pointer on this machine
+#   error:
+#  endif
+			:"=r"(fp):);
+	return fp;
+}
+
+static void *get_base_sp(void)
+{
+	void *fp= 0;
+	for (fp= get_curr_fp();  (*(void **)fp);  fp= *(void **)fp);
+	return fp;
+}
+
+#ifdef HAVE_PTHREAD
+void GCCollector::inject_my_thread(void *base_sp) {
+ 	if(!base_sp)
+ 		base_sp = get_base_sp();
+	threads->inject(base_sp, current_mark);
+}
+#endif
+
diff --git a/vmkit/lib/Mvm/GCMmap2/gcthread.cc b/vmkit/lib/Mvm/GCMmap2/gcthread.cc
new file mode 100644
index 0000000..5e84e8c
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/gcthread.cc
@@ -0,0 +1,70 @@
+//===-------------- gcthread.cc - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gccollector.h"
+
+using namespace mvm;
+
+void *GCThreadCollector::operator new(size_t sz)   { 
+	return GCCollector::allocate_unprotected(sz); 
+}
+
+void GCThreadCollector::operator delete(void *ptr) { 
+	//printf("DELETE %p\n", ptr);
+	GCCollector::free_unprotected(ptr); 
+}
+
+void GCThreadCollector::destroy_Key(void *ptr) {
+	GCCollector::remove_thread((GCThreadCollector *)ptr);
+}
+
+void GCThread::waitStacks() {
+	_stackLock.lock();
+	while(_nb_collected < _nb_threads)
+		_stackCond.wait(&_stackLock);
+	_stackLock.unlock();
+}
+
+void GCThread::waitCollection() {
+	unsigned int cm = GCCollector::current_mark;
+
+	if(Thread::self() != collector_tid) {
+		collectorGo();
+		while((GCCollector::current_mark == cm) && (GCCollector::status == GCCollector::stat_collect))
+			_collectionCond.wait(&_stackLock);
+	}
+}
+
+void GCThread::synchronize() {
+ 	GCThreadCollector *cur;
+	int signo = GCCollector::siggc();
+	int reached = 0;
+	collector_tid = Thread::self();
+	
+	_nb_collected = 0;
+ 	for(cur=(GCThreadCollector *)base.next(); cur!=&base; cur=(GCThreadCollector *)cur->next()) {
+		int t = cur->tid();
+		if(t != Thread::self())
+			Thread::kill(cur->tid(), signo);
+		else
+			reached = 1;
+	}
+	if(reached)  /* moi aussi je dois collecter... */
+		GCCollector::siggc_handler(signo);
+	waitStacks();
+}
+
+int GCLockRecovery::verify_recall(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
+	if(owner() == Thread::self()) {
+		_fct = fct;    _args[0] = a0; _args[1] = a1; _args[2] = a2; _args[3] = a3;
+		_args[4] = a4; _args[5] = a5; _args[6] = a6; _args[7] = a7;
+		return 0;
+	} else
+		return 1;
+}
diff --git a/vmkit/lib/Mvm/GCMmap2/gcthread.h b/vmkit/lib/Mvm/GCMmap2/gcthread.h
new file mode 100644
index 0000000..2619627
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/gcthread.h
@@ -0,0 +1,147 @@
+//===--------------- gcthread.h - Mvm Garbage Collector -------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _GC_THREAD_H_
+#define _GC_THREAD_H_
+
+//#include "gcalloc.h"
+//#include "ctlock.h"
+#include "ctcircular.h"
+#include "mvm/GC/GC.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Key.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Thread.h" // only for self
+
+// class GCAllocator;
+
+namespace mvm {
+
+class GCThreadCollector : public CircularBase {
+ 	void							*_base_sp;
+ 	int								_cur_mark;
+ 	int								_tid;
+	
+public:
+ 	static void initialise_Key(void *) {}
+ 	static void duplicate_for_thread(void *, void *) {}
+ 	static void destroy_Key(void *ptr);
+
+	inline GCThreadCollector() {}
+ 	inline GCThreadCollector(GCThreadCollector *pred, int t, void *p, int m) : CircularBase(pred) {
+		_base_sp = p;
+  	_cur_mark = m;
+		_tid = t;
+	}
+
+	/* cette fonction n'est appelée que dans deux cas: soit parsqu'un thread quit */
+	/* dans ce cas, tout est déjà fait */
+	/* soit parce que le collecteur quitte et dans ce cas, toute la mémoire est bien libérée */
+ 	inline 	~GCThreadCollector() {}
+	
+ 	void *operator new(size_t sz);
+ 	void operator delete(void *ptr);
+
+ 	inline int					tid()						{ return _tid; }
+ 	inline unsigned int current_mark()	{ return _cur_mark; }
+ 	inline void					current_mark(unsigned int m)	{ _cur_mark = m; }
+ 	inline unsigned int **base_sp()	{ return (unsigned int **)_base_sp; }
+};
+
+class GCLockRecovery : public LockNormal {
+	gc_lock_recovery_fct_t _fct;
+	int                    _args[8];
+	
+public:
+	inline GCLockRecovery() { _fct = 0; }
+
+	int verify_recall(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7);
+
+	inline void unlock_dont_recovery() { 
+		if(owner() == Thread::self()) {
+			LockNormal::unlock(); 
+		}
+	}
+
+	inline void unlock() {
+		if(_fct) {
+			gc_lock_recovery_fct_t tmp = _fct;
+			int l[8];
+			l[0] = _args[0]; l[1] = _args[1]; l[2] = _args[2]; l[3] = _args[3]; 
+			l[4] = _args[4]; l[5] = _args[5]; l[6] = _args[6]; l[7] = _args[7]; 
+			_fct = 0;
+			LockNormal::unlock();
+			tmp(l[0], l[1], l[2], l[3], l[4], l[5], l[6], l[7]);
+		} else
+			LockNormal::unlock();
+	}
+};
+
+class GCThread {
+ 	Key<GCThreadCollector>	_loc;
+ 	GCThreadCollector				base;
+	GCLockRecovery         _globalLock;    /* lock global pour gcmalloc */
+	LockNormal              _stackLock;     /* lock de la pile pour la syncro */
+	Cond                    _stackCond;     /* condition pour déverouiller les autres taches (write protect) */
+	Cond                    _collectionCond;/* condition pour débloquer le collecteur */
+ 	unsigned int						_nb_threads;    /* nombre de threads actifs */
+ 	unsigned int						_nb_collected;  /* nombre de threads ayant collecté */
+	int                     collector_tid;  /* il ne faut pas le synchroniser celui là */
+
+public:
+
+	inline void lock()   { _globalLock.lock(); }
+	inline void unlock() { _globalLock.unlock(); }
+	inline void unlock_dont_recovery() { _globalLock.unlock_dont_recovery(); }
+	inline int isStable(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) { 
+		return _globalLock.verify_recall(fct, a0, a1, a2, a3, a4, a5, a6, a7);
+	}
+
+	inline void stackLock() { _stackLock.lock(); }
+	inline void stackUnlock() { _stackLock.unlock(); }
+
+	void        waitStacks();
+	void        waitCollection();
+	inline void collectionFinished() { _collectionCond.broadcast(); }
+	inline void collectorGo() { _stackCond.broadcast(); }
+
+	inline void cancel() { 
+		_nb_collected = _nb_threads;  /* toutes les piles sont collectées */
+		collectorGo();                /* débloque les autres threads sur la phase de collection de pile */
+		collectionFinished();         /* débloque les mutateurs */
+	}
+
+ 	inline GCThreadCollector *myloc() { return _loc.get(); }
+
+ 	inline void another_mark() { _nb_collected++; }
+
+	void synchronize();
+
+	inline void remove(GCThreadCollector *loc) {
+		lock();
+		loc->remove();
+		_nb_threads--;
+		delete loc;
+		unlock();
+	}
+
+	inline void inject(void *sp, int m) {
+		GCThreadCollector *me = _loc.get();
+		if(me)
+			gcfatal("thread %d is already in pool for allocator %p", Thread::self(), this);
+		lock(); /* the new should be protected */
+		me = new GCThreadCollector(&base, Thread::self(), sp, m);
+		_nb_threads++;
+		_loc.set(me);
+		unlock();
+	}
+};
+
+}
+#endif
diff --git a/vmkit/lib/Mvm/GCMmap2/main.cc b/vmkit/lib/Mvm/GCMmap2/main.cc
new file mode 100644
index 0000000..34b098d
--- /dev/null
+++ b/vmkit/lib/Mvm/GCMmap2/main.cc
@@ -0,0 +1,36 @@
+//===---------------- main.cc - Mvm Garbage Collector ---------------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/GC/GC.h"
+#include <stdio.h>
+
+void destr(gc *me, size_t sz) {
+ 	printf("Destroy %p\n", me);
+}
+
+void trace(gc *me, size_t sz) {
+	// 	printf("Trace %p\n", me);
+}
+
+void marker(void) {
+	//	printf("Marker...\n");
+}
+
+int main(int argc, char **argv) {
+	gc::initialise(marker, 0);
+
+	gc::destroy();
+ 	return 0;
+}
+
+
+
+
+
+
diff --git a/vmkit/lib/Mvm/JIT.cc b/vmkit/lib/Mvm/JIT.cc
new file mode 100644
index 0000000..8ee1804
--- /dev/null
+++ b/vmkit/lib/Mvm/JIT.cc
@@ -0,0 +1,792 @@
+//===---------------- JIT.cc - Initialize the JIT -------------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// 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/PassManager.h"
+#include "llvm/ValueSymbolTable.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 <stdio.h>
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+#include "mvm/VMLet.h"
+
+#include "MvmMemoryManager.h"
+
+using namespace mvm;
+using namespace mvm::jit;
+using namespace llvm;
+
+
+extern "C" void printFloat(float f) {
+  printf("%f\n", f);
+}
+
+extern "C" void printDouble(double d) {
+  printf("%f\n", d);
+}
+
+extern "C" void printLong(sint64 l) {
+  printf("%lld\n", l);
+}
+
+extern "C" void printInt(sint32 i) {
+  printf("%d\n", i);
+}
+
+extern "C" void printObject(mvm::Object* obj) {
+  printf("%s\n", obj->printString());
+}
+
+static void addPass(FunctionPassManager *PM, Pass *P) {
+  // Add the pass to the pass manager...
+  PM->add(P);
+}
+
+void jit::AddStandardCompilePasses(FunctionPassManager *PM) {
+  llvm::MutexGuard locked(mvm::jit::executionEngine->lock);
+  // LLVM does not allow calling functions from other modules in verifier
+  //PM->add(createVerifierPass());                  // Verify that input is correct
+  
+  addPass(PM, createCFGSimplificationPass());    // Clean up disgusting code
+  addPass(PM, createScalarReplAggregatesPass());// Kill useless allocas
+  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
+  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE
+  addPass(PM, createPromoteMemoryToRegisterPass());// Kill useless allocas
+  addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE
+  addPass(PM, createCFGSimplificationPass());    // Clean up after IPCP & DAE
+  
+  addPass(PM, createTailDuplicationPass());      // Simplify cfg by copying code
+  addPass(PM, createInstructionCombiningPass()); // Cleanup for scalarrepl.
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas
+  addPass(PM, createInstructionCombiningPass()); // Combine silly seq's
+  addPass(PM, createCondPropagationPass());      // Propagate conditionals
+  
+   
+  addPass(PM, createTailCallEliminationPass());  // Eliminate tail calls
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  addPass(PM, createReassociatePass());          // Reassociate expressions
+  addPass(PM, createLoopRotatePass());
+  addPass(PM, createLICMPass());                 // Hoist loop invariants
+  addPass(PM, createLoopUnswitchPass());         // Unswitch loops.
+  addPass(PM, createInstructionCombiningPass()); // Clean up after LICM/reassoc
+  addPass(PM, createIndVarSimplifyPass());       // Canonicalize indvars
+  addPass(PM, createLoopUnrollPass());           // Unroll small loops
+  addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller
+  addPass(PM, createGVNPass());                  // GVN for load instructions
+  addPass(PM, createGCSEPass());                 // Remove common subexprs
+  addPass(PM, createSCCPPass());                 // Constant prop with SCCP
+  
+  
+  // Run instcombine after redundancy elimination to exploit opportunities
+  // opened up by them.
+  addPass(PM, createInstructionCombiningPass());
+  addPass(PM, createCondPropagationPass());      // Propagate conditionals
+
+  addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores
+  addPass(PM, createAggressiveDCEPass());        // SSA based 'Aggressive DCE'
+  addPass(PM, createCFGSimplificationPass());    // Merge & remove BBs
+  
+}
+
+
+
+
+static void initialiseTypes(llvm::Module* mod) {
+  {
+  // llvm::Type Definitions
+  std::vector<const llvm::Type*>StructTy_struct_NativeString_fields;
+  StructTy_struct_NativeString_fields.push_back(IntegerType::get(8));
+  StructType* StructTy_struct_NativeString =
+    StructType::get(StructTy_struct_NativeString_fields, /*isPacked=*/true);
+  mod->addTypeName("struct.mvm::NativeString", StructTy_struct_NativeString);
+  
+  mod->addTypeName("struct.mvm::Object", StructTy_struct_NativeString);
+  mod->addTypeName("struct.mvm::Thread", StructTy_struct_NativeString);
+  
+  std::vector<const llvm::Type*>StructTy_struct_PrintBuffer_fields;
+  StructTy_struct_PrintBuffer_fields.push_back(IntegerType::get(32));
+  StructTy_struct_PrintBuffer_fields.push_back(IntegerType::get(32));
+  PointerType* PointerTy_0 = PointerType::getUnqual(StructTy_struct_NativeString);
+  
+  StructTy_struct_PrintBuffer_fields.push_back(PointerTy_0);
+  StructType* StructTy_struct_PrintBuffer =
+    StructType::get(StructTy_struct_PrintBuffer_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::PrintBuffer", StructTy_struct_PrintBuffer);
+  
+  std::vector<const llvm::Type*>StructTy_struct_VirtualTable_fields;
+  std::vector<const llvm::Type*>StructTy_struct_gc_vt_fields;
+  std::vector<const llvm::Type*>FuncTy_2_args;
+  FuncTy_2_args.push_back(PointerTy_0);
+  FuncTy_2_args.push_back(IntegerType::get(32));
+  FunctionType* FuncTy_2 = FunctionType::get(
+    /*Result=*/llvm::Type::VoidTy,
+    /*Params=*/FuncTy_2_args,
+    /*isVarArg=*/false);
+  
+  PointerType* PointerTy_1 = PointerType::getUnqual(FuncTy_2);
+  
+  StructTy_struct_gc_vt_fields.push_back(PointerTy_1);
+  StructTy_struct_gc_vt_fields.push_back(PointerTy_1);
+  StructType* StructTy_struct_gc_vt =
+    StructType::get(StructTy_struct_gc_vt_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::gc_vt", StructTy_struct_gc_vt);
+  
+  StructTy_struct_VirtualTable_fields.push_back(PointerTy_1);
+  StructTy_struct_VirtualTable_fields.push_back(PointerTy_1);
+  std::vector<const llvm::Type*>FuncTy_4_args;
+  FuncTy_4_args.push_back(PointerTy_0);
+  PointerType* PointerTy_5 = PointerType::getUnqual(StructTy_struct_PrintBuffer);
+  
+  FuncTy_4_args.push_back(PointerTy_5);
+  FunctionType* FuncTy_4 = FunctionType::get(
+    /*Result=*/llvm::Type::VoidTy,
+    /*Params=*/FuncTy_4_args,
+    /*isVarArg=*/false);
+  
+  PointerType* PointerTy_3 = PointerType::getUnqual(FuncTy_4);
+  
+  StructTy_struct_VirtualTable_fields.push_back(PointerTy_3);
+  std::vector<const llvm::Type*>FuncTy_7_args;
+  FuncTy_7_args.push_back(PointerTy_0);
+  FunctionType* FuncTy_7 = FunctionType::get(
+    /*Result=*/IntegerType::get(32),
+    /*Params=*/FuncTy_7_args,
+    /*isVarArg=*/false);
+  
+  PointerType* PointerTy_6 = PointerType::getUnqual(FuncTy_7);
+  
+  StructTy_struct_VirtualTable_fields.push_back(PointerTy_6);
+  StructTy_struct_VirtualTable_fields.push_back(IntegerType::get(32));
+  OpaqueType* OpaqueTy_struct_llvm__Type = OpaqueType::get();
+  mod->addTypeName("struct.llvm::Type", OpaqueTy_struct_llvm__Type);
+  
+  PointerType* PointerTy_8 = PointerType::getUnqual(OpaqueTy_struct_llvm__Type);
+  
+  StructTy_struct_VirtualTable_fields.push_back(PointerTy_8);
+  StructType* StructTy_struct_VirtualTable = 
+    StructType::get(StructTy_struct_VirtualTable_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::VirtualTable", StructTy_struct_VirtualTable);
+  
+  mod->addTypeName("struct.mvm::gc_vt", StructTy_struct_gc_vt);
+  mod->addTypeName("struct.llvm::Type", OpaqueTy_struct_llvm__Type);
+  }
+
+
+
+  {
+  // Lock llvm::Type Definitions
+  std::vector<const llvm::Type*>StructTy_struct_mvm__Lock_fields;
+  std::vector<const llvm::Type*>StructTy_struct_mvm__SpinLock_fields;
+  StructTy_struct_mvm__SpinLock_fields.push_back(IntegerType::get(32));
+  StructType* StructTy_struct_mvm__SpinLock =
+    StructType::get(StructTy_struct_mvm__SpinLock_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::SpinLock", StructTy_struct_mvm__SpinLock);
+  
+  StructTy_struct_mvm__Lock_fields.push_back(StructTy_struct_mvm__SpinLock);
+  std::vector<const llvm::Type*>FuncTy_1_args;
+  PATypeHolder StructTy_struct_mvm__Lock_fwd = OpaqueType::get();
+  PointerType* PointerTy_2 = PointerType::getUnqual(StructTy_struct_mvm__Lock_fwd);
+  
+  FuncTy_1_args.push_back(PointerTy_2);
+  FunctionType* FuncTy_1 = FunctionType::get(
+    /*Result=*/llvm::Type::VoidTy,
+    /*Params=*/FuncTy_1_args,
+    /*isVarArg=*/false);
+  
+  PointerType* PointerTy_0 = PointerType::getUnqual(FuncTy_1);
+  
+  StructTy_struct_mvm__Lock_fields.push_back(PointerTy_0);
+  StructTy_struct_mvm__Lock_fields.push_back(PointerTy_0);
+  std::vector<const llvm::Type*>FuncTy_4_args;
+  FuncTy_4_args.push_back(PointerTy_2);
+  FunctionType* FuncTy_4 = FunctionType::get(
+    /*Result=*/IntegerType::get(32),
+    /*Params=*/FuncTy_4_args,
+    /*isVarArg=*/false);
+  
+  PointerType* PointerTy_3 = PointerType::getUnqual(FuncTy_4);
+  
+  StructTy_struct_mvm__Lock_fields.push_back(PointerTy_3);
+  StructTy_struct_mvm__Lock_fields.push_back(IntegerType::get(32));
+  StructType* StructTy_struct_mvm__Lock =
+    StructType::get(StructTy_struct_mvm__Lock_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::Lock", StructTy_struct_mvm__Lock);
+  mod->addTypeName("struct.mvm::LockNormal", StructTy_struct_mvm__Lock);
+  cast<OpaqueType>(StructTy_struct_mvm__Lock_fwd.get())->
+    refineAbstractTypeTo(StructTy_struct_mvm__Lock);
+  StructTy_struct_mvm__Lock =
+    cast<StructType>(StructTy_struct_mvm__Lock_fwd.get());
+  
+  
+  std::vector<const llvm::Type*>StructTy_struct_mvm__LockRecursive_fields;
+  StructTy_struct_mvm__LockRecursive_fields.push_back(StructTy_struct_mvm__Lock);
+  StructTy_struct_mvm__LockRecursive_fields.push_back(IntegerType::get(32));
+  StructType* StructTy_struct_mvm__LockRecursive =
+    StructType::get(StructTy_struct_mvm__LockRecursive_fields,
+                    /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::LockRecursive",
+                   StructTy_struct_mvm__LockRecursive);
+  
+  std::vector<const llvm::Type*>StructTy_struct_mvm__Object_fields;
+  StructTy_struct_mvm__Object_fields.push_back(IntegerType::get(8));
+  StructType* StructTy_struct_mvm__Object =
+    StructType::get(StructTy_struct_mvm__Object_fields, /*isPacked=*/true);
+  mod->addTypeName("struct.mvm::Object", StructTy_struct_mvm__Object);
+  
+  mod->addTypeName("struct.mvm::SpinLock", StructTy_struct_mvm__SpinLock);
+  
+
+  // llvm::Type definition of Cond and CollectableArea
+  std::vector<const llvm::Type*>StructTy_struct_collectablearea_fields;
+  StructTy_struct_collectablearea_fields.push_back(IntegerType::get(32));
+  StructTy_struct_collectablearea_fields.push_back(IntegerType::get(32));
+  StructTy_struct_collectablearea_fields.push_back(IntegerType::get(32));
+  StructType* StructTy_struct_collectablearea =
+  StructType::get(StructTy_struct_collectablearea_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::Cond", StructTy_struct_collectablearea);
+  mod->addTypeName("struct.mvm::CollectableArea", StructTy_struct_collectablearea);
+  }
+
+  // llvm::Type Definitions of Key
+  std::vector<const llvm::Type*>StructTy_struct_Key_fields;
+  PointerType* PointerTy_0 = PointerType::getUnqual(IntegerType::get(8));
+  
+  StructTy_struct_Key_fields.push_back(PointerTy_0);
+  StructType* StructTy_struct_Key =
+    StructType::get(StructTy_struct_Key_fields, /*isPacked=*/false);
+  mod->addTypeName("struct.mvm::ThreadKey", StructTy_struct_Key);
+
+  // TODO
+  mod->addTypeName("struct.mvm::Method", StructTy_struct_Key);
+  mod->addTypeName("struct.mvm::Code", StructTy_struct_Key);
+  
+}
+
+extern "C" void __register_frame(void*);
+
+void VMLet::initialise() {
+  llvm::SizedMemoryCode = true;
+  llvm::NoFramePointerElim = true;
+  llvm::ExceptionHandling = true;
+  llvm::Module *module = jit::globalModule = new llvm::Module ("microvm");
+  jit::globalModuleProvider = new llvm::ExistingModuleProvider (jit::globalModule);
+  jit::memoryManager = new MvmMemoryManager();
+  
+  initialiseTypes(globalModule);
+
+  executionEngine = llvm::ExecutionEngine::createJIT(jit::globalModuleProvider, 0, jit::memoryManager);
+  executionEngine->InstallExceptionTableRegister(__register_frame);
+  
+  ptrType = PointerType::getUnqual(Type::Int8Ty);
+  
+  {
+    std::vector<const llvm::Type *> arg_types;
+    arg_types.insert (arg_types.begin (), llvm::PointerType::getUnqual(ptrType));
+    
+    llvm::FunctionType *mtype = llvm::FunctionType::get (llvm::Type::VoidTy, arg_types, false);
+    new llvm::Function(mtype,  llvm::GlobalValue::ExternalLinkage, "llvm.va_start", module);
+  }
+
+  {
+    std::vector<const llvm::Type *> arg_types;
+    arg_types.insert (arg_types.begin (), llvm::Type::Int32Ty);
+  
+    llvm::FunctionType *mtype = llvm::FunctionType::get (ptrType, arg_types, false);
+    new llvm::Function(mtype,  llvm::GlobalValue::ExternalLinkage, "llvm.frameaddress", module);
+  }
+
+  {
+     const llvm::Type *BPTy = ptrType;
+     // Prototype malloc as "char* malloc(...)", because we don't know in
+     // doInitialization whether size_t is int or long.
+     FunctionType *FT = FunctionType::get(BPTy, std::vector<const llvm::Type*>(), true);
+     new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, "_ZN2gcnwEjP5gc_vt", module); 
+  }
+
+
+  // Create printFloatLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(Type::FloatTy);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  printFloatLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "printFloat",
+                     module);
+  }
+  
+  // Create printDoubleLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(Type::DoubleTy);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  printDoubleLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "printDouble",
+                     module);
+  }
+  
+  // Create printLongLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(Type::Int64Ty);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  printLongLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "printLong",
+                     module);
+  }
+  
+  // Create printIntLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(Type::Int32Ty);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  printIntLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "printInt",
+                     module);
+  }
+  
+  // Create printObjectLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(ptrType);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  printObjectLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "printObject",
+                     module);
+  }
+
+
+   {
+  const PointerType* PointerTy_0 = ptrType;
+
+  std::vector<const Type*>FuncTy_4_args;
+  FuncTy_4_args.push_back(IntegerType::get(32));
+
+
+  std::vector<const Type*>FuncTy_7_args;  
+  FuncTy_7_args.push_back(PointerTy_0);
+  FuncTy_7_args.push_back(PointerTy_0);
+  std::vector<const Type*>FuncTy_9_args;
+  FuncTy_9_args.push_back(PointerTy_0);
+  FunctionType* FuncTy_9 = FunctionType::get(
+    /*Result=*/Type::VoidTy,
+    /*Params=*/FuncTy_9_args,
+    /*isVarArg=*/false);
+  PointerType* PointerTy_8 = PointerType::getUnqual(FuncTy_9);
+  
+  FuncTy_7_args.push_back(PointerTy_8);
+
+  std::vector<const Type*>FuncTy_11_args;
+  FunctionType* FuncTy_11 = FunctionType::get(
+    /*Result=*/PointerTy_0,
+    /*Params=*/FuncTy_11_args,
+    /*isVarArg=*/false);
+
+  llvmGetException = new Function(
+    /*Type=*/FuncTy_11,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.eh.exception", module); // (external, no body)
+  
+  std::vector<const Type*>FuncTy_13_args;
+  FuncTy_13_args.push_back(PointerTy_0);
+  FuncTy_13_args.push_back(PointerTy_0);
+  FunctionType* FuncTy_13 = FunctionType::get(
+    /*Result=*/IntegerType::get(32),
+    /*Params=*/FuncTy_13_args,
+    /*isVarArg=*/true);
+
+  if (sizeof(void*) == 4) {
+    exceptionSelector = new Function(
+    /*Type=*/FuncTy_13,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.eh.selector.i32", module); // (external, no body)
+  } else {
+    exceptionSelector = new Function(
+    /*Type=*/FuncTy_13,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"llvm.eh.selector.i64", module); // (external, no body)
+  }
+  
+  std::vector<const Type*>FuncTy_19_args;
+  FunctionType* FuncTy_19 = FunctionType::get(
+    /*Result=*/Type::VoidTy,
+    /*Params=*/FuncTy_19_args,
+    /*isVarArg=*/false);
+
+  personality = new Function(
+    /*Type=*/FuncTy_19,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"__gxx_personality_v0", module); // (external, no body)
+  
+  unwindResume = new Function(
+    /*Type=*/FuncTy_9,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"_Unwind_Resume_or_Rethrow", module); // (external, no body)
+  
+    
+  std::vector<const Type*>FuncTy_17_args;
+  FuncTy_17_args.push_back(PointerTy_0);
+  FunctionType* FuncTy_17 = FunctionType::get(
+    /*Result=*/PointerTy_0,
+    /*Params=*/FuncTy_17_args,
+    /*isVarArg=*/false);
+
+  exceptionBeginCatch = new Function(
+    /*Type=*/FuncTy_17,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"__cxa_begin_catch", module); // (external, no body)
+  
+  exceptionEndCatch = new Function(
+    /*Type=*/FuncTy_19,
+    /*Linkage=*/GlobalValue::ExternalLinkage,
+    /*Name=*/"__cxa_end_catch", module); // (external, no body)
+  }
+
+  // Math function
+  {
+    std::vector<const Type*>args1;
+    args1.push_back(Type::DoubleTy);
+    FunctionType* FuncTy = FunctionType::get(
+      /*Result=*/Type::DoubleTy,
+      /*Params=*/args1,
+      /*isVarArg=*/false);
+    
+    func_llvm_sqrt_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "llvm.sqrt.f64", module);
+    func_llvm_sin_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "llvm.sin.f64", module);
+    func_llvm_cos_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "llvm.cos.f64", module);
+    func_llvm_tan_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "tan", module);
+    func_llvm_asin_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "asin", module);
+    func_llvm_acos_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "acos", module);
+    func_llvm_atan_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "atan", module);
+    func_llvm_exp_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "exp", module);
+    func_llvm_log_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "log", module);
+    func_llvm_ceil_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "ceil", module);
+    func_llvm_floor_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "floor", module);
+    func_llvm_cbrt_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "cbrt", module);
+    func_llvm_cosh_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "cosh", module);
+    func_llvm_expm1_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "expm1", module);
+    func_llvm_log10_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "log10", module);
+    func_llvm_log1p_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "log1p", module);
+    func_llvm_sinh_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "sinh", module);
+    func_llvm_tanh_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "tanh", module);
+    func_llvm_fabs_f64 = new Function(FuncTy, GlobalValue::ExternalLinkage, "fabs", module);
+    
+    std::vector<const Type*>args2;
+    args2.push_back(Type::DoubleTy);
+    args2.push_back(Type::DoubleTy);
+    FunctionType* FuncTy2 = FunctionType::get(
+      /*Result=*/Type::DoubleTy,
+      /*Params=*/args2,
+      /*isVarArg=*/false);
+  
+    func_llvm_hypot_f64 = new Function(FuncTy2, GlobalValue::ExternalLinkage, "hypot", module);
+    //func_llvm_pow_f64 = new Function(FuncTy2, GlobalValue::ExternalLinkage, "llvm.pow.f64", module);
+    func_llvm_pow_f64 = new Function(FuncTy2, GlobalValue::ExternalLinkage, "pow", module);
+    func_llvm_atan2_f64 = new Function(FuncTy2, GlobalValue::ExternalLinkage, "atan2", module);
+    
+    std::vector<const Type*>args3;
+    args3.push_back(Type::DoubleTy);
+    FunctionType* FuncTy3 = FunctionType::get(
+      /*Result=*/Type::DoubleTy,
+      /*Params=*/args3,
+      /*isVarArg=*/false);
+    
+    func_llvm_rint_f64 = new Function(FuncTy3, GlobalValue::ExternalLinkage, "rint", module);
+    
+    std::vector<const Type*>args4;
+    args4.push_back(Type::FloatTy);
+    FunctionType* FuncTyF = FunctionType::get(
+      /*Result=*/Type::FloatTy,
+      /*Params=*/args4,
+      /*isVarArg=*/false);
+    
+    func_llvm_fabs_f32 = new Function(FuncTyF, GlobalValue::ExternalLinkage, "fabsf", module);
+
+  }
+
+  // Create setjmp
+  {
+    std::vector<const Type*> args;
+    args.push_back(ptrType);
+    const FunctionType* type = FunctionType::get(Type::Int32Ty, args,
+                                               false);
+
+    setjmpLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "setjmp",
+                     module);
+    
+  }
+
+    /* Create memcpy */
+  {
+    PointerType* PointerTy_2 = PointerType::getUnqual(IntegerType::get(8));
+    std::vector<const Type*>FuncTy_4_args;
+    FuncTy_4_args.push_back(PointerTy_2);
+    FuncTy_4_args.push_back(PointerTy_2);
+    FuncTy_4_args.push_back(IntegerType::get(32));
+    FuncTy_4_args.push_back(IntegerType::get(32));
+    FunctionType* FuncTy_4 = FunctionType::get(
+      /*Result=*/Type::VoidTy,
+      /*Params=*/FuncTy_4_args,
+      /*isVarArg=*/false);
+    llvm_memcpy_i32 = new Function(
+      /*Type=*/FuncTy_4,
+      /*Linkage=*/GlobalValue::ExternalLinkage,
+      /*Name=*/"llvm.memcpy.i32", module); // (external, no body)
+  }
+  
+  /* Create memset */
+  {
+    PointerType* PointerTy_2 = PointerType::getUnqual(IntegerType::get(8));
+    std::vector<const Type*>FuncTy_4_args;
+    FuncTy_4_args.push_back(PointerTy_2);
+    FuncTy_4_args.push_back(IntegerType::get(8));
+    FuncTy_4_args.push_back(IntegerType::get(32));
+    FuncTy_4_args.push_back(IntegerType::get(32));
+    FunctionType* FuncTy_4 = FunctionType::get(
+      /*Result=*/Type::VoidTy,
+      /*Params=*/FuncTy_4_args,
+      /*isVarArg=*/false);
+    llvm_memset_i32 = new Function(
+      /*Type=*/FuncTy_4,
+      /*Linkage=*/GlobalValue::ExternalLinkage,
+      /*Name=*/"llvm.memset.i32", module); // (external, no body)
+  }
+
+  
+    // Constant declaration
+  constantLongMinusOne = ConstantInt::get(Type::Int64Ty, -1);
+  constantLongZero = ConstantInt::get(Type::Int64Ty, 0);
+  constantLongOne = ConstantInt::get(Type::Int64Ty, 1);
+  constantZero = ConstantInt::get(Type::Int32Ty, 0);
+  constantInt8Zero = ConstantInt::get(Type::Int8Ty, 0);
+  constantOne = ConstantInt::get(Type::Int32Ty, 1);
+  constantTwo = ConstantInt::get(Type::Int32Ty, 2);
+  constantThree = ConstantInt::get(Type::Int32Ty, 3);
+  constantFour = ConstantInt::get(Type::Int32Ty, 4);
+  constantFive = ConstantInt::get(Type::Int32Ty, 5);
+  constantSix = ConstantInt::get(Type::Int32Ty, 6);
+  constantSeven = ConstantInt::get(Type::Int32Ty, 7);
+  constantEight = ConstantInt::get(Type::Int32Ty, 8);
+  constantMinusOne = ConstantInt::get(Type::Int32Ty, -1);
+  constantMinInt = ConstantInt::get(Type::Int32Ty, MinInt);
+  constantMaxInt = ConstantInt::get(Type::Int32Ty, MaxInt);
+  constantMinLong = ConstantInt::get(Type::Int64Ty, MinLong);
+  constantMaxLong = ConstantInt::get(Type::Int64Ty, MaxLong);
+  constantFloatZero = ConstantFP::get(Type::FloatTy, APFloat(0.0f));
+  constantFloatOne = ConstantFP::get(Type::FloatTy, APFloat(1.0f));
+  constantFloatTwo = ConstantFP::get(Type::FloatTy, APFloat(2.0f));
+  constantDoubleZero = ConstantFP::get(Type::DoubleTy, APFloat(0.0));
+  constantDoubleOne = ConstantFP::get(Type::DoubleTy, APFloat(1.0));
+  constantMaxIntFloat = ConstantFP::get(Type::FloatTy, APFloat(MaxIntFloat));
+  constantMinIntFloat = ConstantFP::get(Type::FloatTy, APFloat(MinIntFloat));
+  constantMinLongFloat = ConstantFP::get(Type::FloatTy, APFloat(MinLongFloat));
+  constantMinLongDouble = ConstantFP::get(Type::DoubleTy, APFloat(MinLongDouble));
+  constantMaxLongFloat = ConstantFP::get(Type::FloatTy, APFloat(MaxLongFloat));
+  constantMaxIntDouble = ConstantFP::get(Type::DoubleTy, APFloat(MaxIntDouble));
+  constantMinIntDouble = ConstantFP::get(Type::DoubleTy, APFloat(MinIntDouble));
+  constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, APFloat(MaxLongDouble));
+  constantMaxLongDouble = ConstantFP::get(Type::DoubleTy, APFloat(MaxLongDouble));
+  constantFloatInfinity = ConstantFP::get(Type::FloatTy, APFloat(MaxFloat));
+  constantFloatMinusInfinity = ConstantFP::get(Type::FloatTy, APFloat(MinFloat));
+  constantDoubleInfinity = ConstantFP::get(Type::DoubleTy, APFloat(MaxDouble));
+  constantDoubleMinusInfinity = ConstantFP::get(Type::DoubleTy, APFloat(MinDouble));
+  constantDoubleMinusZero = ConstantFP::get(Type::DoubleTy, APFloat(-0.0));
+  constantFloatMinusZero = ConstantFP::get(Type::FloatTy, APFloat(-0.0f));
+
+  constantPtrNull = Constant::getNullValue(ptrType); 
+  arrayPtrType = PointerType::getUnqual(ArrayType::get(Type::Int8Ty, 0));
+  
+
+  //mvm::jit::protectTypes = mvm::Lock::allocNormal();
+  //mvm::Object::pushRoot((mvm::Object*)mvm::jit::protectTypes);
+  
+  //mvm::jit::protectConstants = mvm::Lock::allocNormal();
+  //mvm::Object::pushRoot((mvm::Object*)mvm::jit::protectConstants);
+  
+  mvm::jit::protectEngine = mvm::Lock::allocNormal();
+  mvm::Object::pushRoot((mvm::Object*)mvm::jit::protectEngine);
+
+}
+
+llvm::Function* mvm::jit::llvm_memcpy_i32;
+llvm::Function* mvm::jit::llvm_memset_i32;
+
+llvm::Function* mvm::jit::exceptionEndCatch;
+llvm::Function* mvm::jit::exceptionBeginCatch;
+llvm::Function* mvm::jit::unwindResume;
+llvm::Function* mvm::jit::exceptionSelector;
+llvm::Function* mvm::jit::personality;
+llvm::Function* mvm::jit::llvmGetException;
+
+llvm::Function* mvm::jit::printFloatLLVM;
+llvm::Function* mvm::jit::printDoubleLLVM;
+llvm::Function* mvm::jit::printLongLLVM;
+llvm::Function* mvm::jit::printIntLLVM;
+llvm::Function* mvm::jit::printObjectLLVM;
+
+llvm::Function* mvm::jit::setjmpLLVM;
+
+llvm::Function* mvm::jit::func_llvm_fabs_f32;
+llvm::Function* mvm::jit::func_llvm_fabs_f64;
+llvm::Function* mvm::jit::func_llvm_sqrt_f64;
+llvm::Function* mvm::jit::func_llvm_sin_f64;
+llvm::Function* mvm::jit::func_llvm_cos_f64;
+llvm::Function* mvm::jit::func_llvm_tan_f64;
+llvm::Function* mvm::jit::func_llvm_asin_f64;
+llvm::Function* mvm::jit::func_llvm_acos_f64;
+llvm::Function* mvm::jit::func_llvm_atan_f64;
+llvm::Function* mvm::jit::func_llvm_atan2_f64;
+llvm::Function* mvm::jit::func_llvm_exp_f64;
+llvm::Function* mvm::jit::func_llvm_log_f64;
+llvm::Function* mvm::jit::func_llvm_pow_f64;
+llvm::Function* mvm::jit::func_llvm_ceil_f64;
+llvm::Function* mvm::jit::func_llvm_floor_f64;
+llvm::Function* mvm::jit::func_llvm_rint_f64;
+llvm::Function* mvm::jit::func_llvm_cbrt_f64;
+llvm::Function* mvm::jit::func_llvm_cosh_f64;
+llvm::Function* mvm::jit::func_llvm_expm1_f64;
+llvm::Function* mvm::jit::func_llvm_hypot_f64;
+llvm::Function* mvm::jit::func_llvm_log10_f64;
+llvm::Function* mvm::jit::func_llvm_log1p_f64;
+llvm::Function* mvm::jit::func_llvm_sinh_f64;
+llvm::Function* mvm::jit::func_llvm_tanh_f64;
+
+llvm::ExecutionEngine* mvm::jit::executionEngine;
+
+//mvm::Lock* mvm::jit::protectTypes;
+//mvm::Lock* mvm::jit::protectConstants;
+mvm::Lock* mvm::jit::protectEngine;
+llvm::ConstantInt* mvm::jit::constantInt8Zero;
+llvm::ConstantInt* mvm::jit::constantZero;
+llvm::ConstantInt* mvm::jit::constantOne;
+llvm::ConstantInt* mvm::jit::constantTwo;
+llvm::ConstantInt* mvm::jit::constantThree;
+llvm::ConstantInt* mvm::jit::constantFour;
+llvm::ConstantInt* mvm::jit::constantFive;
+llvm::ConstantInt* mvm::jit::constantSix;
+llvm::ConstantInt* mvm::jit::constantSeven;
+llvm::ConstantInt* mvm::jit::constantEight;
+llvm::ConstantInt* mvm::jit::constantMinusOne;
+llvm::ConstantInt* mvm::jit::constantLongMinusOne;
+llvm::ConstantInt* mvm::jit::constantLongZero;
+llvm::ConstantInt* mvm::jit::constantLongOne;
+llvm::ConstantInt* mvm::jit::constantMinInt;
+llvm::ConstantInt* mvm::jit::constantMaxInt;
+llvm::ConstantInt* mvm::jit::constantMinLong;
+llvm::ConstantInt* mvm::jit::constantMaxLong;
+llvm::ConstantFP*  mvm::jit::constantFloatZero;
+llvm::ConstantFP*  mvm::jit::constantFloatOne;
+llvm::ConstantFP*  mvm::jit::constantFloatTwo;
+llvm::ConstantFP*  mvm::jit::constantDoubleZero;
+llvm::ConstantFP*  mvm::jit::constantDoubleOne;
+llvm::ConstantFP*  mvm::jit::constantMaxIntFloat;
+llvm::ConstantFP*  mvm::jit::constantMinIntFloat;
+llvm::ConstantFP*  mvm::jit::constantMinLongFloat;
+llvm::ConstantFP*  mvm::jit::constantMinLongDouble;
+llvm::ConstantFP*  mvm::jit::constantMaxLongFloat;
+llvm::ConstantFP*  mvm::jit::constantMaxIntDouble;
+llvm::ConstantFP*  mvm::jit::constantMinIntDouble;
+llvm::ConstantFP*  mvm::jit::constantMaxLongDouble;
+llvm::ConstantFP*  mvm::jit::constantDoubleInfinity;
+llvm::ConstantFP*  mvm::jit::constantDoubleMinusInfinity;
+llvm::ConstantFP*  mvm::jit::constantFloatInfinity;
+llvm::ConstantFP*  mvm::jit::constantFloatMinusInfinity;
+llvm::ConstantFP*  mvm::jit::constantFloatMinusZero;
+llvm::ConstantFP*  mvm::jit::constantDoubleMinusZero;
+llvm::Constant*    mvm::jit::constantPtrNull;
+const llvm::PointerType* mvm::jit::ptrType;
+const llvm::Type* mvm::jit::arrayPtrType;
+
+llvm::Module *mvm::jit::globalModule;
+llvm::ExistingModuleProvider *mvm::jit::globalModuleProvider;
+llvm::JITMemoryManager *mvm::jit::memoryManager;
+
+
+uint64 mvm::jit::getTypeSize(const llvm::Type* type) {
+  return executionEngine->getTargetData()->getABITypeSize(type);
+}
+
+extern "C" void __deregister_frame(void*);
+
+void ExceptionTable::destroyer(size_t sz) {
+  __deregister_frame(this->frameRegister());
+}
+
+void mvm::jit::runPasses(llvm::Function* func,  llvm::FunctionPassManager* pm) {
+  llvm::MutexGuard locked(mvm::jit::executionEngine->lock);
+  pm->run(*func);
+}
+
+void mvm::jit::protectConstants() {
+  mvm::jit::executionEngine->lock.acquire();
+}
+
+void mvm::jit::unprotectConstants() {
+  mvm::jit::executionEngine->lock.release();
+}
+
+void mvm::jit::protectTypes() {
+  mvm::jit::executionEngine->lock.acquire();
+}
+
+void mvm::jit::unprotectTypes() {
+  mvm::jit::executionEngine->lock.release();
+}
diff --git a/vmkit/lib/Mvm/Main.cc b/vmkit/lib/Mvm/Main.cc
new file mode 100644
index 0000000..1c25915
--- /dev/null
+++ b/vmkit/lib/Mvm/Main.cc
@@ -0,0 +1,57 @@
+//===--------------- Main.cc - Execution of the mvm -----------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/GC/GC.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Thread.h"
+#include "mvm/Sigsegv.h"
+#include "mvm/VMLet.h"
+
+
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+
+#include "CommandLine.h"
+
+using namespace mvm;
+
+
+typedef int (*boot)(int, char**, char**);
+
+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);
+}
+
+int main(int argc, char **argv, char **envp) {
+  llvm::llvm_shutdown_obj X;  
+  int base;
+  llvm::cl::ParseCommandLineOptions(argc, argv,
+                                    " VMKit: a virtual machine launcher\n");
+  Object::initialise(&base);
+  VMLet::initialise();
+  
+  CommandLine cl;
+  cl.start();
+   
+  clearSignals();
+	Thread::exit(0);
+    
+  return 0;
+}
diff --git a/vmkit/lib/Mvm/Makefile.am b/vmkit/lib/Mvm/Makefile.am
new file mode 100644
index 0000000..cfbf317
--- /dev/null
+++ b/vmkit/lib/Mvm/Makefile.am
@@ -0,0 +1,23 @@
+SUBDIRS = CommonThread Allocator GCMmap2
+DIST_SUBDIRS = CommonThread Allocator GCMmap2
+
+bin_PROGRAMS = main
+uvmdatadir=$(pkgdatadir)/lib
+
+THREADDIR=CommonThread
+ALLOCDIR=Allocator
+GCDIR=GCMmap2
+INCLUDEDIRS=-I@srcdir@/$(THREADDIR) -I@srcdir@/$(ALLOCDIR) -I@srcdir@/$(GCDIR)\
+	    @bare_header@
+
+LIBTHREAD=$(THREADDIR)/libuvm_@vvmthreadtype@_thread.a
+LIBALLOC=$(ALLOCDIR)/libuvm_alloc.a
+LIBGC=$(GCDIR)/libuvm_gc_@vvmgctype@.a @GC_LIBS@
+MAIN_O=main-main.o
+LIBSUVM=$(LIBLLVM) $(LIBGC) $(LIBALLOC) $(LIBTHREAD)
+PREFIX=@prefix@
+
+main_SOURCES = Main.cc Object.cc Sigsegv.cc JIT.cc CommandLine.cpp CommandLine.h MvmMemoryManager.h MvmMemoryManager.cpp EscapeAnalysis.cpp
+main_CXXFLAGS = $(INCLUDEDIRS) -DPREFIX=\"$(PREFIX)\" -W -Wall -ansi -Wno-unused-parameter -pedantic -Wno-long-long -fno-omit-frame-pointer -O2 -g
+main_LDFLAGS=@rdynamic@
+main_LDADD = $(LIBSUVM) @LLVMDYLIB@ -lopcodes -lbfd -liberty
diff --git a/vmkit/lib/Mvm/MvmMemoryManager.cpp b/vmkit/lib/Mvm/MvmMemoryManager.cpp
new file mode 100644
index 0000000..2ac012c
--- /dev/null
+++ b/vmkit/lib/Mvm/MvmMemoryManager.cpp
@@ -0,0 +1,75 @@
+//===----- MvmMemoryManager.cpp - LLVM Memory manager for Mvm -------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+
+#include "mvm/Method.h"
+#include "mvm/Object.h"
+
+#include "MvmMemoryManager.h"
+
+using namespace mvm;
+using namespace llvm;
+
+unsigned char* MvmMemoryManager::startFunctionBody(const Function* F, 
+                                                   uintptr_t &ActualSize) {
+  size_t nbb = ((ActualSize - 1) & -4) + 4 + sizeof(Method *);
+  Code *res = (Code *)Object::gcmalloc(nbb, Code::VT);
+  
+  Method* meth = gc_new(Method)(res, ActualSize);
+  res->method(meth);
+  currentMethod = meth;
+  return (unsigned char*) (res + 1);
+}
+
+unsigned char *MvmMemoryManager::allocateStub(unsigned StubSize, 
+                                              unsigned Alignment) {
+  size_t nbb = ((StubSize - 1) & -4) + 4 + sizeof(Method *);
+  Code *res = (Code *)Object::gcmalloc(nbb, Code::VT); 
+  Method* meth = gc_new(Method)(res, StubSize);
+  res->method(meth);
+  Object::pushRoot(meth);
+  return (unsigned char*) (res + 1); 
+}
+
+void MvmMemoryManager::endFunctionBody(const Function *F, 
+                                       unsigned char *FunctionStart,
+                                       unsigned char *FunctionEnd) {
+}
+
+
+void MvmMemoryManager::deallocateMemForFunction(const Function *F) {
+}
+
+void MvmMemoryManager::AllocateGOT() {
+  assert(GOTBase == 0 && "Cannot allocate the got multiple times");
+  GOTBase = new unsigned char[sizeof(void*) * 8192];
+  HasGOT = true;
+}
+
+unsigned char *MvmMemoryManager::getGOTBase() const {
+  return GOTBase;
+}
+
+unsigned char *MvmMemoryManager::startExceptionTable(const Function* F, 
+                                                     uintptr_t &ActualSize) {
+  ExceptionTable *res = (ExceptionTable*)Object::gcmalloc(ActualSize + 4, 
+                                                          ExceptionTable::VT);
+  currentMethod->exceptionTable(res);
+  return (unsigned char*)(res + 1);
+}                                                     
+
+void MvmMemoryManager::endExceptionTable(const Function *F, 
+                                         unsigned char *TableStart,
+                                         unsigned char *TableEnd,
+                                         unsigned char* FrameRegister) {
+  ExceptionTable* table = currentMethod->exceptionTable();
+  table->frameRegister(FrameRegister);
+}
+
diff --git a/vmkit/lib/Mvm/MvmMemoryManager.h b/vmkit/lib/Mvm/MvmMemoryManager.h
new file mode 100644
index 0000000..4c61be9
--- /dev/null
+++ b/vmkit/lib/Mvm/MvmMemoryManager.h
@@ -0,0 +1,86 @@
+//===------- MvmMemoryManager.h - LLVM Memory manager for Mvm -------------===//
+//
+//                              Mvm
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef MVM_MEMORY_MANAGER_H
+#define MVM_MEMORY_MANAGER_H
+
+#include <llvm/ExecutionEngine/JITMemoryManager.h>
+
+using namespace llvm;
+
+namespace mvm {
+
+class Method;
+class Object;
+
+class MvmMemoryManager : public JITMemoryManager {
+  Method* currentMethod;       // Current method being compiled
+  unsigned char *GOTBase;      // Target Specific reserved memory
+public:
+  
+  MvmMemoryManager() : JITMemoryManager() { GOTBase = 0; }
+   ~MvmMemoryManager() { delete[] GOTBase; }     
+  /// startFunctionBody - When we start JITing a function, the JIT calls this 
+  /// method to allocate a block of free RWX memory, which returns a pointer to
+  /// it.  The JIT doesn't know ahead of time how much space it will need to
+  /// emit the function, so it doesn't pass in the size.  Instead, this method
+  /// is required to pass back a "valid size".  The JIT will be careful to not
+  /// write more than the returned ActualSize bytes of memory. 
+  virtual unsigned char *startFunctionBody(const Function *F, 
+                                           uintptr_t &ActualSize);
+  
+  /// allocateStub - This method is called by the JIT to allocate space for a
+  /// function stub (used to handle limited branch displacements) while it is
+  /// JIT compiling a function.  For example, if foo calls bar, and if bar
+  /// either needs to be lazily compiled or is a native function that exists too
+  /// far away from the call site to work, this method will be used to make a
+  /// thunk for it.  The stub should be "close" to the current function body,
+  /// but should not be included in the 'actualsize' returned by
+  /// startFunctionBody.
+  virtual unsigned char *allocateStub(unsigned StubSize, unsigned Alignment);
+  
+  /// endFunctionBody - This method is called when the JIT is done codegen'ing
+  /// the specified function.  At this point we know the size of the JIT
+  /// compiled function.  This passes in FunctionStart (which was returned by
+  /// the startFunctionBody method) and FunctionEnd which is a pointer to the 
+  /// actual end of the function.  This method should mark the space allocated
+  /// and remember where it is in case the client wants to deallocate it.
+  virtual void endFunctionBody(const Function *F, unsigned char *FunctionStart,
+                               unsigned char *FunctionEnd);
+  
+  /// deallocateMemForFunction - Free JIT memory for the specified function.
+  /// This is never called when the JIT is currently emitting a function.
+  virtual void deallocateMemForFunction(const Function *F);
+  
+  /// AllocateGOT - If the current table requires a Global Offset Table, this
+  /// method is invoked to allocate it.  This method is required to set HasGOT
+  /// to true.
+  virtual void AllocateGOT();
+
+  /// getGOTBase - If this is managing a Global Offset Table, this method should
+  /// return a pointer to its base.
+  virtual unsigned char *getGOTBase() const;
+  
+
+  /// startExceptionTable - When we finished JITing the function, if exception
+  /// handling is set, we emit the exception table.
+  virtual unsigned char* startExceptionTable(const Function* F,
+                                             uintptr_t &ActualSize);
+  
+  /// endExceptionTable - This method is called when the JIT is done emitting
+  /// the exception table.
+  virtual void endExceptionTable(const Function *F, unsigned char *TableStart,
+                               unsigned char *TableEnd, 
+                               unsigned char* FrameRegister);
+};
+
+} // End mvm namespace
+
+#endif
diff --git a/vmkit/lib/Mvm/Object.cc b/vmkit/lib/Mvm/Object.cc
new file mode 100644
index 0000000..c2b34e4
--- /dev/null
+++ b/vmkit/lib/Mvm/Object.cc
@@ -0,0 +1,215 @@
+//===--------- Object.cc - Common objects for vmlets ----------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+#include "mvm/CollectableArea.h"
+#include "mvm/Method.h"
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/GC/GC.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Key.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/VMLet.h"
+
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
+
+
+using namespace mvm;
+
+VirtualTable *Object::VT = 0;
+VirtualTable *Method::VT = 0;
+VirtualTable *Code::VT = 0;
+VirtualTable *ExceptionTable::VT = 0;
+VirtualTable *NativeString::VT = 0;
+VirtualTable *PrintBuffer::VT = 0;
+//VirtualTable *Lock::VT = 0;
+//VirtualTable *LockNormal::VT = 0;
+//VirtualTable *LockRecursive::VT = 0;
+//VirtualTable *ThreadKey::VT = 0;
+//VirtualTable *Cond::VT = 0;
+
+
+Object **Object::rootTable= 0;
+int	  Object::rootTableSize= 0;
+int	  Object::rootTableLimit= 0;
+
+void Object::growRootTable(void) {
+  if (rootTableLimit != 0) {
+    assert(rootTable != 0);
+    rootTableLimit*= 2;
+    rootTable= (Object **)
+      ::realloc((void *)rootTable, rootTableLimit * sizeof(Object **));
+    return;
+  }
+  rootTableLimit= 32;
+  rootTable= (Object **)malloc(32 * sizeof(Object **));
+}
+
+
+void Object::markAndTraceRoots(void) {
+  for (int i= 0; i < rootTableSize; ++i)
+    rootTable[i]->markAndTrace();
+}
+
+size_t Object::objectSize(void) const {
+  return gc::objectSize();
+}
+
+bool Object::isObject() const { 
+  return gc::isObject(this); 
+}
+
+Object *Object::begOf() const { 
+  return (Object *)gc::begOf(this);
+}
+
+Object *Object::gcmalloc(size_t sz, VirtualTable* VT) {
+  return (Object *)operator new(sz, VT);
+}
+
+void Object::initialise(void *b_sp) {
+# define INIT(X) { \
+  X fake; \
+  X::VT = ((void**)(void*)(&fake))[0]; }
+  
+  INIT(Object);
+  INIT(Method);
+  INIT(Code);
+  INIT(NativeString);
+  INIT(PrintBuffer);
+  //INIT(Lock);
+  //INIT(LockNormal);
+  //INIT(LockRecursive);
+  //INIT(ThreadKey);
+  //INIT(Cond);
+  INIT(ExceptionTable);
+  
+#undef INIT
+
+  gc::initialise(Object::markAndTraceRoots, b_sp);
+}
+
+void Code::tracer(size_t sz) {
+	((Code *)this)->method(sz)->markAndTrace();
+}
+
+void Method::tracer(size_t sz) {
+	Method *const self= (Method *)this;
+  self->definition()->markAndTrace();
+  self->literals()->markAndTrace();
+  self->name()->markAndTrace();
+  self->code()->markAndTrace();
+  self->exceptionTable()->markAndTrace();
+}
+
+void PrintBuffer::tracer(size_t sz) {
+	((PrintBuffer *)this)->contents()->markAndTrace();
+}
+
+PrintBuffer *PrintBuffer::alloc(void) {
+  return allocPrintBuffer();
+}
+
+
+PrintBuffer *PrintBuffer::writeObj(const Object *obj) {
+	Object *beg = obj->begOf();
+	
+	if(beg) {
+		if(beg == obj)
+			obj->print((mvm::PrintBuffer*)this);
+		else {
+			write("<In Object [");
+			beg->print(this);
+			write("] -- offset ");
+			writeS4((int)obj - (int)beg);
+			write(">");
+		}
+	} else {
+		write("<DirectValue: ");
+		writeS4((int)obj);
+		write(">");
+	}
+	return this;
+}
+
+extern "C" void write_ptr(PrintBuffer* buf, void* obj) {
+  buf->writePtr(obj);
+}
+
+extern "C" void write_int(PrintBuffer* buf, int a) {
+  buf->writeS4(a);
+}
+
+extern "C" void write_str(PrintBuffer* buf, char* a) {
+  buf->write(a);
+}
+
+char *Object::printString(void) const {
+  PrintBuffer *buf= PrintBuffer::alloc();
+	buf->writeObj(this);
+  return buf->contents()->cString();
+}
+
+char * Object::printStatic(const Object * obj) {
+  return obj->printString();
+}
+
+void Object::print(PrintBuffer *buf) const {
+	buf->write("<Object@");
+	buf->writePtr((void*)this);
+  buf->write(">");
+}
+
+void Code::print(PrintBuffer *buf) const {
+	buf->write("Code<");
+	buf->write(">");
+}
+
+void Method::print(PrintBuffer *buf) const {
+  Method *const self= (Method *)this;
+	buf->write("Method<");
+  if (self->name()) {
+	  self->name()->print(buf);
+  } else {
+    buf->write("lambda");
+  }
+	buf->write(">");
+}
+
+void NativeString::print(PrintBuffer *buf) const {
+  NativeString *const self= (NativeString *)this;
+  buf->write("\"");
+  for (size_t i= 0; i < strlen(self->cString()); ++i) {
+    int c= self->cString()[i];
+    switch (c) {
+	    case '\b': buf->write("\\b"); break;
+	    case '\f': buf->write("\\f"); break;
+	    case '\n': buf->write("\\n"); break;
+	    case '\r': buf->write("\\r"); break;
+	    case '\t': buf->write("\\t"); break;
+	    case '"':  buf->write("\\\""); break;
+	    default: {
+	      char esc[32];
+	      if (c < 32)
+	        sprintf(esc, "\\x%02x", c);
+	      else
+	        sprintf(esc, "%c", c);
+	      buf->write(esc);
+	    }
+	  }
+  }
+  buf->write("\"");
+}
+
+NativeString      *PrintBuffer::getContents() { return contents(); }
diff --git a/vmkit/lib/Mvm/Sigsegv.cc b/vmkit/lib/Mvm/Sigsegv.cc
new file mode 100644
index 0000000..66f0d6d
--- /dev/null
+++ b/vmkit/lib/Mvm/Sigsegv.cc
@@ -0,0 +1,74 @@
+//===----------- Sigsegv.cc - Sigsegv default handling --------------------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "mvm/GC/GC.h"
+#include "mvm/Sigsegv.h"
+#include "mvm/VMLet.h"
+
+#include <signal.h>
+#include <stdio.h>
+
+using namespace mvm;
+
+void (*client_sigsegv_handler)(int, void *) = 0;
+
+#if defined(__MACH__) && defined(__i386__)
+#include "ucontext.h"
+#endif
+
+void sigsegv_handler(int n, siginfo_t *_info, void *context) {
+	void *addr = _info->si_addr;
+#if defined(__i386__)
+	struct frame {
+		struct frame *caller;
+		void         *ip;
+	};
+
+	struct frame *fp;	/* my frame */
+  asm ("mov %%ebp, %0" : "=&r"(fp)); /* get it */
+	struct frame *caller = fp->caller; /* my caller */
+  /* preserve my caller if I return from the handler */
+	void *caller_ip = caller->ip; 
+
+# if defined(__MACH__)
+  //.gregs[REG_EIP]; /* comme si c'était lui qui était sur la pile... */
+	caller->ip = (void *)((ucontext_t*)context)->uc_mcontext->ss.eip;
+# else
+  /* comme si c'était lui qui était sur la pile... */
+	caller->ip = (void *)((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP]; 
+# endif
+#endif
+	
+	/* Il faut libérer le gc si il s'est planté tout seul pendant une collection.
+	   Ca le laisse dans un état TRES instable, c'est à dire que plus aucune
+     collection n'est possible */
+	gc::die_if_sigsegv_occured_during_collection(addr);
+	
+	//	sys_exit(0);
+	if(client_sigsegv_handler)
+		client_sigsegv_handler(n, addr);
+	else
+		signal(SIGSEGV, SIG_DFL);
+	
+#if defined(__i386__)
+	caller->ip = caller_ip; /* restaure the caller ip */
+#endif
+}
+
+void VMLet::register_sigsegv_handler(void (*fct)(int, void *)) {
+	struct sigaction sa;
+
+	sigaction(SIGSEGV, 0, &sa);
+	sa.sa_sigaction = sigsegv_handler;
+	sa.sa_flags |= (SA_RESTART | SA_SIGINFO | SA_NODEFER);
+	sigaction(SIGSEGV, &sa, 0);
+	client_sigsegv_handler = fct;
+}
+
diff --git a/vmkit/lib/Mvm/VTOffset.cpp b/vmkit/lib/Mvm/VTOffset.cpp
new file mode 100644
index 0000000..45b39b7
--- /dev/null
+++ b/vmkit/lib/Mvm/VTOffset.cpp
@@ -0,0 +1,88 @@
+//===-- VTOffset.cpp - Calculates compiler dependant VT offsets -----------===//
+//
+//                     The Micro Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "mvm/GC/GC.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Thread.h"
+#include "mvm/Sigsegv.h"
+#include "mvm/VMLet.h"
+
+class Toto : public mvm::Object {
+public:
+  
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const {
+    printf("in print!\n");
+  }
+  virtual int hashCode() {
+    printf("in hashcode!\n");
+    return 1;
+  }
+
+  virtual void tracer(size_t sz) {
+    printf("in tracer\n");
+  }
+
+  virtual void destroyer(size_t sz) {
+    printf("in destroy!\n");
+  }
+
+  virtual ~Toto() {
+    printf("in delete Toto!\n");
+  }
+};
+
+static void clearSignals(void) {
+  sys_signal(SIGINT,  SIG_DFL);
+  sys_signal(SIGILL,  SIG_DFL);
+#if !defined(WIN32)
+  sys_signal(SIGIOT,  SIG_DFL);
+  sys_signal(SIGBUS,  SIG_DFL);
+#endif 
+  sys_signal(SIGSEGV, SIG_DFL);
+}
+
+
+VirtualTable* Toto::VT = 0;
+typedef void (*toto_t)(Toto* t);
+
+int main(int argc, char **argv, char **envp) {
+  int base;
+  
+  mvm::VMLet::initialise();
+  mvm::Object::initialise(&base);
+  
+  initialiseVT();
+  initialiseStatics();
+  
+  /*void* handle = sys_dlopen("libLisp.so", RTLD_LAZY | RTLD_GLOBAL);
+  boot func = (boot)sys_dlsym(handle, "boot");
+  func(argc, argv, envp);*/
+  
+  Toto t;
+  Toto::VT =((void**)(void*)&t)[0];
+  toto_t* ptr = (toto_t*)Toto::VT;
+  printf("ptr[0] = %d, ptr[1]= %d, ptr[2] = %d ptr[3] = %d ptr[4] = %d ptr[5] = %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
+  ptr[0](&t);
+  //ptr[1](&t); // This should be ~gc
+  ptr[2](&t);
+  ptr[3](&t);
+  ptr[4](&t);
+  ptr[5](&t);
+
+  clearSignals();
+  mvm::Thread::exit(0);
+   
+  return 0; 
+}
diff --git a/vmkit/lib/N3/Main.cpp b/vmkit/lib/N3/Main.cpp
new file mode 100644
index 0000000..61796fb
--- /dev/null
+++ b/vmkit/lib/N3/Main.cpp
@@ -0,0 +1,82 @@
+//===------------ Main.cpp - Simple execution of N3 -----------------------===//
+//
+//                            N3
+//
+// This file is distributed under the University of Illinois Open Source 
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/GC/GC.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/VMLet.h"
+#include "mvm/Threads/Thread.h"
+
+
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace mvm;
+
+
+typedef int (*boot_t)(int, char**, char**);
+
+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**);
+
+#include "VMCore/CLIJit.h"
+
+void handler2(int n, void *context) {
+  printf("[%d] crashed\n", (int)mvm::Thread::self());
+  n3::CLIJit::printBacktrace();
+  assert(0);
+}
+
+void handler(int n, siginfo_t *_info, void *context) {
+  printf("[%d] crashed\n", (int)mvm::Thread::self());
+  n3::CLIJit::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();
+  boot();
+  start_app(argc, argv);
+
+  clearSignals();
+    
+  return 0;
+}
diff --git a/vmkit/lib/N3/Makefile.am b/vmkit/lib/N3/Makefile.am
new file mode 100644
index 0000000..7c7a28c
--- /dev/null
+++ b/vmkit/lib/N3/Makefile.am
@@ -0,0 +1,20 @@
+SUBDIRS = VMCore
+bin_PROGRAMS = main
+
+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/libN3.a $(LIBSUVM) @LLVMDYLIB@ -lopcodes -lbfd -liberty
+main_LDFLAGS = @rdynamic@
diff --git a/vmkit/lib/N3/README b/vmkit/lib/N3/README
new file mode 100644
index 0000000..41d592a
--- /dev/null
+++ b/vmkit/lib/N3/README
@@ -0,0 +1,15 @@
+1 - Install pnetlib-0.7.4
+
+2 - Patch and compile pnet
+  tar zxvf pnet-0.7.4.tar.gz
+  patch -p0 < pnet-0.7.4.patch
+  ./auto_gen.sh
+  ./configure
+  make
+
+3 - Compile n3
+
+3 - Run
+  export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{dynamic libraries compiled in 2: pnet-0.7.4/engine/.libs:pnet-0.7.4/support/.libs}
+  export MSCORLIB={directory of pnetlib's mscorlib.dll}
+  ./run-n3 HelloWorld.exe
diff --git a/vmkit/lib/N3/VMCore/Assembly.cpp b/vmkit/lib/N3/VMCore/Assembly.cpp
new file mode 100644
index 0000000..ab18f19
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/Assembly.cpp
@@ -0,0 +1,1452 @@
+//===--------- Assembly.cpp - Definition of an assembly -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "debug.h"
+#include "types.h"
+
+#include "Assembly.h"
+#include "CLIAccess.h"
+#include "CLIString.h"
+#include "LockedMap.h"
+#include "N3.h"
+#include "Reader.h"
+#include "VirtualMachine.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+void Header::print(mvm::PrintBuffer* buf) const {
+  buf->write("Header<>");
+}
+
+void Section::print(mvm::PrintBuffer* buf) const {
+  buf->write("Section<>");
+}
+
+void Table::print(mvm::PrintBuffer* buf) const {
+  buf->write("Table<>");
+}
+
+void Stream::print(mvm::PrintBuffer* buf) const {
+  buf->write("Table<>");
+}
+
+void Assembly::print(mvm::PrintBuffer* buf) const {
+  buf->write("Assembly<");
+  name->print(buf);
+  buf->write(">");
+}
+
+static VMCommonClass* arrayDup(ClassNameCmp &cmp, Assembly* ass) {
+  VMClassArray* cl = gc_new(VMClassArray)();
+  cl->initialise(ass->vm, true);
+  cl->name = cmp.name;
+  cl->nameSpace = cmp.nameSpace;
+  cl->super = VMClassArray::SuperArray;
+  cl->interfaces = VMClassArray::InterfacesArray;
+  cl->virtualMethods = VMClassArray::VirtualMethodsArray;
+  cl->staticMethods = VMClassArray::StaticMethodsArray;
+  cl->virtualFields = VMClassArray::VirtualFieldsArray;
+  cl->staticFields = VMClassArray::StaticFieldsArray;
+  cl->depth = 1;
+  cl->display.push_back(VMClassArray::SuperArray);
+  cl->display.push_back(cl);
+  cl->status = loaded;
+  cl->assembly = ass;
+  return cl; 
+}
+
+VMClassArray* Assembly::constructArray(VMCommonClass* base, uint32 dims) {
+  if (this != base->assembly) 
+    return base->assembly->constructArray(base, dims);
+
+  ClassNameCmp CC(VMClassArray::constructArrayName(base->name, dims),
+                  base->nameSpace);
+  VMClassArray* cl = (VMClassArray*)(loadedNameClasses->lookupOrCreate(CC, this, arrayDup));
+  if (!cl->baseClass) {
+    cl->dims = dims;
+    if (dims > 1)
+      cl->baseClass = constructArray(base, dims - 1);
+    else
+      cl->baseClass = base;
+  }
+  return cl;
+}
+
+static VMCommonClass* pointerDup(ClassNameCmp &cmp, Assembly* ass) {
+  VMClassPointer* cl = gc_new(VMClassPointer)();
+  cl->initialise(ass->vm, false);
+  cl->isPointer = true;
+  cl->name = cmp.name;
+  cl->nameSpace = cmp.nameSpace;
+  cl->depth = 0;
+  cl->display.push_back(cl);
+  cl->status = loaded;
+  cl->assembly = ass;
+  return cl; 
+}
+
+VMClassPointer* Assembly::constructPointer(VMCommonClass* base, uint32 dims) {
+  if (this != base->assembly) 
+    return base->assembly->constructPointer(base, dims);
+  
+  ClassNameCmp CC(VMClassPointer::constructPointerName(base->name, dims),
+                  base->nameSpace);
+  VMClassPointer* cl = (VMClassPointer*)(loadedNameClasses->lookupOrCreate(CC, this, pointerDup));
+  if (!cl->baseClass) {
+    cl->dims = dims;
+    cl->baseClass = base;
+  }
+  return cl;
+}
+
+VMClassArray* Assembly::constructArray(const UTF8* name, const UTF8* nameSpace,
+                                       uint32 dims) {
+  assert(this == ((N3*)VMThread::get()->vm)->coreAssembly);
+  ClassNameCmp CC(VMClassArray::constructArrayName(name, dims),
+                  nameSpace);
+  VMClassArray* cl = (VMClassArray*)(loadedNameClasses->lookupOrCreate(CC, this, arrayDup));
+  cl->dims = dims;
+  return cl;
+}
+
+static VMCommonClass* classDup(ClassNameCmp &cmp, Assembly* ass) {
+  VMClass* cl = gc_new(VMClass)();
+  cl->initialise(ass->vm, false);
+  cl->name = cmp.name;
+  cl->nameSpace = cmp.nameSpace;
+  cl->virtualTracer = 0;
+  cl->staticInstance = 0;
+  cl->virtualInstance = 0;
+  cl->virtualType = 0;
+  cl->super = 0;
+  cl->status = hashed;
+  cl->assembly = ass;
+  return cl;
+}
+
+VMClass* Assembly::constructClass(const UTF8* name,
+                                  const UTF8* nameSpace, uint32 token) {
+  ClassNameCmp CC(name, nameSpace);
+  VMClass* cl = (VMClass*)loadedNameClasses->lookupOrCreate(CC, this, classDup);
+  loadedTokenClasses->lookupOrCreate(token, cl);
+  cl->token = token;
+  cl->assembly = this;
+  return cl;
+}
+
+static VMField* fieldDup(uint32& key, Assembly* ass) {
+  VMField* field = gc_new(VMField)();
+  field->token = key;
+  return field;
+}
+
+VMField*  Assembly::constructField(VMClass* cl, const UTF8* name,
+                                   VMCommonClass* signature,
+                                   uint32 token) {
+  VMField* field = loadedTokenFields->lookupOrCreate(token, this, fieldDup);
+  field->classDef = cl;
+  field->signature = signature;
+  field->name = name;
+  return field;
+}
+
+static VMMethod* methodDup(uint32& key, Assembly* ass) {
+  VMMethod* meth = gc_new(VMMethod)();
+  meth->token = key;
+  meth->canBeInlined = false;
+  return meth;
+}
+
+VMMethod* Assembly::constructMethod(VMClass* cl, const UTF8* name, 
+                                    uint32 token) {
+  VMMethod* meth = loadedTokenMethods->lookupOrCreate(token, this, methodDup);
+  meth->classDef = cl;
+  meth->_signature = 0;
+  meth->name = name;
+  return meth;
+}
+
+Assembly* Assembly::allocate(const UTF8* name) {
+  Assembly* ass = gc_new(Assembly)();
+  ass->loadedNameClasses = ClassNameMap::allocate();
+  ass->loadedTokenClasses = ClassTokenMap::allocate();
+  ass->loadedTokenMethods = MethodTokenMap::allocate();
+  ass->loadedTokenFields = FieldTokenMap::allocate();
+  ass->assemblyRefs = 0;
+  ass->isRead = false;
+  ass->name = name;
+  return ass;
+}
+
+static void unimplemented(uint32 index, std::vector<Table*>& tables,
+                          uint32 heapSizes) {
+  VMThread::get()->vm->error("Unknown table %x", index);
+}
+
+maskVector_t Assembly::maskVector[64] = {
+  METHOD_Module,                // 0x00
+  METHOD_TypeRef,               // 0x01
+  METHOD_TypeDef,               // 0x02
+  unimplemented,                // 0x03
+  METHOD_Field,                 // 0x04
+  unimplemented,                // 0x05
+  METHOD_MethodDef,             // 0x06
+  unimplemented,                // 0x07
+  METHOD_Param,                 // 0x08
+  METHOD_InterfaceImpl,         // 0x09
+  METHOD_MemberRef,             // 0x0A
+  METHOD_Constant,              // 0x0B
+  METHOD_CustomAttribute,       // 0x0C
+  METHOD_FieldMarshal,          // 0x0D
+  METHOD_DeclSecurity,          // 0x0E
+  METHOD_ClassLayout,           // 0x1F
+  METHOD_FieldLayout,           // 0x10
+  METHOD_StandaloneSig,         // 0x11
+  METHOD_EventMap,              // 0x12
+  unimplemented,                // 0x13
+  METHOD_Event,                 // 0x14
+  METHOD_PropertyMap,           // 0x15
+  unimplemented,                // 0x16
+  METHOD_Property,              // 0x17
+  METHOD_MethodSemantics,       // 0x18
+  METHOD_MethodImpl,            // 0x19
+  METHOD_ModuleRef,             // 0x1A
+  METHOD_TypeSpec,              // 0x1B
+  METHOD_ImplMap,               // 0x1C
+  METHOD_FieldRva,              // 0x1D
+  unimplemented,                // 0x1E
+  unimplemented,                // 0x1F
+  METHOD_Assembly,              // 0x20
+  METHOD_AssemblyProcessor,     // 0x21
+  METHOD_AssemblyOS,            // 0x22
+  METHOD_AssemblyRef,           // 0x23
+  unimplemented,                // 0x24
+  unimplemented,                // 0x25
+  METHOD_File,                  // 0x26
+  unimplemented,                // 0x27
+  METHOD_ManifestResource,      // 0x28
+  METHOD_NestedClass,           // 0x29
+  unimplemented,                // 0x2A
+  METHOD_MethodSpec,            // 0x2B
+  METHOD_GenericParamConstraint,// 0x2C
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented, 
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented,
+  unimplemented
+};
+
+const char* Assembly::maskVectorName[64] = {
+  "METHOD_Module",                // 0x00
+  "METHOD_TypeRef",               // 0x01
+  "METHOD_TypeDef",               // 0x02
+  "unimplemented",                // 0x03
+  "METHOD_Field",                 // 0x04
+  "unimplemented",                // 0x05
+  "METHOD_MethodDef",             // 0x06
+  "unimplemented",                // 0x07
+  "METHOD_Param",                 // 0x08
+  "METHOD_InterfaceImpl",         // 0x09
+  "METHOD_MemberRef",             // 0x0A
+  "METHOD_Constant",              // 0x0B
+  "METHOD_CustomAttribute",       // 0x0C
+  "METHOD_FieldMarshal",          // 0x0D
+  "METHOD_DeclSecurity",          // 0x0E
+  "METHOD_ClassLayout",           // 0x1F
+  "METHOD_FieldLayout",           // 0x10
+  "METHOD_StandaloneSig",         // 0x11
+  "METHOD_EventMap",              // 0x12
+  "unimplemented",                // 0x13
+  "METHOD_Event",                 // 0x14
+  "METHOD_PropertyMap",           // 0x15
+  "unimplemented",                // 0x16
+  "METHOD_Property",              // 0x17
+  "METHOD_MethodSemantics",       // 0x18
+  "METHOD_MethodImpl",            // 0x19
+  "METHOD_ModuleRef",             // 0x1A
+  "METHOD_TypeSpec",              // 0x1B
+  "METHOD_ImplMap",               // 0x1C
+  "METHOD_FieldRva",              // 0x1D
+  "unimplemented",                // 0x1E
+  "unimplemented",                // 0x1F
+  "METHOD_Assembly",              // 0x20
+  "METHOD_AssemblyProcessor",     // 0x21
+  "METHOD_AssemblyOS",            // 0x22
+  "METHOD_AssemblyRef",           // 0x23
+  "unimplemented",                // 0x24
+  "unimplemented",                // 0x25
+  "METHOD_File",                  // 0x26
+  "unimplemented",                // 0x27
+  "METHOD_ManifestResource",      // 0x28
+  "METHOD_NestedClass",           // 0x29
+  "unimplemented",                // 0x2A
+  "METHOD_MethodSpec",            // 0x2B
+  "METHOD_GenericParamConstraint", // 0x2C
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented", 
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented",
+  "unimplemented"
+};
+
+#define EXTRACT_SIZE(bitmask, index) \
+  (1 + (3 & (bitmask >> (index << 1))))
+
+void Table::readRow(uint32* result, uint32 row, ArrayUInt8* array) {
+  uint32 rowOffset = offset + ((row - 1) * rowSize);
+  for (uint32 i = 0; i < count; ++i) {
+    uint32 size = EXTRACT_SIZE(sizeMask, i);
+    switch(size) {
+      case 1: VMThread::get()->vm->error("implement me"); break;
+      case 2: result[i] = READ_U2(array, rowOffset); break;
+      case 4: result[i] = READ_U4(array, rowOffset); break;
+      default: VMThread::get()->vm->error("unknown size %d", size); break;
+    }
+  }
+}
+
+uint32 Table::readIndexInRow(uint32 row, uint32 index, ArrayUInt8* array) {
+  uint32 indexOffset = offset + ((row - 1) * rowSize);
+  for (uint32 i = 0; i < index; ++i) {
+    indexOffset += EXTRACT_SIZE(sizeMask, i);
+  }
+
+  uint32 size = EXTRACT_SIZE(sizeMask, index);
+
+  switch(size) {
+    case 1: VMThread::get()->vm->error("implement me"); break;
+    case 2: return READ_U2(array, indexOffset);
+    case 4: return READ_U4(array, indexOffset);
+    default: VMThread::get()->vm->error("unknown size %d", size); break;
+  }
+
+  // unreachable
+  return 0;
+}
+
+void Section::read(Reader* reader, N3* vm) {
+  name = (char*) malloc(SECTION_NAME_LENGTH);
+  memcpy(name, &(reader->bytes->elements[reader->cursor]),
+             SECTION_NAME_LENGTH);
+  reader->cursor += SECTION_NAME_LENGTH;
+
+  virtualSize       = reader->readU4();
+  virtualAddress    = reader->readU4();
+  rawSize           = reader->readU4();
+  rawAddress        = reader->readU4();
+  relocAddress      = reader->readU4();
+  lineNumbers       = reader->readU4();
+  relocationsNumber = reader->readU2();
+  lineNumbersNumber = reader->readU2();
+  characteristics   = reader->readU4();
+}
+
+void Header::read(Reader* reader, N3* vm) {
+  uint32 start = reader->cursor;
+  signature = reader->readU4();
+  major = reader->readU2();
+  minor = reader->readU2();
+  reserved = reader->readU4();
+  versionLength = reader->readU4();
+  versionName = Assembly::readUTF8(vm, versionLength, reader);
+  flags = reader->readU2();
+  nbStreams = reader->readU2();
+
+  for (uint32 i = 0; i < nbStreams; ++i) {
+    uint32 offset = reader->readU4();
+    uint32 size = reader->readU4();
+    uint32 len = 
+      strlen((char*)(&(reader->bytes->elements[reader->cursor])));
+
+    Stream* stream = gc_new(Stream)();
+    char* str = (char*)malloc(len + 1);
+    memcpy(str, &(reader->bytes->elements[reader->cursor]), len + 1);
+    reader->cursor += (len + (4 - (len % 4)));
+
+    stream->realOffset = start + offset;
+    stream->size = size;
+    stream->name = str;
+
+    if (!(strcmp(str, "#~"))) tildStream = stream;
+    else if (!(strcmp(str, "#Strings"))) stringStream = stream;
+    else if (!(strcmp(str, "#US"))) usStream = stream;
+    else if (!(strcmp(str, "#Blob"))) blobStream = stream;
+    else if (!(strcmp(str, "#GUID"))) guidStream = stream;
+    else VMThread::get()->vm->error("invalid stream %s", str);
+  }
+}
+
+const UTF8* Assembly::readUTF16(VirtualMachine* vm, uint32 len, 
+                                Reader* reader) {
+  return readUTF16(vm, len, reader->bytes, reader->cursor);
+}
+
+const UTF8* Assembly::readUTF16(VirtualMachine* vm, uint32 len, 
+                                ArrayUInt8* bytes, uint32 &offset) {
+  uint32 realLen = len >> 1;
+  uint16* buf = (uint16*)alloca(len);
+  uint32 i = 0;
+  while (i < realLen) {
+    uint16 cur = READ_U2(bytes, offset);
+    buf[i] = cur;
+    ++i;
+  }
+  const UTF8* utf8 = UTF8::readerConstruct(vm, buf, realLen);
+
+  return utf8;
+}
+
+const UTF8* Assembly::readUTF8(VirtualMachine* vm, uint32 len, Reader* reader) {
+  return readUTF8(vm, len, reader->bytes, reader->cursor);
+}
+
+const UTF8* Assembly::readUTF8(VirtualMachine* vm, uint32 len,
+                               ArrayUInt8* bytes, uint32 &offset) {
+  uint16* buf = (uint16*)alloca(len * sizeof(uint16));
+  uint32 n = 0;
+  uint32 i = 0;
+  
+  while (i < len) {
+    uint32 cur = READ_U1(bytes, offset);
+    if (cur & 0x80) {
+      uint32 y = READ_U1(bytes, offset);
+      if (cur & 0x20) {
+        uint32 z = READ_U1(bytes, offset);
+        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);
+
+  return utf8;
+}
+
+const UTF8* Assembly::readString(VirtualMachine* vm, uint32 offset) {
+  uint32 end = offset;
+  uint32 cur = 0;
+  while ((cur = READ_U1(bytes, end)) != 0);
+  return readUTF8(vm, (end - 1 - offset), bytes, offset);
+}
+
+void Assembly::readTables(Reader* reader) {
+  //uint32 reserved1 = 
+  reader->readU4();
+  //uint8 major = 
+  reader->readU1();
+  //uint8 minor = 
+  reader->readU1();
+  uint8 heapSizes = reader->readU1();
+  //uint8 reserved2 = 
+  reader->readU1();
+  uint32 validLow = reader->readU4();
+  uint32 validHigh = reader->readU4();
+  //uint32 sortedLow = 
+  reader->readU4();
+  //uint32 sortedHigh = 
+  reader->readU4();
+  uint32 tableNumber = 0;
+  uint32 offset = 0;
+
+  for (uint32 i = 0; i < 32; ++i) {
+    Table* table = gc_new(Table)();
+    if ((1 << i) & validLow) {
+      table->rowsNumber = reader->readU4();
+      ++tableNumber;
+    } else {
+      table->rowsNumber = 0;
+    }
+    CLIHeader->tables.push_back(table);
+  }
+
+  for (uint32 i = 0; i < 32; ++i) {
+    Table* table = gc_new(Table)();
+    if ((1 << i) & validHigh) {
+      table->rowsNumber = reader->readU4();
+      ++tableNumber;
+    } else {
+      table->rowsNumber = 0;
+    }
+    CLIHeader->tables.push_back(table);
+  }
+
+  offset = reader->cursor;
+  
+  uint32 index = 0;
+  for (std::vector<Table*>::iterator i = CLIHeader->tables.begin(),
+       e = CLIHeader->tables.end(); i != e; ++i, ++index) {
+    Table* table = (*i);
+    if (table->rowsNumber) {
+      maskVector[index](index, CLIHeader->tables, heapSizes);
+      table->offset = offset;
+      offset += (table->rowsNumber * table->rowSize);
+    }
+  }
+}
+
+void Assembly::read() {
+  Reader* reader = Reader::allocateReader(bytes);
+  PRINT_DEBUG(DEBUG_LOAD, 1, LIGHT_GREEN, "Reading %s::%s", vm->printString(),
+              this->printString());
+
+  textSection = gc_new(Section)();
+  rsrcSection = gc_new(Section)();
+  relocSection = gc_new(Section)();
+
+  reader->seek(TEXT_SECTION_HEADER, Reader::SeekSet);
+  textSection->read(reader, vm);
+  rsrcSection->read(reader, vm);
+  relocSection->read(reader, vm);
+
+  reader->seek(CLI_HEADER, Reader::SeekSet);
+  CLIHeaderLocation = reader->readU4();
+  reader->seek(textSection->rawAddress + 
+                  (CLIHeaderLocation - textSection->virtualAddress),
+               Reader::SeekSet);
+
+  cb          = reader->readU4();
+  major       = reader->readU2();
+  minor       = reader->readU2();
+  mdRva       = reader->readU4();
+  mdSize      = reader->readU4();
+  flags       = reader->readU4();
+  entryPoint  = reader->readU4();
+  resRva      = reader->readU4();
+  resSize     = reader->readU4();
+  
+  reader->seek(textSection->rawAddress + (mdRva - textSection->virtualAddress),
+               Reader::SeekSet);
+
+  CLIHeader = gc_new(Header)();
+  CLIHeader->read(reader, vm);
+
+  reader->seek(CLIHeader->tildStream->realOffset, Reader::SeekSet);
+
+  readTables(reader);
+}
+
+uint32 Assembly::getTypeDefTokenFromMethod(uint32 token) {
+  uint32 index = token & 0xffff;
+  Table* typeTable = CLIHeader->tables[CONSTANT_TypeDef];
+  uint32 nbRows = typeTable->rowsNumber;
+  bool found = false;
+  uint32 i = 0;
+  
+  while (!found && (i < nbRows - 1)) {
+    
+    uint32 myId = typeTable->readIndexInRow(i + 1, CONSTANT_TYPEDEF_METHODLIST,
+                                            bytes);
+    uint32 nextId = typeTable->readIndexInRow(i + 2, CONSTANT_TYPEDEF_METHODLIST,
+                                              bytes);
+
+    if (index < nextId && index >= myId) {
+      found = true;
+    } else {
+      ++i;
+    }
+  }
+  
+  return i + 1 + (CONSTANT_TypeDef << 24);
+}
+
+VMCommonClass* Assembly::readTypeSpec(N3* vm, uint32 index) {
+  uint32 blobOffset = CLIHeader->blobStream->realOffset;
+  Table* typeTable  = CLIHeader->tables[CONSTANT_TypeSpec];
+  uint32* typeArray = (uint32*)alloca(sizeof(uint32) * typeTable->rowSize);
+  typeTable->readRow(typeArray, index, bytes);
+  
+  uint32 signOffset = typeArray[CONSTANT_TYPESPEC_SIGNATURE];
+  
+  uint32 offset = blobOffset + signOffset;
+  return extractTypeInSignature(offset);
+  
+}
+
+VMCommonClass* Assembly::lookupClassFromName(const UTF8* name,
+                                             const UTF8* nameSpace) {
+  ClassNameCmp CC(name, nameSpace);
+  return loadedNameClasses->lookup(CC);
+}
+
+VMCommonClass* Assembly::lookupClassFromToken(uint32 token) {
+  return loadedTokenClasses->lookup(token);
+}
+
+VMMethod* Assembly::lookupMethodFromToken(uint32 token) {
+  return loadedTokenMethods->lookup(token);
+}
+VMField* Assembly::lookupFieldFromToken(uint32 token) {
+  return loadedTokenFields->lookup(token);
+}
+
+
+
+VMCommonClass* Assembly::getClassFromName(N3* vm, const UTF8* name,
+                                          const UTF8* nameSpace) {
+  VMCommonClass* type = lookupClassFromName(name, nameSpace);
+
+  if (type == 0) {
+    Table* typeTable  = CLIHeader->tables[CONSTANT_TypeDef];
+    uint32 nb = typeTable->rowsNumber;
+    uint32 stringOffset = CLIHeader->stringStream->realOffset;
+
+    for (uint32 i = 0; i < nb; ++i) {
+      uint32 value = typeTable->readIndexInRow(i + 1, CONSTANT_TYPEDEF_NAME, bytes);
+      const UTF8* curName = readString(vm, stringOffset + value);
+      if (name == curName) {
+        uint32 value = typeTable->readIndexInRow(i + 1,
+                                                 CONSTANT_TYPEDEF_NAMESPACE,
+                                                 bytes);
+        const UTF8* curNameSpace = readString(vm, stringOffset + value);
+        if (curNameSpace == nameSpace) {
+          return readTypeDef(vm, i + 1);
+        }
+      }
+    }
+  }
+
+  return type;
+}
+
+Assembly* Assembly::readAssemblyRef(N3* vm, uint32 index) {
+  if (assemblyRefs == 0) {
+    uint32 size = sizeof(Assembly*)*
+                      CLIHeader->tables[CONSTANT_AssemblyRef]->rowsNumber;
+    assemblyRefs = (Assembly**)malloc(size);
+    memset(assemblyRefs, 0, size);
+  }
+  Assembly* ref = assemblyRefs[index - 1];
+  if (ref == 0) {
+    uint32 stringOffset = CLIHeader->stringStream->realOffset;
+    Table* assTable = CLIHeader->tables[CONSTANT_AssemblyRef];
+    uint32* assArray = (uint32*)alloca(sizeof(uint32) * assTable->rowSize);
+    assTable->readRow(assArray, index, bytes);
+    const UTF8* name = 
+      readString(vm, stringOffset + assArray[CONSTANT_ASSEMBLY_REF_NAME]);
+    
+    ref = vm->loadAssembly(name, "dll");
+    if (ref == 0) VMThread::get()->vm->error("implement me");
+    assemblyRefs[index - 1] = ref;
+  }
+  return ref;
+}
+
+VMCommonClass* Assembly::readTypeRef(N3* vm, uint32 index) {
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  
+  Table* typeTable  = CLIHeader->tables[CONSTANT_TypeRef];
+  uint32* typeArray = (uint32*)alloca(sizeof(uint32) * typeTable->rowSize);
+  
+  typeTable->readRow(typeArray, index, bytes);
+
+  uint32 resScope   = typeArray[CONSTANT_TYPEREF_RESOLUTION_SCOPE];
+  uint32 name       = typeArray[CONSTANT_TYPEREF_NAME];
+  uint32 nameSpace  = typeArray[CONSTANT_TYPEREF_NAMESPACE];
+  
+
+  uint32 val = resScope & 3;
+  uint32 entry = resScope >> 2;
+  VMCommonClass* type = 0;
+  
+  switch (val) {
+    case 0: VMThread::get()->vm->error("implement me %d %d", val, entry); break;
+    case 1: VMThread::get()->vm->error("implement me %d, %d", val, entry); break;
+    case 2: {
+      Assembly* refAssembly = readAssemblyRef(vm, entry);
+      type = refAssembly->getClassFromName(vm, readString(vm, stringOffset + name), 
+                                           readString(vm, stringOffset + nameSpace));
+      break;
+    }
+    case 3: VMThread::get()->vm->error("implement me %d %d",val, entry); break;
+    default: 
+      VMThread::get()->vm->error("unkknown resolution scope %x", val);
+      break;
+  }
+  return type;
+}
+
+VMClass* Assembly::readTypeDef(N3* vm, uint32 index) {
+  uint32 token = (CONSTANT_TypeDef << 24) + index;
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+
+  Table* typeTable  = CLIHeader->tables[CONSTANT_TypeDef];
+  uint32* typeArray = (uint32*)alloca(sizeof(uint32) * typeTable->rowSize);
+  
+  typeTable->readRow(typeArray, index, bytes);
+
+  uint32 flags      = typeArray[CONSTANT_TYPEDEF_FLAGS];
+  uint32 name       = typeArray[CONSTANT_TYPEDEF_NAME];
+  uint32 nameSpace  = typeArray[CONSTANT_TYPEDEF_NAMESPACE];
+  uint32 extends    = typeArray[CONSTANT_TYPEDEF_EXTENDS];
+  //uint32 fieldList  = typeArray[CONSTANT_TYPEDEF_FIELDLIST];
+  //uint32 methodList = typeArray[CONSTANT_TYPEDEF_METHODLIST];
+
+  //Table* fieldTable   = CLIHeader->tables[CONSTANT_Field];
+  //uint32 fieldSize    = fieldTable->rowsNumber;
+  //Table* methodTable  = CLIHeader->tables[CONSTANT_MethodDef];
+  //uint32 methodSize   = methodTable->rowsNumber;
+
+  VMClass* type = constructClass(readString(vm, name + stringOffset),
+                                 readString(vm, nameSpace + stringOffset),
+                                 token);
+
+  type->vm = vm;
+
+  uint32 val = 3 & extends;
+  uint32 entry = extends >> 2;
+
+  switch (val) {
+    case 0: {
+      type->superToken = entry + (CONSTANT_TypeDef << 24);
+      break;
+    }
+    case 1: {
+      type->superToken = entry + (CONSTANT_TypeRef << 24);
+      break;
+    }
+    case 2: {
+      VMThread::get()->vm->error("implement me");
+      break;
+    }
+    default: {
+      VMThread::get()->vm->error("implement me");
+      break;
+    }
+  }
+
+  getInterfacesFromTokenType(type->interfacesToken, token);
+  type->flags = flags;
+
+  return type;
+}
+
+void Assembly::getInterfacesFromTokenType(std::vector<uint32>& tokens,
+                                          uint32 token) {
+  uint32 index = token & 0xffff;
+  Table* interfacesTable = CLIHeader->tables[CONSTANT_InterfaceImpl];
+  uint32 nbRows = interfacesTable->rowsNumber;
+
+  for (uint32 i = 0; i < nbRows; ++i) {
+    uint32 interfaceId = 
+      interfacesTable->readIndexInRow(i + 1, CONSTANT_INTERFACE_IMPL_CLASS,
+                                      bytes);
+    if (interfaceId == index) {
+      uint32 cl = interfacesTable->readIndexInRow(i + 1,
+                                        CONSTANT_INTERFACE_IMPL_INTERFACE,
+                                        bytes);
+      uint32 table = cl & 3;
+      uint32 interfaceToken = cl >> 2;
+
+      switch (table) {
+        case 0: interfaceToken += (CONSTANT_TypeDef << 24); break;
+        case 1: interfaceToken += (CONSTANT_TypeRef << 24); break;
+        case 2: interfaceToken += (CONSTANT_TypeSpec << 24); break;
+        default: VMThread::get()->vm->error("unknown table %x", table); break;
+      }
+      tokens.push_back(interfaceToken);
+    }
+  }
+}
+
+
+
+VMCommonClass* Assembly::loadType(N3* vm, uint32 token, bool resolve,
+                            bool resolveStatic, bool clinit, bool dothrow) {
+  
+  VMCommonClass* type = lookupClassFromToken(token);
+  if (!type || type->status == hashed) {
+    uint32 table = token >> 24;
+    uint32 index = token & 0xffff;
+
+    if (table == CONSTANT_TypeDef) {
+      type = readTypeDef(vm, index);
+    } else if (table == CONSTANT_TypeRef) {
+      type = readTypeRef(vm, index);
+    } else if (table == CONSTANT_TypeSpec) {
+      type = readTypeSpec(vm, index);
+    } else {
+      VMThread::get()->vm->error("implement me %x", token);
+    }
+  }
+
+  if (type == 0) VMThread::get()->vm->error("implement me");
+  if (type->status == hashed) {
+    type->aquire();
+    if (type->status == hashed) {
+      type->status = loaded;
+    }
+    type->release();
+  }
+
+  if (resolve) type->resolveType(resolveStatic, clinit);
+
+  return type;
+}
+
+void Assembly::readClass(VMCommonClass* cl) {
+  uint32 index = cl->token & 0xffff;
+  Table* typeTable = CLIHeader->tables[CONSTANT_TypeDef];
+  uint32 typeSize = typeTable->rowsNumber;
+  uint32* typeArray = (uint32*)alloca(sizeof(uint32) * typeTable->rowSize);
+  typeTable->readRow(typeArray, index, bytes);
+  
+  uint32 fieldList  = typeArray[CONSTANT_TYPEDEF_FIELDLIST];
+  uint32 methodList = typeArray[CONSTANT_TYPEDEF_METHODLIST];
+
+  Table* fieldTable   = CLIHeader->tables[CONSTANT_Field];
+  uint32 fieldSize    = fieldTable->rowsNumber;
+  Table* methodTable  = CLIHeader->tables[CONSTANT_MethodDef];
+  uint32 methodSize   = methodTable->rowsNumber;
+  
+  getProperties(cl);
+
+  if (methodList && methodTable != 0 && methodList <= methodSize) {
+    uint32 endMethod = (index == typeSize) ? 
+        methodSize + 1 : 
+        typeTable->readIndexInRow(index + 1, CONSTANT_TYPEDEF_METHODLIST,
+                                  bytes);
+
+    uint32 nbMethods = endMethod - methodList;
+
+    for (uint32 i = 0; i < nbMethods; ++i) {
+      VMMethod* meth = readMethodDef(i + methodList, cl);
+      if (isStatic(meth->flags)) {
+        cl->staticMethods.push_back(meth);
+      } else {
+        cl->virtualMethods.push_back(meth);
+      }
+    }
+  }
+  
+  if (fieldList && fieldTable != 0 && fieldList <= fieldSize) {
+    uint32 endField = (index == typeSize) ? 
+        fieldSize + 1 : 
+        typeTable->readIndexInRow(index + 1, CONSTANT_TYPEDEF_FIELDLIST, bytes);
+
+    uint32 nbFields = endField - fieldList;
+
+    for (uint32 i = 0; i < nbFields; ++i) {
+      VMField* field = readField(i + fieldList, cl);
+      if (isStatic(field->flags)) {
+        cl->staticFields.push_back(field);
+      } else {
+        cl->virtualFields.push_back(field);
+      }
+    }
+  }
+}
+
+void Assembly::readCustomAttributes(uint32 offset, std::vector<llvm::GenericValue>& args, VMMethod* meth) {
+  uncompressSignature(offset);
+  uint16 prolog = READ_U2(bytes, offset);
+
+  if (prolog != 0x1) VMThread::get()->vm->error("unknown prolog");
+
+  uint32 start = meth->virt ? 1 : 0;
+
+  for (uint32 i = start + 1; i < meth->parameters.size(); ++i) {
+    if (meth->parameters[i] == N3::pSInt32) {
+      llvm::GenericValue gv;
+      gv.IntVal = llvm::APInt(32, READ_U4(bytes, offset));
+      args.push_back(gv);
+    } else {
+      VMThread::get()->vm->error("implement me");
+    }
+  }
+
+}
+
+ArrayObject* Assembly::getCustomAttributes(uint32 token, VMCommonClass* cl) {
+  Table* attrTable = CLIHeader->tables[CONSTANT_CustomAttribute];
+  uint32 attrSize = attrTable->rowsNumber;
+  uint32* attrArray = (uint32*)alloca(sizeof(uint32) * attrTable->rowSize);
+  std::vector<VMObject*> vec;
+
+  for (uint32 i = 0; i < attrSize; ++i) {
+    attrTable->readRow(attrArray, i + 1, bytes);
+    uint32 meth = attrArray[CONSTANT_CUSTOM_ATTRIBUTE_TYPE];
+    uint32 table = meth & 7;
+    uint32 index = meth >> 3;
+    VMMethod* cons = 0;
+
+    switch(table) {
+      default: 
+        VMThread::get()->vm->error("implement me"); 
+        break;
+      case 2: 
+        cons = getMethodFromToken(index + (CONSTANT_MethodDef << 24));
+        break;
+      case 3:
+        cons = getMethodFromToken(index + (CONSTANT_MemberRef << 24));
+        break;
+    }
+
+    if (cl == cons->classDef) {
+      uint32 blobOffset = CLIHeader->blobStream->realOffset;
+      std::vector<llvm::GenericValue> args;
+      VMObject* obj = (*cons->classDef)();
+      args.push_back(llvm::GenericValue(obj));
+      readCustomAttributes(blobOffset + attrArray[CONSTANT_CUSTOM_ATTRIBUTE_VALUE], args, cons);
+
+      (*cons)(args);
+      vec.push_back(obj);
+    }
+  }
+
+  ArrayObject* res = ArrayObject::acons(vec.size(), N3::arrayObject);
+  for (uint32 i = 0; i < vec.size(); ++i)
+    res->elements[i] = vec[i];
+  
+  return res;
+}
+
+void Assembly::getProperties(VMCommonClass* cl) {
+  uint32 index = cl->token & 0xffff;
+  Table* mapTable = CLIHeader->tables[CONSTANT_PropertyMap];
+  uint32 mapSize = mapTable->rowsNumber;
+  
+  Table* propertyTable = CLIHeader->tables[CONSTANT_Property];
+  uint32 propertySize = propertyTable->rowsNumber;
+  
+  uint32 propertyList = 0;
+  uint32 i = 0;
+
+  while (!propertyList && i != mapSize) {
+    uint32 parent = mapTable->readIndexInRow(i + 1,
+                                        CONSTANT_PROPERTY_MAP_PARENT, bytes);
+    if (parent == index) {
+      propertyList = mapTable->readIndexInRow(i + 1,
+                                  CONSTANT_PROPERTY_MAP_PROPERTY_LIST, bytes);
+    } else {
+      ++i;
+    }
+  }
+
+  if (propertyList && propertyTable != 0 && propertyList <= propertySize) {
+    uint32 endProperty = (i + 1 == mapSize) ? 
+        propertySize + 1 : 
+        mapTable->readIndexInRow(i + 2, CONSTANT_PROPERTY_MAP_PROPERTY_LIST,
+                                 bytes);
+    uint32 nbProperties = endProperty - propertyList;
+
+    for (uint32 j = 0; j < nbProperties; ++j) {
+      cl->properties.push_back(readProperty(j + propertyList, cl));
+    }
+
+  } 
+}
+
+Property* Assembly::readProperty(uint32 index, VMCommonClass* cl) {
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  uint32 blobOffset = CLIHeader->blobStream->realOffset;
+  
+  Table* propTable  = CLIHeader->tables[CONSTANT_Property];
+  uint32* propArray = (uint32*)alloca(sizeof(uint32) * propTable->rowSize);
+  
+  propTable->readRow(propArray, index, bytes);
+
+  uint32 flags      = propArray[CONSTANT_PROPERTY_FLAGS];
+  uint32 nameIndex  = propArray[CONSTANT_PROPERTY_NAME];
+  uint32 type       = propArray[CONSTANT_PROPERTY_TYPE];
+
+  Property* prop = gc_new(Property)();
+  prop->name = readString(VMThread::get()->vm, stringOffset + nameIndex);
+  prop->flags = flags;
+  prop->type = cl;
+  uint32 offset = blobOffset + type;
+  prop->virt = extractMethodSignature(offset, cl, prop->parameters);
+  return prop;
+}
+
+VMMethod* Assembly::readMethodDef(uint32 index, VMCommonClass* cl) {
+  uint32 token = index + (CONSTANT_MethodDef << 24);
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  uint32 blobOffset = CLIHeader->blobStream->realOffset;
+  
+  Table* paramTable  = CLIHeader->tables[CONSTANT_Param];
+  uint32 paramSize    = paramTable->rowsNumber;
+  
+  Table* methTable  = CLIHeader->tables[CONSTANT_MethodDef];
+  uint32 methodSize    = methTable->rowsNumber;
+  uint32* methArray = (uint32*)alloca(sizeof(uint32) * methTable->rowSize);
+  
+  methTable->readRow(methArray, index, bytes);
+
+  uint32 rva        = methArray[CONSTANT_METHODDEF_RVA];
+  uint32 implFlags  = methArray[CONSTANT_METHODDEF_IMPLFLAGS];
+  uint32 flags      = methArray[CONSTANT_METHODDEF_FLAGS];
+  uint32 name       = methArray[CONSTANT_METHODDEF_NAME];
+  uint32 signature  = methArray[CONSTANT_METHODDEF_SIGNATURE];
+  uint32 paramList  = methArray[CONSTANT_METHODDEF_PARAMLIST];
+  
+  uint32 offset = blobOffset + signature;
+  VMMethod* meth = 
+    constructMethod((VMClass*)cl, readString(cl->vm, (name + stringOffset)),
+                    token);
+  meth->virt = extractMethodSignature(offset, cl, meth->parameters);
+  meth->flags = flags;
+  meth->implFlags = implFlags;
+  
+  if (rva) {
+    meth->offset = textSection->rawAddress + 
+                   (rva - textSection->virtualAddress);
+  }
+  
+  if (paramList && paramTable != 0 && paramList <= paramSize) {
+    uint32 endParam = (index == methodSize) ? 
+        paramSize + 1 : 
+        methTable->readIndexInRow(index + 1, CONSTANT_METHODDEF_PARAMLIST,
+                                  bytes);
+
+    uint32 nbParams = endParam - paramList;
+
+    for (uint32 j = 0; j < nbParams; ++j) {
+      meth->params.push_back(readParam(j + paramList, meth));
+    }
+
+  }
+
+  return meth;
+}
+
+VMField* Assembly::readField(uint32 index, VMCommonClass* cl) {
+  uint32 token = index + (CONSTANT_Field << 24);
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  uint32 blobOffset = CLIHeader->blobStream->realOffset;
+  
+  Table* fieldTable  = CLIHeader->tables[CONSTANT_Field];
+  uint32* fieldArray = (uint32*)alloca(sizeof(uint32) * fieldTable->rowSize);
+  
+  fieldTable->readRow(fieldArray, index, bytes);
+
+  uint32 flags      = fieldArray[CONSTANT_FIELD_FLAGS];
+  uint32 name       = fieldArray[CONSTANT_FIELD_NAME];
+  uint32 signature  = fieldArray[CONSTANT_FIELD_SIGNATURE];
+  
+  uint32 offset = blobOffset + signature;
+  VMField* field = 
+    constructField((VMClass*)cl, readString(cl->vm, (name + stringOffset)),
+                   extractFieldSignature(offset), token);
+  field->flags = flags;
+  
+  return field;
+}
+
+Param* Assembly::readParam(uint32 index, VMMethod* meth) {
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  
+  Table* paramTable  = CLIHeader->tables[CONSTANT_Param];
+  uint32* paramArray = (uint32*)alloca(sizeof(uint32) * paramTable->rowSize);
+  
+  paramTable->readRow(paramArray, index, bytes);
+
+  uint32 flags      = paramArray[CONSTANT_PARAM_FLAGS];
+  uint32 name       = paramArray[CONSTANT_PARAM_NAME];
+  uint32 sequence   = paramArray[CONSTANT_PARAM_SEQUENCE];
+  
+  Param* param = gc_new(Param)();
+  param->flags = flags;
+  param->sequence = sequence;
+  param->name = readString(meth->classDef->vm, stringOffset + name);
+  param->method = meth;
+  
+  return param;
+}
+
+VMCommonClass* Assembly::loadTypeFromName(const UTF8* name, 
+                                          const UTF8* nameSpace, 
+                                          bool resolve, bool unify,
+                                          bool clinit, bool dothrow) {
+  VMCommonClass* cl = lookupClassFromName(name, nameSpace);
+  if (cl == 0 || cl->status == hashed) {
+    cl = getClassFromName(((N3*)VMThread::get()->vm), name, nameSpace);
+    
+    if (cl == 0) VMThread::get()->vm->error("implement me");
+
+    if (cl->status == hashed) {
+      cl->aquire();
+      if (cl->status == hashed) {
+        cl->status = loaded;
+      }
+      cl->release();
+    }
+  }
+
+  if (resolve) cl->resolveType(unify, clinit);
+
+  return cl;
+}
+
+void Assembly::readSignature(uint32 localVarSig, 
+                             std::vector<VMCommonClass*>& locals) {
+  uint32 table = localVarSig >> 24;
+  uint32 index = localVarSig & 0xffff;
+  if (table != CONSTANT_StandaloneSig) {
+    VMThread::get()->vm->error("locals do not point to a StandAloneSig table");
+  }
+  Table* signatures = CLIHeader->tables[CONSTANT_StandaloneSig];
+  uint32* array = (uint32*)alloca(sizeof(uint32) * signatures->rowSize);
+  signatures->readRow(array, index, bytes);
+
+  uint32 blobOffset = CLIHeader->blobStream->realOffset;
+  uint32 blobEntry = blobOffset + array[CONSTANT_STANDALONE_SIG_SIGNATURE];
+  
+
+  localVarSignature(blobEntry, locals);
+}
+
+VMField* Assembly::getFieldFromToken(uint32 token, bool stat) {
+  VMField* field = lookupFieldFromToken(token);
+  if (!field) {
+    uint32 table = token >> 24;
+    switch (table) {
+      case CONSTANT_Field : {
+        uint32 typeToken = getTypedefTokenFromField(token);
+        uint32 newTable = typeToken >> 24;
+        switch (newTable) {
+          case CONSTANT_TypeDef : {
+            loadType((N3*)(VMThread::get()->vm), typeToken, true, true, false,
+                     true);
+            field = lookupFieldFromToken(token);
+            if (!field) {
+              VMThread::get()->vm->error("implement me");
+            }
+            break;
+          }
+          default : {
+            VMThread::get()->vm->error("implement me");
+          }
+        }
+        break;
+      }
+
+      case CONSTANT_MemberRef : {
+        field = readMemberRefAsField(token, stat);
+        break;
+      }
+
+      default : {
+        VMThread::get()->vm->error("implement me");
+      }
+    }
+  }
+  field->classDef->resolveType(false, false);
+  return field;
+}
+
+uint32 Assembly::getTypedefTokenFromField(uint32 token) {
+  uint32 index = token & 0xffff;
+  Table* typeTable = CLIHeader->tables[CONSTANT_TypeDef];
+  uint32 nbRows = typeTable->rowsNumber;
+
+  bool found = false;
+  uint32 i = 0;
+
+  while (!found && i < nbRows - 1) {
+    uint32 myId = typeTable->readIndexInRow(i + 1, CONSTANT_TYPEDEF_FIELDLIST, bytes);
+    uint32 nextId = typeTable->readIndexInRow(i + 2, CONSTANT_TYPEDEF_FIELDLIST, bytes);
+
+    if ((index < nextId) && (index >= myId)) {
+      found = true;
+    } else {
+      ++i;
+    }
+  }
+
+  return i + 1 + (CONSTANT_TypeDef << 24);
+}
+
+uint32 Assembly::getExplicitLayout(uint32 token) {
+  uint32 index = token & 0xffff;
+  Table* layoutTable = CLIHeader->tables[CONSTANT_ClassLayout];
+  uint32 tableSize = layoutTable->rowsNumber;
+
+  bool found = false;
+  uint32 i = 0;
+  uint32 size = 0;
+
+  while (!found && i != tableSize) {
+    uint32 parent = layoutTable->readIndexInRow(i + 1,
+                                        CONSTANT_CLASS_LAYOUT_PARENT, bytes);
+    if (parent == index) {
+      found = true;
+      size = layoutTable->readIndexInRow(i + 1,
+                                  CONSTANT_CLASS_LAYOUT_CLASS_SIZE, bytes);
+    }
+    ++i;
+  }
+
+  if (!found)
+    VMThread::get()->vm->error("implement me");
+
+  return size;
+}
+
+VMField* Assembly::readMemberRefAsField(uint32 token, bool stat) {
+  uint32 index = token & 0xffff;
+  Table* memberTable = CLIHeader->tables[CONSTANT_MemberRef];
+  uint32* memberArray = (uint32*)alloca(sizeof(uint32) * memberTable->rowSize);
+  
+  memberTable->readRow(memberArray, index, bytes);
+
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  uint32 blobOffset   = CLIHeader->blobStream->realOffset;
+  
+  const UTF8* name = readString((N3*)(VMThread::get()->vm), stringOffset + 
+                                          memberArray[CONSTANT_MEMBERREF_NAME]);
+  
+  uint32 offset = blobOffset + memberArray[CONSTANT_MEMBERREF_SIGNATURE];
+  VMCommonClass* signature = extractFieldSignature(offset);
+                                    
+
+  uint32 value = memberArray[CONSTANT_MEMBERREF_CLASS];
+  uint32 table = value & 7;
+  index = value >> 3;
+
+  switch (table) {
+    case 0 : {
+      uint32 typeToken = index + (CONSTANT_TypeDef << 24);
+      VMCommonClass* type = loadType(((N3*)VMThread::get()->vm), typeToken,
+                                     true, false, false, true);
+      VMField* field = type->lookupField(name, signature, stat, true);
+      return field;
+    }
+
+    case 1 : {
+      uint32 typeToken = index + (CONSTANT_TypeRef << 24);
+      VMCommonClass* type = loadType(((N3*)VMThread::get()->vm), typeToken,
+                                     true, false, false, true);
+      VMField* field = type->lookupField(name, signature, stat, true);
+      return field;
+    }
+
+    case 2:
+    case 3:
+    case 4: VMThread::get()->vm->error("implement me"); break;
+    default:
+      VMThread::get()->vm->error("unknown MemberRefParent tag %d", table);
+      
+  }
+
+  return 0;
+}
+
+
+VMMethod* Assembly::getMethodFromToken(uint32 token) {
+  VMMethod* meth = lookupMethodFromToken(token);
+  if (!meth) {
+    uint32 table = token >> 24;
+    switch (table) {
+      case CONSTANT_MethodDef : {
+        uint32 typeToken = getTypedefTokenFromMethod(token);
+        uint32 newTable = typeToken >> 24;
+        switch (newTable) {
+          case CONSTANT_TypeDef : {
+            loadType((N3*)(VMThread::get()->vm), typeToken, true, true, false,
+                     true);
+            meth = lookupMethodFromToken(token);
+            if (!meth) {
+              VMThread::get()->vm->error("implement me");
+            }
+            break;
+          }
+          default : {
+            VMThread::get()->vm->error("implement me");
+          }
+        }
+        break;
+      }
+
+      case CONSTANT_MemberRef : {
+        meth = readMemberRefAsMethod(token);
+        break;
+      }
+
+      default : {
+        VMThread::get()->vm->error("implement me");
+      }
+    }
+  }
+  meth->getSignature();
+  return meth;
+}
+
+uint32 Assembly::getTypedefTokenFromMethod(uint32 token) {
+  uint32 index = token & 0xffff;
+  Table* typeTable = CLIHeader->tables[CONSTANT_TypeDef];
+  uint32 nbRows = typeTable->rowsNumber;
+
+  bool found = false;
+  uint32 i = 0;
+
+  while (!found && i < nbRows - 1) {
+    uint32 myId = typeTable->readIndexInRow(i + 1, CONSTANT_TYPEDEF_METHODLIST, bytes);
+    uint32 nextId = typeTable->readIndexInRow(i + 2, CONSTANT_TYPEDEF_METHODLIST, bytes);
+
+    if ((index < nextId) && (index >= myId)) {
+      found = true;
+    } else {
+      ++i;
+    }
+  }
+
+  return i + 1 + (CONSTANT_TypeDef << 24);
+}
+
+VMMethod* Assembly::readMemberRefAsMethod(uint32 token) {
+  uint32 index = token & 0xffff;
+  Table* memberTable = CLIHeader->tables[CONSTANT_MemberRef];
+  uint32* memberArray = (uint32*)alloca(sizeof(uint32) * memberTable->rowSize);
+  
+  memberTable->readRow(memberArray, index, bytes);
+
+  uint32 stringOffset = CLIHeader->stringStream->realOffset;
+  uint32 blobOffset   = CLIHeader->blobStream->realOffset;
+  
+  const UTF8* name = readString((N3*)(VMThread::get()->vm), stringOffset + 
+                                          memberArray[CONSTANT_MEMBERREF_NAME]);
+  
+  uint32 offset = blobOffset + memberArray[CONSTANT_MEMBERREF_SIGNATURE];
+  std::vector<VMCommonClass*> args;
+                                    
+
+  uint32 value = memberArray[CONSTANT_MEMBERREF_CLASS];
+  uint32 table = value & 7;
+  index = value >> 3;
+
+  switch (table) {
+    case 0 : {
+      uint32 typeToken = index + (CONSTANT_TypeDef << 24);
+      VMCommonClass* type = loadType(((N3*)VMThread::get()->vm), typeToken,
+                                     true, false, false, true);
+      bool virt = extractMethodSignature(offset, type, args);
+      VMMethod* meth = type->lookupMethod(name, args, !virt, true);
+      return meth;
+    }
+
+    case 1 : {
+      uint32 typeToken = index + (CONSTANT_TypeRef << 24);
+      VMCommonClass* type = loadType(((N3*)VMThread::get()->vm), typeToken,
+                                     true, false, false, true);
+      bool virt = extractMethodSignature(offset, type, args);
+      VMMethod* meth = type->lookupMethod(name, args, !virt, true);
+      return meth;
+    }
+
+    case 2:
+    case 3: VMThread::get()->vm->error("implement me %d", table); break;
+    case 4: {
+      VMClass* type = (VMClass*)readTypeSpec(vm, index);
+      VMMethod* meth = gc_new(VMMethod)();
+      bool virt = extractMethodSignature(offset, type, args);
+      bool structReturn = false;
+      const llvm::FunctionType* signature = VMMethod::resolveSignature(args, virt, structReturn);
+      meth->_signature = signature;
+      meth->classDef = type;
+      meth->name = name;
+      meth->virt = virt;
+      meth->structReturn = structReturn;
+      return meth;
+    }
+    default:
+      VMThread::get()->vm->error("unknown MemberRefParent tag %d", table);
+      
+  }
+
+  return 0;
+}
+
+const UTF8* Assembly::readUserString(uint32 token) {
+  uint32 offset = CLIHeader->usStream->realOffset + token;
+
+  uint8 size = READ_U1(bytes, offset);
+  if (size >> 7) {
+    if ((size >> 6) == 3) {
+      uint32 size1 = READ_U1(bytes, offset);
+      uint32 size2 = READ_U1(bytes, offset);
+      uint32 size3 = READ_U1(bytes, offset);
+      size = ((size ^ 0xc0) << 24) + (size1 << 16) + (size2 << 8) + size3;
+    } else {
+      size = ((size ^ 0x80) << 8) + READ_U1(bytes, offset);
+    }
+  }
+
+  const UTF8* res = readUTF16((N3*)(VMThread::get()->vm), size, bytes, offset);
+  return res;
+}
+
+uint32 Assembly::getRVAFromField(uint32 token) {
+  
+  uint32 index = token & 0xffff;
+  Table* rvaTable = CLIHeader->tables[CONSTANT_FieldRVA];
+  uint32 rvaSize = rvaTable->rowsNumber;
+  
+  uint32 i = 0;
+  bool found = false;
+
+  while (!found && i != rvaSize) {
+    uint32 fieldId = rvaTable->readIndexInRow(i + 1, CONSTANT_FIELD_RVA_FIELD,
+                                              bytes);
+    if (fieldId == index) {
+      found = true;
+    } else {
+      ++i;
+    }
+  }
+  if (!found) {
+    return 0;
+  } else {
+    return rvaTable->readIndexInRow(i + 1, CONSTANT_FIELD_RVA_RVA, bytes);
+  }
+}
+
diff --git a/vmkit/lib/N3/VMCore/Assembly.h b/vmkit/lib/N3/VMCore/Assembly.h
new file mode 100644
index 0000000..e46dc0b
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/Assembly.h
@@ -0,0 +1,896 @@
+//===---------- Assembly.h - Definition of an assembly --------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef N3_ASSEMBLY_H
+#define N3_ASSEMBLY_H
+
+#include <vector>
+
+#include "types.h"
+
+#include "mvm/Object.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Cond.h"
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/Type.h"
+
+namespace llvm {
+  class GenericValue;
+}
+
+namespace n3 {
+
+class ArrayUInt8;
+class ArrayObject;
+class Assembly;
+class ClassNameMap;
+class ClassTokenMap;
+class FieldTokenMap;
+class MethodTokenMap;
+class N3;
+class Param;
+class Property;
+class Reader;
+class UTF8;
+class VirtualMachine;
+class VMClass;
+class VMClassArray;
+class VMClassPointer;
+class VMCommonClass;
+class VMField;
+class VMMethod;
+class VMObject;
+
+class Section : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+  
+  char* name;
+  uint32 virtualSize;
+  uint32 virtualAddress;
+  uint32 rawSize;
+  uint32 rawAddress;
+  uint32 relocAddress;
+  uint32 lineNumbers;
+  uint32 relocationsNumber;
+  uint32 lineNumbersNumber;
+  uint32 characteristics;
+
+  void read(Reader* reader, N3* vm);
+};
+
+class Stream : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  char* name;
+  uint32 realOffset;
+  uint32 size;
+};
+
+class Table : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  uint32 offset;
+  uint32 rowsNumber;
+  uint32 rowSize;
+  uint32 count;
+  uint32 sizeMask;
+
+  void readRow(uint32* result, uint32 row, ArrayUInt8* array);
+  uint32 readIndexInRow(uint32 row, uint32 index, ArrayUInt8* array);
+
+};
+
+
+class Header : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  uint32 signature;
+  uint32 major;
+  uint32 minor;
+  uint32 reserved;
+  uint32 versionLength;
+  uint32 flags;
+  uint32 nbStreams;
+
+  const UTF8* versionName;
+  Stream* tildStream;
+  Stream* stringStream;
+  Stream* usStream;
+  Stream* blobStream;
+  Stream* guidStream;
+  std::vector<Table*> tables;
+  
+  void read(Reader* reader, N3* vm);
+};
+
+typedef void (*maskVector_t)(uint32 index, std::vector<Table*>& tables,
+                             uint32 heapSizes);
+
+typedef VMCommonClass* (*signatureVector_t)(uint32 op, Assembly* ass,
+                                            uint32& offset);
+
+class Assembly : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  VMClassPointer* constructPointer(VMCommonClass* base, uint32 dims);
+  VMClassArray* constructArray(VMCommonClass* base, uint32 dims);
+  VMClassArray* constructArray(const UTF8* name, const UTF8* nameSpace,
+                               uint32 dims);
+  VMClass*      constructClass(const UTF8* name,
+                               const UTF8* nameSpace, uint32 token);
+  VMField*      constructField(VMClass* cl, const UTF8* name,
+                               VMCommonClass* signature, uint32 token);
+  VMMethod*     constructMethod(VMClass* cl, const UTF8* name,
+                                uint32 token);
+  VMCommonClass* lookupClassFromName(const UTF8* name, const UTF8* nameSpace);
+  VMCommonClass* lookupClassFromToken(uint32 token);
+  VMMethod* lookupMethodFromToken(uint32 token);
+  VMField* lookupFieldFromToken(uint32 token);
+  
+  ClassNameMap* loadedNameClasses;
+  ClassTokenMap* loadedTokenClasses;
+  MethodTokenMap* loadedTokenMethods;
+  FieldTokenMap* loadedTokenFields;
+
+  mvm::Lock* lockVar;
+  mvm::Cond* condVar;
+  const UTF8* name;
+  ArrayUInt8* bytes;
+  Section* textSection;
+  Section* rsrcSection;
+  Section* relocSection;
+  Header* CLIHeader;
+  N3* vm;
+  VMObject* delegatee;
+  Assembly** assemblyRefs;
+  VMObject* getAssemblyDelegatee();
+
+  uint32 CLIHeaderLocation;
+  bool isRead;
+  uint32 cb;
+  uint32 major;
+  uint32 minor;
+  uint32 mdRva;
+  uint32 mdSize;
+  uint32 flags;
+  uint32 entryPoint;
+  uint32 resRva;
+  uint32 resSize;
+
+  static Assembly* allocate(const UTF8* name);
+  static const UTF8* readUTF8(VirtualMachine* vm, uint32 len, Reader* reader);
+  static const UTF8* readUTF16(VirtualMachine* vm, uint32 len, Reader* reader);
+  static const UTF8* readUTF8(VirtualMachine* vm, uint32 len, ArrayUInt8* bytes,
+                              uint32& offset);
+  static const UTF8* readUTF16(VirtualMachine* vm, uint32 len, 
+                               ArrayUInt8* bytes, uint32& offset);
+  const UTF8* readString(VirtualMachine* vm, uint32 offset);
+  void read();
+  void readTables(Reader* reader);
+
+  static maskVector_t maskVector[64];
+  static const char* maskVectorName[64];
+  static signatureVector_t signatureVector[0x46];
+  static const char* signatureNames[0x46];
+  
+
+  uint32 uncompressSignature(uint32& offset);
+  uint32 getTypeDefTokenFromMethod(uint32 token);
+  VMCommonClass* loadType(N3* vm, uint32 token, bool resolveFunc, bool resolve,
+                          bool clinit, bool dothrow);
+  
+  VMCommonClass* loadTypeFromName(const UTF8* name, const UTF8* nameSpace, 
+                                  bool resolveFunc, bool resolve,
+                                  bool clinit, bool dothrow);
+  void readClass(VMCommonClass* cl);
+  void getProperties(VMCommonClass* cl);
+  Property* readProperty(uint32 index, VMCommonClass* cl);
+  VMMethod* readMethodDef(uint32 index, VMCommonClass* cl);
+  VMField* readField(uint32 index, VMCommonClass* cl);
+  Param* readParam(uint32 index, VMMethod* meth);
+  VMClass* readTypeDef(N3* vm, uint32 index);
+  VMCommonClass* readTypeSpec(N3* vm, uint32 index);
+  Assembly* readAssemblyRef(N3* vm, uint32 index);
+  VMCommonClass* readTypeRef(N3* vm, uint32 index);
+  void readSignature(uint32 offset, std::vector<VMCommonClass*>& locals);
+  
+  void getInterfacesFromTokenType(std::vector<uint32>& tokens, uint32 token);
+  
+  bool extractMethodSignature(uint32& offset, VMCommonClass* cl,
+                              std::vector<VMCommonClass*> &params);
+  void localVarSignature(uint32& offset,
+                         std::vector<VMCommonClass*>& locals);
+  VMCommonClass* extractFieldSignature(uint32& offset);
+  VMCommonClass* extractTypeInSignature(uint32& offset);
+  VMCommonClass* exploreType(uint32& offset); 
+  
+  VMCommonClass* getClassFromName(N3* vm, const UTF8* name, const UTF8* nameSpace);
+  
+  VMField* getFieldFromToken(uint32 token, bool stat); 
+  uint32 getTypedefTokenFromField(uint32 token);
+  VMField* readMemberRefAsField(uint32 token, bool stat);
+  
+  VMMethod* getMethodFromToken(uint32 token); 
+  uint32 getTypedefTokenFromMethod(uint32 token);
+  VMMethod* readMemberRefAsMethod(uint32 token);
+
+  const UTF8* readUserString(uint32 token); 
+  uint32 getExplicitLayout(uint32 token);
+  uint32 getRVAFromField(uint32 token);
+  
+  static Assembly* getCallingAssembly();
+  static Assembly* getExecutingAssembly();
+
+  void readCustomAttributes(uint32 offset, std::vector<llvm::GenericValue>& args, VMMethod* meth);
+  ArrayObject* getCustomAttributes(uint32 token, VMCommonClass* cl);
+
+
+};
+
+
+#define CONSTANT_Assembly 0x20
+#define CONSTANT_AssemblyOS 0x22
+#define CONSTANT_AssemblyProcessor 0x21
+#define CONSTANT_AssemblyRef 0x23
+#define CONSTANT_AssemblyRefOS 0x25
+#define CONSTANT_AssemblyRefProcessor 0x24
+#define CONSTANT_ClassLayout 0x0F
+#define CONSTANT_Constant 0x0B
+#define CONSTANT_CustomAttribute 0x0C
+#define CONSTANT_DeclSecurity 0x0E
+#define CONSTANT_EventMap 0x12
+#define CONSTANT_Event 0x14
+#define CONSTANT_ExportedType 0x27
+#define CONSTANT_Field 0x04
+#define CONSTANT_FieldLayout 0x10
+#define CONSTANT_FieldMarshal 0x0D
+#define CONSTANT_FieldRVA 0x1D
+#define CONSTANT_File 0x26
+#define CONSTANT_GenericParam 0x2A
+#define CONSTANT_GenericParamConstraint 0x2C
+#define CONSTANT_ImplMap 0x1C
+#define CONSTANT_InterfaceImpl 0x09
+#define CONSTANT_ManifestResource 0x28
+#define CONSTANT_MemberRef 0x0A
+#define CONSTANT_MethodDef 0x06
+#define CONSTANT_MethodImpl 0x19
+#define CONSTANT_MethodSemantics 0x18
+#define CONSTANT_MethodSpec 0x2B
+#define CONSTANT_Module 0x00
+#define CONSTANT_ModuleRef 0x1A
+#define CONSTANT_NestedClass 0x29
+#define CONSTANT_Param 0x08
+#define CONSTANT_Property 0x17
+#define CONSTANT_PropertyMap 0x15
+#define CONSTANT_StandaloneSig 0x11
+#define CONSTANT_TypeDef 0x02
+#define CONSTANT_TypeRef 0x01
+#define CONSTANT_TypeSpec 0x1B
+
+
+#define CONSTANT_HasThis 0x20
+#define CONSTANT_ExplicitThis 0x40
+#define CONSTANT_Default 0x0
+#define CONSTANT_Vararg 0x5
+#define CONSTANT_C 0x1
+#define CONSTANT_StdCall 0x2
+#define CONSTANT_ThisCall 0x3
+#define CONSTANT_FastCall 0x4
+#define CONSTANT_Generic 0x10
+#define CONSTANT_Sentinel 0x41
+
+
+#define CONSTANT_CorILMethod_TinyFormat 0x2
+#define CONSTANT_CorILMethod_FatFormat 0x3
+#define CONSTANT_CorILMethod_MoreSects 0x8
+#define CONSTANT_CorILMethod_InitLocals 0x10
+#define CONSTANT_CorILMethod_Sect_FatFormat 0x40
+#define CONSTANT_COR_ILEXCEPTION_CLAUSE_EXCEPTION  0x0000
+#define CONSTANT_COR_ILEXCEPTION_CLAUSE_FILTER     0x0001
+#define CONSTANT_COR_ILEXCEPTION_CLAUSE_FINALLY    0x0002
+#define CONSTANT_COR_ILEXCEPTION_CLAUSE_FAULT      0x0004
+
+
+#define CLI_HEADER 0x168
+#define TEXT_SECTION_HEADER 0x178
+#define RSRC_SECTION_HEADER 0x178
+#define RELOC_SECTION_HEADER 0x178
+#define SECTION_NAME_LENGTH 8
+#define TABLE_MAX 64
+#define NB_TABLES 41
+
+#define INT16(offset)                       \
+  rowSize += 2;                             \
+  bitmask = bitmask | (1 << (offset << 1));
+
+#define INT32(offset)                       \
+  rowSize += 4;                             \
+  bitmask = bitmask | (3 << (offset << 1));
+
+
+#define STRING(offset) {                    \
+  uint32 fieldSize = 0;                     \
+  if (heapSizes & 0x01) {                   \
+    fieldSize = 4;                          \
+  } else {                                  \
+    fieldSize = 2;                          \
+  }                                         \
+  rowSize += fieldSize;                     \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define GUID(offset) {                      \
+  uint32 fieldSize = 0;                     \
+  if (heapSizes & 0x02) {                   \
+    fieldSize = 4;                          \
+  } else {                                  \
+    fieldSize = 2;                          \
+  }                                         \
+  rowSize += fieldSize;                     \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define BLOB(offset) {                      \
+  uint32 fieldSize = 0;                     \
+  if (heapSizes & 0x04) {                   \
+    fieldSize = 4;                          \
+  } else {                                  \
+    fieldSize = 2;                          \
+  }                                         \
+  rowSize += fieldSize;                     \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define TABLE(table, offset) {                  \
+  uint32 fieldSize = 0;                         \
+  if (tables[table]->rowsNumber < 0x10000) {    \
+    fieldSize = 2;                              \
+  } else {                                      \
+    fieldSize = 4;                              \
+  }                                             \
+  rowSize += fieldSize;                         \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+
+#define TYPEDEF_OR_REF(offset) { \
+  uint32 fieldSize = 0; \
+  if (tables[CONSTANT_TypeDef]->rowsNumber < 0x4000 &&      \
+      tables[CONSTANT_TypeRef]->rowsNumber < 0x4000 &&      \
+      tables[CONSTANT_TypeSpec]->rowsNumber < 0x4000) {     \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+
+#define HAS_CONSTANT(offset) { \
+  uint32 fieldSize = 0; \
+  if (tables[CONSTANT_Field]->rowsNumber < 0x4000 &&      \
+      tables[CONSTANT_Param]->rowsNumber < 0x4000 &&      \
+      tables[CONSTANT_Property]->rowsNumber < 0x4000) {   \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define HAS_CUSTOM_ATTRIBUTE(offset) {                          \
+  uint32 fieldSize = 0;                                         \
+  if (tables[CONSTANT_MethodDef]->rowsNumber < 0x800 &&         \
+      tables[CONSTANT_Field]->rowsNumber < 0x800 &&             \
+      tables[CONSTANT_TypeRef]->rowsNumber < 0x800 &&           \
+      tables[CONSTANT_TypeDef]->rowsNumber < 0x800 &&           \
+      tables[CONSTANT_Param]->rowsNumber < 0x800 &&             \
+      tables[CONSTANT_InterfaceImpl]->rowsNumber < 0x800 &&     \
+      tables[CONSTANT_MemberRef]->rowsNumber < 0x800 &&         \
+      tables[CONSTANT_Module]->rowsNumber < 0x800 &&            \
+      tables[CONSTANT_DeclSecurity]->rowsNumber < 0x800 &&      \
+      tables[CONSTANT_Property]->rowsNumber < 0x800 &&          \
+      tables[CONSTANT_Event]->rowsNumber < 0x800 &&             \
+      tables[CONSTANT_StandaloneSig]->rowsNumber < 0x800 &&     \
+      tables[CONSTANT_ModuleRef]->rowsNumber < 0x800 &&         \
+      tables[CONSTANT_TypeSpec]->rowsNumber < 0x800 &&          \
+      tables[CONSTANT_Assembly]->rowsNumber < 0x800 &&          \
+      tables[CONSTANT_AssemblyRef]->rowsNumber < 0x800 &&       \
+      tables[CONSTANT_File]->rowsNumber < 0x800 &&              \
+      tables[CONSTANT_ExportedType]->rowsNumber < 0x800 &&      \
+      tables[CONSTANT_ManifestResource]->rowsNumber < 0x800) {  \
+    fieldSize = 2;                                              \
+  } else {                                                      \
+    fieldSize = 4;                                              \
+  }                                                             \
+  rowSize += fieldSize;                                         \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1));       \
+}
+
+#define HAS_FIELD_MARSHAL(offset) {                       \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_Field]->rowsNumber < 0x8000 &&      \
+      tables[CONSTANT_Param]->rowsNumber < 0x8000) {      \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define HAS_DECL_SECURITY(offset) {                       \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_TypeDef]->rowsNumber < 0x4000 &&    \
+      tables[CONSTANT_MethodDef]->rowsNumber < 0x4000 &&  \
+      tables[CONSTANT_Assembly]->rowsNumber < 0x4000) {   \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define MEMBER_REF_PARENT(offset) {                       \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_TypeDef]->rowsNumber < 0x2000 &&    \
+      tables[CONSTANT_TypeRef]->rowsNumber < 0x2000 &&    \
+      tables[CONSTANT_ModuleRef]->rowsNumber < 0x2000 &&  \
+      tables[CONSTANT_MethodDef]->rowsNumber < 0x2000 &&  \
+      tables[CONSTANT_TypeSpec]->rowsNumber < 0x2000) {   \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define HAS_SEMANTICS(offset) {                           \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_Event]->rowsNumber < 0x8000 &&      \
+      tables[CONSTANT_Property]->rowsNumber < 0x8000) {   \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define METHODDEF_OR_REF(offset) {                        \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_MethodDef]->rowsNumber < 0x8000 &&  \
+      tables[CONSTANT_MemberRef]->rowsNumber < 0x8000) {  \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define MEMBER_FORWARDED(offset) {                        \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_Field]->rowsNumber < 0x8000 &&      \
+      tables[CONSTANT_MethodDef]->rowsNumber < 0x8000) {  \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define IMPLEMENTATION(offset) {                              \
+  uint32 fieldSize = 0;                                       \
+  if (tables[CONSTANT_File]->rowsNumber < 0x4000 &&           \
+      tables[CONSTANT_AssemblyRef]->rowsNumber < 0x4000 &&    \
+      tables[CONSTANT_ExportedType]->rowsNumber < 0x4000) {   \
+    fieldSize = 2;                                            \
+  } else {                                                    \
+    fieldSize = 4;                                            \
+  }                                                           \
+  rowSize += fieldSize;                                       \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1));     \
+}
+
+// Some encondigs are not used here
+#define CUSTOM_ATTRIBUTE_TYPE(offset) {                   \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_MethodDef]->rowsNumber < 0x2000 &&  \
+      tables[CONSTANT_MemberRef]->rowsNumber < 0x2000) {  \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+#define RESOLUTION_SCOPE(offset) {                            \
+  uint32 fieldSize = 0;                                       \
+  if (tables[CONSTANT_Module]->rowsNumber < 0x4000 &&         \
+      tables[CONSTANT_ModuleRef]->rowsNumber < 0x4000 &&      \
+      tables[CONSTANT_AssemblyRef]->rowsNumber < 0x4000 &&    \
+      tables[CONSTANT_TypeRef]->rowsNumber < 0x4000) {        \
+    fieldSize = 2;                                            \
+  } else {                                                    \
+    fieldSize = 4;                                            \
+  }                                                           \
+  rowSize += fieldSize;                                       \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1));     \
+}
+
+#define TYPE_OR_METHODDEF(offset) {                       \
+  uint32 fieldSize = 0;                                   \
+  if (tables[CONSTANT_TypeDef]->rowsNumber < 0x8000 &&    \
+      tables[CONSTANT_MethodDef]->rowsNumber < 0x8000) {  \
+    fieldSize = 2;                                        \
+  } else {                                                \
+    fieldSize = 4;                                        \
+  }                                                       \
+  rowSize += fieldSize;                                   \
+  bitmask = bitmask | ((fieldSize - 1) << (offset << 1)); \
+}
+
+
+#define DEF_TABLE_MASK(name, nb, ...) \
+  static void name(uint32 index, std::vector<Table*>& tables, uint32 heapSizes) { \
+    Table* table = tables[index]; \
+    uint32 rowSize = 0; \
+    uint32 bitmask = 0; \
+    __VA_ARGS__; \
+    table->count = nb; \
+    table->sizeMask = bitmask; \
+    table->rowSize = rowSize; \
+  }
+  
+#define CONSTANT_MODULE_GENERATION 0
+#define CONSTANT_MODULE_NAME 1
+#define CONSTANT_MODULE_MVID 2
+#define CONSTANT_MODULE_ENCID 3
+#define CONSTANT_MODULE_ENCBASEID 4
+
+
+DEF_TABLE_MASK(METHOD_Module, 5,
+  INT16(CONSTANT_MODULE_GENERATION)
+  STRING(CONSTANT_MODULE_NAME)
+  GUID(CONSTANT_MODULE_MVID)
+  GUID(CONSTANT_MODULE_ENCID)
+  GUID(CONSTANT_MODULE_ENCBASEID))
+  
+#define CONSTANT_TYPEREF_RESOLUTION_SCOPE 0
+#define CONSTANT_TYPEREF_NAME 1
+#define CONSTANT_TYPEREF_NAMESPACE 2
+
+DEF_TABLE_MASK(METHOD_TypeRef, 3,
+  RESOLUTION_SCOPE(CONSTANT_TYPEREF_RESOLUTION_SCOPE)
+  STRING(CONSTANT_TYPEREF_NAME)
+  STRING(CONSTANT_TYPEREF_NAMESPACE))
+  
+#define CONSTANT_TYPEDEF_FLAGS 0
+#define CONSTANT_TYPEDEF_NAME 1
+#define CONSTANT_TYPEDEF_NAMESPACE 2
+#define CONSTANT_TYPEDEF_EXTENDS 3
+#define CONSTANT_TYPEDEF_FIELDLIST 4
+#define CONSTANT_TYPEDEF_METHODLIST 5
+
+DEF_TABLE_MASK(METHOD_TypeDef, 6,
+  INT32(CONSTANT_TYPEDEF_FLAGS)
+  STRING(CONSTANT_TYPEDEF_NAME)
+  STRING(CONSTANT_TYPEDEF_NAMESPACE)
+  TYPEDEF_OR_REF(CONSTANT_TYPEDEF_EXTENDS)
+  TABLE(CONSTANT_Field, CONSTANT_TYPEDEF_FIELDLIST)
+  TABLE(CONSTANT_MethodDef, CONSTANT_TYPEDEF_METHODLIST))
+
+#define CONSTANT_METHODDEF_RVA 0
+#define CONSTANT_METHODDEF_IMPLFLAGS 1
+#define CONSTANT_METHODDEF_FLAGS 2
+#define CONSTANT_METHODDEF_NAME 3
+#define CONSTANT_METHODDEF_SIGNATURE 4
+#define CONSTANT_METHODDEF_PARAMLIST 5
+
+DEF_TABLE_MASK(METHOD_MethodDef, 6,
+  INT32(CONSTANT_METHODDEF_RVA)
+  INT16(CONSTANT_METHODDEF_IMPLFLAGS)
+  INT16(CONSTANT_METHODDEF_FLAGS)
+  STRING(CONSTANT_METHODDEF_NAME)
+  BLOB(CONSTANT_METHODDEF_SIGNATURE)
+  TABLE(CONSTANT_Param, CONSTANT_METHODDEF_PARAMLIST))
+  
+#define CONSTANT_PARAM_FLAGS 0
+#define CONSTANT_PARAM_SEQUENCE 1
+#define CONSTANT_PARAM_NAME 2
+
+DEF_TABLE_MASK(METHOD_Param, 3,
+  INT16(CONSTANT_PARAM_FLAGS)
+  INT16(CONSTANT_PARAM_SEQUENCE)
+  STRING(CONSTANT_PARAM_NAME))
+  
+#define CONSTANT_MEMBERREF_CLASS 0
+#define CONSTANT_MEMBERREF_NAME 1
+#define CONSTANT_MEMBERREF_SIGNATURE 2
+
+DEF_TABLE_MASK(METHOD_MemberRef, 3,
+  MEMBER_REF_PARENT(CONSTANT_MEMBERREF_CLASS)
+  STRING(CONSTANT_MEMBERREF_NAME)
+  BLOB(CONSTANT_MEMBERREF_SIGNATURE))
+  
+#define CONSTANT_CUSTOM_ATTRIBUTE_PARENT 0
+#define CONSTANT_CUSTOM_ATTRIBUTE_TYPE 1
+#define CONSTANT_CUSTOM_ATTRIBUTE_VALUE 2
+  
+DEF_TABLE_MASK(METHOD_CustomAttribute, 3,
+  HAS_CUSTOM_ATTRIBUTE(CONSTANT_CUSTOM_ATTRIBUTE_PARENT)
+  CUSTOM_ATTRIBUTE_TYPE(CONSTANT_CUSTOM_ATTRIBUTE_TYPE)
+  BLOB(CONSTANT_CUSTOM_ATTRIBUTE_VALUE))
+  
+#define CONSTANT_STANDALONE_SIG_SIGNATURE 0
+
+DEF_TABLE_MASK(METHOD_StandaloneSig, 1,
+  BLOB(CONSTANT_STANDALONE_SIG_SIGNATURE))
+  
+#define CONSTANT_TYPESPEC_SIGNATURE 0
+
+DEF_TABLE_MASK(METHOD_TypeSpec, 1,
+  BLOB(CONSTANT_TYPESPEC_SIGNATURE))
+  
+#define CONSTANT_ASSEMBLY_HASH_ALG_ID 0
+#define CONSTANT_ASSEMBLY_MAJOR 1
+#define CONSTANT_ASSEMBLY_MINOR 2
+#define CONSTANT_ASSEMBLY_BUILD 3
+#define CONSTANT_ASSEMBLY_REVISION 4
+#define CONSTANT_ASSEMBLY_FLAGS 5
+#define CONSTANT_ASSEMBLY_PUBLIC_KEY 6
+#define CONSTANT_ASSEMBLY_NAME 7
+#define CONSTANT_ASSEMBLY_CULTURE 8
+
+DEF_TABLE_MASK(METHOD_Assembly, 9,
+  INT32(CONSTANT_ASSEMBLY_HASH_ALG_ID)
+  INT16(CONSTANT_ASSEMBLY_MAJOR)
+  INT16(CONSTANT_ASSEMBLY_MINOR)
+  INT16(CONSTANT_ASSEMBLY_BUILD)
+  INT16(CONSTANT_ASSEMBLY_REVISION)
+  INT32(CONSTANT_ASSEMBLY_FLAGS)
+  BLOB(CONSTANT_ASSEMBLY_PUBLIC_KEY)
+  STRING(CONSTANT_ASSEMBLY_NAME)
+  STRING(CONSTANT_ASSEMBLY_CULTURE))
+  
+#define CONSTANT_ASSEMBLY_REF_MAJOR 0
+#define CONSTANT_ASSEMBLY_REF_MINOR 1
+#define CONSTANT_ASSEMBLY_REF_BUILD 2
+#define CONSTANT_ASSEMBLY_REF_REVISION 3
+#define CONSTANT_ASSEMBLY_REF_FLAGS 4
+#define CONSTANT_ASSEMBLY_REF_PUBLIC_KEY 5
+#define CONSTANT_ASSEMBLY_REF_NAME 6
+#define CONSTANT_ASSEMBLY_REF_CULTURE 7
+#define CONSTANT_ASSEMBLY_REF_HASH_VALUE 8
+
+DEF_TABLE_MASK(METHOD_AssemblyRef, 9,
+  INT16(CONSTANT_ASSEMBLY_REF_MAJOR)
+  INT16(CONSTANT_ASSEMBLY_REF_MINOR)
+  INT16(CONSTANT_ASSEMBLY_REF_BUILD)
+  INT16(CONSTANT_ASSEMBLY_REF_REVISION)
+  INT32(CONSTANT_ASSEMBLY_REF_FLAGS)
+  BLOB(CONSTANT_ASSEMBLY_REF_PUBLIC_KEY)
+  STRING(CONSTANT_ASSEMBLY_REF_NAME)
+  STRING(CONSTANT_ASSEMBLY_REF_CULTURE)
+  BLOB(CONSTANT_ASSEMBLY_REF_HASH_VALUE))
+  
+#define CONSTANT_FIELD_FLAGS 0
+#define CONSTANT_FIELD_NAME 1
+#define CONSTANT_FIELD_SIGNATURE 2
+
+DEF_TABLE_MASK(METHOD_Field, 3,
+  INT16(CONSTANT_FIELD_FLAGS)
+  STRING(CONSTANT_FIELD_NAME)
+  BLOB(CONSTANT_FIELD_SIGNATURE))
+  
+#define CONSTANT_INTERFACE_IMPL_CLASS 0
+#define CONSTANT_INTERFACE_IMPL_INTERFACE 1
+
+DEF_TABLE_MASK(METHOD_InterfaceImpl, 2,
+  TABLE(CONSTANT_TypeDef, CONSTANT_INTERFACE_IMPL_CLASS)
+  TYPEDEF_OR_REF(CONSTANT_INTERFACE_IMPL_INTERFACE))
+  
+#define CONSTANT_NESTED_CLASS_NESTED_CLASS 0
+#define CONSTANT_NESTED_CLASS_ENCLOSING_CLASS 1
+
+DEF_TABLE_MASK(METHOD_NestedClass, 2,
+  TABLE(CONSTANT_TypeDef, CONSTANT_NESTED_CLASS_NESTED_CLASS)
+  TABLE(CONSTANT_TypeDef, CONSTANT_NESTED_CLASS_ENCLOSING_CLASS))
+
+#define CONSTANT_METHOD_SPEC_METHOD 0
+#define CONSTANT_METHOD_SPEC_INSTANTIATION 1
+
+DEF_TABLE_MASK(METHOD_MethodSpec, 2,
+  METHODDEF_OR_REF(CONSTANT_METHOD_SPEC_METHOD)
+  BLOB(CONSTANT_METHOD_SPEC_INSTANTIATION))
+
+#define CONSTANT_GENERIC_PARAM_CONSTRAINT_OWNER 0
+#define CONSTANT_GENERIC_PARAM_CONSTRAINT_CONSTRAINT 1
+
+DEF_TABLE_MASK(METHOD_GenericParamConstraint, 2,
+  TABLE(CONSTANT_GenericParam, CONSTANT_GENERIC_PARAM_CONSTRAINT_OWNER)
+  TYPEDEF_OR_REF(CONSTANT_GENERIC_PARAM_CONSTRAINT_CONSTRAINT))
+  
+#define CONSTANT_CONSTANT_TYPE 0
+#define CONSTANT_CONSTANT_PARENT 1
+#define CONSTANT_CONSTANT_VALUE 2
+
+DEF_TABLE_MASK(METHOD_Constant, 3,
+  INT16(CONSTANT_CONSTANT_TYPE)
+  HAS_CONSTANT(CONSTANT_CONSTANT_PARENT)
+  BLOB(CONSTANT_CONSTANT_VALUE))
+  
+#define CONSTANT_FIELD_MARSHAL_PARENT 0
+#define CONSTANT_FIELD_MARSHAL_NATIVE_TYPE 1
+
+DEF_TABLE_MASK(METHOD_FieldMarshal, 2,
+  HAS_FIELD_MARSHAL(CONSTANT_FIELD_MARSHAL_PARENT)
+  BLOB(CONSTANT_FIELD_MARSHAL_NATIVE_TYPE))
+  
+#define CONSTANT_DECL_SECURITY_ACTION 0
+#define CONSTANT_DECL_SECURITY_PARENT 1
+#define CONSTANT_DECL_SECURITY_PERMISSION_SET 2
+
+DEF_TABLE_MASK(METHOD_DeclSecurity, 3,
+  INT16(CONSTANT_DECL_SECURITY_ACTION)
+  HAS_DECL_SECURITY(CONSTANT_DECL_SECURITY_PARENT)
+  BLOB(CONSTANT_DECL_SECURITY_PERMISSION_SET))
+
+#define CONSTANT_CLASS_LAYOUT_PACKING_SIZE 0
+#define CONSTANT_CLASS_LAYOUT_CLASS_SIZE 1
+#define CONSTANT_CLASS_LAYOUT_PARENT 2
+
+DEF_TABLE_MASK(METHOD_ClassLayout, 3,
+  INT16(CONSTANT_CLASS_LAYOUT_PACKING_SIZE)
+  INT32(CONSTANT_CLASS_LAYOUT_CLASS_SIZE)
+  TABLE(CONSTANT_TypeDef, CONSTANT_CLASS_LAYOUT_PARENT))
+  
+#define CONSTANT_FIELD_LAYOUT_OFFSET 0
+#define CONSTANT_FIELD_LAYOUT_FIELD 1
+
+DEF_TABLE_MASK(METHOD_FieldLayout, 2,
+  INT32(CONSTANT_FIELD_LAYOUT_OFFSET)
+  TABLE(CONSTANT_Field, CONSTANT_FIELD_LAYOUT_FIELD))
+
+#define CONSTANT_EVENT_MAP_PARENT 0
+#define CONSTANT_EVEN_MAP_EVENT_LIST 1
+
+DEF_TABLE_MASK(METHOD_EventMap, 2,
+  TABLE(CONSTANT_TypeDef, CONSTANT_EVENT_MAP_PARENT)
+  TABLE(CONSTANT_Event, CONSTANT_EVEN_MAP_EVENT_LIST))
+
+#define CONSTANT_EVENT_EVENT_FLAGS 0
+#define CONSTANT_EVENT_NAME 1
+#define CONSTANT_EVENT_TYPE 2
+
+DEF_TABLE_MASK(METHOD_Event, 3,
+  INT16(CONSTANT_EVENT_EVENT_FLAGS)
+  STRING(CONSTANT_EVENT_NAME)
+  TYPEDEF_OR_REF(CONSTANT_EVENT_TYPE))
+  
+#define CONSTANT_PROPERTY_MAP_PARENT 0
+#define CONSTANT_PROPERTY_MAP_PROPERTY_LIST 1
+
+DEF_TABLE_MASK(METHOD_PropertyMap, 2,
+  TABLE(CONSTANT_TypeDef, CONSTANT_PROPERTY_MAP_PARENT)
+  TABLE(CONSTANT_Property, CONSTANT_PROPERTY_MAP_PROPERTY_LIST))
+  
+#define CONSTANT_PROPERTY_FLAGS 0
+#define CONSTANT_PROPERTY_NAME 1
+#define CONSTANT_PROPERTY_TYPE 2
+
+DEF_TABLE_MASK(METHOD_Property, 3,
+  INT16(CONSTANT_PROPERTY_FLAGS)
+  STRING(CONSTANT_PROPERTY_NAME)
+  BLOB(CONSTANT_PROPERTY_TYPE))
+  
+#define CONSTANT_METHOD_SEMANTICS_SEMANTICS 0
+#define CONSTANT_METHOD_SEMANTICS_METHOD 1
+#define CONSTANT_METHOD_SEMANTICS_ASSOCIATION 2
+
+DEF_TABLE_MASK(METHOD_MethodSemantics, 3,
+  INT16(CONSTANT_METHOD_SEMANTICS_SEMANTICS)
+  TABLE(CONSTANT_MethodDef, CONSTANT_METHOD_SEMANTICS_METHOD)
+  HAS_SEMANTICS(CONSTANT_METHOD_SEMANTICS_ASSOCIATION))
+
+#define CONSTANT_METHOD_IMPL_CLASS 0
+#define CONSTANT_METHOD_IMPL_METHOD_BODY 1
+#define CONSTANT_METHOD_IMPL_METHOD_DECLARATION 2
+
+DEF_TABLE_MASK(METHOD_MethodImpl, 3,
+  TABLE(CONSTANT_TypeDef, CONSTANT_METHOD_IMPL_CLASS)
+  METHODDEF_OR_REF(CONSTANT_METHOD_IMPL_METHOD_BODY)
+  METHODDEF_OR_REF(CONSTANT_METHOD_IMPL_METHOD_DECLARATION))
+  
+#define CONSTANT_MODULE_REF_NAME 0
+
+DEF_TABLE_MASK(METHOD_ModuleRef, 1,
+  STRING(CONSTANT_MODULE_REF_NAME))
+  
+#define CONSTANT_IMPL_MAP_MAPPING_FLAGS 0
+#define CONSTANT_IMPL_MAP_MEMBER_FORWARDED 1
+#define CONSTANT_IMPL_MAP_IMPORT_NAME 2
+#define CONSTANT_IMPL_MAP_IMPORT_SCOPE 3
+
+DEF_TABLE_MASK(METHOD_ImplMap, 4,
+  INT16(CONSTANT_IMPL_MAP_MAPPING_FLAGS)
+  MEMBER_FORWARDED(CONSTANT_IMPL_MAP_MEMBER_FORWARDED)
+  STRING(CONSTANT_IMPL_MAP_IMPORT_NAME)
+  TABLE(CONSTANT_ModuleRef, CONSTANT_IMPL_MAP_IMPORT_SCOPE))
+  
+#define CONSTANT_FIELD_RVA_RVA 0
+#define CONSTANT_FIELD_RVA_FIELD 1
+
+DEF_TABLE_MASK(METHOD_FieldRva, 2,
+  INT32(CONSTANT_FIELD_RVA_RVA)
+  TABLE(CONSTANT_Field, CONSTANT_FIELD_RVA_FIELD))
+
+#define CONSTANT_MANIFEST_RESOURCE_OFFSET 0
+#define CONSTANT_MANIFEST_RESOURCE_FLAGS 1
+#define CONSTANT_MANIFEST_RESOURCE_NAME 2
+#define CONSTANT_MANIFEST_RESOURCE_IMPLEMENTATION 3
+
+DEF_TABLE_MASK(METHOD_ManifestResource, 4,
+  INT32(CONSTANT_MANIFEST_RESOURCE_OFFSET)
+  INT32(CONSTANT_MANIFEST_RESOURCE_FLAGS)
+  STRING(CONSTANT_MANIFEST_RESOURCE_NAME)
+  IMPLEMENTATION(CONSTANT_MANIFEST_RESOURCE_IMPLEMENTATION))
+  
+#define CONSTANT_ASSEMBLY_PROCESSOR_PROCESSOR 0
+
+DEF_TABLE_MASK(METHOD_AssemblyProcessor, 1,
+  INT32(CONSTANT_ASSEMBLY_PROCESSOR_PROCESSOR))
+  
+#define CONSTANT_ASSEMBLY_OS_PLATFORM_ID 0
+#define CONSTANT_ASSEMBLY_OS_MAJOR_VERSION 1
+#define CONSTANT_ASSEMBLY_OS_MINOR_VERSION 2
+
+DEF_TABLE_MASK(METHOD_AssemblyOS, 3,
+  INT32(CONSTANT_ASSEMBLY_OS_PLATFORM_ID)
+  INT32(CONSTANT_ASSEMBLY_OS_MAJOR_VERSION)
+  INT32(CONSTANT_ASSEMBLY_OS_MINOR_VERSION))
+  
+#define CONSTANT_FILE_FLAGS 0
+#define CONSTANT_FILE_NAME 1
+#define CONSTANT_FILE_HASH_VALUE 2
+
+DEF_TABLE_MASK(METHOD_File, 3,
+  INT32(CONSTANT_FILE_FLAGS)
+  STRING(CONSTANT_FILE_NAME)
+  BLOB(CONSTANT_FILE_HASH_VALUE))
+
+
+} // end namespace n3
+
+#endif
+
diff --git a/vmkit/lib/N3/VMCore/BackTrace.cpp b/vmkit/lib/N3/VMCore/BackTrace.cpp
new file mode 100644
index 0000000..7bf3532
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/BackTrace.cpp
@@ -0,0 +1,123 @@
+//===------------ Backtrace.cpp - Backtrace utilities ---------------------===//
+//
+//                               N3
+//
+// 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 "Assembly.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "N3.h"
+#include "N3ModuleProvider.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+#include <execinfo.h>
+
+using namespace n3;
+
+void CLIJit::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();
+          VMMethod* meth = (VMMethod*)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 VMThread::get()->vm->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]);
+      }
+    }
+  }
+}
+
+
+
+Assembly* Assembly::getExecutingAssembly() {
+  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();
+          VMMethod* meth = (VMMethod*)m->definition();
+          if (meth && meth->getVirtualTable() == VMMethod::VT) {
+            return meth->classDef->assembly;
+          } else {
+            ++i;
+          }
+        } else {
+          VMThread::get()->vm->unknownError("in global variable?");
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+Assembly* Assembly::getCallingAssembly() {
+  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();
+          VMMethod* meth = (VMMethod*)m->definition();
+          if (meth && i >= 1 && meth->getVirtualTable() == VMMethod::VT) {
+            return meth->classDef->assembly;
+          } else {
+            ++i;
+          }
+        } else {
+          VMThread::get()->vm->unknownError("in global variable?");
+        }
+      }
+    }
+  }
+  return 0;
+}
diff --git a/vmkit/lib/N3/VMCore/CLIAccess.h b/vmkit/lib/N3/VMCore/CLIAccess.h
new file mode 100644
index 0000000..45c6fdb
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLIAccess.h
@@ -0,0 +1,41 @@
+//===------------- CLIAccess.h - CLI access description -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_CLI_ACCESS_H
+#define N3_CLI_ACCESS_H
+
+namespace n3 {
+
+#define ACC_STATIC        0x0010
+#define ACC_VIRTUAL       0x0040
+#define ACC_INTERFACE     0x0020
+#define ACC_INTERNAL      0x1000
+#define ACC_SYNCHRO       0x0020
+
+#define EXPLICIT_LAYOUT 0x00000010
+
+#define MK_VERIFIER(name, flag)                   \
+  inline bool name(unsigned int param) {          \
+    return (flag & param) != 0;                   \
+  }                                               \
+
+MK_VERIFIER(isStatic,     ACC_STATIC)
+MK_VERIFIER(isVirtual,    ACC_VIRTUAL)
+MK_VERIFIER(isInterface,  ACC_INTERFACE)
+MK_VERIFIER(isInternal,   ACC_INTERNAL)
+MK_VERIFIER(isSynchro,    ACC_SYNCHRO)
+
+MK_VERIFIER(hasExplicitLayout,    EXPLICIT_LAYOUT)
+  
+
+#undef MK_VERIFIER
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/CLIJit.cpp b/vmkit/lib/N3/VMCore/CLIJit.cpp
new file mode 100644
index 0000000..53a7453
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLIJit.cpp
@@ -0,0 +1,2149 @@
+//===------------ CLIJit.cpp - CLI just in time compiler ------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University Of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG 0
+#define N3_COMPILE 0
+#define N3_EXECUTE 0
+
+#include "debug.h"
+#include "types.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/Support/MutexGuard.h"
+
+#include <llvm/Transforms/IPO.h>
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+#include "mvm/VMLet.h"
+
+#include "Assembly.h"
+#include "CLIAccess.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "NativeUtil.h"
+#include "N3.h"
+#include "N3ModuleProvider.h"
+#include "Reader.h"
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMCache.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+using namespace llvm;
+using namespace n3;
+
+#include <iostream>
+
+void Exception::print(mvm::PrintBuffer* buf) const {
+  buf->write("Exception<>");
+}
+
+// for structs
+static void traceStruct(VMCommonClass* cl, BasicBlock* block, Value* arg) { 
+  for (std::vector<VMField*>::iterator i = cl->virtualFields.begin(), 
+            e = cl->virtualFields.end(); i!= e; ++i) {
+    VMField* field = *i;
+    if (field->signature->super == N3::pValue) {
+      if (!field->signature->isPrimitive) {
+        Value* ptr = new GetElementPtrInst(arg, field->offset, "",
+                                           block);
+        traceStruct(field->signature, block, ptr);
+      } else if (field->signature == N3::pIntPtr || field->signature == N3::pUIntPtr)  {
+        Value* valCast = new BitCastInst(arg, VMObject::llvmType, "", block);
+        new CallInst(CLIJit::markAndTraceLLVM, valCast, "", block);
+      }
+    } else if (field->signature->super != N3::pEnum) {
+      Value* valCast = new BitCastInst(arg, VMObject::llvmType, "", block);
+      new CallInst(CLIJit::markAndTraceLLVM, valCast, "", block);
+    }
+  }
+}
+
+
+// Always classes
+static void traceClass(VMCommonClass* cl, BasicBlock* block, Value* arg, 
+                       std::vector<VMField*>& fields, bool boxed = false) {
+  
+  Constant* zero = mvm::jit::constantZero;
+  for (std::vector<VMField*>::iterator i = fields.begin(), 
+            e = fields.end(); i!= e; ++i) {
+    VMField* field = *i;
+    if (field->signature->super == N3::pValue) {
+      std::vector<Value*> args; //size = 2
+      args.push_back(zero);
+      if (boxed) {
+        mvm::jit::protectConstants();
+        args.push_back(ConstantInt::get(field->offset->getValue() + 1));
+        mvm::jit::unprotectConstants();
+      } else {
+        args.push_back(field->offset);
+      }
+      Value* ptr = new GetElementPtrInst(arg, args.begin(), args.end(), "",
+                                         block);
+      traceStruct(field->signature, block, ptr);
+    } else if (field->signature->super != N3::pEnum) {
+      std::vector<Value*> args; //size = 2
+      args.push_back(zero);
+      if (boxed) {
+        mvm::jit::protectConstants();
+        args.push_back(ConstantInt::get(field->offset->getValue() + 1));
+        mvm::jit::unprotectConstants();
+      } else {
+        args.push_back(field->offset);
+      }
+      Value* ptr = new GetElementPtrInst(arg, args.begin(), args.end(), "",
+                                         block);
+      Value* val = new LoadInst(ptr, "", block);
+      Value* valCast = new BitCastInst(val, VMObject::llvmType, "", block);
+      new CallInst(CLIJit::markAndTraceLLVM, valCast, "", block);
+    }
+  }
+}
+
+VirtualTable* CLIJit::makeArrayVT(VMClassArray* cl) {
+  Function* func = new Function(markAndTraceLLVMType,
+                                GlobalValue::ExternalLinkage,
+                                "markAndTraceObject",
+                                cl->vm->module);
+  Argument* arg = func->arg_begin();
+  
+    // Constant Definitions
+  Constant* const_int32_8 = mvm::jit::constantZero;
+  ConstantInt* const_int32_9 = mvm::jit::constantOne;
+  ConstantInt* const_int32_10 = mvm::jit::constantTwo;
+  
+  
+  // Function Definitions
+  
+  {
+    BasicBlock* label_entry = new BasicBlock("entry",func,0);
+    BasicBlock* label_bb = new BasicBlock("bb",func,0);
+    BasicBlock* label_return = new BasicBlock("return",func,0);
+    
+    Value* ptr_v = new BitCastInst(arg, cl->naturalType, "", label_entry);
+    
+    // Block entry (label_entry)
+    std::vector<Value*> ptr_tmp918_indices;
+    ptr_tmp918_indices.push_back(const_int32_8);
+    ptr_tmp918_indices.push_back(const_int32_9);
+    Instruction* ptr_tmp918 = new GetElementPtrInst(ptr_v, ptr_tmp918_indices.begin(), ptr_tmp918_indices.end(), "tmp918", label_entry);
+    LoadInst* int32_tmp1019 = new LoadInst(ptr_tmp918, "tmp1019", false, label_entry);
+    ICmpInst* int1_tmp1221 = new ICmpInst(ICmpInst::ICMP_SGT, int32_tmp1019, const_int32_8, "tmp1221", label_entry);
+    new BranchInst(label_bb, label_return, int1_tmp1221, label_entry);
+    
+    // Block bb (label_bb)
+    Argument* fwdref_12 = new Argument(IntegerType::get(32));
+    PHINode* int32_i_015_0 = new PHINode(IntegerType::get(32), "i.015.0", label_bb);
+    int32_i_015_0->reserveOperandSpace(2);
+    int32_i_015_0->addIncoming(fwdref_12, label_bb);
+    int32_i_015_0->addIncoming(const_int32_8, label_entry);
+    
+    std::vector<Value*> ptr_tmp3_indices;
+    ptr_tmp3_indices.push_back(const_int32_8);
+    ptr_tmp3_indices.push_back(const_int32_10);
+    ptr_tmp3_indices.push_back(int32_i_015_0);
+    Instruction* ptr_tmp3 = new GetElementPtrInst(ptr_v, ptr_tmp3_indices.begin(), ptr_tmp3_indices.end(), "tmp3", label_bb);
+    if (cl->baseClass->super == N3::pValue) {
+      traceStruct(cl->baseClass, label_bb, ptr_tmp3);
+    } else if (cl->baseClass->super != N3::pEnum) {
+      LoadInst* ptr_tmp4 = new LoadInst(ptr_tmp3, "tmp4", false, label_bb);
+      Value* arg = new BitCastInst(ptr_tmp4, VMObject::llvmType, "", label_bb);
+      new CallInst(markAndTraceLLVM, arg, "", label_bb);
+    }
+    BinaryOperator* int32_tmp6 = BinaryOperator::create(Instruction::Add, int32_i_015_0, const_int32_9, "tmp6", label_bb);
+    LoadInst* int32_tmp10 = new LoadInst(ptr_tmp918, "tmp10", false, label_bb);
+    ICmpInst* int1_tmp12 = new ICmpInst(ICmpInst::ICMP_SGT, int32_tmp10, int32_tmp6, "tmp12", label_bb);
+    new BranchInst(label_bb, label_return, int1_tmp12, label_bb);
+    
+    // Block return (label_return)
+    new ReturnInst(label_return);
+    
+    // Resolve Forward References
+    fwdref_12->replaceAllUsesWith(int32_tmp6); delete fwdref_12;
+    
+  }
+  
+  VirtualTable * res = malloc(VT_SIZE);
+  memcpy(res, VMObject::VT, VT_SIZE);
+  void* tracer = mvm::jit::executionEngine->getPointerToGlobal(func);
+  ((void**)res)[VT_TRACER_OFFSET] = tracer;
+  cl->virtualTracer = func;
+  cl->codeVirtualTracer = (mvm::Code*)((intptr_t)tracer - sizeof(intptr_t));
+
+  return res;
+}
+
+VirtualTable* CLIJit::makeVT(VMClass* cl, bool stat) {
+  const Type* type = stat ? cl->staticType : cl->virtualType;
+  std::vector<VMField*> &fields = stat ? cl->staticFields : cl->virtualFields;
+  
+  Function* func = new Function(markAndTraceLLVMType,
+                                GlobalValue::ExternalLinkage,
+                                "markAndTraceObject",
+                                cl->vm->module);
+
+  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(vmObjectTracerLLVM, arg, "", block);
+  } else {
+    new CallInst(((VMClass*)cl->super)->virtualTracer, arg, "", block);
+  }
+  
+  traceClass(cl, block, realArg, fields, (cl->super == N3::pValue && !stat));
+  new ReturnInst(block);
+
+  VirtualTable * res = malloc(VT_SIZE);
+  memcpy(res, VMObject::VT, VT_SIZE);
+  void* tracer = mvm::jit::executionEngine->getPointerToGlobal(func);
+  ((void**)res)[VT_TRACER_OFFSET] = tracer;
+  
+  if (!stat) {
+    cl->virtualTracer = func;
+    cl->codeVirtualTracer = (mvm::Code*)((intptr_t)tracer - sizeof(intptr_t));
+  } else {
+    cl->staticTracer = func;
+    cl->codeStaticTracer = (mvm::Code*)((intptr_t)tracer - sizeof(intptr_t));
+  }
+  return res;
+
+}
+
+BasicBlock* CLIJit::createBasicBlock(const char* name) {
+  return new BasicBlock(name, llvmFunction);
+}
+
+void CLIJit::setCurrentBlock(BasicBlock* newBlock) {
+
+  std::vector<Value*> newStack;
+  uint32 index = 0;
+  for (BasicBlock::iterator i = newBlock->begin(), e = newBlock->end(); i != e;
+       ++i, ++index) {
+    if (!(isa<PHINode>(i))) {
+      break;
+    } else {
+      newStack.push_back(i);
+    }
+  }
+  
+  stack = newStack;
+  currentBlock = newBlock;
+}
+
+extern void convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock);
+
+static void testPHINodes(BasicBlock* dest, BasicBlock* insert, CLIJit* jit) {
+  if(dest->empty()) {
+    for (std::vector<Value*>::iterator i = jit->stack.begin(),
+            e = jit->stack.end(); i!= e; ++i) {
+      Value* cur = (*i);
+      PHINode* node = new PHINode(cur->getType(), "", dest);
+      node->addIncoming(cur, insert);
+    }
+  } else {
+    std::vector<Value*>::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);
+        convertValue(cur, ins->getType(), insert);
+        ((PHINode*)ins)->addIncoming(cur, insert);
+        ++stackit;
+      }
+    }
+  }
+}
+
+void CLIJit::branch(llvm::BasicBlock* dest, llvm::BasicBlock* insert) {
+  testPHINodes(dest, insert, this);
+  new BranchInst(dest, insert);
+}
+
+void CLIJit::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);
+}
+
+Value* CLIJit::pop() {
+  assert(stack.size());
+  Value* ret = top();
+  stack.pop_back();
+  return ret;
+}
+
+Value* CLIJit::top() {
+  return stack.back();
+}
+
+void CLIJit::push(Value* val) {
+  assert(val);
+  stack.push_back(val);
+}
+
+Value* CLIJit::changeType(Value* val, const Type* type) {
+  const Type* valType = val->getType();
+  if (type->isInteger()) {
+    if (valType == PointerType::getUnqual(type)) {
+      // in cast it's a struct
+      val = new LoadInst(val, "", currentBlock);
+    }
+    else if (type->getPrimitiveSizeInBits() < valType->getPrimitiveSizeInBits()) {
+      val = new TruncInst(val, type, "", currentBlock);
+    } else {
+      val = new SExtInst(val, type, "", currentBlock);
+    }
+  } else if (type == Type::FloatTy) {
+    val = new FPTruncInst(val, type, "", currentBlock);
+  } else if (type == Type::DoubleTy) {
+    val = new FPExtInst(val, type, "", currentBlock);
+  } else {
+    val = new BitCastInst(val, type, "", currentBlock);
+  }
+  return val;
+}
+
+void CLIJit::makeArgs(const FunctionType* type, std::vector<Value*>& Args,
+                      bool structReturn) {
+  uint32 size = type->getNumParams();
+  Value* args[size];
+  sint32 index = size - 1;
+  FunctionType::param_iterator e = type->param_end();
+  e--;
+  if (structReturn) { e--; index--; size--; }
+  for (; index >= 0; --e, --index) {
+    const Type* argType = (*e);
+    Value* val = pop();
+    if (val->getType() != argType) {
+      val = changeType(val, argType);
+    }
+    args[index] = val;
+  }
+
+  for (uint32 i = 0; i < size; ++i) {
+    Args.push_back(args[i]);
+  }
+}
+
+Instruction* CLIJit::lowerMathOps(VMMethod* meth, 
+                                  std::vector<Value*>& args) {
+  
+  if (meth->name == N3::sqrt) {
+    return new CallInst(mvm::jit::func_llvm_sqrt_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::sin) {
+    return new CallInst(mvm::jit::func_llvm_sin_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::cos) {
+    return new CallInst(mvm::jit::func_llvm_cos_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::exp) {
+    return new CallInst(mvm::jit::func_llvm_exp_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::log) {
+    return new CallInst(mvm::jit::func_llvm_log_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::floor) {
+    return new CallInst(mvm::jit::func_llvm_floor_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::log10) {
+    return new CallInst(mvm::jit::func_llvm_log10_f64, args[0], "tmp1", currentBlock);
+  } else if (meth->name == N3::pow) {
+    Instruction* val = new CallInst(mvm::jit::func_llvm_pow_f64, args.begin(), args.end(), "tmp1", currentBlock);
+    return val;
+  }
+  return 0;
+
+}
+
+Instruction* CLIJit::invokeInline(VMMethod* meth, 
+                                  std::vector<Value*>& args) {
+  
+  CLIJit* jit = gc_new(CLIJit)();
+  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 CLIJit::invoke(uint32 value) {
+  VMMethod* meth = compilingClass->assembly->getMethodFromToken(value);
+
+  if (meth->classDef->isArray) {
+    uint8 func = 0;
+    if (meth->name == VMThread::get()->vm->asciizConstructUTF8("Set")) {
+      func = 0;
+    } else if (meth->name == VMThread::get()->vm->asciizConstructUTF8("Get")) {
+      func = 1;
+    } else if (meth->name == VMThread::get()->vm->asciizConstructUTF8("Address")) {
+      func = 2;
+    } else {
+      VMThread::get()->vm->error("implement me %s", meth->name->printString());
+    }
+      
+    VMClassArray* type = (VMClassArray*)meth->classDef;
+    uint32 dims = type->dims;
+    Value* args[dims];
+    Value* val = 0;
+    if (func == 0) {
+      val = pop();
+    }
+    for (sint32 i = dims - 1; i >= 0 ; --i) {
+      args[i] = pop();
+    }
+    Value* obj = pop();
+    VMClassArray* base = type;
+    for (uint32 v = 0; v < dims; ++v) {
+      std::vector<Value*> Args;
+      Args.push_back(mvm::jit::constantZero);
+      Args.push_back(mvm::jit::constantTwo);
+      Args.push_back(args[v]);
+      obj = verifyAndComputePtr(obj, args[v], base->naturalType, true);
+      if (v != dims - 1) {
+        base = (VMClassArray*)base->baseClass;
+        obj = new LoadInst(obj, "", currentBlock);
+      }
+    }
+    
+    if (func == 0) {
+      new StoreInst(val, obj, false, currentBlock);
+    } else if (func == 1) {
+      push(new LoadInst(obj, "", currentBlock));
+    } else {
+      push(obj);
+    }
+    return;
+  }
+
+  std::vector<Value*> Args;
+  const llvm::FunctionType* type = meth->getSignature();
+  makeArgs(type, Args, meth->structReturn);
+  
+  if (meth->classDef->nameSpace == N3::system && meth->classDef->name == N3::math) {
+    Value* val = lowerMathOps(meth, Args); 
+    if (val) {
+      push(val);
+      return;
+    }
+  } else if (meth->classDef->nameSpace == N3::system && meth->classDef->name == N3::doubleName) {
+    if (meth->name == N3::isNan) {
+      push(new FCmpInst(FCmpInst::FCMP_UNO, Args[0], mvm::jit::constantDoubleZero, "tmp1", currentBlock));
+      return;
+    } else if (meth->name == N3::testInfinity) {
+      BasicBlock* endBlock = createBasicBlock("end test infinity");
+      BasicBlock* minusInfinity = createBasicBlock("- infinity");
+      BasicBlock* noInfinity = createBasicBlock("no infinity");
+      PHINode* node = new PHINode(Type::Int32Ty, "", endBlock);
+      node->addIncoming(mvm::jit::constantOne, currentBlock);
+      node->addIncoming(mvm::jit::constantMinusOne, minusInfinity);
+      node->addIncoming(mvm::jit::constantZero, noInfinity);
+      Value* val1 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], mvm::jit::constantDoubleInfinity, "tmp1", currentBlock); 
+      new BranchInst(endBlock, minusInfinity, val1, currentBlock);
+      Value* val2 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], mvm::jit::constantDoubleMinusInfinity, "tmp1", minusInfinity); 
+      new BranchInst(endBlock, noInfinity, val2, minusInfinity);
+      new BranchInst(endBlock, noInfinity);
+      currentBlock = endBlock; 
+      push(node);
+      return;
+    }
+  } else if (meth->classDef->nameSpace == N3::system && meth->classDef->name == N3::floatName) {
+    if (meth->name == N3::isNan) {
+      push(new FCmpInst(FCmpInst::FCMP_UNO, Args[0], mvm::jit::constantFloatZero, "tmp1", currentBlock));
+      return;
+    } else if (meth->name == N3::testInfinity) {
+      BasicBlock* endBlock = createBasicBlock("end test infinity");
+      BasicBlock* minusInfinity = createBasicBlock("- infinity");
+      BasicBlock* noInfinity = createBasicBlock("no infinity");
+      PHINode* node = new PHINode(Type::Int32Ty, "", endBlock);
+      node->addIncoming(mvm::jit::constantOne, currentBlock);
+      node->addIncoming(mvm::jit::constantMinusOne, minusInfinity);
+      node->addIncoming(mvm::jit::constantZero, noInfinity);
+      Value* val1 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], mvm::jit::constantFloatInfinity, "tmp1", currentBlock); 
+      new BranchInst(endBlock, minusInfinity, val1, currentBlock);
+      Value* val2 = new FCmpInst(FCmpInst::FCMP_OEQ, Args[0], mvm::jit::constantFloatMinusInfinity, "tmp1", minusInfinity); 
+      new BranchInst(endBlock, noInfinity, val2, minusInfinity);
+      new BranchInst(endBlock, noInfinity);
+      currentBlock = endBlock; 
+      push(node);
+      return;
+    }
+  }
+  
+  Value* res = 0;
+  if (meth && meth->canBeInlined && meth != compilingMethod && 
+      inlineMethods[meth] == 0) {
+    res = invokeInline(meth, Args);
+  } else {
+    Function* func = meth->compiledPtr();
+    
+    res = invoke(func, Args, "", currentBlock, meth->structReturn);
+  }
+  if (meth->parameters[0] != N3::pVoid) {
+    push(res);
+  }
+}
+
+void CLIJit::invokeNew(uint32 value) {
+  Assembly* ass = compilingClass->assembly;
+  VMMethod* meth = ass->getMethodFromToken(value);
+  VMClass* type = meth->classDef;
+  const FunctionType* funcType = meth->getSignature();
+    
+  Value* obj = 0;
+  if (type->isPointer) {
+    VMThread::get()->vm->error("implement me %s", type->printString());
+  } else if (type->isArray) {
+    VMClassArray* arrayType = (VMClassArray*)type;
+    Value* valCl = new LoadInst(arrayType->llvmVar(), "", currentBlock);
+    Value* args[arrayType->dims + 1];
+    args[0] = valCl;
+
+    for (int cur = arrayType->dims; cur > 0; --cur)
+      args[cur] = pop();
+     
+    std::vector<Value*> Args;
+    for (uint32 v = 0; v < arrayType->dims + 1; ++v) {
+      Args.push_back(args[v]);
+    }
+    push(invoke(arrayMultiConsLLVM, Args, "", currentBlock, false));
+    return;
+
+  } else if (type->super == N3::pValue || type->super == N3::pEnum) {
+    obj = new AllocaInst(type->naturalType, "", currentBlock);
+    uint64 size = mvm::jit::getTypeSize(type->naturalType);
+        
+    std::vector<Value*> params;
+    params.push_back(new BitCastInst(obj, mvm::jit::ptrType, "", currentBlock));
+    params.push_back(mvm::jit::constantInt8Zero);
+    mvm::jit::protectConstants();
+    params.push_back(ConstantInt::get(Type::Int32Ty, size));
+    mvm::jit::unprotectConstants();
+    params.push_back(mvm::jit::constantZero);
+    new CallInst(mvm::jit::llvm_memset_i32, params.begin(), params.end(), "", currentBlock);
+  } else {
+    Value* var = new LoadInst(type->llvmVar(), "", currentBlock);
+    Value* val = new CallInst(objConsLLVM, var, "", currentBlock);
+    obj = new BitCastInst(val, type->naturalType, "", currentBlock);
+  }
+  
+  std::vector<Value*>::iterator i = stack.end();
+  uint32 nbParams = funcType->getNumParams();
+  while (--nbParams) --i;
+  stack.insert(i, obj);
+
+  std::vector<Value*> Args;
+  makeArgs(funcType, Args, meth->structReturn);
+  if (meth && meth->canBeInlined && meth != compilingMethod && 
+      inlineMethods[meth] == 0) {
+    invokeInline(meth, Args);
+  } else {
+    Function* func = meth->compiledPtr();
+    
+    invoke(func, Args, "", currentBlock, meth->structReturn);
+  }
+    
+  if ((type->super == N3::pValue || type->super == N3::pEnum) && type->virtualFields.size() == 1) {
+    push(new LoadInst(obj, "", currentBlock));
+  } else {
+    push(obj);
+  }
+}
+  
+llvm::Value* CLIJit::getVirtualField(uint32 value) {
+  VMField* field = compilingClass->assembly->getFieldFromToken(value, false);
+  Value* obj = pop();
+  if ((field->classDef->super == N3::pValue ||
+      field->classDef->super == N3::pEnum) &&
+      field->classDef->virtualFields.size() == 1){
+    // struct!
+    return obj;
+  } else {
+    if (field->classDef->super != N3::pValue && field->classDef->super != N3::pEnum) {
+      obj = new BitCastInst(obj, field->classDef->naturalType, "", currentBlock);
+    }
+    std::vector<Value*> args;
+    args.push_back(mvm::jit::constantZero);
+    args.push_back(field->offset);
+    Value* ptr = new GetElementPtrInst(obj, args.begin(), args.end(), "", 
+                                       currentBlock);
+    return ptr;
+  }
+}
+
+llvm::Value* CLIJit::getStaticField(uint32 value) {
+  VMField* field = compilingClass->assembly->getFieldFromToken(value, true);
+  VMCommonClass* cl = field->classDef;
+  cl->resolveType(true, false);
+  Value* arg = new LoadInst(cl->llvmVar(), "", currentBlock);
+  Value* call = invoke(initialiseClassLLVM, arg, "", currentBlock, false);
+  Value* staticCl = new BitCastInst(call, cl->staticType, "", currentBlock);
+  
+  std::vector<Value*> args;
+  args.push_back(mvm::jit::constantZero);
+  args.push_back(field->offset);
+  Value* ptr = new GetElementPtrInst(staticCl, args.begin(), args.end(), "",
+                                     currentBlock);
+  
+  return ptr;
+
+}
+  
+void CLIJit::setVirtualField(uint32 value) {
+  VMField* field = compilingClass->assembly->getFieldFromToken(value, false);
+  Value* val = pop();
+  Value* obj = pop();
+  const Type* valType = val->getType();
+
+  Value* ptr = 0;
+  const Type* type = obj->getType();
+  if ((field->classDef->super == N3::pValue ||
+      field->classDef->super == N3::pEnum) &&
+      field->classDef->virtualFields.size() == 1){
+    // struct!
+    ptr = obj;
+  } else {
+    if (field->classDef->super != N3::pValue && field->classDef->super != N3::pEnum) {
+      obj = new BitCastInst(obj, field->classDef->naturalType, "", currentBlock);
+    }
+    std::vector<Value*> args;
+    args.push_back(mvm::jit::constantZero);
+    args.push_back(field->offset);
+    ptr = new GetElementPtrInst(obj, args.begin(), args.end(), "",
+                                currentBlock);
+  }
+
+  type = field->signature->naturalType;
+  if (val == constantVMObjectNull) {
+    mvm::jit::protectConstants();
+    val = Constant::getNullValue(type);
+    mvm::jit::unprotectConstants();
+  } else if (type != valType) {
+    val = changeType(val, type);
+  }
+  
+  new StoreInst(val, ptr, false, currentBlock);
+}
+
+void CLIJit::setStaticField(uint32 value) {
+  VMField* field = compilingClass->assembly->getFieldFromToken(value, true);
+  
+  VMCommonClass* cl = field->classDef;
+  Value* arg = new LoadInst(cl->llvmVar(), "", currentBlock);
+  Value* call = invoke(initialiseClassLLVM, arg, "", currentBlock, false);
+  Value* staticCl = new BitCastInst(call, cl->staticType, "", currentBlock);
+  
+  std::vector<Value*> args;
+  args.push_back(mvm::jit::constantZero);
+  args.push_back(field->offset);
+  Value* ptr = new GetElementPtrInst(staticCl, args.begin(), args.end(), "",
+                                     currentBlock);
+  Value* val = pop();
+  const Type* type = field->signature->naturalType;
+  const Type* valType = val->getType();
+  if (val == constantVMObjectNull) {
+    mvm::jit::protectConstants();
+    val = Constant::getNullValue(type);
+    mvm::jit::unprotectConstants();
+  } else if (type != valType) {
+    val = changeType(val, type);
+  }
+  new StoreInst(val, ptr, false, currentBlock);
+}
+
+void CLIJit::JITVerifyNull(Value* obj) {
+  CLIJit* jit = this;
+  mvm::jit::protectConstants();
+  Constant* zero = Constant::getNullValue(obj->getType());
+  mvm::jit::unprotectConstants();
+  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(CLIJit::nullPointerExceptionLLVM, unifiedUnreachable,
+                   currentExceptionBlock, args.begin(),
+                   args.end(), "", exit);
+  } else {
+    new CallInst(CLIJit::nullPointerExceptionLLVM, args.begin(),
+                 args.end(), "", exit);
+    new UnreachableInst(exit);
+  }
+
+
+  jit->currentBlock = cont;
+}
+
+llvm::Value* CLIJit::verifyAndComputePtr(llvm::Value* obj, llvm::Value* index,
+                                         const llvm::Type* arrayType,
+                                         bool verif) {
+  JITVerifyNull(obj);
+  
+  if (index->getType() != Type::Int32Ty) {
+    index = changeType(index, Type::Int32Ty);
+  }
+  
+  if (true) {
+    Value* size = arraySize(obj);
+    
+    Value* cmp = new ICmpInst(ICmpInst::ICMP_SLT, 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(new BitCastInst(obj, VMObject::llvmType, "", ifFalse));
+    args.push_back(index);
+    if (currentExceptionBlock != endExceptionBlock) {
+      new InvokeInst(CLIJit::indexOutOfBoundsExceptionLLVM, unifiedUnreachable,
+                     currentExceptionBlock, args.begin(),
+                     args.end(), "", ifFalse);
+    } else {
+      new CallInst(CLIJit::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(VMArray::elementsOffset());
+  indexes.push_back(index);
+  Value* ptr = new GetElementPtrInst(val, indexes.begin(), indexes.end(), 
+                                     "", currentBlock);
+
+  return ptr;
+
+}
+
+ConstantInt* VMArray::sizeOffset() {
+  return mvm::jit::constantOne;
+}
+
+ConstantInt* VMArray::elementsOffset() {
+  return mvm::jit::constantTwo;
+}
+
+Value* CLIJit::arraySize(Value* array) {
+  if (array->getType() != VMArray::llvmType) {
+    array = new BitCastInst(array, VMArray::llvmType, "", currentBlock);
+  }
+  return new CallInst(arrayLengthLLVM, array, "", currentBlock);
+  /*
+  std::vector<Value*> args; //size=  2
+  args.push_back(mvm::jit::constantZero);
+  args.push_back(VMArray::sizeOffset());
+  Value* ptr = new GetElementPtrInst(array, args.begin(), args.end(),
+                                     "", currentBlock);
+  return new LoadInst(ptr, "", currentBlock);*/
+}
+
+Function* CLIJit::createDelegate() {
+  Function* func = llvmFunction = compilingMethod->methPtr;
+  Function::arg_iterator i = func->arg_begin()++, e = func->arg_end();
+  Value* obj = i++;
+  Value* target = i++;
+  Value* handle = i++;
+  assert(i == e);
+  
+  BasicBlock* entry = createBasicBlock("entry");
+  obj = new BitCastInst(obj, N3::pDelegate->virtualType, "", entry);
+  std::vector<Value*> elts;
+  elts.push_back(mvm::jit::constantZero);
+  elts.push_back(mvm::jit::constantOne);
+  Value* targetPtr = new GetElementPtrInst(obj, elts.begin(), elts.end(), "",
+                                           entry);
+  
+  elts.pop_back();
+  elts.push_back(mvm::jit::constantTwo);
+  Value* handlePtr = new GetElementPtrInst(obj, elts.begin(), elts.end(), "",
+                                           entry);
+  new StoreInst(target, targetPtr, false, entry); 
+  new StoreInst(handle, handlePtr, false, entry);
+  new ReturnInst(entry);
+  
+  return func;
+}
+Function* CLIJit::invokeDelegate() {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+Function* CLIJit::compileIntern() {
+  PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "intern compile %s\n",
+              compilingMethod->printString());
+
+  if (compilingClass->subclassOf(N3::pDelegate)) {
+    const UTF8* name = compilingMethod->name;
+    if (name == N3::ctorName) return createDelegate();
+    else if (name == N3::invokeName) return invokeDelegate();
+    else VMThread::get()->vm->error("implement me");
+  } else {
+    VMThread::get()->vm->error("implement me %s", compilingClass->printString());
+  }
+  return 0;
+}
+
+Function* CLIJit::compileNative() {
+  PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "native compile %s\n",
+              compilingMethod->printString());
+  
+  const FunctionType *funcType = compilingMethod->getSignature();
+  
+  Function* func = llvmFunction = compilingMethod->methPtr;
+  currentBlock = createBasicBlock("start");
+  // TODO
+  /*endExceptionBlock = createBasicBlock("exceptionBlock");
+  endBlock = createBasicBlock("end");
+  new UnwindInst(endExceptionBlock);*/
+  
+  uint32 nargs = func->arg_size();
+  std::vector<Value*> nativeArgs;
+  
+  uint32 index = 0;
+  for (Function::arg_iterator i = func->arg_begin(); 
+       index < nargs; ++i, ++index) {   
+    nativeArgs.push_back(i);
+  }
+
+  void* natPtr = NativeUtil::nativeLookup(compilingClass, compilingMethod);
+  
+  mvm::jit::protectConstants();
+  Value* valPtr = 
+    ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (uint64)natPtr),
+                              PointerType::getUnqual(funcType));
+  mvm::jit::unprotectConstants();
+  
+  Value* result = new CallInst(valPtr, nativeArgs.begin(), nativeArgs.end(), "", currentBlock);
+  
+  
+  if (result->getType() != Type::VoidTy)
+    new ReturnInst(result, currentBlock);
+  else
+    new ReturnInst(currentBlock);
+  
+  
+  return llvmFunction;
+}
+
+uint32 CLIJit::readExceptionTable(uint32 offset, bool fat) {
+  Assembly* ass = compilingClass->assembly;
+  ArrayUInt8* bytes = ass->bytes;
+  uint32 nbe = 0;
+  if (fat) {
+    nbe = (READ_U3(bytes, offset) - 4) / 24;
+  } else {
+    nbe = (READ_U1(bytes, offset) - 4) / 12;
+    READ_U2(bytes, offset);
+  }
+  
+   if (nbe) {
+    supplLocal = new AllocaInst(VMObject::llvmType, "exceptionVar",
+                                currentBlock);
+  }
+  
+  BasicBlock* realEndExceptionBlock = endExceptionBlock;
+  // TODO synchronized
+
+  for (uint32 i = 0; i < nbe; ++i) {
+    Exception* ex = gc_new(Exception)();
+    uint32 flags = 0;
+    uint32 classToken = 0;
+    if (fat) {
+      flags = READ_U4(bytes, offset);
+      ex->tryOffset = READ_U4(bytes, offset);
+      ex->tryLength = READ_U4(bytes, offset);
+      ex->handlerOffset = READ_U4(bytes, offset);
+      ex->handlerLength = READ_U4(bytes, offset);
+      classToken = READ_U4(bytes, offset);
+    } else {
+      flags = READ_U2(bytes, offset);
+      ex->tryOffset = READ_U2(bytes, offset);
+      ex->tryLength = READ_U1(bytes, offset);
+      ex->handlerOffset = READ_U2(bytes, offset);
+      ex->handlerLength = READ_U1(bytes, offset);
+      classToken = READ_U4(bytes, offset);
+    }
+    
+    if (!(opcodeInfos[ex->handlerOffset].newBlock)) {
+      opcodeInfos[ex->handlerOffset].newBlock = createBasicBlock("handlerException");
+    }
+    
+    ex->handler = opcodeInfos[ex->handlerOffset].newBlock;
+    
+    if (flags == CONSTANT_COR_ILEXCEPTION_CLAUSE_EXCEPTION) {
+      ex->test = createBasicBlock("testException");
+      if (classToken) {
+        ex->catchClass = ass->loadType((N3*)VMThread::get()->vm, classToken,
+                                       true, false, false, true);
+      } else {
+        ex->catchClass = N3::pException;
+      }
+      opcodeInfos[ex->handlerOffset].reqSuppl = true;
+      exceptions.push_back(ex);
+
+      for (uint16 i = ex->tryOffset; i < ex->tryOffset + ex->tryLength; ++i) {
+        if (opcodeInfos[i].exceptionBlock == endExceptionBlock) {
+          opcodeInfos[i].exceptionBlock = ex->test;
+        }    
+      }  
+
+    } else if (flags == CONSTANT_COR_ILEXCEPTION_CLAUSE_FINALLY) {
+      ex->catchClass = 0;
+      finallyHandlers.push_back(ex);
+    } else {
+      VMThread::get()->vm->error("implement me");
+    }
+  }
+  
+  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;
+    }
+    
+    if (next && cur->tryOffset == next->tryOffset && 
+        cur->tryOffset + cur->tryLength == next->tryOffset + next->tryLength)
+      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;
+    if (i + 1 != e) {
+      next = *(i + 1);
+      if (cur->tryOffset >= next->tryOffset && 
+          cur->tryOffset + cur->tryLength <= next->tryOffset + next->tryLength) {
+        bbNext = realEndExceptionBlock;
+      } else {
+        bbNext = next->realTest;
+      }
+    } 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);
+      mvm::jit::protectConstants();
+      int32_eh_select_params.push_back(ConstantExpr::getCast(Instruction::BitCast, mvm::jit::personality, PointerTy_0));
+      mvm::jit::unprotectConstants();
+      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);
+    } 
+
+    Value* cl = new LoadInst(cur->catchClass->llvmVar(), "", cur->realTest);
+    Value* cmp = new CallInst(compareExceptionLLVM, cl, "", cur->realTest);
+    new BranchInst(cur->handler, bbNext, cmp, cur->realTest);
+    
+    if (cur->handler->empty()) {
+      Value* cpp = new CallInst(getCppExceptionLLVM, "", cur->handler);
+      Value* exc = new CallInst(getCLIExceptionLLVM, "", cur->handler);
+      new CallInst(clearExceptionLLVM, "", cur->handler);
+      new CallInst(mvm::jit::exceptionBeginCatch, cpp, "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);
+      
+      for (uint16 i = cur->tryOffset; i < cur->tryOffset + cur->tryLength; ++i) {
+        opcodeInfos[i].exception = exc;
+      }  
+    } 
+     
+  }
+
+  return nbe;
+
+}
+
+#include <iostream>  
+Function* CLIJit::compileFatOrTiny() {
+  PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "tiny or fat compile %s\n",
+              compilingMethod->printString());
+  uint32 offset = compilingMethod->offset;
+  ArrayUInt8* bytes = compilingClass->assembly->bytes;
+  uint8 header = READ_U1(bytes, offset);
+  bool tiny = false;
+  uint32 localVarSig = 0;
+  uint32 maxStack = 0;
+  uint32 codeLen = 0;
+  uint32 nbe = 0;
+
+  if ((header & 3) == CONSTANT_CorILMethod_TinyFormat) {
+    tiny = true;
+    codeLen = (header & 0xfffc) >> 2;
+  } else if ((header & 3) != CONSTANT_CorILMethod_FatFormat) {
+    VMThread::get()->vm->error("unknown Method Format");
+  } else {
+    header += (READ_U1(bytes, offset) << 8); //header
+    maxStack = READ_U2(bytes, offset);
+    codeLen = READ_U4(bytes, offset);
+    localVarSig = READ_U4(bytes, offset);
+  }
+    
+
+  /* TODO Synchronize
+  bool synchro = isSynchro(compilingMethod->flags);
+  */
+
+  const FunctionType *funcType = compilingMethod->getSignature();
+  
+  Function* func = llvmFunction = compilingMethod->methPtr;
+  currentBlock = createBasicBlock("start");
+  endExceptionBlock = createBasicBlock("exceptionBlock");
+  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 (!tiny) {
+    if (header & CONSTANT_CorILMethod_MoreSects) {
+      uint32 excpOffset = 0;
+      if ((codeLen % 4) == 0) {
+        excpOffset = offset + codeLen;
+      } else {
+        excpOffset = offset + codeLen + (4 - (codeLen % 4));
+      }
+
+      uint8 flags = READ_U1(bytes, excpOffset);
+      nbe = readExceptionTable(excpOffset, 
+                         flags & CONSTANT_CorILMethod_Sect_FatFormat);
+    }
+  }
+
+  for (Function::arg_iterator i = func->arg_begin(), e = func->arg_end(); 
+       i != e; ++i) {
+    
+    const Type* cur = i->getType();
+
+    AllocaInst* alloc = new AllocaInst(cur, "", currentBlock);
+    new StoreInst(i, alloc, false, currentBlock);
+    arguments.push_back(alloc);
+  } 
+  
+  if (localVarSig) {
+    std::vector<VMCommonClass*> temp;
+    compilingClass->assembly->readSignature(localVarSig, temp);
+
+    for (std::vector<VMCommonClass*>::iterator i = temp.begin(), 
+            e = temp.end(); i!= e; ++i) {
+      VMCommonClass* cl = *i;
+      cl->resolveType(false, false);
+      AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock);
+      if (cl->naturalType->isFirstClassType()) {
+        mvm::jit::protectConstants();
+        new StoreInst(Constant::getNullValue(cl->naturalType), alloc, false,
+                      currentBlock);
+        mvm::jit::unprotectConstants();
+      } else {
+        uint64 size = mvm::jit::getTypeSize(cl->naturalType);
+        
+        std::vector<Value*> params;
+        params.push_back(new BitCastInst(alloc, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+        params.push_back(mvm::jit::constantInt8Zero);
+        mvm::jit::protectConstants();
+        params.push_back(ConstantInt::get(Type::Int32Ty, size));
+        mvm::jit::unprotectConstants();
+        params.push_back(mvm::jit::constantZero);
+        new CallInst(mvm::jit::llvm_memset_i32, params.begin(), params.end(), "", currentBlock);
+
+      }
+      locals.push_back(alloc);
+    }
+  }
+
+  exploreOpcodes(&compilingClass->assembly->bytes->elements[offset], codeLen); 
+ 
+  endBlock = createBasicBlock("end");
+
+  const Type* endType = funcType->getReturnType(); 
+  if (endType != Type::VoidTy) {
+    endNode = new PHINode(endType, "", endBlock);
+  } else if (compilingMethod->structReturn) {
+    const Type* lastType = 
+      funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+    endNode = new PHINode(lastType, "", endBlock);
+  }
+
+  compileOpcodes(&compilingClass->assembly->bytes->elements[offset], codeLen);
+  
+  currentBlock = endBlock;
+  pred_iterator PI = pred_begin(endBlock);
+  pred_iterator PE = pred_end(endBlock);
+  if (PI == PE) {
+    endBlock->eraseFromParent();
+  } else {
+    if (endType != Type::VoidTy) {
+      new ReturnInst(endNode, endBlock);
+    } else if (compilingMethod->structReturn) {
+      const Type* lastType = 
+        funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+      uint64 size = mvm::jit::getTypeSize(lastType->getContainedType(0));
+      Value* obj = --llvmFunction->arg_end();
+      std::vector<Value*> params;
+      params.push_back(new BitCastInst(obj, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+      params.push_back(new BitCastInst(endNode, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+      mvm::jit::protectConstants();
+      params.push_back(ConstantInt::get(Type::Int32Ty, size));
+      mvm::jit::unprotectConstants();
+      params.push_back(mvm::jit::constantFour);
+      new CallInst(mvm::jit::llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock);
+      new ReturnInst(currentBlock);
+    } else {
+      new ReturnInst(endBlock);
+    }
+  }
+  
+  PI = pred_begin(endExceptionBlock);
+  PE = pred_end(endExceptionBlock);
+  if (PI == PE) {
+    endExceptionBlock->eraseFromParent();
+  } else {
+    CallInst* ptr_eh_ptr = new CallInst(getCppExceptionLLVM, "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, VMThread::get()->perFunctionPasses);
+  
+  if (nbe == 0 && codeLen < 50) {
+    PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "%s can be inlined\n",
+                compilingMethod->printString());
+    compilingMethod->canBeInlined = true;
+  }
+  
+  return llvmFunction;
+}
+
+Instruction* CLIJit::inlineCompile(Function* parentFunction, BasicBlock*& curBB,
+                                   BasicBlock* endExBlock,
+                                   std::vector<Value*>& args) {
+  
+  PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "tiny or fat inline compile %s\n",
+              compilingMethod->printString());
+  uint32 offset = compilingMethod->offset;
+  ArrayUInt8* bytes = compilingClass->assembly->bytes;
+  uint8 header = READ_U1(bytes, offset);
+  bool tiny = false;
+  uint32 localVarSig = 0;
+  uint32 maxStack = 0;
+  uint32 codeLen = 0;
+  
+  if ((header & 3) == CONSTANT_CorILMethod_TinyFormat) {
+    tiny = true;
+    codeLen = (header & 0xfffc) >> 2;
+  } else if ((header & 3) != CONSTANT_CorILMethod_FatFormat) {
+    VMThread::get()->vm->error("unknown Method Format");
+  } else {
+    header += (READ_U1(bytes, offset) << 8); //header
+    maxStack = READ_U2(bytes, offset);
+    codeLen = READ_U4(bytes, offset);
+    localVarSig = READ_U4(bytes, offset);
+  }
+    
+
+  /* TODO Synchronize
+  bool synchro = isSynchro(compilingMethod->flags);
+  */
+
+  const FunctionType *funcType = compilingMethod->getSignature();
+  
+  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;
+  }
+  
+  if (!tiny) {
+    if (header & CONSTANT_CorILMethod_MoreSects) {
+      assert(0 && "inlining a function with exceptions!");
+      uint32 excpOffset = 0;
+      if ((codeLen % 4) == 0) {
+        excpOffset = offset + codeLen;
+      } else {
+        excpOffset = offset + codeLen + (4 - (codeLen % 4));
+      }
+
+      uint8 flags = READ_U1(bytes, excpOffset);
+      readExceptionTable(excpOffset, 
+                         flags & CONSTANT_CorILMethod_Sect_FatFormat);
+    }
+  }
+
+  for (std::vector<Value*>::iterator i = args.begin(), e = args.end(); 
+       i != e; ++i) {
+    
+    const Type* cur = (*i)->getType();
+
+    AllocaInst* alloc = new AllocaInst(cur, "", currentBlock);
+    new StoreInst(*i, alloc, false, currentBlock);
+    arguments.push_back(alloc);
+  } 
+
+  if (localVarSig) {
+    std::vector<VMCommonClass*> temp;
+    compilingClass->assembly->readSignature(localVarSig, temp);
+
+    for (std::vector<VMCommonClass*>::iterator i = temp.begin(), 
+            e = temp.end(); i!= e; ++i) {
+      VMCommonClass* cl = *i;
+      cl->resolveType(false, false);
+      AllocaInst* alloc = new AllocaInst(cl->naturalType, "", currentBlock);
+      if (cl->naturalType->isFirstClassType()) {
+        mvm::jit::protectConstants();
+        new StoreInst(Constant::getNullValue(cl->naturalType), alloc, false,
+                      currentBlock);
+        mvm::jit::unprotectConstants();
+      } else {
+        uint64 size = mvm::jit::getTypeSize(cl->naturalType);
+        
+        std::vector<Value*> params;
+        params.push_back(new BitCastInst(alloc, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+        params.push_back(mvm::jit::constantInt8Zero);
+        mvm::jit::protectConstants();
+        params.push_back(ConstantInt::get(Type::Int32Ty, size));
+        mvm::jit::unprotectConstants();
+        params.push_back(mvm::jit::constantZero);
+        new CallInst(mvm::jit::llvm_memset_i32, params.begin(), params.end(), "", currentBlock);
+
+      }
+      locals.push_back(alloc);
+    }
+  }
+
+  exploreOpcodes(&compilingClass->assembly->bytes->elements[offset], codeLen); 
+ 
+  endBlock = createBasicBlock("end");
+
+  const Type* endType = funcType->getReturnType(); 
+  if (endType != Type::VoidTy) {
+    endNode = new PHINode(endType, "", endBlock);
+  } else if (compilingMethod->structReturn) {
+    const Type* lastType = 
+      funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+    endNode = new PHINode(lastType, "", endBlock);
+  }
+
+  compileOpcodes(&compilingClass->assembly->bytes->elements[offset], codeLen);
+  
+  curBB = endBlock;
+  
+  PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "end tiny or fat inline compile %s\n",
+              compilingMethod->printString());
+  
+  return endNode;
+}
+
+
+Function* CLIJit::compile(VMClass* cl, VMMethod* meth) {
+  CLIJit* jit = gc_new(CLIJit)();
+  jit->compilingClass = cl; 
+  jit->compilingMethod = meth;
+
+  meth->getSignature();
+  if (isInternal(meth->implFlags)) {
+    return jit->compileNative();
+  } else if (meth->offset == 0) {
+    return jit->compileIntern();
+  } else {
+    return jit->compileFatOrTiny();
+  }
+}
+
+llvm::Function *VMMethod::compiledPtr() {
+  if (methPtr != 0) return methPtr;
+  else {
+    classDef->aquire();
+    if (methPtr == 0) {
+      methPtr = new llvm::Function(getSignature(), GlobalValue::GhostLinkage,
+                                   printString(), classDef->vm->module);
+      classDef->vm->functions->hash(methPtr, this);
+    }
+    classDef->release();
+    return methPtr;
+  }
+}
+
+void VMField::initField(VMObject* obj) {
+  VMField* field = this;
+  ConstantInt* offset = field->offset;
+  const TargetData* targetData = mvm::jit::executionEngine->getTargetData();
+  bool stat = isStatic(field->flags);
+  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;
+
+}
+
+extern "C" VMObject* initialiseClass(VMClass* cl) {
+  cl->clinitClass();
+  return cl->staticInstance;
+}
+
+extern "C" void classCastException() {
+  fflush(stdout);
+  assert(0 && "implement class cast exception");
+}
+
+extern "C" void nullPointerException() {
+  fflush(stdout);
+  assert(0 && "implement null pointer exception");
+}
+
+extern "C" void indexOutOfBounds() {
+  fflush(stdout);
+  assert(0 && "implement index out of bounds exception");
+}
+
+
+extern "C" bool isInCode(void* value) {
+  mvm::Object* obj = (mvm::Object*)gc::begOf(value);
+  if (obj && obj->getVirtualTable() == mvm::Code::VT) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+extern "C" VMObject* newString(const UTF8* utf8) {
+  CLIString * str = 
+    (CLIString*)(((N3*)VMThread::get()->vm)->UTF8ToStr(utf8));
+  return str;
+}
+
+void CLIJit::initialise() {
+}
+
+void CLIJit::initialiseAppDomain(N3* vm) {
+  mvm::jit::protectEngine->lock();
+  mvm::jit::executionEngine->addModuleProvider(vm->TheModuleProvider);
+  mvm::jit::protectEngine->unlock();
+}
+
+void CLIJit::initialiseBootstrapVM(N3* vm) {
+  Module* module = vm->module;
+  mvm::jit::protectEngine->lock();
+  mvm::jit::executionEngine->addModuleProvider(vm->TheModuleProvider);
+  mvm::jit::protectEngine->unlock();
+ 
+  
+
+  {
+    std::vector<const llvm::Type *> arg_types;
+    arg_types.insert (arg_types.begin (), llvm::PointerType::getUnqual(llvm::PointerType::getUnqual(llvm::Type::Int8Ty)));
+    
+    llvm::FunctionType *mtype = llvm::FunctionType::get (llvm::Type::VoidTy, arg_types, false);
+    new llvm::Function(mtype,  llvm::GlobalValue::ExternalLinkage, "llvm.va_start", module);
+  }
+
+  {
+    std::vector<const llvm::Type *> arg_types;
+    arg_types.insert (arg_types.begin (), llvm::Type::Int32Ty);
+  
+    llvm::FunctionType *mtype = llvm::FunctionType::get (llvm::PointerType::getUnqual(llvm::Type::Int8Ty), arg_types, false);
+    new llvm::Function(mtype,  llvm::GlobalValue::ExternalLinkage, "llvm.frameaddress", module);
+  }
+
+  
+  {
+     const llvm::Type *BPTy = PointerType::getUnqual(llvm::Type::Int8Ty);
+     // Prototype malloc as "char* malloc(...)", because we don't know in
+     // doInitialization whether size_t is int or long.
+     FunctionType *FT = FunctionType::get(BPTy, std::vector<const llvm::Type*>(), true);
+     new llvm::Function(FT, llvm::GlobalValue::ExternalLinkage, "_ZN2gcnwEjP5gc_vt", module); 
+  }
+
+
+  // Create VMObject::llvmType
+  const llvm::Type* Pty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+  
+  std::vector<const llvm::Type*> objectFields;
+  objectFields.push_back(Pty); // VT
+  objectFields.push_back(Pty); // Class
+  objectFields.push_back(Pty); // Lock
+  VMObject::llvmType = 
+    llvm::PointerType::getUnqual(llvm::StructType::get(objectFields, false));
+
+  // Create VMArray::llvmType
+  {
+  std::vector<const llvm::Type*> arrayFields;
+  arrayFields.push_back(VMObject::llvmType->getContainedType(0));
+  arrayFields.push_back(llvm::Type::Int32Ty);
+  VMArray::llvmType =
+    llvm::PointerType::getUnqual(llvm::StructType::get(arrayFields, false));
+  }
+
+#define ARRAY_TYPE(name, type)                                            \
+  {                                                                       \
+  std::vector<const Type*> arrayFields;                                   \
+  arrayFields.push_back(VMObject::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, VMObject::llvmType);
+
+#undef ARRAY_TYPE
+
+  // Create UTF8::llvmType
+  {
+  std::vector<const llvm::Type*> arrayFields;
+  arrayFields.push_back(VMObject::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(PointerType::getUnqual(Type::Int8Ty)); // VT
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // methPtr
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // lastCible
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // next
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // enveloppe
+  arrayFields.push_back(Type::Int1Ty); // box
+  CacheNode::llvmType =
+    PointerType::getUnqual(StructType::get(arrayFields, false));
+  }
+  
+  // Create Enveloppe::llvmType
+  {
+  std::vector<const llvm::Type*> arrayFields;
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // VT
+  arrayFields.push_back(CacheNode::llvmType); // firstCache
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // cacheLock
+  arrayFields.push_back(PointerType::getUnqual(Type::Int8Ty)); // originalMethod
+  Enveloppe::llvmType =
+    PointerType::getUnqual(StructType::get(arrayFields, false));
+  }
+
+  // Create markAndTraceLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  markAndTraceLLVMType = FunctionType::get(llvm::Type::VoidTy, args, false);
+  markAndTraceLLVM = new Function(markAndTraceLLVMType,
+                                  GlobalValue::ExternalLinkage,
+                                  "_ZNK2gc12markAndTraceEv",
+                                  module);
+  }
+  
+  // Create vmObjectTracerLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+  vmObjectTracerLLVM = new Function(type,
+                                    GlobalValue::ExternalLinkage,
+                                    "_ZN2n38VMObject6tracerEj",
+                                    module);
+  }
+
+  // Create intialiseClassLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args, false);
+  initialiseClassLLVM = new Function(type,
+                                     GlobalValue::ExternalLinkage,
+                                     "initialiseClass",
+                                     module);
+  }
+
+  
+  // Create resolveStringLLVM
+  /*{
+  std::vector<const Type*> args;
+  args.push_back(UTF8::llvmType);
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  args.push_back(llvm::Type::Int32Ty);
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               false);
+  stringLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                "_ZN5n37CLIJit12stringLookupEPKNS_4UTF8EPNS_5ClassEj",
+                module);
+  }*/
+ 
+  // Create staticLookupLLVM
+  /*{
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  args.push_back(llvm::Type::Int32Ty);
+  const FunctionType* type =
+    FunctionType::get(llvm::PointerType::getUnqual(llvm::Type::Int8Ty), args,
+                      false);
+
+  staticLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n37CLIJit12staticLookupEPNS_5ClassEj",
+                     module);
+  }*/
+  
+  // Create virtualLookupLLVM
+  {
+  std::vector<const Type*> args;
+  //args.push_back(VMObject::llvmType);
+  //args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  //args.push_back(llvm::Type::Int32Ty);
+  args.push_back(CacheNode::llvmType);
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type =
+    FunctionType::get(CacheNode::llvmType, args, false);
+
+  virtualLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                                   "virtualLookup", module);
+
+/*
+  virtualLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n37CLIJit13virtualLookupEPNS_10VMObjectEPNS_5ClassEj",
+                     module);
+*/
+  }
+  
+  // Create newLookupLLVM
+  /*{
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  args.push_back(llvm::Type::Int32Ty);
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               false);
+
+  newLookupLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n37CLIJit9newLookupEPNS_5ClassEj",
+                     module);
+  }*/
+  
+  // Create arrayConsLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  args.push_back(Type::Int32Ty);
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               false);
+
+  arrayConsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n312VMClassArray5doNewEj",
+                     module);
+  }
+  
+  // Create objConsLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               false);
+
+  objConsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n37VMClass5doNewEv",
+                     module);
+  }
+  
+  // Create objInitLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               false);
+
+  objInitLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n37VMClass16initialiseObjectEPNS_8VMObjectE",
+                     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());
+  objInitLLVM->setParamAttrs(func_toto_PAL);
+  }
+  
+  // Create arrayLengthLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMArray::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 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;
+  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(VMObject::llvmType);
+  args.push_back(Type::Int32Ty);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  indexOutOfBoundsExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "indexOutOfBounds",
+                     module);
+  }
+  
+  // Create proceedPendingExceptionLLVM
+  /*{
+  std::vector<const Type*> args;
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  jniProceedPendingExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n37CLIJit26jniProceedPendingExceptionEv",
+                     module);
+  }*/
+  
+  // Create printExecutionLLVM
+  {
+  std::vector<const Type*> args;
+  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,
+                     "_ZN2n36CLIJit14printExecutionEPcPNS_8VMMethodE",
+                     module);
+  }
+  
+  // Create throwExceptionLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  throwExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n38VMThread14throwExceptionEPNS_8VMObjectE",
+                     module);
+  }
+   
+  // Create clearExceptionLLVM
+  {
+  std::vector<const Type*> args;
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  clearExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n38VMThread14clearExceptionEv",
+                     module);
+  }
+  
+  
+  // Create compareExceptionLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  const FunctionType* type = FunctionType::get(Type::Int1Ty, args, false);
+
+  compareExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n38VMThread16compareExceptionEPNS_7VMClassE",
+                     module);
+  }
+  
+  // Create instanceOfLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  const FunctionType* type = FunctionType::get(Type::Int32Ty, args, false);
+
+  instanceOfLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n38VMObject10instanceOfEPNS_13VMCommonClassE",
+                     module);
+  }
+  
+  // Create isInCodeLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type = FunctionType::get(Type::Int1Ty, args, false);
+
+  isInCodeLLVM = new Function(type, GlobalValue::ExternalLinkage, "isInCode",
+                              module);
+  }
+  
+  // Create arrayMultiConsLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               true);
+
+  arrayMultiConsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "doMultiNew",
+                     module);
+  }
+
+  /*
+  // Create aquireObjectLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  aquireObjectLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n310VMObject6aquireEv",
+                     module);
+  }
+  
+  // Create releaseObjectLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(VMObject::llvmType);
+  const FunctionType* type = FunctionType::get(Type::VoidTy, args, false);
+
+  releaseObjectLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n310VMObject6unlockEv",
+                     module);
+  }
+  
+  */
+  
+  
+  // Create *AconsLLVM
+  /*{
+  std::vector<const Type*> args;
+  args.push_back(Type::Int32Ty);
+  args.push_back(PointerType::getUnqual(Type::Int8Ty));
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, args,
+                                               false);
+
+  FloatAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n310ArrayFloat5aconsEiPNS_10VMClassArrayE",
+                     module);
+  
+  Int8AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n310ArraySInt85aconsEiPNS_10VMClassArrayE",
+                     module);
+  
+  DoubleAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n311ArrayDouble5aconsEiPNS_10VMClassArrayE",
+                     module);
+   
+  Int16AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n311ArraySInt165aconsEiPNS_10VMClassArrayE",
+                     module);
+  
+  Int32AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n311ArraySInt325aconsEiPNS_10VMClassArrayE",
+                     module);
+  
+  UTF8AconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n34UTF85aconsEiPNS_10VMClassArrayE",
+                     module);
+  
+  LongAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n39ArrayLong5aconsEiPNS_10VMClassArrayE",
+                     module);
+  
+  ObjectAconsLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN5n311ArrayObject5aconsEiPNS_10VMClassArrayE",
+                     module);
+  }*/
+  
+  // Create getCppExceptionLLVM
+  {
+  std::vector<const Type*> args;
+  const FunctionType* type = FunctionType::get(mvm::jit::ptrType, 
+                                               args, false);
+
+  getCppExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n38VMThread15getCppExceptionEv",
+                     module);
+  }
+  
+  // Create getCLIExceptionLLVM
+  {
+  std::vector<const Type*> args;
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, 
+                                               args, false);
+
+  getCLIExceptionLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "_ZN2n38VMThread15getCLIExceptionEv",
+                     module);
+  }
+  
+  // Create newStringLLVM
+  {
+  std::vector<const Type*> args;
+  args.push_back(mvm::jit::ptrType);
+  const FunctionType* type = FunctionType::get(VMObject::llvmType, 
+                                               args, false);
+
+  newStringLLVM = new Function(type, GlobalValue::ExternalLinkage,
+                     "newString",
+                     module);
+  }
+
+  
+  constantVMObjectNull = Constant::getNullValue(VMObject::llvmType);
+}
+
+Constant* CLIJit::constantVMObjectNull;
+
+
+static void printArgs(std::vector<llvm::Value*> args, BasicBlock* insertAt) {
+  for (std::vector<llvm::Value*>::iterator i = args.begin(),
+       e = args.end(); i!= e; ++i) {
+    llvm::Value* arg = *i;
+    const llvm::Type* type = arg->getType();
+    if (type == Type::Int8Ty || type == Type::Int16Ty || type == Type::Int1Ty) {
+      new CallInst(mvm::jit::printIntLLVM, new ZExtInst(arg, Type::Int32Ty, "", insertAt), "", insertAt);
+    } else if (type == Type::Int32Ty) {
+      new CallInst(mvm::jit::printIntLLVM, arg, "", insertAt);
+    } else if (type == Type::Int64Ty) {
+      new CallInst(mvm::jit::printLongLLVM, arg, "", insertAt);
+    } else if (type == Type::FloatTy) {
+      new CallInst(mvm::jit::printFloatLLVM, arg, "", insertAt);
+    } else if (type == Type::DoubleTy) {
+      new CallInst(mvm::jit::printDoubleLLVM, arg, "", insertAt);
+    } else {
+      new CallInst(mvm::jit::printObjectLLVM, new BitCastInst(arg, VMObject::llvmType, "", insertAt), "", insertAt);
+    }
+  }
+
+}
+
+Value* CLIJit::invoke(Value *F, std::vector<llvm::Value*> args,
+                       const char* Name,
+                       BasicBlock *InsertAtEnd, bool structReturn) {
+#if N3_EXECUTE > 1
+  printArgs(args, InsertAtEnd);
+#endif
+
+  Value* ret = 0;
+  if (structReturn) {
+    const Type* funcType = F->getType();
+    if (isa<PointerType>(funcType)) {
+      funcType = funcType->getContainedType(0);
+    }
+    const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+    ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd);
+    args.push_back(ret);
+  }
+  Value* val = 0;
+  // means: is there a handler for me?
+  if (currentExceptionBlock != endExceptionBlock) {
+    BasicBlock* ifNormal = createBasicBlock("no exception block");
+    currentBlock = ifNormal;
+    val = new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(), 
+                         args.end(), Name, InsertAtEnd);
+  } else {
+    val = new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
+  }
+  if (ret) return ret;
+  else return val;
+}
+
+Value* CLIJit::invoke(Value *F, Value* arg1, const char* Name,
+                       BasicBlock *InsertAtEnd, bool structReturn) {
+  
+  std::vector<Value*> args;
+  args.push_back(arg1);
+#if N3_EXECUTE > 1
+  printArgs(args, InsertAtEnd);
+#endif
+  Value* ret = 0;
+  if (structReturn) {
+    const Type* funcType = F->getType();
+    if (isa<PointerType>(funcType)) {
+      funcType = funcType->getContainedType(0);
+    }
+    const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+    ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd);
+    args.push_back(ret);
+  }
+  
+  Value* val = 0;
+  // means: is there a handler for me?
+  if (currentExceptionBlock != endExceptionBlock) {
+    BasicBlock* ifNormal = createBasicBlock("no exception block");
+    currentBlock = ifNormal;
+    val = new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
+                                args.end(), Name, InsertAtEnd);
+  } else {
+    val = new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
+  }
+  
+  if (ret) return ret;
+  else return val; 
+}
+
+Value* CLIJit::invoke(Value *F, Value* arg1, Value* arg2,
+                       const char* Name, BasicBlock *InsertAtEnd, 
+                       bool structReturn) {
+  
+  std::vector<Value*> args;
+  args.push_back(arg1);
+  args.push_back(arg2);
+#if N3_EXECUTE > 1
+  printArgs(args, InsertAtEnd);
+#endif
+  
+  Value* ret = 0;
+  if (structReturn) {
+    const Type* funcType = F->getType();
+    if (isa<PointerType>(funcType)) {
+      funcType = funcType->getContainedType(0);
+    }
+    const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+    ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd);
+    args.push_back(ret);
+  }
+
+  Value* val = 0;
+  // means: is there a handler for me?
+  if (currentExceptionBlock != endExceptionBlock) {
+    BasicBlock* ifNormal = createBasicBlock("no exception block");
+    currentBlock = ifNormal;
+    val = new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
+                         args.end(), Name, InsertAtEnd);
+  } else {
+    val = new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
+  }
+  if (ret) return ret;
+  else return val; 
+}
+
+Value* CLIJit::invoke(Value *F, const char* Name,
+                       BasicBlock *InsertAtEnd, bool structReturn) {
+  
+  std::vector<Value*> args;
+  Value* ret = 0;
+  if (structReturn) {
+    const Type* funcType = F->getType();
+    if (isa<PointerType>(funcType)) {
+      funcType = funcType->getContainedType(0);
+    }
+    const Type* lastType = funcType->getContainedType(funcType->getNumContainedTypes() - 1);
+    ret = new AllocaInst(lastType->getContainedType(0), "", InsertAtEnd);
+    args.push_back(ret);
+  }
+
+  Value* val = 0;
+  // means: is there a handler for me?
+  if (currentExceptionBlock != endExceptionBlock) {
+    BasicBlock* ifNormal = createBasicBlock("no exception block");
+    currentBlock = ifNormal;
+    val = new InvokeInst(F, ifNormal, currentExceptionBlock, args.begin(),
+                         args.end(), Name, InsertAtEnd);
+  } else {
+    val = new CallInst(F, args.begin(), args.end(), Name, InsertAtEnd);
+  }
+  if (ret) return ret;
+  else return val; 
+}
+
+
+
+
+namespace mvm {
+llvm::FunctionPass* createEscapeAnalysisPass(llvm::Function*, llvm::Function*);
+}
+
+namespace n3 {
+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
+  
+  addPass(PM, mvm::createEscapeAnalysisPass(CLIJit::objConsLLVM, CLIJit::objInitLLVM));
+  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, n3::createLowerArrayLengthPass());
+}
diff --git a/vmkit/lib/N3/VMCore/CLIJit.h b/vmkit/lib/N3/VMCore/CLIJit.h
new file mode 100644
index 0000000..b039226
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLIJit.h
@@ -0,0 +1,491 @@
+//===------------- CLIJit.h - CLI just in time compiler -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_CLIJit_H
+#define N3_CLIJit_H
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+#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/Type.h"
+
+#include "types.h"
+
+namespace n3 {
+
+class CacheNode;
+class N3;
+class N3ModuleProvider;
+class VMClass;
+class VMClassArray;
+class VMCommonClass;
+class VMMethod;
+class VMObject;
+
+class Exception : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  uint32 tryOffset;
+  uint32 tryLength;
+  uint32 handlerOffset;
+  uint32 handlerLength;
+  VMCommonClass* catchClass;
+  llvm::BasicBlock* test;
+  llvm::BasicBlock* realTest;
+  llvm::BasicBlock* handler;
+
+  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;
+  llvm::BasicBlock* exceptionBlock;
+  bool reqSuppl;
+  llvm::Value* exception;
+  
+  virtual void print(mvm::PrintBuffer* buf) const {
+    buf->write("Opinfo");
+  }
+  virtual void tracer(size_t sz);
+};
+
+
+class CLIJit : public mvm::Object {
+public:
+  
+  static VirtualTable* VT; 
+  virtual void print(mvm::PrintBuffer* buf) const {
+    buf->write("CLIJit");
+  }
+  virtual void tracer(size_t sz);
+  
+  
+  static const char* OpcodeNames[0xE1];
+  static const char* OpcodeNamesFE[0x23];
+
+  static VirtualTable* makeVT(VMClass* cl, bool isStatic);
+  static VirtualTable* makeArrayVT(VMClassArray* cl);
+  
+  static void printExecution(char*, n3::VMMethod*);
+  void compileOpcodes(uint8*, uint32);
+  void exploreOpcodes(uint8*, uint32);
+  
+  llvm::Function* llvmFunction;
+  VMMethod* compilingMethod;
+  VMClass* compilingClass;
+
+  std::vector<llvm::Value*> arguments;
+  std::vector<llvm::Value*> locals;
+  
+  // end function
+  llvm::BasicBlock* endBlock;
+  llvm::PHINode* endNode;
+
+  // 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);
+   
+  // stack manipulation
+  std::vector<llvm::Value*> stack;
+  void push(llvm::Value*);
+  llvm::Value* pop();
+  llvm::Value* top();
+  
+  // exceptions
+  llvm::BasicBlock* endExceptionBlock;
+  llvm::BasicBlock* currentExceptionBlock;
+  llvm::BasicBlock* unifiedUnreachable;
+  std::vector<Exception*> exceptions;
+  std::vector<Exception*> finallyHandlers;
+  uint32 readExceptionTable(uint32 offset, bool fat);
+  std::vector<llvm::BasicBlock*> leaves; 
+  llvm::Value* supplLocal;
+
+  // calls
+  void invoke(uint32 value);
+  void invokeInterfaceOrVirtual(uint32 value);
+  void invokeNew(uint32 value);
+  llvm::Value* getVirtualField(uint32 value);
+  llvm::Value* getStaticField(uint32 value);
+  void setVirtualField(uint32 value);
+  void setStaticField(uint32 value);
+
+  void JITVerifyNull(llvm::Value* obj);
+  
+  // array manipulation
+  llvm::Value* verifyAndComputePtr(llvm::Value* obj, llvm::Value* index,
+                                   const llvm::Type* arrayType,
+                                   bool verif = true);
+  llvm::Value* arraySize(llvm::Value* obj);
+
+  Opinfo* opcodeInfos;
+
+  static llvm::Function* printExecutionLLVM;
+  static llvm::Function* indexOutOfBoundsExceptionLLVM;
+  static llvm::Function* nullPointerExceptionLLVM;
+  static llvm::Function* initialiseClassLLVM;
+  static llvm::Function* throwExceptionLLVM;
+  static llvm::Function* clearExceptionLLVM;
+  static llvm::Function* compareExceptionLLVM;
+  static llvm::Function* classCastExceptionLLVM;
+  static llvm::Function* isInCodeLLVM;
+  static llvm::Function* newStringLLVM;
+  static llvm::Function* arrayLengthLLVM;
+
+  static llvm::Function* compile(VMClass* cl, VMMethod* meth);
+
+  static llvm::Function* markAndTraceLLVM;
+  static const llvm::FunctionType* markAndTraceLLVMType;
+  static llvm::Function* vmObjectTracerLLVM;
+  static llvm::Function* arrayConsLLVM;
+  static llvm::Function* arrayMultiConsLLVM;
+  static llvm::Function* objConsLLVM;
+  static llvm::Function* objInitLLVM;
+  static llvm::Function* instanceOfLLVM;
+  static llvm::Function* getCppExceptionLLVM;
+  static llvm::Function* getCLIExceptionLLVM;
+  
+  static void initialise();
+  static void initialiseAppDomain(N3* vm);
+  static void initialiseBootstrapVM(N3* vm);
+
+  llvm::Function* compileNative();
+  llvm::Function* compileFatOrTiny();
+  llvm::Function* compileIntern();
+
+  llvm::Function* createDelegate();
+  llvm::Function* invokeDelegate();
+
+  llvm::Value* invoke(llvm::Value *F, std::vector<llvm::Value*> args,
+                      const char* Name,
+                      llvm::BasicBlock *InsertAtEnd, bool structReturn);
+  // Alternate CallInst ctors w/ two actuals, w/ one actual and no
+  // actuals, respectively.
+  llvm::Value* invoke(llvm::Value *F, llvm::Value *Actual1,
+                      llvm::Value *Actual2, const char* Name,
+                      llvm::BasicBlock *InsertAtEnd, bool structReturn);
+  llvm::Value* invoke(llvm::Value *F, llvm::Value *Actual1,
+                      const char* Name, llvm::BasicBlock *InsertAtEnd,
+                      bool structReturn);
+  llvm::Value* invoke(llvm::Value *F, const char* Name,
+                      llvm::BasicBlock *InsertAtEnd, bool structReturn);
+  
+  void makeArgs(const llvm::FunctionType* type, 
+                std::vector<llvm::Value*>& Args, bool structReturn);
+  llvm::Value* changeType(llvm::Value* val, const llvm::Type* type);
+  
+  static llvm::Function* virtualLookupLLVM;
+
+  static void printBacktrace();
+  
+  llvm::Instruction* lowerMathOps(VMMethod* meth, 
+                                  std::vector<llvm::Value*>& args);
+
+  static llvm::Constant* constantVMObjectNull;
+
+  llvm::Instruction* inlineCompile(llvm::Function* parentFunction, 
+                                   llvm::BasicBlock*& curBB,
+                                   llvm::BasicBlock* endExBlock,
+                                   std::vector<llvm::Value*>& args);
+
+  std::map<VMMethod*, bool> inlineMethods;
+
+  llvm::Instruction* invokeInline(VMMethod* meth, 
+                                  std::vector<llvm::Value*>& args);
+
+};
+
+enum Opcode {
+  NOP = 0x00,
+  BREAK = 0x01,
+  LDARG_0 = 0x02,
+  LDARG_1 = 0x03,
+  LDARG_2 = 0x04,
+  LDARG_3 = 0x05,
+  LDLOC_0 = 0x06,
+  LDLOC_1 = 0x07,
+  LDLOC_2 = 0x08,
+  LDLOC_3 = 0x09,
+  STLOC_0 = 0x0A,
+  STLOC_1 = 0x0B,
+  STLOC_2 = 0x0C,
+  STLOC_3 = 0x0D,
+  LDARG_S = 0x0E,
+  LDARGA_S = 0x0F,
+  STARG_S = 0x10,
+  LDLOC_S = 0x11,
+  LDLOCA_S = 0x12,
+  STLOC_S = 0x13,
+  LDNULL = 0x14,
+  LDC_I4_M1 = 0x15,
+  LDC_I4_0 = 0x16,
+  LDC_I4_1 = 0x17,
+  LDC_I4_2 = 0x18,
+  LDC_I4_3 = 0x19,
+  LDC_I4_4 = 0x1A,
+  LDC_I4_5 = 0x1B,
+  LDC_I4_6 = 0x1C,
+  LDC_I4_7 = 0x1D,
+  LDC_I4_8 = 0x1E,
+  LDC_I4_S = 0x1F,
+  LDC_I4 = 0x20,
+  LDC_I8 = 0x21,
+  LDC_R4 = 0x22,
+  LDC_R8 = 0x23,
+  UNUSED99 = 0x24,
+  DUP = 0x25,
+  POP = 0x26,
+  JMP = 0x27,
+  CALL = 0x28,
+  CALLI = 0x29,
+  RET = 0x2A,
+  BR_S = 0x2B,
+  BRFALSE_S = 0x2C,
+  BRTRUE_S = 0x2D,
+  BEQ_S = 0x2E,
+  BGE_S = 0x2F,
+  BGT_S = 0x30,
+  BLE_S = 0x31,
+  BLT_S = 0x32,
+  BNE_UN_S = 0x33,
+  BGE_UN_S = 0x34,
+  BGT_UN_S = 0x35,
+  BLE_UN_S = 0x36,
+  BLT_UN_S = 0x37,
+  BR = 0x38,
+  BRFALSE = 0x39,
+  BRTRUE = 0x3A,
+  BEQ = 0x3B,
+  BGE = 0x3C,
+  BGT = 0x3D,
+  BLE = 0x3E,
+  BLT = 0x3F,
+  BNE_UN = 0x40,
+  BGE_UN = 0x41,
+  BGT_UN = 0x42,
+  BLE_UN = 0x43,
+  BLT_UN = 0x44,
+  SWITCH = 0x45,
+  LDIND_I1 = 0x46,
+  LDIND_U1 = 0x47,
+  LDIND_I2 = 0x48,
+  LDIND_U2 = 0x49,
+  LDIND_I4 = 0x4A,
+  LDIND_U4 = 0x4B,
+  LDIND_I8 = 0x4C,
+  LDIND_I = 0x4D,
+  LDIND_R4 = 0x4E,
+  LDIND_R8 = 0x4F,
+  LDIND_REF = 0x50,
+  STIND_REF = 0x51,
+  STIND_I1 = 0x52,
+  STIND_I2 = 0x53,
+  STIND_I4 = 0x54,
+  STIND_I8 = 0x55,
+  STIND_R4 = 0x56,
+  STIND_R8 = 0x57,
+  ADD = 0x58,
+  SUB = 0x59,
+  MUL = 0x5A,
+  DIV = 0x5B,
+  DIV_UN = 0x5C,
+  REM = 0x5D,
+  REM_UN = 0x5E,
+  AND = 0x5F,
+  OR = 0x60,
+  XOR = 0x61,
+  SHL = 0x62,
+  SHR = 0x63,
+  SHR_UN = 0x64,
+  NEG = 0x65,
+  NOT = 0x66,
+  CONV_I1 = 0x67,
+  CONV_I2 = 0x68,
+  CONV_I4 = 0x69,
+  CONV_I8 = 0x6A,
+  CONV_R4 = 0x6B,
+  CONV_R8 = 0x6C,
+  CONV_U4 = 0x6D,
+  CONV_U8 = 0x6E,
+  CALLVIRT = 0x6F,
+  CPOBJ = 0x70,
+  LDOBJ = 0x71,
+  LDSTR = 0x72,
+  NEWOBJ = 0x73,
+  CASTCLASS = 0x74,
+  ISINST = 0x75,
+  CONV_R_UN = 0x76,
+  UNUSED58 = 0x77,
+  UNUSED1 = 0x78,
+  UNBOX = 0x79,
+  THROW = 0x7A,
+  LDFLD = 0x7B,
+  LDFLDA = 0x7C,
+  STFLD = 0x7D,
+  LDSFLD = 0x7E,
+  LDSFLDA = 0x7F,
+  STSFLD = 0x80,
+  STOBJ = 0x81,
+  CONV_OVF_I1_UN = 0x82,
+  CONV_OVF_I2_UN = 0x83,
+  CONV_OVF_I4_UN = 0x84,
+  CONV_OVF_I8_UN = 0x85,
+  CONV_OVF_U1_UN = 0x86,
+  CONV_OVF_U2_UN = 0x87,
+  CONV_OVF_U4_UN = 0x88,
+  CONV_OVF_U8_UN = 0x89,
+  CONV_OVF_I_UN = 0x8A,
+  CONV_OVF_U_UN = 0x8B,
+  BOX = 0x8C,
+  NEWARR = 0x8D,
+  LDLEN = 0x8E,
+  LDELEMA = 0x8F,
+  LDELEM_I1 = 0x90,
+  LDELEM_U1 = 0x91,
+  LDELEM_I2 = 0x92,
+  LDELEM_U2 = 0x93,
+  LDELEM_I4 = 0x94,
+  LDELEM_U4 = 0x95,
+  LDELEM_I8 = 0x96,
+  LDELEM_I = 0x97,
+  LDELEM_R4 = 0x98,
+  LDELEM_R8 = 0x99,
+  LDELEM_REF = 0x9A,
+  STELEM_I = 0x9B,
+  STELEM_I1 = 0x9C,
+  STELEM_I2 = 0x9D,
+  STELEM_I4 = 0x9E,
+  STELEM_I8 = 0x9F,
+  STELEM_R4 = 0xA0,
+  STELEM_R8 = 0xA1,
+  STELEM_REF = 0xA2,
+  LDELEM = 0xA3,
+  STELEM = 0xA4,
+  UNBOX_ANY = 0xA5,
+  UNUSED5 = 0xA6,
+  UNUSED6 = 0xA7,
+  UNUSED7 = 0xA8,
+  UNUSED8 = 0xA9,
+  UNUSED9 = 0xAA,
+  UNUSED10 = 0xAB,
+  UNUSED11 = 0xAC,
+  UNUSED12 = 0xAD,
+  UNUSED13 = 0xAE,
+  UNUSED14 = 0xAF,
+  UNUSED15 = 0xB0,
+  UNUSED16 = 0xB1,
+  UNUSED17 = 0xB2,
+  CONV_OVF_I1 = 0xB3,
+  CONV_OVF_U1 = 0xB4,
+  CONV_OVF_I2 = 0xB5,
+  CONV_OVF_U2 = 0xB6,
+  CONV_OVF_I4 = 0xB7,
+  CONV_OVF_U4 = 0xB8,
+  CONV_OVF_I8 = 0xB9,
+  CONV_OVF_U8 = 0xBA,
+  UNUSED50 = 0xBB,
+  UNUSED18 = 0xBC,
+  UNUSED19 = 0xBD,
+  UNUSED20 = 0xBE,
+  UNUSED21 = 0xBF,
+  UNUSED22 = 0xC0,
+  UNUSED23 = 0xC1,
+  REFANYVAL = 0xC2,
+  CKFINITE = 0xC3,
+  UNUSED24 = 0xC4,
+  UNUSED25 = 0xC5,
+  MKREFANY = 0xC6,
+  UNUSED59 = 0xC7,
+  UNUSED60 = 0xC8,
+  UNUSED61 = 0xC9,
+  UNUSED62 = 0xCA,
+  UNUSED63 = 0xCB,
+  UNUSED64 = 0xCC,
+  UNUSED65 = 0xCD,
+  UNUSED66 = 0xCE,
+  UNUSED67 = 0xCF,
+  LDTOKEN = 0xD0,
+  CONV_U2 = 0xD1,
+  CONV_U1 = 0xD2,
+  CONV_I = 0xD3,
+  CONV_OVF_I = 0xD4,
+  CONV_OVF_U = 0xD5,
+  ADD_OVF = 0xD6,
+  ADD_OVF_UN = 0xD7,
+  MUL_OVF = 0xD8,
+  MUL_OVF_UN = 0xD9,
+  SUB_OVF = 0xDA,
+  SUB_OVF_UN = 0xDB,
+  ENDFINALLY = 0xDC,
+  LEAVE = 0xDD,
+  LEAVE_S = 0xDE,
+  STIND_I = 0xDF,
+  CONV_U = 0xE0
+};
+
+enum OpcodeFE {
+  ARGLIST = 0x00,
+  CEQ = 0x01,
+  CGT = 0x02,
+  CGT_UN = 0x03,
+  CLT = 0x04,
+  CLT_UN = 0x05,
+  LDFTN = 0x06,
+  LDVIRTFTN = 0x07,
+  UNUSED56 = 0x08,
+  LDARG = 0x09,
+  LDARGA = 0x0A,
+  STARG = 0x0B,
+  LDLOC = 0x0C,
+  LDLOCA = 0x0D,
+  STLOC = 0x0E,
+  LOCALLOC = 0x0F,
+  UNUSED57 = 0x10,
+  ENDFILTER = 0x11,
+  UNALIGNED_ = 0x12,
+  VOLATILE_ = 0x13,
+  TAIL_ = 0x14,
+  INITOBJ = 0x15,
+  CONSTRAINED_ = 0x16,
+  CPBLK = 0x17,
+  INITBLK = 0x18,
+  NO_ = 0x19,
+  RETHROW = 0x1A,
+  UNUSED = 0x1B,
+  SIZEOF = 0x1C,
+  REFANYTYPE = 0x1D,
+  READONLY_ = 0x1E,
+  UNUSED53 = 0x1F,
+  UNUSED54 = 0x20,
+  UNUSED55 = 0x21,
+  UNUSED70 = 0x22
+};
+
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/CLIJitMeta.cpp b/vmkit/lib/N3/VMCore/CLIJitMeta.cpp
new file mode 100644
index 0000000..2bea63d
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLIJitMeta.cpp
@@ -0,0 +1,457 @@
+//===------ CLIJitMeta.cpp - CLI class/method/field operators -------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdarg.h>
+
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/GlobalVariable.h"
+
+#include "types.h"
+
+#include "mvm/JIT.h"
+
+#include "CLIAccess.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "VirtualMachine.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+using namespace n3;
+using namespace llvm;
+
+VMObject* VMClass::operator()() {
+  if (status < ready) 
+    resolveType(true, true);
+  return doNew();
+}
+
+void VMField::operator()(VMObject* obj, float val) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) obj = classDef->staticInstance;
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  
+  if (signature->naturalType == Type::FloatTy) {
+    ((float*)ptr)[0] = val;
+  } else {
+    VMThread::get()->vm->unknownError("wrong type in field assignment");
+  }
+
+  return;
+}
+
+void VMField::operator()(VMObject* obj, double val) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) obj = classDef->staticInstance;
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  
+  if (signature->naturalType == Type::DoubleTy) {
+    ((double*)ptr)[0] = val;
+  } else {
+    VMThread::get()->vm->unknownError("wrong type in field assignment");
+  }
+
+  return;
+}
+
+void VMField::operator()(VMObject* obj, sint64 val) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) obj = classDef->staticInstance;
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  
+  if (signature->naturalType == Type::Int64Ty) {
+    ((uint64*)ptr)[0] = val;
+  } else {
+    VMThread::get()->vm->unknownError("wrong type in field assignment");
+  }
+  
+  return;
+}
+
+void VMField::operator()(VMObject* obj, sint32 val) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) obj = classDef->staticInstance;
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  
+  if (signature->naturalType == Type::Int32Ty) {
+    ((uint32*)ptr)[0] = val;
+  } else {
+    VMThread::get()->vm->unknownError("wrong type in field assignment");
+  }
+
+  return;
+}
+
+void VMField::operator()(VMObject* obj, VMObject* val) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) obj = classDef->staticInstance;
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  
+  if (llvm::isa<PointerType>(signature->naturalType)) {
+    ((VMObject**)ptr)[0] = val;
+  } else {
+    VMThread::get()->vm->unknownError("wrong type in field assignment");
+  }
+
+  return;
+}
+void VMField::operator()(VMObject* obj, bool val) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) obj = classDef->staticInstance;
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  
+  if (signature->naturalType == Type::Int1Ty) {
+    ((bool*)ptr)[0] = val;
+  } else {
+    VMThread::get()->vm->unknownError("wrong type in field assignment");
+  }
+
+  return;
+}
+
+GenericValue VMField::operator()(VMObject* obj) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  bool stat = isStatic(flags);
+  if (stat) {
+    if (obj != 0) {
+      // Assignment to a static var
+      void* ptr = (void*)((uint64)(classDef->staticInstance) + ptrOffset);
+      ((VMObject**)ptr)[0] = obj;
+      return GenericValue(0);
+    } else {
+      // Get a static var
+      obj = classDef->staticInstance;
+    }
+  }
+  
+  void* ptr = (void*)((uint64)obj + ptrOffset);
+  const Type* type = signature->naturalType;
+  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 {
+    GenericValue gv(((VMObject**)ptr)[0]);
+    return gv;
+  }
+}
+
+GenericValue VMMethod::operator()(va_list ap) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  Function* func = compiledPtr();
+  
+  std::vector<GenericValue> args;
+  for (Function::arg_iterator i = func->arg_begin(), e = func->arg_end();
+       i != e; ++i) {
+    const Type* type = i->getType();
+    if (type == Type::Int8Ty) {
+      GenericValue gv;
+      gv.IntVal = APInt(8, va_arg(ap, int));
+      args.push_back(gv);
+    } else if (type == Type::Int16Ty) {
+      GenericValue gv;
+      gv.IntVal = APInt(16, va_arg(ap, int));
+      args.push_back(gv);
+    } else if (type == Type::Int32Ty) {
+      GenericValue gv;
+      gv.IntVal = APInt(32, va_arg(ap, int));
+      args.push_back(gv);
+    } else if (type == Type::Int64Ty) {
+      GenericValue gv1;
+      gv1.IntVal = APInt(64, va_arg(ap, uint64));
+      args.push_back(gv1);
+    } else if (type == Type::DoubleTy) { 
+      GenericValue gv1;
+      gv1.DoubleVal = va_arg(ap, double);
+      args.push_back(gv1);
+    } else if (type == Type::FloatTy) {
+      GenericValue gv;
+      gv.FloatVal = (float)(va_arg(ap, double));
+      args.push_back(gv);
+    } else {
+      GenericValue gv(va_arg(ap, VMObject*));
+      args.push_back(gv);
+    }
+  }
+  
+  return mvm::jit::executionEngine->runFunction(func, args);
+}
+
+GenericValue VMMethod::operator()(VMObject* obj, va_list ap) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  Function* func = compiledPtr();
+  
+  std::vector<GenericValue> args;
+  GenericValue object(obj);
+  args.push_back(object);
+
+  for (Function::arg_iterator i = ++(func->arg_begin()), e = func->arg_end();
+       i != e; ++i) {
+    const Type* type = i->getType();
+    if (type == Type::Int8Ty) {
+      GenericValue gv;
+      gv.IntVal = APInt(8, va_arg(ap, int));
+      args.push_back(gv);
+    } else if (type == Type::Int16Ty) {
+      GenericValue gv;
+      gv.IntVal = APInt(16, va_arg(ap, int));
+      args.push_back(gv);
+    } else if (type == Type::Int32Ty) {
+      GenericValue gv;
+      gv.IntVal = APInt(32, va_arg(ap, int));
+      args.push_back(gv);
+    } else if (type == Type::Int64Ty) {
+      GenericValue gv1;
+      gv1.IntVal = APInt(64, va_arg(ap, uint64));
+      args.push_back(gv1);
+    } else if (type == Type::DoubleTy) { 
+      GenericValue gv1;
+      gv1.DoubleVal = va_arg(ap, double);
+      args.push_back(gv1);
+    } else if (type == Type::FloatTy) {
+      GenericValue gv;
+      gv.FloatVal = (float)(va_arg(ap, double));
+      args.push_back(gv);
+    } else {
+      GenericValue gv(va_arg(ap, VMObject*));
+      args.push_back(gv);
+    }
+  }
+      
+  return mvm::jit::executionEngine->runFunction(func, args);
+}
+
+
+GenericValue VMMethod::operator()(...) {
+  va_list ap;
+  va_start(ap, this);
+  GenericValue ret = (*this)(ap);
+  va_end(ap);
+  return  ret;
+}
+
+GenericValue VMMethod::run(...) {
+  va_list ap;
+  va_start(ap, this);
+  GenericValue ret = (*this)(ap);
+  va_end(ap);
+  return  ret;
+}
+
+GenericValue VMMethod::operator()(std::vector<GenericValue>& args) {
+  
+  if (classDef->status < ready) 
+    classDef->resolveType(true, true);
+  
+  Function* func = compiledPtr();
+  return mvm::jit::executionEngine->runFunction(func, args);
+}
+
+GenericValue VMObject::operator()(VMField* field) {
+  return (*field)(this);
+}
+
+void VMObject::operator()(VMField* field, float val) {
+  return (*field)(this, val);
+}
+
+void VMObject::operator()(VMField* field, double val) {
+  return (*field)(this, val);
+}
+
+void VMObject::operator()(VMField* field, sint32 val) {
+  return (*field)(this, val);
+}
+
+void VMObject::operator()(VMField* field, sint64 val) {
+  return (*field)(this, val);
+}
+
+void VMObject::operator()(VMField* field, VMObject* val) {
+  return (*field)(this, val);
+}
+
+void VMObject::operator()(VMField* field, bool val) {
+  return (*field)(this, val);
+}
+
+void VMField::operator()(float val) {
+  VMField * field = this;
+  return (*field)(classDef->virtualInstance, val);
+}
+
+void VMField::operator()(double val) {
+  VMField * field = this;
+  return (*field)(classDef->virtualInstance, val);
+}
+
+void VMField::operator()(sint64 val) {
+  VMField * field = this;
+  return (*field)(classDef->virtualInstance, val);
+}
+
+void VMField::operator()(sint32 val) {
+  VMField * field = this;
+  return (*field)(classDef->virtualInstance, val);
+}
+
+void VMField::operator()(bool val) {
+  VMField * field = this;
+  return (*field)(classDef->virtualInstance, val);
+}
+
+GlobalVariable* VMCommonClass::llvmVar() {
+  if (!_llvmVar) {
+    aquire();
+    if (!_llvmVar) {
+      const Type* pty = mvm::jit::ptrType;
+      mvm::jit::protectConstants();
+      Constant* cons = 
+        ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)),
+                                    pty);
+      mvm::jit::unprotectConstants();
+
+      vm->protectModule->lock();
+      _llvmVar = new GlobalVariable(pty, true,
+                                    GlobalValue::ExternalLinkage,
+                                    cons, "",
+                                    vm->module);
+      vm->protectModule->unlock();
+    
+    }
+    release();
+  }
+  return _llvmVar;
+}
+
+GlobalVariable* VMField::llvmVar() {
+  if (!_llvmVar) {
+    classDef->aquire();
+    if (!_llvmVar) {
+      const Type* pty = mvm::jit::ptrType;
+      mvm::jit::protectConstants();
+      Constant* cons = 
+        ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)),
+                                  pty);
+      mvm::jit::unprotectConstants();
+
+      classDef->vm->protectModule->lock();
+      _llvmVar = new GlobalVariable(pty, true,
+                                    GlobalValue::ExternalLinkage,
+                                    cons, "",
+                                    classDef->vm->module);
+      classDef->vm->protectModule->unlock();
+    }
+    classDef->release();
+  }
+  return _llvmVar;
+}
+
+GlobalVariable* VMMethod::llvmVar() {
+  if (!_llvmVar) {
+    classDef->aquire();
+    if (!_llvmVar) {
+      const Type* pty = mvm::jit::ptrType;
+      mvm::jit::protectConstants();
+      Constant* cons = 
+        ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)),
+                                  pty);
+      mvm::jit::unprotectConstants();
+
+      classDef->vm->protectModule->lock();
+      _llvmVar = new GlobalVariable(pty, true,
+                                    GlobalValue::ExternalLinkage,
+                                    cons, "",
+                                    classDef->vm->module);
+      classDef->vm->protectModule->unlock();
+    
+    }
+    classDef->release();
+  }
+  return _llvmVar;
+}
+
+ConstantInt* VMObject::classOffset() {
+  return mvm::jit::constantOne;
+}
+
+GlobalVariable* CLIString::llvmVar() {
+  if (!_llvmVar) {
+    VirtualMachine* vm = VMThread::get()->vm;
+    vm->protectModule->lock();
+    if (!_llvmVar) {
+      const Type* pty = mvm::jit::ptrType;
+      mvm::jit::protectConstants();
+      Constant* cons = 
+        ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (this)),
+                                  pty);
+      mvm::jit::unprotectConstants();
+      _llvmVar = new GlobalVariable(pty, true,
+                                    GlobalValue::ExternalLinkage,
+                                    cons, "",
+                                    vm->module);
+    }
+    vm->protectModule->unlock();
+  }
+  return _llvmVar;
+}
diff --git a/vmkit/lib/N3/VMCore/CLISignature.cpp b/vmkit/lib/N3/VMCore/CLISignature.cpp
new file mode 100644
index 0000000..0de3503
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLISignature.cpp
@@ -0,0 +1,392 @@
+//===--------- CLIsignature.cpp - Reads CLI signatures --------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "Assembly.h"
+#include "N3.h"
+#include "Reader.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+#include "SignatureNames.def"
+
+using namespace n3;
+
+static VMCommonClass* METHOD_ElementTypeEnd(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeVoid(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pVoid;
+}
+
+static VMCommonClass* METHOD_ElementTypeBoolean(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pBoolean;
+}
+
+static VMCommonClass* METHOD_ElementTypeChar(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pChar;
+}
+
+static VMCommonClass* METHOD_ElementTypeI1(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pSInt8;
+}
+
+static VMCommonClass* METHOD_ElementTypeU1(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pUInt8;
+}
+
+static VMCommonClass* METHOD_ElementTypeI2(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pSInt16;
+}
+
+static VMCommonClass* METHOD_ElementTypeU2(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pUInt16;
+}
+
+static VMCommonClass* METHOD_ElementTypeI4(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pSInt32;
+}
+
+static VMCommonClass* METHOD_ElementTypeU4(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pUInt32;
+}
+
+static VMCommonClass* METHOD_ElementTypeI8(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pSInt64;
+}
+
+static VMCommonClass* METHOD_ElementTypeU8(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pUInt64;
+}
+
+static VMCommonClass* METHOD_ElementTypeR4(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pFloat;
+}
+
+static VMCommonClass* METHOD_ElementTypeR8(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pDouble;
+}
+
+static VMCommonClass* METHOD_ElementTypeString(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pString;
+}
+
+static VMCommonClass* METHOD_ElementTypePtr(uint32 op, Assembly* ass, uint32& offset) {
+  VMCommonClass* contains = ass->exploreType(offset);
+  return ass->constructPointer(contains, 1);
+}
+
+static VMCommonClass* METHOD_ElementTypeByRef(uint32 op, Assembly* ass, uint32& offset) {
+  VMCommonClass* contains = ass->exploreType(offset);
+  return ass->constructPointer(contains, 1);
+}
+
+static VMCommonClass* METHOD_ElementTypeValueType(uint32 op, Assembly* ass,
+                                                     uint32& offset) {
+  uint32 value = ass->uncompressSignature(offset);
+  uint32 table = value & 3;
+  uint32 index = value >> 2;
+  uint32 token = 0;
+
+
+  switch (table) {
+    case 0: table = CONSTANT_TypeDef; break;
+    case 1: table = CONSTANT_TypeRef; break;
+    case 2: table = CONSTANT_TypeSpec; break;
+    default:
+      VMThread::get()->vm->error("unknown TypeDefOrRefEncoded %d", index);
+      break;
+  }
+
+  token = (table << 24) + index;
+  VMCommonClass* cl = ass->loadType((N3*)(VMThread::get()->vm), token, false,
+                                    false, false, true);
+  return cl;
+}
+
+static VMCommonClass* METHOD_ElementTypeClass(uint32 op, 
+                                              Assembly* ass, uint32& offset) {
+  uint32 value = ass->uncompressSignature(offset);
+  uint32 table = value & 3;
+  uint32 index = value >> 2;
+  uint32 token = 0;
+
+
+  switch (table) {
+    case 0: table = CONSTANT_TypeDef; break;
+    case 1: table = CONSTANT_TypeRef; break;
+    case 2: table = CONSTANT_TypeSpec; break;
+    default:
+      VMThread::get()->vm->error("unknown TypeDefOrRefEncoded %d", index);
+      break;
+  }
+
+  token = (table << 24) + index;
+  VMCommonClass* cl = ass->loadType((N3*)(VMThread::get()->vm), token, false, 
+                                    false, false, true);
+  return cl;
+}
+
+static VMCommonClass* METHOD_ElementTypeVar(uint32 op, Assembly* ass, uint32& offset) {
+  //uint32 type = READ_U4(ass->bytes, offset);
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeArray(uint32 op, Assembly* ass, uint32& offset) {
+  VMCommonClass* cl = ass->exploreType(offset);
+  uint32 rank = ass->uncompressSignature(offset);
+  uint32 numSizes = ass->uncompressSignature(offset);
+
+  if (numSizes != 0) {
+    printf("type = %s\n", cl->printString());
+    VMThread::get()->vm->error("implement me");
+  }
+
+  for (uint32 i = 0; i < numSizes; ++i) {
+    ass->uncompressSignature(offset);
+  }
+
+  uint32 numObounds = ass->uncompressSignature(offset);
+  if (numObounds != 0) VMThread::get()->vm->error("implement me");
+
+  for (uint32 i = 0; i < numObounds; ++i) {
+    ass->uncompressSignature(offset);
+  }
+  
+  VMClassArray* array = ass->constructArray(cl, rank);
+  return array;
+}
+
+static VMCommonClass* METHOD_ElementTypeGenericInst(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeTypedByRef(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::typedReference;
+}
+
+static VMCommonClass* METHOD_ElementTypeI(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pIntPtr;
+}
+
+static VMCommonClass* METHOD_ElementTypeU(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pUIntPtr;
+}
+
+static VMCommonClass* METHOD_ElementTypeFnptr(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeObject(uint32 op, Assembly* ass, uint32& offset) {
+  return N3::pObject;
+}
+
+static VMCommonClass* METHOD_ElementTypeSzarray(uint32 op, Assembly* ass, uint32& offset) {
+  VMCommonClass* contains = ass->exploreType(offset);
+  VMClassArray* res = ass->constructArray(contains, 1);
+  return res;
+}
+
+static VMCommonClass* METHOD_ElementTypeMvar(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeCmodReqd(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeCmodOpt(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeInternal(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeModifier(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypeSentinel(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* METHOD_ElementTypePinned(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("implement me");
+  return 0;
+}
+
+static VMCommonClass* unimplemented(uint32 op, Assembly* ass, uint32& offset) {
+  VMThread::get()->vm->error("unknown signature");
+  return 0;
+}
+
+signatureVector_t Assembly::signatureVector[0x46] = {
+  METHOD_ElementTypeEnd,           // 0x00
+  METHOD_ElementTypeVoid,          // 0x01
+  METHOD_ElementTypeBoolean,       // 0x02
+  METHOD_ElementTypeChar,          // 0x03
+  METHOD_ElementTypeI1,            // 0x04
+  METHOD_ElementTypeU1,            // 0x05
+  METHOD_ElementTypeI2,            // 0x06
+  METHOD_ElementTypeU2,            // 0x07
+  METHOD_ElementTypeI4,            // 0x08
+  METHOD_ElementTypeU4,            // 0x09
+  METHOD_ElementTypeI8,            // 0x0A
+  METHOD_ElementTypeU8,            // 0x0B
+  METHOD_ElementTypeR4,            // 0x0C
+  METHOD_ElementTypeR8,            // 0x0D
+  METHOD_ElementTypeString,        // 0x0E
+  METHOD_ElementTypePtr,           // 0x1F
+  METHOD_ElementTypeByRef,         // 0x10
+  METHOD_ElementTypeValueType,     // 0x11
+  METHOD_ElementTypeClass,         // 0x12
+  METHOD_ElementTypeVar,           // 0x13
+  METHOD_ElementTypeArray,         // 0x14
+  METHOD_ElementTypeGenericInst,   // 0x15
+  METHOD_ElementTypeTypedByRef,    // 0x16
+  unimplemented,                   // 0x17
+  METHOD_ElementTypeI,             // 0x18
+  METHOD_ElementTypeU,             // 0x19
+  unimplemented,                   // 0x1A
+  METHOD_ElementTypeFnptr,         // 0x1B
+  METHOD_ElementTypeObject,        // 0x1C
+  METHOD_ElementTypeSzarray,       // 0x1D
+  METHOD_ElementTypeMvar,          // 0x1E
+  METHOD_ElementTypeCmodReqd,      // 0x1F
+  METHOD_ElementTypeCmodOpt,       // 0x20
+  METHOD_ElementTypeInternal,      // 0x21
+  METHOD_ElementTypeModifier,      // 0x22
+  unimplemented,                   // 0x23
+  unimplemented,                   // 0x24
+  unimplemented,                   // 0x25
+  unimplemented,                   // 0x26
+  unimplemented,                   // 0x27
+  unimplemented,                   // 0x28
+  unimplemented,                   // 0x29
+  unimplemented,                   // 0x2A
+  unimplemented,                   // 0x2B
+  unimplemented,                   // 0x2C
+  unimplemented,                   // 0x2D
+  unimplemented,                   // 0x2E
+  unimplemented,                   // 0x2F
+  unimplemented,                   // 0x30
+  unimplemented,                   // 0x31
+  unimplemented,                   // 0x32
+  unimplemented,                   // 0x33
+  unimplemented,                   // 0x34
+  unimplemented,                   // 0x35
+  unimplemented,                   // 0x36
+  unimplemented,                   // 0x37
+  unimplemented,                   // 0x38
+  unimplemented,                   // 0x39
+  unimplemented,                   // 0x3A
+  unimplemented,                   // 0x3B
+  unimplemented,                   // 0x3C
+  unimplemented,                   // 0x3D
+  unimplemented,                   // 0x3E
+  unimplemented,                   // 0x3F
+  METHOD_ElementTypeSentinel,      // 0x41
+  unimplemented,                   // 0x42
+  unimplemented,                   // 0x43
+  unimplemented,                   // 0x44
+  METHOD_ElementTypePinned         // 0x45
+};
+
+bool Assembly::extractMethodSignature(uint32& offset, VMCommonClass* cl,
+                                      std::vector<VMCommonClass*>& types) {
+  //uint32 count      = 
+  uncompressSignature(offset);
+  uint32 call       = uncompressSignature(offset);
+  uint32 paramCount = uncompressSignature(offset);
+
+  uint32 hasThis = call & CONSTANT_HasThis ? 1 : 0;
+  uint32 realCount = paramCount + hasThis;
+
+  VMCommonClass* ret = exploreType(offset);
+  types.push_back(ret);
+  
+  if (hasThis) {
+    types.push_back(cl);
+  }
+  for (uint32 i = hasThis; i < realCount; ++i) {
+    VMCommonClass* cur = exploreType(offset);
+    types.push_back(cur);
+  }
+  
+  return hasThis != 0;
+}
+
+void Assembly::localVarSignature(uint32& offset,
+                                 std::vector<VMCommonClass*>& locals) {
+  //uint32 count      = 
+  uncompressSignature(offset);
+  uint32 localSig   = uncompressSignature(offset);
+  uint32 nbLocals   = uncompressSignature(offset);
+
+  if (localSig != 0x7) {
+    VMThread::get()->vm->error("unknown local sig %x", localSig);
+  }
+  
+  for (uint32 i = 0; i < nbLocals; ++i) {
+    locals.push_back(exploreType(offset));
+  }
+}
+
+VMCommonClass* Assembly::extractFieldSignature(uint32& offset) {
+  //uint32 count      = 
+  uncompressSignature(offset);
+  uint32 fieldSig   = uncompressSignature(offset);
+  
+  if (fieldSig != 0x6) {
+    VMThread::get()->vm->error("unknown field sig %x", fieldSig);
+  }
+
+  return exploreType(offset);
+
+}
+
+VMCommonClass* Assembly::extractTypeInSignature(uint32& offset) {
+  //uint32 count      = 
+  uncompressSignature(offset);
+  return exploreType(offset); 
+}
+
+VMCommonClass* Assembly::exploreType(uint32& offset) {
+  uint32 op = READ_U1(bytes, offset);
+  //printf("reading %s\n", signatureNames[op]);
+  return (signatureVector[op])(op, this, offset);
+}
+
+uint32 Assembly::uncompressSignature(uint32& offset) {
+  uint32 value = READ_U1(bytes, offset);
+
+  if ((value & 0x80) == 0) {
+    return value;
+  } else if ((value & 0x40) == 0) {
+    uint32 val2 = READ_U1(bytes, offset);
+    return (((value & 0x3f) << 8) | val2);
+  } else {
+    uint32 val2 = READ_U1(bytes, offset);
+    uint32 val3 = READ_U1(bytes, offset);
+    uint32 val4 = READ_U1(bytes, offset);
+    return ((value & 0x1f) << 24) | (val2 << 16) | (val3 << 8) | val4;
+  }
+}
diff --git a/vmkit/lib/N3/VMCore/CLIString.cpp b/vmkit/lib/N3/VMCore/CLIString.cpp
new file mode 100644
index 0000000..8a1692c
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLIString.cpp
@@ -0,0 +1,38 @@
+//===---- CLIString.cpp - Internal correspondance with CLI Strings --------===//
+//
+//                                N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CLIString.h"
+#include "N3.h"
+#include "VMArray.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+
+CLIString* CLIString::stringDup(const UTF8*& utf8, N3* vm) {
+  CLIString* obj = (CLIString*)(*N3::pString)();
+  obj->capacity = utf8->size;
+  obj->length = utf8->size;
+  if (utf8->size == 0) {
+    obj->firstChar = 0;
+  } else {
+    obj->firstChar = utf8->at(0);
+  }
+  obj->value = utf8; 
+  return obj;
+}
+
+char* CLIString::strToAsciiz() {
+  return value->UTF8ToAsciiz();
+}
+
+const UTF8* CLIString::strToUTF8(N3* vm) {
+  return value;
+}
diff --git a/vmkit/lib/N3/VMCore/CLIString.h b/vmkit/lib/N3/VMCore/CLIString.h
new file mode 100644
index 0000000..1583cab
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/CLIString.h
@@ -0,0 +1,50 @@
+//===----- CLIString.h - Internal correspondance with CLI Strings ---------===//
+//
+//                               N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_CLI_STRING_H
+#define N3_CLI_STRING_H
+
+#include "llvm/GlobalVariable.h"
+
+#include "types.h"
+#include "mvm/PrintBuffer.h"
+
+#include "VMObject.h"
+
+namespace n3 {
+
+class UTF8;
+class N3;
+
+class CLIString : public VMObject {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const {
+    buf->write("CLI string");
+  }
+  virtual void tracer(size_t sz);
+  
+  // !!! pnetlib layout !!!
+  sint32 capacity;
+  sint32 length;
+  uint8 firstChar;
+  const UTF8* value;
+  llvm::GlobalVariable* _llvmVar;
+  llvm::GlobalVariable* llvmVar();
+
+  
+  static CLIString* stringDup(const UTF8*& utf8, N3* vm);
+  char* strToAsciiz();
+  const UTF8* strToUTF8(N3* vm);
+
+};
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/LockedMap.cpp b/vmkit/lib/N3/VMCore/LockedMap.cpp
new file mode 100644
index 0000000..8739fa1
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/LockedMap.cpp
@@ -0,0 +1,115 @@
+//===------- LockedMap.cpp - Implementation of the UTF8 map ---------------===//
+//
+//                               N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+
+#include "Assembly.h"
+#include "CLIString.h"
+#include "LockedMap.h"
+#include "N3.h"
+#include "VMArray.h"
+#include "VMClass.h"
+
+#include <string.h>
+
+using namespace n3;
+
+
+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)));
+}
+
+
+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, N3::arrayChar);
+    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, N3::arrayChar);
+    memcpy(tmp->elements, buf, len * sizeof(uint16));
+    res = (const UTF8*)tmp;
+    map.insert(std::make_pair(key, res));
+  }
+  
+  lock->unlock();
+  return res;
+}
+
diff --git a/vmkit/lib/N3/VMCore/LockedMap.h b/vmkit/lib/N3/VMCore/LockedMap.h
new file mode 100644
index 0000000..21ab937
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/LockedMap.h
@@ -0,0 +1,233 @@
+//===------- LockedMap.h - A thread-safe map implementation ---------------===//
+//
+//                               N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_LOCKED_MAP_H
+#define N3_LOCKED_MAP_H
+
+#include <map>
+
+
+#include <string.h>
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+#include "types.h"
+
+#include "VMArray.h"
+
+namespace n3 {
+
+class Assembly;
+class CLIString;
+class N3;
+class VMClass;
+class VMCommonClass;
+class VMField;
+class VMObject;
+class VMMethod;
+class VMField;
+class UTF8;
+class llvm::Function;
+
+template<class Key, class Container, class Compare, class Upcall>
+class LockedMap : public mvm::Object {
+public:
+  typedef typename std::map<Key, Container*, Compare>::iterator iterator;
+  typedef Container* (*funcCreate)(Key& V, Upcall* ass);
+
+  mvm::Lock* lock;
+  std::map<Key, Container*, Compare> map;
+  
+  inline Container* lookupOrCreate(Key& V, Upcall* ass, funcCreate func) {
+    lock->lock();
+    iterator End = map.end();
+    iterator I = map.find(V);
+    if (I == End) {
+      Container* res = func(V, ass);
+      map.insert(std::make_pair(V, res));
+      lock->unlock();
+      return res;
+    } else {
+      lock->unlock();
+      return ((Container*)(I->second));
+    }
+  }
+  
+  inline Container* lookupOrCreate(Key&V, Container* C) {
+    lock->lock();
+    iterator End = map.end();
+    iterator I = map.find(V);
+    if (I == End) {
+      map.insert(std::make_pair(V, C));
+      lock->unlock();
+      return C;
+    } 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 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("Hashtable<>");
+  }
+
+};
+
+class ClassNameCmp {
+public:
+  const UTF8* name;
+  const UTF8* nameSpace;
+
+  ClassNameCmp(const UTF8* u, const UTF8* n) : name(u), nameSpace(n) {}
+
+  inline bool operator<(const ClassNameCmp &cmp) const {
+    if (name < cmp.name) return true;
+    else if (name > cmp.name) return false;
+    else return nameSpace < cmp.nameSpace;
+  }
+};
+
+
+class ClassNameMap : 
+  public LockedMap<ClassNameCmp, VMCommonClass, std::less<ClassNameCmp>, Assembly > {
+public:
+  static VirtualTable* VT; 
+  static ClassNameMap* allocate() {
+    ClassNameMap* map = gc_new(ClassNameMap)();
+    map->lock = mvm::Lock::allocNormal();
+    return map;
+  }
+};
+
+class ClassTokenMap : 
+  public LockedMap<uint32, VMCommonClass, std::less<uint32>, Assembly > {
+public:
+  static VirtualTable* VT; 
+  static ClassTokenMap* allocate() {
+    ClassTokenMap* map = gc_new(ClassTokenMap)();
+    map->lock = mvm::Lock::allocNormal();
+    return map;
+  }
+  
+};
+
+class FieldTokenMap : 
+  public LockedMap<uint32, VMField, std::less<uint32>, Assembly > {
+public:
+  static VirtualTable* VT; 
+  static FieldTokenMap* allocate() {
+    FieldTokenMap* map = gc_new(FieldTokenMap)();
+    map->lock = mvm::Lock::allocNormal();
+    return map;
+  }
+};
+
+class MethodTokenMap : 
+  public LockedMap<uint32, VMMethod, std::less<uint32>, Assembly > {
+public:
+  static VirtualTable* VT; 
+  static MethodTokenMap* allocate() {
+    MethodTokenMap* map = gc_new(MethodTokenMap)();
+    map->lock = mvm::Lock::allocNormal();
+    return map;
+  }
+};
+
+class AssemblyMap : 
+  public LockedMap<const UTF8*, Assembly, std::less<const UTF8*>, N3 > {
+public:
+  static VirtualTable* VT; 
+  static AssemblyMap* allocate() {
+    AssemblyMap* map = gc_new(AssemblyMap)();
+    map->lock = mvm::Lock::allocNormal();
+    return map;
+  }
+};
+
+
+class StringMap :
+    public LockedMap<const UTF8*, CLIString, std::less<const UTF8*>, N3 > { 
+public:
+  static VirtualTable* VT; 
+  static StringMap* allocate() {
+    StringMap* map = gc_new(StringMap)();
+    map->lock = mvm::Lock::allocRecursive();
+    return map;
+  }
+};
+
+class FunctionMap :
+    public LockedMap<llvm::Function*, VMMethod, std::less<llvm::Function*>, N3 > { 
+public:
+  static VirtualTable* VT; 
+  static FunctionMap* allocate() {
+    FunctionMap* map = gc_new(FunctionMap)();
+    map->lock = mvm::Lock::allocNormal();
+    return map;
+  }
+};
+
+
+
+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);
+  
+  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;
+  }
+
+
+};
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/LowerArrayLength.cpp b/vmkit/lib/N3/VMCore/LowerArrayLength.cpp
new file mode 100644
index 0000000..548ec39
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/LowerArrayLength.cpp
@@ -0,0 +1,71 @@
+//===------- LowerArrayLength.cpp - Lowers array length calls -------------===//
+//
+//                           N3
+//
+// 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 "VMArray.h"
+#include "CLIJit.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) == n3::CLIJit::arrayLengthLLVM) {
+          Changed = true;
+          Value* val = CI->getOperand(1); // get the array
+          std::vector<Value*> args; //size=  2
+          args.push_back(mvm::jit::constantZero);
+          args.push_back(n3::VMArray::sizeOffset());
+          Value* ptr = new GetElementPtrInst(val, args.begin(), args.end(),
+                                         "", CI);
+          Value* load = new LoadInst(ptr, "", CI);
+          CI->replaceAllUsesWith(load);
+          CI->eraseFromParent();
+        }
+      }
+    }
+  }
+
+  return Changed;
+}
+
+namespace n3 {
+
+LowerArrayLength* createLowerArrayLengthPass() {
+  return new LowerArrayLength();
+}
+
+}
diff --git a/vmkit/lib/N3/VMCore/Makefile.am b/vmkit/lib/N3/VMCore/Makefile.am
new file mode 100644
index 0000000..044fc2c
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/Makefile.am
@@ -0,0 +1,20 @@
+# $Id: Makefile.am,v 1.4 2008/03/21 11:12:39 varth Exp $
+EXTRA_DIST = SignatureNames.def OpcodeNames.def
+lib_LTLIBRARIES = libN3.la
+
+THREADDIR=../../Mvm/CommonThread
+ALLOCDIR=../../Mvm/Allocator
+GCDIR=../../Mvm/GCMmap2
+INCLUDEDIRS=-I@srcdir@/$(THREADDIR) -I@srcdir@/$(ALLOCDIR) -I@srcdir@/$(GCDIR)
+
+PREFIX=@prefix@
+
+libN3_la_SOURCES = \
+	Assembly.cpp Assembly.h CLIAccess.h CLISignature.cpp LockedMap.cpp LockedMap.h N3.cpp N3.h \
+	Reader.cpp Reader.h VMArray.cpp VMArray.h VMCache.cpp VMCache.h VMClass.cpp VMClass.h \
+	VMObject.cpp VMObject.h VMThread.cpp VMThread.h VirtualMachine.cpp VirtualMachine.h \
+	VirtualTables.cpp CLIString.cpp CLIString.h N3Initialise.cpp CLIJitMeta.cpp CLIJit.h CLIJit.cpp \
+	Opcodes.cpp NativeUtil.h NativeUtil.cpp PNetLib.cpp N3ModuleProvider.cpp N3ModuleProvider.h \
+	PNetLib.h BackTrace.cpp LowerArrayLength.cpp
+
+libN3_la_CXXFLAGS =$(INCLUDEDIRS) -DPREFIX=\"$(PREFIX)\" -W -Wall -ansi -Wno-unused-parameter -Wno-long-long -Wno-unused-function -fno-omit-frame-pointer -g -O2
diff --git a/vmkit/lib/N3/VMCore/N3.cpp b/vmkit/lib/N3/VMCore/N3.cpp
new file mode 100644
index 0000000..6fb42ba
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/N3.cpp
@@ -0,0 +1,265 @@
+//===--------------- N3.cpp - The N3 virtual machine ----------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "llvm/Module.h"
+#include "llvm/Support/CommandLine.h"
+
+#include "types.h"
+#include "Assembly.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "LockedMap.h"
+#include "N3.h"
+#include "N3ModuleProvider.h"
+#include "Reader.h"
+#include "VirtualMachine.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+void N3::print(mvm::PrintBuffer* buf) const {
+  buf->write("N3 virtual machine<>");
+}
+
+VMObject* N3::asciizToStr(const char* asciiz) {
+  const UTF8* var = asciizConstructUTF8(asciiz);
+  return UTF8ToStr(var);
+}
+
+VMObject* N3::UTF8ToStr(const UTF8* utf8) {
+  VMObject* res = CLIString::stringDup(utf8, this);
+  //VMObject* res = hashStr->lookupOrCreate(utf8, this, CLIString::stringDup);
+  return res;
+}
+
+static Assembly* assemblyDup(const UTF8*& name, N3* vm) {
+  Assembly* res = Assembly::allocate(name);
+  return res;
+}
+
+Assembly* N3::constructAssembly(const UTF8* name) {
+  return loadedAssemblies->lookupOrCreate(name, this, assemblyDup);
+}
+
+Assembly* N3::lookupAssembly(const UTF8* name) {
+  return loadedAssemblies->lookup(name);
+}
+
+N3* N3::allocateBootstrap() {
+  N3 *vm= gc_new(N3)();
+  
+  vm->module = new llvm::Module("Bootstrap N3");
+  vm->protectModule = mvm::Lock::allocNormal();
+  vm->functions = FunctionMap::allocate();
+  vm->TheModuleProvider = new N3ModuleProvider(vm->module, vm->functions);
+  CLIJit::initialiseBootstrapVM(vm);
+  
+  
+  vm->bootstrapThread = VMThread::allocate(0, vm);
+  VMThread::threadKey->set(vm->bootstrapThread);
+  vm->name = "bootstrapN3";
+  vm->hashUTF8 = UTF8Map::allocate();
+  vm->hashStr = StringMap::allocate();
+  vm->loadedAssemblies = AssemblyMap::allocate();
+  
+  
+  return vm;
+}
+
+
+N3* N3::allocate(char* name, N3* parent) {
+  N3 *vm= gc_new(N3)();
+  
+  vm->module = new llvm::Module("App Domain");
+  vm->protectModule = mvm::Lock::allocNormal();
+  vm->functions = FunctionMap::allocate();
+  vm->TheModuleProvider = new N3ModuleProvider(vm->module, vm->functions);
+  CLIJit::initialiseAppDomain(vm);
+
+  vm->bootstrapThread = VMThread::allocate(0, vm);
+  VMThread::threadKey->set(vm->bootstrapThread);
+  vm->threadSystem = ThreadSystem::allocateThreadSystem();
+  vm->name = name;
+  vm->hashUTF8 = parent->hashUTF8;
+  vm->hashStr = StringMap::allocate();
+  vm->loadedAssemblies = AssemblyMap::allocate();
+  vm->assemblyPath = parent->assemblyPath;
+  vm->coreAssembly = parent->coreAssembly;
+  vm->loadedAssemblies->hash(parent->coreAssembly->name, parent->coreAssembly);
+  
+  
+  return vm; 
+}
+
+ArrayUInt8* N3::openAssembly(const UTF8* name, const char* ext) {
+  char* asciiz = name->UTF8ToAsciiz();
+  uint32 alen = strlen(asciiz);
+ 
+  ArrayUInt8* res = 0;
+  uint32 idx = 0;
+
+  while ((res == 0) && (idx < assemblyPath.size())) {
+    char* cur = assemblyPath[idx];
+    uint32 strLen = strlen(cur);
+    char* buf = (char*)alloca(strLen + alen + 16);
+
+    if (ext != 0) {
+      sprintf(buf, "%s%s.%s", cur, asciiz, ext);
+    } else {
+      sprintf(buf, "%s%s", cur, asciiz);
+    }
+
+    res = Reader::openFile(buf);
+    ++idx;
+  }
+
+  return res;
+}
+
+
+class ClArgumentsInfo {
+public:
+  uint32 appArgumentsPos;
+  char* assembly;
+
+  void readArgs(int argc, char** argv, N3 *vm);
+
+  void printInformation();
+  void nyi();
+  void printVersion();
+};
+
+void ClArgumentsInfo::nyi() {
+  fprintf(stdout, "Not yet implemented\n");
+}
+
+void ClArgumentsInfo::printVersion() {
+  fprintf(stdout, "N3 -- a VVM implementation of the Common Language Infrastructure\n");
+}
+
+void ClArgumentsInfo::printInformation() {
+  fprintf(stdout, 
+  "Usage: n3 [-options] assembly [args...] \n"
+    "No option is available\n");
+}
+
+void ClArgumentsInfo::readArgs(int argc, char** argv, N3* n3) {
+  assembly = 0;
+  appArgumentsPos = 0;
+  sint32 i = 1;
+  if (i == argc) printInformation();
+  while (i < argc) {
+    char* cur = argv[i];
+    if (cur[0] == '-') {
+    } else {
+      assembly = cur;
+      appArgumentsPos = i;
+      return;
+    }
+    ++i;
+  }
+}
+
+
+void N3::mapInitialThread() {
+  VMClass* cl = (VMClass*)coreAssembly->loadTypeFromName(
+                                        asciizConstructUTF8("Thread"),
+                                        asciizConstructUTF8("System.Threading"),
+                                        true, true, true, true);
+  VMObject* th = (*cl)();
+  std::vector<VMCommonClass*> args;
+  args.push_back(N3::pVoid);
+  args.push_back(cl);
+  args.push_back(N3::pIntPtr);
+  VMMethod* meth = cl->lookupMethod(asciizConstructUTF8(".ctor"), args, 
+                                    false, false);
+  VMThread* myth = VMThread::get();
+  (*meth)(th, myth);
+  myth->vmThread = th;
+}
+
+void N3::loadBootstrap() {
+  mapInitialThread();
+}
+
+void N3::waitForExit() { 
+  threadSystem->nonDaemonLock->lock();
+  --(threadSystem->nonDaemonThreads);
+  
+  while (threadSystem->nonDaemonThreads) {
+    threadSystem->nonDaemonVar->wait(threadSystem->nonDaemonLock);
+  }
+
+  threadSystem->nonDaemonLock->unlock();
+
+  return;
+}
+
+Assembly* N3::loadAssembly(const UTF8* name, const char* ext) {
+  Assembly* ass = lookupAssembly(name);
+  if (ass == 0 || !ass->isRead) {
+    ArrayUInt8* bytes = openAssembly(name, ext);
+    if (bytes != 0) {
+      if (ass == 0) ass = constructAssembly(name);
+      ass->bytes = bytes;
+      ass->vm = this;
+      ass->read();
+      ass->isRead = true;
+    }
+  }
+  return ass;
+}
+
+void N3::executeAssembly(const char* _name, ArrayObject* args) {
+  const UTF8* name = asciizConstructUTF8(_name);
+  Assembly* assembly = loadAssembly(name, 0);
+  if (assembly == 0) {
+    error("Can not found assembly %s", _name);
+  } else {
+    uint32 entryPoint = assembly->entryPoint;
+    uint32 table = entryPoint >> 24;
+    if (table != CONSTANT_MethodDef) {
+      error("Entry point does not point to a method");
+    } else {
+      uint32 typeToken = assembly->getTypeDefTokenFromMethod(entryPoint);
+      assembly->loadType(this, typeToken, true, true, true ,true);
+      VMMethod* mainMeth = assembly->lookupMethodFromToken(entryPoint);
+      (*mainMeth)(args);
+    }
+  }
+}
+
+void N3::runMain(int argc, char** argv) {
+  ClArgumentsInfo info;
+
+  info.readArgs(argc, argv, this);
+  if (info.assembly) {
+    int pos = info.appArgumentsPos;
+    llvm::cl::ParseCommandLineOptions(pos, argv,
+                                      "N3 CLI virtual machine\n");
+    argv = argv + info.appArgumentsPos - 1;
+    argc = argc - info.appArgumentsPos + 1;
+    
+    loadBootstrap();
+    
+    ArrayObject* args = ArrayObject::acons(argc - 2, arrayString);
+    for (int i = 2; i < argc; ++i) {
+      args->setAt(i - 2, (VMObject*)asciizToStr(argv[i]));
+    }
+    try{
+      executeAssembly(info.assembly, args);
+    }catch(...) {
+      printf("N3 catched it\n");
+    }
+    waitForExit();
+  }
+}
diff --git a/vmkit/lib/N3/VMCore/N3.h b/vmkit/lib/N3/VMCore/N3.h
new file mode 100644
index 0000000..18f2a7f
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/N3.h
@@ -0,0 +1,148 @@
+//===---------------- N3.h - The N3 virtual machine -----------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef N3_N3_H
+#define N3_N3_H
+
+#include "types.h"
+
+#include "VirtualMachine.h"
+
+namespace n3 {
+
+class ArrayObject;
+class ArrayUInt8;
+class Assembly;
+class AssemblyMap;
+class FunctionMap;
+class N3ModuleProvider;
+class StringMap;
+class UTF8;
+class UTF8Map;
+class VMClass;
+class VMClassArray;
+class VMCommonClass;
+class VMField;
+class VMMethod;
+
+class N3 : public VirtualMachine {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  VMObject*     asciizToStr(const char* asciiz);
+  VMObject*     UTF8ToStr(const UTF8* utf8);
+  Assembly*     constructAssembly(const UTF8* name);
+  Assembly*     lookupAssembly(const UTF8* name);
+  
+  char* name;
+  StringMap * hashStr;
+  AssemblyMap* loadedAssemblies;
+  std::vector<char*> assemblyPath;
+  Assembly* coreAssembly;
+
+
+  static N3* allocateBootstrap();
+  static N3* allocate(char* name, N3* parent);
+  
+  ArrayUInt8* openAssembly(const UTF8* name, const char* extension);
+ 
+  Assembly* loadAssembly(const UTF8* name, const char* extension);
+  void executeAssembly(const char* name, ArrayObject* args);
+  void runMain(int argc, char** argv);
+  void mapInitialThread();
+  void loadBootstrap();
+  void waitForExit();
+  
+  static N3* bootstrapVM;
+
+  static VMClass* pVoid;
+  static VMClass* pBoolean;
+  static VMClass* pChar;
+  static VMClass* pSInt8;
+  static VMClass* pUInt8;
+  static VMClass* pSInt16;
+  static VMClass* pUInt16;
+  static VMClass* pSInt32;
+  static VMClass* pUInt32;
+  static VMClass* pSInt64;
+  static VMClass* pUInt64;
+  static VMClass* pFloat;
+  static VMClass* pDouble;
+  static VMClass* pIntPtr;
+  static VMClass* pUIntPtr;
+  static VMClass* pString;
+  static VMClass* pObject;
+  static VMClass* pValue;
+  static VMClass* pEnum;
+  static VMClass* pArray;
+  static VMClass* pDelegate;
+  static VMClass* pException;
+  static VMClassArray* arrayChar;
+  static VMClassArray* arrayString;
+  static VMClassArray* arrayByte;
+  static VMClassArray* arrayObject;
+  static VMField* ctorBoolean;
+  static VMField* ctorUInt8;
+  static VMField* ctorSInt8;
+  static VMField* ctorChar;
+  static VMField* ctorSInt16;
+  static VMField* ctorUInt16;
+  static VMField* ctorSInt32;
+  static VMField* ctorUInt32;
+  static VMField* ctorSInt64;
+  static VMField* ctorUInt64;
+  static VMField* ctorIntPtr;
+  static VMField* ctorUIntPtr;
+  static VMField* ctorDouble;
+  static VMField* ctorFloat;
+
+  static const UTF8* clinitName;
+  static const UTF8* ctorName;
+  static const UTF8* invokeName;
+  static const UTF8* math;
+  static const UTF8* system;
+  static const UTF8* sqrt;
+  static const UTF8* sin;
+  static const UTF8* cos;
+  static const UTF8* exp;
+  static const UTF8* log;
+  static const UTF8* floor;
+  static const UTF8* log10;
+  static const UTF8* isNan;
+  static const UTF8* pow;
+  static const UTF8* floatName;
+  static const UTF8* doubleName;
+  static const UTF8* testInfinity;
+
+  static VMMethod* ctorClrType;
+  static VMClass* clrType;
+  static VMField* typeClrType;
+  
+  static VMMethod* ctorAssemblyReflection;
+  static VMClass* assemblyReflection;
+  static VMClass* typedReference;
+  static VMField* assemblyAssemblyReflection;
+  static VMClass* propertyType;
+  static VMClass* methodType;
+  
+  static VMMethod* ctorPropertyType;
+  static VMMethod* ctorMethodType;
+  static VMField* propertyPropertyType;
+  static VMField* methodMethodType;
+
+  static VMClass* resourceStreamType;
+  static VMMethod* ctorResourceStreamType;
+};
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/N3Initialise.cpp b/vmkit/lib/N3/VMCore/N3Initialise.cpp
new file mode 100644
index 0000000..f39a909
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/N3Initialise.cpp
@@ -0,0 +1,432 @@
+//===----------- N3Initialise.cpp - Initialization of N3 ------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include <vector>
+
+#include "mvm/JIT.h"
+#include "mvm/Threads/Locks.h"
+
+#include "Assembly.h"
+#include "CLIString.h"
+#include "CLIJit.h"
+#include "LockedMap.h"
+#include "NativeUtil.h"
+#include "N3.h"
+#include "N3ModuleProvider.h"
+#include "Reader.h"
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMCache.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+N3* N3::bootstrapVM = 0;
+mvm::Lock* VMObject::globalLock = 0;
+mvm::Key<VMThread>* VMThread::threadKey = 0;
+
+VMCommonClass* VMClassArray::SuperArray = 0;
+std::vector<VMClass*> VMClassArray::InterfacesArray;
+std::vector<VMMethod*> VMClassArray::VirtualMethodsArray;
+std::vector<VMMethod*> VMClassArray::StaticMethodsArray;
+std::vector<VMField*> VMClassArray::VirtualFieldsArray;
+std::vector<VMField*> VMClassArray::StaticFieldsArray;
+
+VMClass* N3::pVoid = 0;
+VMClass* N3::pBoolean= 0;
+VMClass* N3::pChar = 0;
+VMClass* N3::pSInt8 = 0;
+VMClass* N3::pUInt8 = 0;
+VMClass* N3::pSInt16 = 0;
+VMClass* N3::pUInt16 = 0;
+VMClass* N3::pSInt32 = 0;
+VMClass* N3::pUInt32 = 0;
+VMClass* N3::pSInt64 = 0;
+VMClass* N3::pUInt64 = 0;
+VMClass* N3::pFloat = 0;
+VMClass* N3::pDouble = 0;
+VMClass* N3::pIntPtr = 0;
+VMClass* N3::pUIntPtr = 0;
+VMClass* N3::pObject = 0;
+VMClass* N3::pString = 0;
+VMClass* N3::pValue = 0;
+VMClass* N3::pEnum = 0;
+VMClass* N3::pArray = 0;
+VMClass* N3::pDelegate = 0;
+VMClass* N3::pException = 0;
+VMClassArray* N3::arrayChar = 0;
+VMClassArray* N3::arrayString = 0;
+VMClassArray* N3::arrayObject = 0;
+VMClassArray* N3::arrayByte = 0;
+VMMethod* N3::ctorPropertyType;
+VMMethod* N3::ctorMethodType;
+VMMethod* N3::ctorClrType;
+VMClass* N3::clrType;
+VMField* N3::typeClrType;
+VMField* N3::propertyPropertyType;
+VMField* N3::methodMethodType;
+VMMethod* N3::ctorAssemblyReflection;
+VMClass* N3::assemblyReflection;
+VMClass* N3::typedReference;
+VMField* N3::assemblyAssemblyReflection;
+VMClass* N3::propertyType;
+VMClass* N3::methodType;
+VMClass* N3::resourceStreamType;
+VMMethod* N3::ctorResourceStreamType;
+
+VMField* N3::ctorBoolean;
+VMField* N3::ctorUInt8;
+VMField* N3::ctorSInt8;
+VMField* N3::ctorChar;
+VMField* N3::ctorSInt16;
+VMField* N3::ctorUInt16;
+VMField* N3::ctorSInt32;
+VMField* N3::ctorUInt32;
+VMField* N3::ctorSInt64;
+VMField* N3::ctorUInt64;
+VMField* N3::ctorIntPtr;
+VMField* N3::ctorUIntPtr;
+VMField* N3::ctorDouble;
+VMField* N3::ctorFloat;
+
+const UTF8* N3::clinitName = 0;
+const UTF8* N3::ctorName = 0;
+const UTF8* N3::invokeName = 0;
+const UTF8* N3::math = 0;
+const UTF8* N3::system = 0;
+const UTF8* N3::sqrt = 0;
+const UTF8* N3::sin = 0;
+const UTF8* N3::cos = 0;
+const UTF8* N3::exp = 0;
+const UTF8* N3::log = 0;
+const UTF8* N3::floor = 0;
+const UTF8* N3::log10 = 0;
+const UTF8* N3::isNan = 0;
+const UTF8* N3::pow = 0;
+const UTF8* N3::floatName = 0;
+const UTF8* N3::doubleName = 0;
+const UTF8* N3::testInfinity = 0;
+
+const llvm::Type* VMArray::llvmType;
+const llvm::Type* VMObject::llvmType;
+const llvm::Type* Enveloppe::llvmType;
+const llvm::Type* CacheNode::llvmType;
+
+llvm::Function* CLIJit::printExecutionLLVM;
+llvm::Function* CLIJit::indexOutOfBoundsExceptionLLVM;
+llvm::Function* CLIJit::nullPointerExceptionLLVM;
+llvm::Function* CLIJit::classCastExceptionLLVM;
+llvm::Function* CLIJit::clearExceptionLLVM;
+llvm::Function* CLIJit::compareExceptionLLVM;
+llvm::Function* CLIJit::arrayLengthLLVM;
+
+llvm::Function* CLIJit::markAndTraceLLVM;
+const llvm::FunctionType* CLIJit::markAndTraceLLVMType;
+llvm::Function* CLIJit::vmObjectTracerLLVM;
+llvm::Function* CLIJit::initialiseClassLLVM;
+llvm::Function* CLIJit::virtualLookupLLVM;
+llvm::Function* CLIJit::arrayConsLLVM;
+llvm::Function* CLIJit::arrayMultiConsLLVM;
+llvm::Function* CLIJit::objConsLLVM;
+llvm::Function* CLIJit::objInitLLVM;
+llvm::Function* CLIJit::throwExceptionLLVM;
+llvm::Function* CLIJit::instanceOfLLVM;
+llvm::Function* CLIJit::isInCodeLLVM;
+llvm::Function* CLIJit::getCLIExceptionLLVM;
+llvm::Function* CLIJit::getCppExceptionLLVM;
+llvm::Function* CLIJit::newStringLLVM;
+
+
+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;
+
+
+
+static void initialiseVT() {
+
+# define INIT(X) { \
+  X fake; \
+  X::VT = ((void**)(void*)(&fake))[0]; }
+  
+  INIT(Assembly);
+  INIT(Header);
+  INIT(Property);
+  INIT(Param);
+  INIT(Section);
+  INIT(Table);
+  INIT(VMArray);
+  INIT(ArrayUInt8);
+  INIT(ArraySInt8);
+  INIT(ArrayUInt16);
+  INIT(ArraySInt16);
+  INIT(ArrayUInt32);
+  INIT(ArraySInt32);
+  INIT(ArrayLong);
+  INIT(ArrayFloat);
+  INIT(ArrayDouble);
+  INIT(ArrayObject);
+  INIT(UTF8);
+  INIT(VMCommonClass);
+  INIT(VMClass);
+  INIT(VMClassArray);
+  INIT(VMMethod);
+  INIT(VMField);
+  INIT(VMCond);
+  INIT(LockObj);
+  INIT(VMObject);
+  INIT(VMThread);
+  //mvm::Key<VMThread>::VT = mvm::ThreadKey::VT;
+  INIT(ThreadSystem);
+  INIT(N3);
+  INIT(Reader);
+  INIT(UTF8Map);
+  INIT(ClassNameMap);
+  INIT(ClassTokenMap);
+  INIT(FieldTokenMap);
+  INIT(MethodTokenMap);
+  INIT(StringMap);
+  INIT(FunctionMap);
+  INIT(VirtualMachine);
+  INIT(CLIString);
+  INIT(CLIJit);
+  INIT(CacheNode);
+  INIT(Enveloppe);
+  INIT(Opinfo);
+  INIT(Exception);
+
+#undef INIT
+
+}
+
+static void loadStringClass(N3* vm) {
+  VMClass* type = (VMClass*)vm->coreAssembly->loadTypeFromName(
+                                           vm->asciizConstructUTF8("String"),
+                                           vm->asciizConstructUTF8("System"),
+                                           false, false, false, true);
+  N3::pString = type;
+  type->resolveType(false, false);
+
+  uint64 size = mvm::jit::getTypeSize(type->virtualType->getContainedType(0)) + sizeof(const UTF8*) + sizeof(llvm::GlobalVariable*);
+  type->virtualInstance = 
+    (VMObject*)mvm::Object::gcmalloc(size, type->virtualInstance->getVirtualTable());
+  type->virtualInstance->initialise(type);
+}
+
+static void initialiseStatics() {
+  NativeUtil::initialise();
+  CLIJit::initialise();
+
+  VMObject::globalLock = mvm::Lock::allocNormal();
+  //mvm::Object::pushRoot((mvm::Object*)VMObject::globalLock);
+
+  VMThread::threadKey = new mvm::Key<VMThread>();
+  //mvm::Object::pushRoot((mvm::Object*)VMThread::threadKey);
+  
+  N3* vm = N3::bootstrapVM = N3::allocateBootstrap();
+  mvm::Object::pushRoot((mvm::Object*)N3::bootstrapVM);
+
+  
+  
+  char* assemblyName = getenv("MSCORLIB");
+  if (assemblyName == 0)
+    VMThread::get()->vm->error("can not find mscorlib.dll. Abort");
+
+  vm->assemblyPath.push_back("");
+  vm->assemblyPath.push_back(assemblyName);
+  
+  const UTF8* mscorlib = vm->asciizConstructUTF8("mscorlib");
+  Assembly* ass = vm->loadAssembly(mscorlib, "dll");
+  if (ass == 0)
+    VMThread::get()->vm->error("can not find mscorlib.dll. Abort");
+
+  vm->coreAssembly = ass;
+
+  // Array initialization
+  const UTF8* System = vm->asciizConstructUTF8("System");
+  const UTF8* utf8OfChar = vm->asciizConstructUTF8("Char");
+  
+  N3::arrayChar = ass->constructArray(utf8OfChar, System, 1);
+  ((UTF8*)System)->classOf = N3::arrayChar;
+  ((UTF8*)utf8OfChar)->classOf = N3::arrayChar;
+  ((UTF8*)mscorlib)->classOf = N3::arrayChar;
+
+#define INIT(var, nameSpace, name, type, prim) {\
+  var = (VMClass*)vm->coreAssembly->loadTypeFromName( \
+                                           vm->asciizConstructUTF8(name),     \
+                                           vm->asciizConstructUTF8(nameSpace),\
+                                           false, false, false, true); \
+  var->isPrimitive = prim; \
+  if (type) { \
+    var->naturalType = type;  \
+    var->virtualType = type;  \
+  }}
+
+  INIT(N3::pObject,   "System", "Object", VMObject::llvmType, false);
+  INIT(N3::pValue,    "System", "ValueType", 0, false);
+  INIT(N3::pVoid,     "System", "Void", llvm::Type::VoidTy, true);
+  INIT(N3::pBoolean,  "System", "Boolean", llvm::Type::Int1Ty, true);
+  INIT(N3::pUInt8,    "System", "Byte", llvm::Type::Int8Ty, true);
+  INIT(N3::pSInt8,    "System", "SByte", llvm::Type::Int8Ty, true);
+  INIT(N3::pChar,     "System", "Char", llvm::Type::Int16Ty, true);
+  INIT(N3::pSInt16,   "System", "Int16", llvm::Type::Int16Ty, true);
+  INIT(N3::pUInt16,   "System", "UInt16", llvm::Type::Int16Ty, true);
+  INIT(N3::pSInt32,   "System", "Int32", llvm::Type::Int32Ty, true);
+  INIT(N3::pUInt32,   "System", "UInt32", llvm::Type::Int32Ty, true);
+  INIT(N3::pSInt64,   "System", "Int64", llvm::Type::Int64Ty, true);
+  INIT(N3::pUInt64,   "System", "UInt64", llvm::Type::Int64Ty, true);
+  INIT(N3::pIntPtr,   "System", "IntPtr", llvm::PointerType::getUnqual(llvm::Type::Int8Ty), true);
+  INIT(N3::pUIntPtr,  "System", "UIntPtr", llvm::PointerType::getUnqual(llvm::Type::Int8Ty), true);
+  INIT(N3::pDouble,   "System", "Double", llvm::Type::DoubleTy, true);
+  INIT(N3::pFloat,    "System", "Single", llvm::Type::FloatTy, true);
+  INIT(N3::pEnum,     "System", "Enum", llvm::Type::Int32Ty, true);
+  INIT(N3::pArray,    "System", "Array", 0, true);
+  INIT(N3::pException,"System", "Exception", 0, false);
+  INIT(N3::pDelegate, "System", "Delegate", 0, false);
+  INIT(N3::clrType,   "System.Reflection", "ClrType", 0, false);
+  INIT(N3::assemblyReflection,   "System.Reflection", "Assembly", 0, false);
+  INIT(N3::typedReference,   "System", "TypedReference", 0, false);
+  INIT(N3::propertyType,   "System.Reflection", "ClrProperty", 0, false);
+  INIT(N3::methodType,   "System.Reflection", "ClrMethod", 0, false);
+  INIT(N3::resourceStreamType,   "System.Reflection", "ClrResourceStream", 0, false);
+
+#undef INIT
+  
+
+  N3::arrayChar->baseClass = N3::pChar;
+  VMClassArray::SuperArray = N3::pArray;
+  N3::arrayChar->super = N3::pArray;
+  
+  loadStringClass(vm);
+  
+  N3::arrayString = ass->constructArray(vm->asciizConstructUTF8("String"),
+                                        System, 1);
+  N3::arrayString->baseClass = N3::pString;
+  
+  N3::arrayByte = ass->constructArray(vm->asciizConstructUTF8("Byte"),
+                                        System, 1);
+  N3::arrayByte->baseClass = N3::pUInt8;
+  
+  N3::arrayObject = ass->constructArray(vm->asciizConstructUTF8("Object"),
+                                        System, 1);
+  N3::arrayObject->baseClass = N3::pObject;
+  
+
+  N3::clinitName = vm->asciizConstructUTF8(".cctor");
+  N3::ctorName = vm->asciizConstructUTF8(".ctor");
+  N3::invokeName = vm->asciizConstructUTF8("Invoke");
+  N3::math = vm->asciizConstructUTF8("Math");
+  N3::system = vm->asciizConstructUTF8("System");
+  N3::sqrt = vm->asciizConstructUTF8("Sqrt");
+  N3::sin = vm->asciizConstructUTF8("Sin");
+  N3::cos = vm->asciizConstructUTF8("Cos");
+  N3::exp = vm->asciizConstructUTF8("Exp");
+  N3::log = vm->asciizConstructUTF8("Log");
+  N3::floor = vm->asciizConstructUTF8("Floor");
+  N3::log10 = vm->asciizConstructUTF8("Log10");
+  N3::isNan = vm->asciizConstructUTF8("IsNaN");
+  N3::pow = vm->asciizConstructUTF8("Pow");
+  N3::floatName = vm->asciizConstructUTF8("Float");
+  N3::doubleName = vm->asciizConstructUTF8("Double");
+  N3::testInfinity = vm->asciizConstructUTF8("TestInfinity");
+  
+  {
+  N3::clrType->resolveType(false, false);
+  std::vector<VMCommonClass*> args;
+  args.push_back(N3::pVoid);
+  args.push_back(N3::clrType);
+  N3::ctorClrType = N3::clrType->lookupMethod(vm->asciizConstructUTF8(".ctor"), args, false, false);
+  N3::typeClrType = N3::clrType->lookupField(vm->asciizConstructUTF8("privateData"), N3::pIntPtr, false, false);
+  }
+
+  {
+  N3::assemblyReflection->resolveType(false, false);
+  std::vector<VMCommonClass*> args;
+  args.push_back(N3::pVoid);
+  args.push_back(N3::assemblyReflection);
+  N3::ctorAssemblyReflection = N3::assemblyReflection->lookupMethod(vm->asciizConstructUTF8(".ctor"), args, false, false);
+  N3::assemblyAssemblyReflection = N3::assemblyReflection->lookupField(vm->asciizConstructUTF8("privateData"), N3::pIntPtr, false, false);
+  }
+  
+  {
+  N3::propertyType->resolveType(false, false);
+  std::vector<VMCommonClass*> args;
+  args.push_back(N3::pVoid);
+  args.push_back(N3::propertyType);
+  N3::ctorPropertyType = N3::propertyType->lookupMethod(vm->asciizConstructUTF8(".ctor"), args, false, false);
+  N3::propertyPropertyType = N3::propertyType->lookupField(vm->asciizConstructUTF8("privateData"), N3::pIntPtr, false, false);
+  }
+  
+  {
+  N3::methodType->resolveType(false, false);
+  std::vector<VMCommonClass*> args;
+  args.push_back(N3::pVoid);
+  args.push_back(N3::methodType);
+  N3::ctorMethodType = N3::methodType->lookupMethod(vm->asciizConstructUTF8(".ctor"), args, false, false);
+  N3::methodMethodType = N3::methodType->lookupField(vm->asciizConstructUTF8("privateData"), N3::pIntPtr, false, false);
+  }
+  
+  {
+  N3::resourceStreamType->resolveType(false, false);
+  std::vector<VMCommonClass*> args;
+  args.push_back(N3::pVoid);
+  args.push_back(N3::resourceStreamType);
+  args.push_back(N3::pIntPtr);
+  args.push_back(N3::pSInt64);
+  args.push_back(N3::pSInt64);
+  N3::ctorResourceStreamType = N3::resourceStreamType->lookupMethod(vm->asciizConstructUTF8(".ctor"), args, false, false);
+  }
+  
+  VMCommonClass* voidPtr = vm->coreAssembly->constructPointer(N3::pVoid, 1);
+#define INIT(var, cl, type) {\
+    cl->resolveType(false, false); \
+    var = cl->lookupField(vm->asciizConstructUTF8("value_"), type, false, false); \
+  }
+  
+  INIT(N3::ctorBoolean,  N3::pBoolean, N3::pBoolean);
+  INIT(N3::ctorUInt8, N3::pUInt8, N3::pUInt8);
+  INIT(N3::ctorSInt8, N3::pSInt8, N3::pSInt8);
+  INIT(N3::ctorChar,  N3::pChar, N3::pChar);
+  INIT(N3::ctorSInt16, N3::pSInt16, N3::pSInt16);
+  INIT(N3::ctorUInt16, N3::pUInt16, N3::pUInt16);
+  INIT(N3::ctorSInt32, N3::pSInt32, N3::pSInt32);
+  INIT(N3::ctorUInt32, N3::pUInt32, N3::pUInt32);
+  INIT(N3::ctorSInt64, N3::pSInt64, N3::pSInt64);
+  INIT(N3::ctorUInt64, N3::pUInt64, N3::pUInt64);
+  INIT(N3::ctorIntPtr, N3::pIntPtr, voidPtr);
+  INIT(N3::ctorUIntPtr, N3::pUIntPtr, voidPtr);
+  INIT(N3::ctorDouble, N3::pDouble, N3::pDouble);
+  INIT(N3::ctorFloat, N3::pFloat, N3::pFloat);
+
+#undef INIT
+}
+
+
+extern "C" int boot(int argc, char **argv, char **envp) {
+  initialiseVT();
+  initialiseStatics();
+  return 0;
+}
+
+extern "C" int start_app(int argc, char** argv) {
+  N3* vm = N3::allocate("", N3::bootstrapVM);
+  vm->runMain(argc, argv);
+  return 0; 
+}
diff --git a/vmkit/lib/N3/VMCore/N3ModuleProvider.cpp b/vmkit/lib/N3/VMCore/N3ModuleProvider.cpp
new file mode 100644
index 0000000..86eb412
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/N3ModuleProvider.cpp
@@ -0,0 +1,51 @@
+//===------ N3ModuleProvider.cpp - LLVM Module Provider for N3 ------------===//
+//
+//                              N3
+//
+// 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 "mvm/VMLet.h"
+
+#include "Assembly.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "N3ModuleProvider.h"
+
+#include "VMClass.h"
+
+using namespace llvm;
+using namespace n3;
+
+
+bool N3ModuleProvider::materializeFunction(Function *F, std::string *ErrInfo) {
+  if (!F->empty()) return false;
+  VMMethod* meth = functions->lookup(F);
+  if (!meth) {
+    // VT methods
+    return false;
+  } else {
+    void* res = 
+      mvm::jit::executionEngine->getPointerToGlobalIfAvailable(meth->methPtr);
+    if (res == 0) {
+      meth->classDef->aquire();
+      res = 
+        mvm::jit::executionEngine->getPointerToGlobalIfAvailable(meth->methPtr);
+      if (res == 0) {
+        CLIJit::compile(meth->classDef, meth);
+        void* res = mvm::jit::executionEngine->getPointerToGlobal(meth->methPtr);
+        meth->code = (mvm::Code*)((intptr_t)res - sizeof(intptr_t));
+        meth->code->method()->definition(meth);
+      }
+      meth->classDef->release();
+      meth->classDef->resolveStatic(true);
+    }
+    return false;
+  }
+}
diff --git a/vmkit/lib/N3/VMCore/N3ModuleProvider.h b/vmkit/lib/N3/VMCore/N3ModuleProvider.h
new file mode 100644
index 0000000..659b577
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/N3ModuleProvider.h
@@ -0,0 +1,36 @@
+//===-------- N3ModuleProvider.h - LLVM Module Provider for N3 ------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_MODULE_PROVIDER_H
+#define N3_MODULE_PROVIDER_H
+
+#include <llvm/ModuleProvider.h>
+
+#include "LockedMap.h"
+
+using namespace llvm;
+
+namespace n3 {
+
+class N3ModuleProvider : public ModuleProvider {
+public:
+  FunctionMap* functions;
+  N3ModuleProvider(Module *m, FunctionMap* f) {
+    TheModule = m;
+    functions = f;
+  }
+  
+  bool materializeFunction(Function *F, std::string *ErrInfo = 0);
+
+  Module* materializeModule(std::string *ErrInfo = 0) { return TheModule; }
+};
+
+} // End n3 namespace
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/NativeUtil.cpp b/vmkit/lib/N3/VMCore/NativeUtil.cpp
new file mode 100644
index 0000000..f0f5e66
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/NativeUtil.cpp
@@ -0,0 +1,78 @@
+//===------- NativeUtil.cpp - Methods to call native functions --------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <dlfcn.h>
+#include <string.h>
+
+#include "llvm/DerivedTypes.h"
+
+#include "NativeUtil.h"
+#include "N3.h"
+#include "VMArray.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+static void cliToInternal(char* buf) {
+  uint32 i = 0;
+  while (buf[i] != 0) {
+    if (buf[i] == '.') buf[i] = '_';
+    ++i;
+  }
+}
+
+static void* makeFull(VMCommonClass* cl, VMMethod* meth) {
+  char* buf = (char*)alloca(4096);
+  sprintf(buf, "%s_%s_%s", cl->nameSpace->printString(), cl->name->printString(), meth->name->printString());
+
+  std::vector<VMCommonClass*>::iterator i = meth->parameters.begin(),
+                                        e = meth->parameters.end();
+  
+  // Remove return type;
+  ++i;
+  for ( ; i!= e; ++i) {
+    VMCommonClass* cl = *i;
+    sprintf(buf, "%s_%s_%s", buf, cl->nameSpace->printString(), cl->name->printString());
+  }
+
+  cliToInternal(buf);
+  void* res = dlsym(0, buf);
+  
+  if (!res) {
+    VMThread::get()->vm->error("unable to find native method %s",
+                               meth->printString());
+  }
+
+  return res;
+}
+
+void* NativeUtil::nativeLookup(VMCommonClass* cl, VMMethod* meth) {
+  char* name = cl->name->printString();
+  char* nameSpace = cl->nameSpace->printString();
+  char* methName = meth->name->printString();
+
+  char* buf = (char*)alloca(6 + strlen(name) + strlen(nameSpace) +
+                            strlen(methName));
+  sprintf(buf, "%s_%s_%s", nameSpace, name, methName);
+  cliToInternal(buf);
+  void* res = dlsym(0, buf);
+  if (!res) {
+    buf = (char*)alloca(6 + strlen(name) + strlen(nameSpace) +
+                        strlen(methName) + 10);
+    sprintf(buf, "%s_%s_%s_%d", nameSpace, name, methName, 
+                meth->getSignature()->getNumParams());
+    cliToInternal(buf);
+    res = dlsym(0, buf);
+    if (!res) {
+      return makeFull(cl, meth);
+    }
+  }
+  return res;
+}
diff --git a/vmkit/lib/N3/VMCore/NativeUtil.h b/vmkit/lib/N3/VMCore/NativeUtil.h
new file mode 100644
index 0000000..ad2a3a9
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/NativeUtil.h
@@ -0,0 +1,27 @@
+//===------- NativeUtil.h - Methods to call native functions --------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_NATIVE_UTIL_H
+#define N3_NATIVE_UTIL_H
+
+namespace n3 {
+
+class VMCommonClass;
+class VMMethod;
+
+class NativeUtil {
+public:
+
+  static void* nativeLookup(VMCommonClass* cl, VMMethod* meth);
+  static void initialise();
+};
+
+}
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/OpcodeNames.def b/vmkit/lib/N3/VMCore/OpcodeNames.def
new file mode 100644
index 0000000..8c59296
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/OpcodeNames.def
@@ -0,0 +1,279 @@
+//===-------------- OpcodeNames.def - Name of opcodes ---------------------===//
+//
+//                              N3
+//
+// 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* n3::CLIJit::OpcodeNames[0xE1] = {
+  "nop", // 0x00
+  "break", // 0x01
+  "ldarg.0", // 0x02
+  "ldarg.1", // 0x03
+  "ldarg.2", // 0x04
+  "ldarg.3", // 0x05
+  "ldloc.0", // 0x06
+  "ldloc.1", // 0x07
+  "ldloc.2", // 0x08
+  "ldloc.3", // 0x09
+  "stloc.0", // 0x0A
+  "stloc.1", // 0x0B
+  "stloc.2", // 0x0C
+  "stloc.3", // 0x0D
+  "ldarg.s", // 0x0E
+  "ldarga.s", // 0x0F
+  "starg.s", // 0x10
+  "ldloc.s", // 0x11
+  "ldloca.s", // 0x12
+  "stloc.s", // 0x13
+  "ldnull", // 0x14
+  "ldc.i4.m1", // 0x15
+  "ldc.i4.0", // 0x16
+  "ldc.i4.1", // 0x17
+  "ldc.i4.2", // 0x18
+  "ldc.i4.3", // 0x19
+  "ldc.i4.4", // 0x1A
+  "ldc.i4.5", // 0x1B
+  "ldc.i4.6", // 0x1C
+  "ldc.i4.7", // 0x1D
+  "ldc.i4.8", // 0x1E
+  "ldc.i4.s", // 0x1F
+  "ldc.i4", // 0x20
+  "ldc.i8", // 0x21
+  "ldc.r4", // 0x22
+  "ldc.r8", // 0x23
+  "unused99", // 0x24
+  "dup", // 0x25
+  "pop", // 0x26
+  "jmp", // 0x27
+  "call", // 0x28
+  "calli", // 0x29
+  "ret", // 0x2A
+  "br.s", // 0x2B
+  "brfalse.s", // 0x2C
+  "brtrue.s", // 0x2D
+  "beq.s", // 0x2E
+  "bge.s", // 0x2F
+  "bgt.s", // 0x30
+  "ble.s", // 0x31
+  "blt.s", // 0x32
+  "bne.un.s", // 0x33
+  "bge.un.s", // 0x34
+  "bgt.un.s", // 0x35
+  "ble.un.s", // 0x36
+  "blt.un.s", // 0x37
+  "br", // 0x38
+  "brfalse", // 0x39
+  "brtrue", // 0x3A
+  "beq", // 0x3B
+  "bge", // 0x3C
+  "bgt", // 0x3D
+  "ble", // 0x3E
+  "blt", // 0x3F
+  "bne.un", // 0x40
+  "bge.un", // 0x41
+  "bgt.un", // 0x42
+  "ble.un", // 0x43
+  "blt.un", // 0x44
+  "switch", // 0x45
+  "ldind.i1", // 0x46
+  "ldind.u1", // 0x47
+  "ldind.i2", // 0x48
+  "ldind.u2", // 0x49
+  "ldind.i4", // 0x4A
+  "ldind.u4", // 0x4B
+  "ldind.i8", // 0x4C
+  "ldind.i", // 0x4D
+  "ldind.r4", // 0x4E
+  "ldind.r8", // 0x4F
+  "ldind.ref", // 0x50
+  "stind.ref", // 0x51
+  "stind.i1", // 0x52
+  "stind.i2", // 0x53
+  "stind.i4", // 0x54
+  "stind.i8", // 0x55
+  "stind.r4", // 0x56
+  "stind.r8", // 0x57
+  "add", // 0x58
+  "sub", // 0x59
+  "mul", // 0x5A
+  "div", // 0x5B
+  "div.un", // 0x5C
+  "rem", // 0x5D
+  "rem.un", // 0x5E
+  "and", // 0x5F
+  "or", // 0x60
+  "xor", // 0x61
+  "shl", // 0x62
+  "shr", // 0x63
+  "shr.un", // 0x64
+  "neg", // 0x65
+  "not", // 0x66
+  "conv.i1", // 0x67
+  "conv.i2", // 0x68
+  "conv.i4", // 0x69
+  "conv.i8", // 0x6A
+  "conv.r4", // 0x6B
+  "conv.r8", // 0x6C
+  "conv.u4", // 0x6D
+  "conv.u8", // 0x6E
+  "callvirt", // 0x6F
+  "cpobj", // 0x70
+  "ldobj", // 0x71
+  "ldstr", // 0x72
+  "newobj", // 0x73
+  "castclass", // 0x74
+  "isinst", // 0x75
+  "conv.r.un", // 0x76
+  "unused58", // 0x77
+  "unused1", // 0x78
+  "unbox", // 0x79
+  "throw", // 0x7A
+  "ldfld", // 0x7B
+  "ldflda", // 0x7C
+  "stfld", // 0x7D
+  "ldsfld", // 0x7E
+  "ldsflda", // 0x7F
+  "stsfld", // 0x80
+  "stobj", // 0x81
+  "conv.ovf.i1.un", // 0x82
+  "conv.ovf.i2.un", // 0x83
+  "conv.ovf.i4.un", // 0x84
+  "conv.ovf.i8.un", // 0x85
+  "conv.ovf.u1.un", // 0x86
+  "conv.ovf.u2.un", // 0x87
+  "conv.ovf.u4.un", // 0x88
+  "conv.ovf.u8.un", // 0x89
+  "conv.ovf.i.un", // 0x8A
+  "conv.ovf.u.un", // 0x8B
+  "box", // 0x8C
+  "newarr", // 0x8D
+  "ldlen", // 0x8E
+  "ldelema", // 0x8F
+  "ldelem.i1", // 0x90
+  "ldelem.u1", // 0x91
+  "ldelem.i2", // 0x92
+  "ldelem.u2", // 0x93
+  "ldelem.i4", // 0x94
+  "ldelem.u4", // 0x95
+  "ldelem.i8", // 0x96
+  "ldelem.i", // 0x97
+  "ldelem.r4", // 0x98
+  "ldelem.r8", // 0x99
+  "ldelem.ref", // 0x9A
+  "stelem.i", // 0x9B
+  "stelem.i1", // 0x9C
+  "stelem.i2", // 0x9D
+  "stelem.i4", // 0x9E
+  "stelem.i8", // 0x9F
+  "stelem.r4", // 0xA0
+  "stelem.r8", // 0xA1
+  "stelem.ref", // 0xA2
+  "ldelem", // 0xA3
+  "stelem", // 0xA4
+  "unbox.any", // 0xA5
+  "unused5", // 0xA6
+  "unused6", // 0xA7
+  "unused7", // 0xA8
+  "unused8", // 0xA9
+  "unused9", // 0xAA
+  "unused10", // 0xAB
+  "unused11", // 0xAC
+  "unused12", // 0xAD
+  "unused13", // 0xAE
+  "unused14", // 0xAF
+  "unused15", // 0xB0
+  "unused16", // 0xB1
+  "unused17", // 0xB2
+  "conv.ovf.i1", // 0xB3
+  "conv.ovf.u1", // 0xB4
+  "conv.ovf.i2", // 0xB5
+  "conv.ovf.u2", // 0xB6
+  "conv.ovf.i4", // 0xB7
+  "conv.ovf.u4", // 0xB8
+  "conv.ovf.i8", // 0xB9
+  "conv.ovf.u8", // 0xBA
+  "unused50", // 0xBB
+  "unused18", // 0xBC
+  "unused19", // 0xBD
+  "unused20", // 0xBE
+  "unused21", // 0xBF
+  "unused22", // 0xC0
+  "unused23", // 0xC1
+  "refanyval", // 0xC2
+  "ckfinite", // 0xC3
+  "unused24", // 0xC4
+  "unused25", // 0xC5
+  "mkrefany", // 0xC6
+  "unused59", // 0xC7
+  "unused60", // 0xC8
+  "unused61", // 0xC9
+  "unused62", // 0xCA
+  "unused63", // 0xCB
+  "unused64", // 0xCC
+  "unused65", // 0xCD
+  "unused66", // 0xCE
+  "unused67", // 0xCF
+  "ldtoken", // 0xD0
+  "conv.u2", // 0xD1
+  "conv.u1", // 0xD2
+  "conv.i", // 0xD3
+  "conv.ovf.i", // 0xD4
+  "conv.ovf.u", // 0xD5
+  "add.ovf", // 0xD6
+  "add.ovf.un", // 0xD7
+  "mul.ovf", // 0xD8
+  "mul.ovf.un", // 0xD9
+  "sub.ovf", // 0xDA
+  "sub.ovf.un", // 0xDB
+  "endfinally", // 0xDC
+  "leave", // 0xDD
+  "leave.s", // 0xDE
+  "stind.i", // 0xDF
+  "conv.u" // 0xE0
+};
+
+const char* n3::CLIJit::OpcodeNamesFE[0x23] = {
+  "arglist", // 0x00
+  "ceq", // 0x01
+  "cgt", // 0x02
+  "cgt.un", // 0x03
+  "clt", // 0x04
+  "clt.un", // 0x05
+  "ldftn", // 0x06
+  "ldvirtftn", // 0x07
+  "unused56", // 0x08
+  "ldarg", // 0x09
+  "ldarga", // 0x0A
+  "starg", // 0x0B
+  "ldloc", // 0x0C
+  "ldloca", // 0x0D
+  "stloc", // 0x0E
+  "localloc", // 0x0F
+  "unused57", // 0x10
+  "endfilter", // 0x11
+  "unaligned.", // 0x12
+  "volatile.", // 0x13
+  "tail.", // 0x14
+  "initobj", // 0x15
+  "constrained.", // 0x16
+  "cpblk", // 0x17
+  "initblk", // 0x18
+  "no.", // 0x19
+  "rethrow", // 0x1A
+  "unused", // 0x1B
+  "sizeof", // 0x1C
+  "refanytype", // 0x1D
+  "readonly.", // 0x1E
+  "unused53", // 0x1F
+  "unused54", // 0x20
+  "unused55", // 0x21
+  "unused70" // 0x22
+};
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/Opcodes.cpp b/vmkit/lib/N3/VMCore/Opcodes.cpp
new file mode 100644
index 0000000..8e00cea
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/Opcodes.cpp
@@ -0,0 +1,2517 @@
+//===----------- Opcodes.cpp - Reads and compiles opcodes -----------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG 0
+#define N3_COMPILE 0
+#define N3_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 <../lib/ExecutionEngine/JIT/JIT.h>
+
+#include <llvm/Transforms/IPO.h>
+
+
+#include "mvm/JIT.h"
+#include "mvm/Method.h"
+
+#include "debug.h"
+
+#include "Assembly.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "N3.h"
+#include "Reader.h"
+#include "VMArray.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+#include "OpcodeNames.def"
+
+#include <iostream>
+
+
+
+using namespace n3;
+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);
+  return val | (readU1(bytecode, i) << 8);
+}
+
+static inline uint16 readU2(uint8* bytecode, uint32& i) {
+  uint16 val = readU1(bytecode, i);
+  return val | (readU1(bytecode, i) << 8);
+}
+
+static inline sint32 readS4(uint8* bytecode, uint32& i) {
+  sint32 val = readU2(bytecode, i);
+  return val | (readU2(bytecode, i) << 16);
+}
+
+
+static inline uint32 readU4(uint8* bytecode, uint32& i) {
+  return readS4(bytecode, i);
+}
+
+static inline sint64 readS8(uint8* bytecode, uint32& i) {
+  uint64 val = readU4(bytecode, i);
+  uint64 _val2 = readU4(bytecode, i);
+  uint64 val2 = _val2 << 32;
+  return val | val2;
+}
+
+typedef union ufloat_t {
+  uint32 i;
+  float f;
+}ufloat_t;
+
+typedef union udouble_t {
+  sint64 l;
+  double d;
+}udouble_t;
+
+
+static inline float readFloat(uint8* bytecode, uint32& i) {
+  ufloat_t tmp;
+  tmp.i = readU4(bytecode, i);
+  return tmp.f;
+}
+
+static inline double readDouble(uint8* bytecode, uint32& i) {
+  udouble_t tmp;
+  tmp.l = readS8(bytecode, i);
+  return tmp.d;
+}
+
+
+void CLIJit::printExecution(char* opcode, VMMethod* meth) {
+  printf("executing %s %s\n", meth->printString(), opcode);
+}
+
+
+static void verifyType(Value*& val1, Value*& val2, BasicBlock* currentBlock) {
+  const Type* t1 = val1->getType();
+  const Type* t2 = val2->getType();
+  if (t1 != t2) {
+    if (t1->isInteger() && t2->isInteger()) {
+      if (t1->getPrimitiveSizeInBits() < t2->getPrimitiveSizeInBits()) {
+        val1 = new SExtInst(val1, t2, "", currentBlock);
+      } else {
+        val2 = new SExtInst(val2, t1, "", currentBlock);
+      }
+    } else if (t1->isFloatingPoint()) {
+      if (t1->getPrimitiveSizeInBits() < t2->getPrimitiveSizeInBits()) {
+        val1 = new FPExtInst(val1, t2, "", currentBlock);
+      } else {
+        val2 = new FPExtInst(val2, t1, "", currentBlock);
+      }
+    } else if (isa<PointerType>(t1) && isa<PointerType>(t2)) {
+      val1 = new BitCastInst(val1, VMObject::llvmType, "", currentBlock);
+      val2 = new BitCastInst(val2, VMObject::llvmType, "", currentBlock);
+    } else if (t1->isInteger() && t2 == PointerType::getUnqual(Type::Int8Ty)) {
+      // CLI says that this is fine for some operation
+      val2 = new PtrToIntInst(val2, t1, "", currentBlock);
+    }
+  }
+}
+
+void convertValue(Value*& val, const Type* t1, BasicBlock* currentBlock) {
+  const Type* t2 = val->getType();
+  if (t1 != t2) {
+    if (t1->isInteger() && t2->isInteger()) {
+      if (t2->getPrimitiveSizeInBits() < t1->getPrimitiveSizeInBits()) {
+        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);
+    }
+  }
+}
+
+static void store(Value* val, Value* local, bool vol, 
+                  BasicBlock* currentBlock) {
+  const Type* contained = local->getType()->getContainedType(0);
+  if (contained->isFirstClassType()) {
+    if (val->getType() != contained) {
+      convertValue(val, contained, currentBlock);
+    }
+    new StoreInst(val, local, vol, currentBlock);
+  } else {
+    uint64 size = mvm::jit::getTypeSize(contained);
+        
+    std::vector<Value*> params;
+    params.push_back(new BitCastInst(local, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+    params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+    mvm::jit::protectConstants();
+    params.push_back(ConstantInt::get(Type::Int32Ty, size));
+    mvm::jit::unprotectConstants();
+    params.push_back(mvm::jit::constantZero);
+    new CallInst(mvm::jit::llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock);
+  }
+}
+
+static Value* load(Value* val, const char* name, BasicBlock* currentBlock) {
+  const Type* contained = val->getType()->getContainedType(0);
+  if (contained->isFirstClassType()) {
+    return new LoadInst(val, name, currentBlock);
+  } else {
+    uint64 size = mvm::jit::getTypeSize(contained);
+    Value* ret = new AllocaInst(contained, "", currentBlock); 
+    std::vector<Value*> params;
+    params.push_back(new BitCastInst(ret, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+    params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+    mvm::jit::protectConstants();
+    params.push_back(ConstantInt::get(Type::Int32Ty, size));
+    mvm::jit::unprotectConstants();
+    params.push_back(mvm::jit::constantZero);
+    new CallInst(mvm::jit::llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock);
+    return ret;
+  }
+}
+
+void CLIJit::compileOpcodes(uint8* bytecodes, uint32 codeLength) {
+  uint32 leaveIndex = 0;
+  for(uint32 i = 0; i < codeLength; ++i) {
+    
+    if (bytecodes[i] != 0xFE) {
+      PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i,
+                  bytecodes[i]);
+      PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "compiling %s::", compilingMethod->printString());
+      PRINT_DEBUG(N3_COMPILE, 1, LIGHT_CYAN, OpcodeNames[bytecodes[i]]);
+      PRINT_DEBUG(N3_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 N3_EXECUTE > 1
+    mvm::jit::protectConstants();
+    std::vector<llvm::Value*> args;
+    args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNames[bytecodes[i]]));
+    args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
+    new CallInst(printExecutionLLVM, args.begin(), args.end(), "", currentBlock);
+    if (bytecodes[i] == 0xFE) {
+      std::vector<llvm::Value*> args;
+      args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)OpcodeNamesFE[bytecodes[i + 1]]));
+      args.push_back(ConstantInt::get(Type::Int32Ty, (int64_t)compilingMethod));
+      new CallInst(printExecutionLLVM, args.begin(), args.end(), "", currentBlock);
+    }
+    mvm::jit::unprotectConstants();
+#endif
+  
+    if (opinfo->reqSuppl) {
+      push(new LoadInst(supplLocal, "", currentBlock));
+    }
+
+    switch (bytecodes[i]) {
+      
+      case ADD: {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        verifyType(val1, val2, currentBlock);
+        push(BinaryOperator::createAdd(val1, val2, "", currentBlock));
+        break;
+      }
+      
+      case ADD_OVF: {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case ADD_OVF_UN: {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case AND: {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        push(BinaryOperator::createAnd(val1, val2, "", currentBlock));
+        break;
+      }
+      
+#define TEST(name, read, cmpf, cmpi, offset) case name : { \
+        uint32 tmp = i;       \
+        Value* val2 = pop();  \
+        Value* val1 = pop();  \
+        BasicBlock* ifTrue = opcodeInfos[tmp + offset + read(bytecodes, i)].newBlock; \
+        Value* test = 0; \
+        verifyType(val1, val2, currentBlock); \
+        if (val1->getType()->isFloatingPoint()) { \
+          test = new FCmpInst(FCmpInst::cmpf, val1, val2, "", currentBlock); \
+        } else {  \
+          test = new ICmpInst(ICmpInst::cmpi, val1, val2, "", currentBlock); \
+        } \
+        BasicBlock* ifFalse = createBasicBlock("false BEQ"); \
+        branch(test, ifTrue, ifFalse, currentBlock); \
+        currentBlock = ifFalse; \
+        break; \
+      }
+      
+      TEST(BEQ, readS4, FCMP_OEQ, ICMP_EQ, 5);
+      TEST(BEQ_S, readS1, FCMP_OEQ, ICMP_EQ, 2);
+      
+      TEST(BGE, readS4, FCMP_OGE, ICMP_SGE, 5);
+      TEST(BGE_S, readS1, FCMP_OGE, ICMP_SGE, 2);
+      TEST(BGE_UN, readS4, FCMP_UGE, ICMP_UGE, 5);
+      TEST(BGE_UN_S, readS1, FCMP_UGE, ICMP_UGE, 2);
+      
+      TEST(BGT, readS4, FCMP_OGT, ICMP_SGT, 5);
+      TEST(BGT_S, readS1, FCMP_OGT, ICMP_SGT, 2);
+      TEST(BGT_UN, readS4, FCMP_UGT, ICMP_UGT, 5);
+      TEST(BGT_UN_S, readS1, FCMP_UGT, ICMP_UGT, 2);
+
+      TEST(BLE, readS4, FCMP_OLE, ICMP_SLE, 5);
+      TEST(BLE_S, readS1, FCMP_OLE, ICMP_SLE, 2);
+      TEST(BLE_UN, readS4, FCMP_ULE, ICMP_ULE, 5);
+      TEST(BLE_UN_S, readS1, FCMP_ULE, ICMP_ULE, 2);
+      
+      TEST(BLT, readS4, FCMP_OLT, ICMP_SLT, 5);
+      TEST(BLT_S, readS1, FCMP_OLT, ICMP_SLT, 2);
+      TEST(BLT_UN, readS4, FCMP_ULT, ICMP_ULT, 5);
+      TEST(BLT_UN_S, readS1, FCMP_ULT, ICMP_ULT, 2);
+      
+      TEST(BNE_UN, readS4, FCMP_UNE, ICMP_NE, 5);
+      TEST(BNE_UN_S, readS1, FCMP_UNE, ICMP_NE, 2);
+
+#undef TEST 
+      
+      case BR : {
+        uint32 tmp = i;
+        BasicBlock* br = opcodeInfos[tmp + 5 + readS4(bytecodes, i)].newBlock;
+        branch(br, currentBlock); 
+        break;
+      }
+      
+      case BR_S : {
+        uint32 tmp = i;
+        BasicBlock* br = opcodeInfos[tmp + 2 + readS1(bytecodes, i)].newBlock;
+        branch(br, currentBlock); 
+        break;
+      }
+
+      case BREAK: break;
+
+#define TEST(name, read, cmpf, cmpi, offset) case name : { \
+        uint32 tmp = i;       \
+        Value* val2 = pop();  \
+        mvm::jit::protectConstants(); \
+        Value* val1 = Constant::getNullValue(val2->getType());  \
+        mvm::jit::unprotectConstants(); \
+        BasicBlock* ifTrue = opcodeInfos[tmp + offset + read(bytecodes, i)].newBlock; \
+        Value* test = 0; \
+        if (val1->getType()->isFloatingPoint()) { \
+          test = new FCmpInst(FCmpInst::cmpf, val1, val2, "", currentBlock); \
+        } else {  \
+          test = new ICmpInst(ICmpInst::cmpi, val1, val2, "", currentBlock); \
+        } \
+        BasicBlock* ifFalse = createBasicBlock("false BR"); \
+        branch(test, ifTrue, ifFalse, currentBlock); \
+        currentBlock = ifFalse; \
+        break; \
+      }
+
+      TEST(BRFALSE, readS4, FCMP_OEQ, ICMP_EQ, 5);
+      TEST(BRFALSE_S, readS1, FCMP_OEQ, ICMP_EQ, 2);
+      TEST(BRTRUE, readS4, FCMP_ONE, ICMP_NE, 5);
+      TEST(BRTRUE_S, readS1, FCMP_ONE, ICMP_NE, 2);
+
+#undef TEST
+      
+      case CALL: {
+        uint32 value = readU4(bytecodes, i);
+        invoke(value);
+        break;
+      }
+
+      case CALLI: {
+        VMThread::get()->vm->unknownError("implement me");
+        break;
+      }
+
+      case CKFINITE : {
+        VMThread::get()->vm->unknownError("implement me");
+        break;
+      }
+
+      case CONV_I1 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToSIInst(val, Type::Int8Ty, "", currentBlock));
+        } else if (type == Type::Int16Ty || type == Type::Int32Ty || 
+                   type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int8Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_I2 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToSIInst(val, Type::Int16Ty, "", currentBlock));
+        } else if (type == Type::Int32Ty || type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int16Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty) {
+          push(new SExtInst(val, Type::Int16Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_I4 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToSIInst(val, Type::Int32Ty, "", currentBlock));
+        } else if (type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int32Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty || type == Type::Int16Ty) {
+          push(new SExtInst(val, Type::Int32Ty, "", currentBlock));
+        } else if (type == Type::Int32Ty) {
+          push(val);
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_I8 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToSIInst(val, Type::Int64Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty || type == Type::Int16Ty || 
+                   type == Type::Int32Ty) {
+          push(new SExtInst(val, Type::Int64Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_R4 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type == Type::DoubleTy) {
+          push(new FPTruncInst(val, Type::FloatTy, "", currentBlock));
+        } else if (type->isInteger()) {
+          push(new SIToFPInst(val, Type::FloatTy, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_R8 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type == Type::FloatTy) {
+          push(new FPExtInst(val, Type::DoubleTy, "", currentBlock));
+        } else if (type->isInteger()) {
+          push(new SIToFPInst(val, Type::DoubleTy, "", currentBlock));
+        } else if (type == Type::DoubleTy) {
+          push(val);
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_U1 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToUIInst(val, Type::Int8Ty, "", currentBlock));
+        } else if (type == Type::Int16Ty || type == Type::Int32Ty || 
+                   type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int8Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_U2 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToUIInst(val, Type::Int16Ty, "", currentBlock));
+        } else if (type == Type::Int32Ty || type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int8Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty) {
+          push(new ZExtInst(val, Type::Int16Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_U4 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToUIInst(val, Type::Int32Ty, "", currentBlock));
+        } else if (type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int8Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty || type == Type::Int16Ty) {
+          push(new ZExtInst(val, Type::Int16Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_U8 : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToUIInst(val, Type::Int64Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty || type == Type::Int16Ty || 
+                   type == Type::Int32Ty) {
+          push(new ZExtInst(val, Type::Int64Ty, "", currentBlock));
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+
+      case CONV_I : {
+        Value* val = pop();
+        if (val->getType() != Type::Int64Ty) 
+          val = new ZExtInst(val, Type::Int64Ty, "", currentBlock);
+        push(new IntToPtrInst(val, PointerType::getUnqual(Type::Int8Ty), "", 
+                              currentBlock));
+        break;
+      }
+
+      case CONV_U : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_R_UN : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type == Type::FloatTy) {
+          push(new FPExtInst(val, Type::DoubleTy, "", currentBlock));
+        } else if (type->isInteger()) {
+          push(new UIToFPInst(val, Type::DoubleTy, "", currentBlock));
+        } else if (type == Type::DoubleTy) {
+          push(val);
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_OVF_I1 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I2 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I4 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I8 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U1 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U2 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U4 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U8 : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I1_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I2_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_I4_UN : {
+        Value* val = pop();
+        const Type* type = val->getType();
+        if (type->isFloatingPoint()) {
+          push(new FPToUIInst(val, Type::Int32Ty, "", currentBlock));
+        } else if (type == Type::Int64Ty) {
+          push(new TruncInst(val, Type::Int8Ty, "", currentBlock));
+        } else if (type == Type::Int8Ty || type == Type::Int16Ty) {
+          push(new ZExtInst(val, Type::Int16Ty, "", currentBlock));
+        } else if (type == Type::Int32Ty) {
+          push(val);
+        } else {
+          VMThread::get()->vm->unknownError("implement me");
+        }
+        break;
+      }
+      
+      case CONV_OVF_I8_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U1_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U2_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U4_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case CONV_OVF_U8_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+
+      case DIV: {
+        Value* two = pop();
+        Value* one = pop();
+        if (one->getType()->isFloatingPoint()) {
+          convertValue(one, two->getType(), currentBlock); 
+          push(BinaryOperator::createFDiv(one, two, "", currentBlock));
+        } else {
+          push(BinaryOperator::createSDiv(one, two, "", currentBlock));
+        }
+        break;
+      }
+      
+      case DIV_UN: {
+        Value* two = pop();
+        Value* one = pop();
+        if (one->getType()->isFloatingPoint()) {
+          push(BinaryOperator::createFDiv(one, two, "", currentBlock));
+        } else {
+          push(BinaryOperator::createUDiv(one, two, "", currentBlock));
+        }
+        break;
+      }
+
+      case DUP: {
+        push(top());
+        break;
+      }
+
+      case ENDFINALLY : {
+        Value* val = new LoadInst(supplLocal, "", currentBlock);
+        /*Value* call = new CallInst(isInCodeLLVM, val, "", currentBlock);
+        BasicBlock* bb1 = createBasicBlock("end finally");
+        BasicBlock* bb2 = createBasicBlock("no end finally");
+        new BranchInst(bb1, bb2, call, currentBlock);
+        currentBlock = bb1;*/
+        val = new PtrToIntInst(val, Type::Int32Ty, "", currentBlock);
+        SwitchInst* inst = new SwitchInst(val, leaves[0], 
+                                          leaves.size(), currentBlock);
+     
+        uint32 index = 0; 
+        mvm::jit::protectConstants();
+        for (std::vector<BasicBlock*>::iterator i = leaves.begin(), 
+             e = leaves.end(); i!= e; ++i, ++index) {
+          inst->addCase(ConstantInt::get(Type::Int32Ty, index), *i); 
+        }
+        mvm::jit::unprotectConstants();
+
+        //currentBlock = bb2;
+
+        break;
+      }
+      
+      case JMP : {
+        VMThread::get()->vm->error("implement me"); 
+        break;
+      }
+ 
+      case LDARG_S : {
+        push(new LoadInst(arguments[readU1(bytecodes, i)], "", currentBlock));
+        break;
+      }
+
+      case LDARG_0 : {
+        push(new LoadInst(arguments[0], "", currentBlock));
+        break;
+      }
+      
+      case LDARG_1 : {
+        push(new LoadInst(arguments[1], "", currentBlock));
+        break;
+      }
+      
+      case LDARG_2 : {
+        push(new LoadInst(arguments[2], "", currentBlock));
+        break;
+      }
+      
+      case LDARG_3 : {
+        push(new LoadInst(arguments[3], "", currentBlock));
+        break;
+      }
+
+      case LDARGA_S : {
+        push(arguments[readU1(bytecodes, i)]);
+        break;
+      }
+
+      case LDC_I4 : {
+        mvm::jit::protectConstants();
+        push(ConstantInt::get(Type::Int32Ty, readS4(bytecodes, i)));
+        mvm::jit::unprotectConstants();
+        break;
+      }
+      
+      case LDC_I8 : {
+        mvm::jit::protectConstants();
+        push(ConstantInt::get(Type::Int64Ty, readS8(bytecodes, i)));
+        mvm::jit::unprotectConstants();
+        break;
+      }
+      
+      case LDC_R4 : {
+        mvm::jit::protectConstants();
+        push(ConstantFP::get(Type::FloatTy, APFloat(readFloat(bytecodes, i))));
+        mvm::jit::unprotectConstants();
+        break;
+      }
+      
+      case LDC_R8 : {
+        mvm::jit::protectConstants();
+        push(ConstantFP::get(Type::DoubleTy, APFloat(readDouble(bytecodes, i))));
+        mvm::jit::unprotectConstants();
+        break;
+      }
+      
+      case LDC_I4_0 : {
+        push(mvm::jit::constantZero);
+        break;
+      }
+      
+      case LDC_I4_1 : {
+        push(mvm::jit::constantOne);
+        break;
+      }
+      
+      case LDC_I4_2 : {
+        push(mvm::jit::constantTwo);
+        break;
+      }
+      
+      case LDC_I4_3 : {
+        push(mvm::jit::constantThree);
+        break;
+      }
+      
+      case LDC_I4_4 : {
+        push(mvm::jit::constantFour);
+        break;
+      }
+      
+      case LDC_I4_5 : {
+        push(mvm::jit::constantFive);
+        break;
+      }
+      
+      case LDC_I4_6 : {
+        push(mvm::jit::constantSix);
+        break;
+      }
+      
+      case LDC_I4_7 : {
+        push(mvm::jit::constantSeven);
+        break;
+      }
+      
+      case LDC_I4_8 : {
+        push(mvm::jit::constantEight);
+        break;
+      }
+      
+      case LDC_I4_M1 : {
+        push(mvm::jit::constantMinusOne);
+        break;
+      }
+      
+      case LDC_I4_S : {
+        mvm::jit::protectConstants();
+        push(ConstantInt::get(Type::Int32Ty, readS1(bytecodes, i)));
+        mvm::jit::unprotectConstants();
+        break;
+      }
+ 
+      case LDIND_U1 :
+      case LDIND_I1 : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDIND_U2 :
+      case LDIND_I2 : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(Type::Int16Ty), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDIND_U4 :
+      case LDIND_I4 : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(Type::Int32Ty), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDIND_I8 : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(Type::Int64Ty), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+
+      case LDIND_R4 : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(Type::FloatTy), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDIND_R8 : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(Type::DoubleTy), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDIND_I : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(
+                                        PointerType::getUnqual(Type::Int8Ty)), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDIND_REF : {
+        Value* _val = pop();
+        Value* val = new BitCastInst(_val, PointerType::getUnqual(
+                                        PointerType::getUnqual(VMObject::llvmType)), "", currentBlock);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+ 
+      case LDLOC_S : {
+        Value* val = load(locals[readU1(bytecodes, i)], "", currentBlock);
+        push(val);
+        break;
+      }
+      
+      case LDLOC_0 : {
+        Value* val = load(locals[0], "", currentBlock);
+        push(val);
+        break;
+      }
+      
+      case LDLOC_1 : {
+        Value* val = load(locals[1], "", currentBlock);
+        push(val);
+        break;
+      }
+      
+      case LDLOC_2 : {
+        Value* val = load(locals[2], "", currentBlock);
+        push(val);
+        break;
+      }
+      
+      case LDLOC_3 : {
+        Value* val = load(locals[3], "", currentBlock);
+        push(val);
+        break;
+      }
+      
+      case LDLOCA_S : {
+        push(locals[readU1(bytecodes, i)]);
+        break;
+      }
+      
+      case LDNULL : {
+        push(CLIJit::constantVMObjectNull);
+        break;
+      }
+
+      case LEAVE : {
+        uint32 tmp = i;
+        uint32 index = tmp + 5 + readS4(bytecodes, i);
+        BasicBlock* bb = opcodeInfos[index].newBlock;
+        assert(bb);
+        stack.clear();
+        if (finallyHandlers.size()) {
+          Exception* res = 0;
+          for (std::vector<Exception*>::iterator i = finallyHandlers.begin(), 
+               e = finallyHandlers.end(); i!= e; ++i) {
+            Exception* ex = (*i);
+            if (tmp >= ex->tryOffset && tmp < ex->tryOffset + ex->tryLength) {
+              res = ex;
+              break;
+            }
+          }
+          if (res) {
+            mvm::jit::protectConstants();
+            Value* expr = ConstantExpr::getIntToPtr(
+                                    ConstantInt::get(Type::Int64Ty,
+                                                     uint64_t (leaveIndex++)),
+                                    VMObject::llvmType);
+            mvm::jit::unprotectConstants();
+
+            new StoreInst(expr, supplLocal, false, currentBlock);
+            branch(res->handler, currentBlock);
+          } else {
+            branch(bb, currentBlock);
+          }
+        } else {
+          branch(bb, currentBlock);
+        }
+        break;
+      }
+      
+      case LEAVE_S : {
+        uint32 tmp = i;
+        BasicBlock* bb = opcodeInfos[tmp + 2 + readS1(bytecodes, i)].newBlock;
+        assert(bb);
+        stack.clear();
+        if (finallyHandlers.size()) {
+          Exception* res = 0;
+          for (std::vector<Exception*>::iterator i = finallyHandlers.begin(), 
+               e = finallyHandlers.end(); i!= e; ++i) {
+            Exception* ex = (*i);
+            if (tmp >= ex->tryOffset && tmp < ex->tryOffset + ex->tryLength) {
+              res = ex;
+              break;
+            }
+          }
+          if (res) {
+            mvm::jit::protectConstants();
+            Value* expr = ConstantExpr::getIntToPtr(
+                                    ConstantInt::get(Type::Int64Ty,
+                                                     uint64_t (leaveIndex++)),
+                                    VMObject::llvmType);
+            mvm::jit::unprotectConstants();
+
+            new StoreInst(expr, supplLocal, false, currentBlock);
+            branch(res->handler, currentBlock);
+          } else {
+            branch(bb, currentBlock);
+          }
+        } else {
+          branch(bb, currentBlock);
+        }
+        break;
+      }
+
+      case MUL : {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        convertValue(val1, val2->getType(), currentBlock); 
+        push(BinaryOperator::createMul(val1, val2, "", currentBlock));
+        break;
+      }
+
+      case MUL_OVF : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case MUL_OVF_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case NEG : {
+        Value* val = pop();
+        mvm::jit::protectConstants();
+        push(BinaryOperator::createSub(
+                              Constant::getNullValue(val->getType()),
+                              val, "", currentBlock));
+        mvm::jit::unprotectConstants();
+        break;
+      }
+      
+      case NOP : break;
+
+      case NOT : {
+        push(BinaryOperator::createNot(pop(), "", currentBlock));
+        break;
+      }
+
+      case OR : {
+        Value* two = pop();
+        Value* one = pop();
+        push(BinaryOperator::createOr(one, two, "", currentBlock));
+        break;
+      }
+
+      case POP : {
+        pop();
+        break;
+      }
+
+      case REM : {
+        Value* two = pop();
+        Value* one = pop();
+        if (one->getType()->isFloatingPoint()) {
+          push(BinaryOperator::createFRem(one, two, "", currentBlock));
+        } else {
+          push(BinaryOperator::createSRem(one, two, "", currentBlock));
+        }
+        break;
+      }
+      
+      case REM_UN : {
+        Value* two = pop();
+        Value* one = pop();
+        if (one->getType()->isFloatingPoint()) {
+          push(BinaryOperator::createFRem(one, two, "", currentBlock));
+        } else {
+          push(BinaryOperator::createURem(one, two, "", currentBlock));
+        }
+        break;
+      }
+
+      case RET : {
+        if (compilingMethod->getSignature()->getReturnType() != Type::VoidTy) {
+          Value* val = pop();
+          if (val->getType() == PointerType::getUnqual(endNode->getType())) {
+            // In case it's a struct
+            val = new LoadInst(val, "", currentBlock);
+          } else {
+            convertValue(val, endNode->getType(), currentBlock);
+          }
+          endNode->addIncoming(val, currentBlock);
+        } else if (compilingMethod->structReturn) {
+          endNode->addIncoming(pop(), currentBlock);
+        }
+        new BranchInst(endBlock, currentBlock);
+        break;
+      }
+      
+      case SHL : {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        verifyType(val1, val2, currentBlock);
+        push(BinaryOperator::createShl(val1, val2, "", currentBlock));
+        break;
+      }
+      
+      case SHR : {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        verifyType(val1, val2, currentBlock);
+        push(BinaryOperator::createAShr(val1, val2, "", currentBlock));
+        break;
+      }
+      
+      case SHR_UN : {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        verifyType(val1, val2, currentBlock);
+        push(BinaryOperator::createLShr(val1, val2, "", currentBlock));
+        break;
+      }
+ 
+      case STARG_S : {
+        Value* val = pop();
+        Value* arg = arguments[readU1(bytecodes, i)];
+        convertValue(val, arg->getType()->getContainedType(0), currentBlock);
+        new StoreInst(val, arg, false, currentBlock);
+        break;
+      }
+
+      case STIND_I1 : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::Int8Ty), "",
+                                      currentBlock);
+        convertValue(val, Type::Int8Ty, currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_I2 : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::Int16Ty), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_I4 : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::Int32Ty), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_I8 : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::Int64Ty), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_R4 : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::FloatTy), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_R8 : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::DoubleTy), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_I : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(Type::Int32Ty), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STIND_REF : {
+        Value* val = pop();
+        Value* _addr = pop();
+        Value* addr = new BitCastInst(_addr, PointerType::getUnqual(val->getType()), 
+                                      "", currentBlock);
+        new StoreInst(val, addr, false, currentBlock);
+        break;
+      }
+      
+      case STLOC_S : {
+        Value* val = pop();
+        Value* local = locals[readU1(bytecodes, i)];
+        store(val, local, false, currentBlock);
+        break;
+      }
+      
+      case STLOC_0 : {
+        Value* val = pop();
+        Value* local = locals[0];
+        store(val, local, false, currentBlock);
+        break;
+      }
+      
+      case STLOC_1 : {
+        Value* val = pop();
+        Value* local = locals[1];
+        store(val, local, false, currentBlock);
+        break;
+      }
+      
+      case STLOC_2 : {
+        Value* val = pop();
+        Value* local = locals[2];
+        store(val, local, false, currentBlock);
+        break;
+      }
+      
+      case STLOC_3 : {
+        Value* val = pop();
+        Value* local = locals[3];
+        store(val, local, false, currentBlock);
+        break;
+      }
+      
+      case SUB : {
+        Value* val2 = pop();
+        Value* val1 = pop();
+        verifyType(val1, val2, currentBlock);
+        push(BinaryOperator::createSub(val1, val2, "", currentBlock));
+        break;
+      }
+
+      case SUB_OVF : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case SUB_OVF_UN : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case SWITCH : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case XOR : {
+        Value* two = pop();
+        Value* one = pop();
+        convertValue(two, one->getType(), currentBlock);
+        push(BinaryOperator::createXor(one, two, "", currentBlock));
+        break;
+      }
+
+      case BOX : {
+        uint32 token = readU4(bytecodes, i);
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        VMCommonClass* type = assembly->loadType(vm, token, true, false, false,
+                                                 true);
+        assert(type);
+
+        Value* var = new LoadInst(type->llvmVar(), "", currentBlock);
+        Value* obj = new CallInst(objConsLLVM, var, "", currentBlock);
+        Value* val = pop();
+        obj = new BitCastInst(obj, type->virtualType, "", currentBlock);
+    
+
+        std::vector<Value*> ptrs;
+        ptrs.push_back(mvm::jit::constantZero);
+        ptrs.push_back(mvm::jit::constantOne);
+        Value* ptr = new GetElementPtrInst(obj, ptrs.begin(), ptrs.end(), "", 
+                                           currentBlock);
+
+        if (val->getType()->getTypeID() != Type::PointerTyID) {
+          convertValue(val, type->naturalType, currentBlock); 
+          Value* tmp = new AllocaInst(type->naturalType, "", currentBlock);
+          new StoreInst(val, tmp, false, currentBlock);
+          val = tmp;
+        }
+        
+        
+        uint64 size = mvm::jit::getTypeSize(type->naturalType);
+        
+        std::vector<Value*> params;
+        params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+        params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+        mvm::jit::protectConstants();
+        params.push_back(ConstantInt::get(Type::Int32Ty, size));
+        mvm::jit::unprotectConstants();
+        params.push_back(mvm::jit::constantZero);
+        new CallInst(mvm::jit::llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock);
+        
+
+        push(obj);
+        break; 
+      }
+
+      case CALLVIRT : {
+        uint32 value = readU4(bytecodes, i);
+        invokeInterfaceOrVirtual(value);
+        break; 
+      }
+
+      case CASTCLASS : {
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        uint32 token = readU4(bytecodes, i);
+        VMCommonClass* dcl = assembly->loadType(vm, token, true, false,
+                                               false, true);
+        Value* obj = new BitCastInst(pop(), VMObject::llvmType, "", currentBlock);
+
+        Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, 
+                                  CLIJit::constantVMObjectNull,
+                                  "", currentBlock);
+     
+        BasicBlock* ifTrue = createBasicBlock("null checkcast");
+        BasicBlock* ifFalse = createBasicBlock("non null checkcast");
+
+        branch(cmp, ifTrue, ifFalse, currentBlock);
+
+        Value* clVar = new LoadInst(dcl->llvmVar(), "", ifFalse);
+        std::vector<Value*> args;
+        args.push_back(obj);
+        args.push_back(clVar);
+        Value* call = new CallInst(instanceOfLLVM, args.begin(), args.end(),
+                                   "", ifFalse);
+     
+        cmp = new ICmpInst(ICmpInst::ICMP_EQ, call,
+                           mvm::jit::constantZero, "", ifFalse);
+
+        BasicBlock* ex = createBasicBlock("false checkcast");
+        branch(cmp, ex, ifTrue, ifFalse);
+        
+        std::vector<Value*> exArgs;
+        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;
+        push(new BitCastInst(obj, dcl->virtualType, "", currentBlock));
+        break;
+      } 
+        
+
+      case CPOBJ : {
+        VMThread::get()->vm->error("implement me");
+        break;  
+      }
+       
+      case ISINST : {
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        uint32 token = readU4(bytecodes, i);
+        VMCommonClass* dcl = assembly->loadType(vm, token, true, false,
+                                               false, true);
+        Value* obj = pop();
+
+        mvm::jit::protectConstants();
+        Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, obj, 
+                                  Constant::getNullValue(obj->getType()),
+                                  "", currentBlock);
+        Constant* nullVirtual = Constant::getNullValue(dcl->virtualType);
+        mvm::jit::unprotectConstants();
+
+     
+        BasicBlock* isInstEndBlock = createBasicBlock("end isinst");
+        PHINode* node = new PHINode(dcl->virtualType, "", isInstEndBlock);
+
+        BasicBlock* ifFalse = createBasicBlock("non null isinst");
+        BasicBlock* ifTrue = createBasicBlock("null isinst");
+        
+        new BranchInst(ifTrue, ifFalse, cmp, currentBlock);
+        node->addIncoming(nullVirtual, ifTrue);
+        new BranchInst(isInstEndBlock, ifTrue);
+
+
+        Value* clVar = new LoadInst(dcl->llvmVar(), "", ifFalse);
+        std::vector<Value*> args;
+        args.push_back(new BitCastInst(obj, VMObject::llvmType, "", ifFalse));
+        args.push_back(clVar);
+        Value* call = new CallInst(instanceOfLLVM, args.begin(), args.end(),
+                                   "", ifFalse);
+     
+        cmp = new ICmpInst(ICmpInst::ICMP_EQ, call,
+                           mvm::jit::constantZero, "", ifFalse);
+
+        BasicBlock* falseInst = createBasicBlock("false isinst");
+        BasicBlock* trueInst = createBasicBlock("true isinst");
+        new BranchInst(falseInst, trueInst, cmp, ifFalse);
+
+        node->addIncoming(new BitCastInst(obj, dcl->virtualType, "", trueInst), trueInst);
+        new BranchInst(isInstEndBlock, trueInst);
+        
+        node->addIncoming(nullVirtual, falseInst);
+        new BranchInst(isInstEndBlock, falseInst);
+       
+        currentBlock = isInstEndBlock;
+        push(node);
+        break;
+      }
+      
+      case LDELEM : {
+        VMThread::get()->vm->error("implement me");
+        break;  
+      }
+      
+      case LDELEM_I1 : {
+        VMThread::get()->vm->error("implement me");
+        break;  
+      }
+
+      case LDELEM_I2 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArraySInt16::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_I4 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_I8 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayLong::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_U1 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt8::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_U2 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt16::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_U4 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayUInt32::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_R4 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayFloat::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_R8 : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayDouble::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_I : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+      
+      case LDELEM_REF : {
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayObject::llvmType);
+        push(new LoadInst(ptr, "", currentBlock));
+        break;
+      }
+
+      case LDELEMA : {
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        uint32 token = readU4(bytecodes, i);
+        VMCommonClass* cl = assembly->loadType(vm, token, true, false,
+                                               false, true);
+        VMClassArray* array = assembly->constructArray(cl, 1);
+        array->resolveType(false, false);
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, array->naturalType);
+        push(ptr);
+        break;
+      }
+
+      case LDFLD : {
+        uint32 value = readU4(bytecodes, i);
+        Value* val = getVirtualField(value);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDFLDA : {
+        uint32 value = readU4(bytecodes, i);
+        push(getVirtualField(value));
+        break;
+      }
+
+      case LDLEN : {
+        push(arraySize(pop()));
+        break;
+      }
+
+      case LDOBJ : {
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        uint32 token = readU4(bytecodes, i);
+        VMCommonClass* cl = assembly->loadType(vm, token, true, false,
+                                               false, true);
+        if (!(cl->super == N3::pValue || cl->super == N3::pEnum)) {
+          push(new LoadInst(pop(), "", currentBlock));
+        }
+        break;
+      }
+
+      case LDSFLD : {
+        uint32 value = readU4(bytecodes, i);
+        Value* val = getStaticField(value);
+        push(new LoadInst(val, "", currentBlock));
+        break;
+      }
+      
+      case LDSFLDA : {
+        uint32 value = readU4(bytecodes, i);
+        push(getStaticField(value));
+        break;
+      }
+
+      case LDSTR : {
+        uint32 value = readU4(bytecodes, i);
+        uint32 index = value & 0xfffffff;
+        const UTF8* utf8 = compilingClass->assembly->readUserString(index);
+        mvm::jit::protectConstants();
+        Value* val = ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, (int64_t)utf8),
+                                               mvm::jit::ptrType);
+        mvm::jit::unprotectConstants();
+        Value* res = new CallInst(newStringLLVM, val, "", currentBlock);
+        /*CLIString * str = 
+          (CLIString*)(((N3*)VMThread::get()->vm)->UTF8ToStr(utf8));
+        GlobalVariable* gv = str->llvmVar();
+        push(new BitCastInst(new LoadInst(gv, "", currentBlock), 
+                             N3::pString->naturalType, "", currentBlock));*/
+        push(new BitCastInst(res, N3::pString->naturalType, "", currentBlock));
+        break;
+      }
+
+      case LDTOKEN : {
+        uint32 token = readU4(bytecodes, i);
+        uint32 table = token >> 24;
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        switch (table) {
+          case CONSTANT_Field : {
+            uint32 typeToken = assembly->getTypedefTokenFromField(token);
+            assembly->loadType(vm, typeToken, true, true, false, true);
+            VMField* field = assembly->lookupFieldFromToken(token);
+            if (!field) {
+              VMThread::get()->vm->error("implement me");
+            }
+            Value* arg = new LoadInst(field->llvmVar(), "", currentBlock);
+            push(arg);
+            break;
+          }
+          
+          case CONSTANT_MethodDef : {
+            uint32 typeToken = assembly->getTypedefTokenFromMethod(token);
+            assembly->loadType(vm, typeToken, true, true, false, true);
+            VMMethod* meth = assembly->lookupMethodFromToken(token);
+            if (!meth) {
+              VMThread::get()->vm->error("implement me");
+            }
+            Value* arg = new LoadInst(meth->llvmVar(), "", currentBlock);
+            push(arg);
+            break;
+          }
+
+          case CONSTANT_TypeDef :
+          case CONSTANT_TypeRef : {
+            VMCommonClass* cl = assembly->loadType(vm, token, true, false,
+                                                   false, true);
+            Value* arg = new LoadInst(cl->llvmVar(), "", currentBlock);
+            push(arg);
+            break;
+          }
+
+          default :
+            VMThread::get()->vm->error("implement me");
+        }
+        break;
+      }
+      
+      case MKREFANY : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case NEWARR : {
+        uint32 value = readU4(bytecodes, i);
+        Assembly* ass = compilingClass->assembly;
+        VMCommonClass* baseType = ass->loadType((N3*)(VMThread::get()->vm),
+                                                value, true, false, false, 
+                                                true);
+
+        VMClassArray* type = ass->constructArray(baseType, 1);
+        type->resolveType(false, false);
+        Value* var = new LoadInst(type->llvmVar(), "", currentBlock);
+        std::vector<Value*> args;
+        args.push_back(var);
+        args.push_back(pop());
+        Value* val = new CallInst(arrayConsLLVM, args.begin(), args.end(), "",
+                                  currentBlock);
+        push(new BitCastInst(val, type->naturalType, "", currentBlock));
+        break;
+      }
+
+      case NEWOBJ : {
+        uint32 value = readU4(bytecodes, i);
+        invokeNew(value);
+        break;
+      }
+      
+      case REFANYVAL : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case STELEM : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case STELEM_I1 : {
+        Value* val = pop();
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArraySInt8::llvmType);
+        convertValue(val, Type::Int8Ty, currentBlock);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+      
+      case STELEM_I2 : {
+        Value* val = pop();
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArraySInt16::llvmType);
+        convertValue(val, Type::Int16Ty, currentBlock);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+      
+      case STELEM_I4 : {
+        Value* val = pop();
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArraySInt32::llvmType);
+        convertValue(val, Type::Int32Ty, currentBlock);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+      
+      case STELEM_I8 : {
+        Value* val = pop();
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayLong::llvmType);
+        convertValue(val, Type::Int64Ty, currentBlock);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+      
+      case STELEM_R4 : {
+        Value* val = pop();
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayFloat::llvmType);
+        convertValue(val, Type::FloatTy, currentBlock);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+      
+      case STELEM_R8 : {
+        Value* val = pop();
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayDouble::llvmType);
+        convertValue(val, Type::DoubleTy, currentBlock);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+
+      case STELEM_I : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case STELEM_REF : {
+        Value* val = new BitCastInst(pop(), VMObject::llvmType, "", 
+                                     currentBlock);
+        Value* index = pop();
+        Value* obj = pop();
+        Value* ptr = verifyAndComputePtr(obj, index, ArrayObject::llvmType);
+        new StoreInst(val, ptr, false, currentBlock);
+        break;
+      }
+      
+      case STFLD : {
+        uint32 index = readU4(bytecodes, i);
+        setVirtualField(index);
+        break;
+      }
+
+      case STOBJ : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case STSFLD : {
+        uint32 index = readU4(bytecodes, i);
+        setStaticField(index);
+        break;
+      }
+
+      case THROW : {
+        llvm::Value* arg = pop();
+        arg = new BitCastInst(arg, VMObject::llvmType, "", currentBlock);
+        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 UNBOX : {
+        uint32 token = readU4(bytecodes, i);
+        Assembly* assembly = compilingClass->assembly;
+        N3* vm = (N3*)(VMThread::get()->vm);
+        VMCommonClass* type = assembly->loadType(vm, token, true, false, false,
+                                                 true);
+        assert(type);
+
+        Value* val = new AllocaInst(type->naturalType, "", currentBlock);
+        Value* obj = pop();
+
+        if (obj->getType() != type->virtualType) {
+          obj = new BitCastInst(obj, type->virtualType, "", currentBlock);
+        }
+        
+        std::vector<Value*> ptrs;
+        ptrs.push_back(mvm::jit::constantZero);
+        ptrs.push_back(mvm::jit::constantOne);
+        Value* ptr = new GetElementPtrInst(obj, ptrs.begin(), ptrs.end(), "", 
+                                           currentBlock);
+
+        uint64 size = mvm::jit::getTypeSize(type->naturalType);
+        
+        std::vector<Value*> params;
+        params.push_back(new BitCastInst(val, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+        params.push_back(new BitCastInst(ptr, PointerType::getUnqual(Type::Int8Ty), "", currentBlock));
+        mvm::jit::protectConstants();
+        params.push_back(ConstantInt::get(Type::Int32Ty, size));
+        mvm::jit::unprotectConstants();
+        params.push_back(mvm::jit::constantZero);
+        new CallInst(mvm::jit::llvm_memcpy_i32, params.begin(), params.end(), "", currentBlock);
+        
+
+        push(val);
+        break;
+      }
+      
+      case UNBOX_ANY : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case 0xFE : {
+        PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i,
+                    bytecodes[i + 1]);
+        PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "compiling %s::", compilingMethod->printString());
+        PRINT_DEBUG(N3_COMPILE, 1, LIGHT_CYAN, OpcodeNamesFE[bytecodes[i + 1]]);
+        PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "\n");
+
+        switch (bytecodes[++i]) {
+
+#define TEST(name, cmpf, cmpi) case name : { \
+          Value* val2 = pop(); \
+          Value* val1 = pop(); \
+          Value* test = 0; \
+          if (val1->getType()->isFloatingPoint()) { \
+            test = new FCmpInst(FCmpInst::cmpf, val1, val2, "", currentBlock); \
+          } else { \
+            convertValue(val2, val1->getType(), currentBlock); \
+            test = new ICmpInst(ICmpInst::cmpi, val1, val2, "", currentBlock); \
+          } \
+          push(test); \
+          break; \
+        }
+      
+        TEST(CEQ, FCMP_OEQ, ICMP_EQ);
+        TEST(CGT, FCMP_OGT, ICMP_SGT);
+        TEST(CGT_UN, FCMP_UGT, ICMP_UGT);
+        TEST(CLT, FCMP_OLT, ICMP_SLT);
+        TEST(CLT_UN, FCMP_ULT, ICMP_ULT);
+
+#undef TEST
+          
+          case CPBLK : {
+            Value* three = pop();
+            Value* two = pop();
+            Value* one = pop();
+            std::vector<Value*> args;
+            args.push_back(one);
+            args.push_back(two);
+            args.push_back(three);
+            new CallInst(mvm::jit::llvm_memcpy_i32,
+                         args.begin(), args.end(), "", currentBlock);
+            break;
+          }
+      
+          case ENDFILTER: {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          
+          case LDARG : {
+            push(new LoadInst(arguments[readU2(bytecodes, i)], "", currentBlock));
+            break;
+          }
+          
+          case LDARGA : {
+            push(arguments[readU2(bytecodes, i)]);
+            break;
+          }
+          
+          case LDFTN : {
+            Assembly* assembly = compilingClass->assembly;
+            N3* vm = (N3*)(VMThread::get()->vm);
+            uint32 token = readU4(bytecodes, i);
+            uint32 table = token >> 24;
+            if (table == CONSTANT_MethodDef) {
+              uint32 typeToken = assembly->getTypedefTokenFromMethod(token);
+              assembly->loadType(vm, typeToken, true, false,  false, true);
+              VMMethod* meth = assembly->lookupMethodFromToken(token);
+              if (!meth) VMThread::get()->vm->error("implement me");
+              Value* arg = new LoadInst(meth->llvmVar(), "", currentBlock);
+              push(arg);
+            } else {
+              VMThread::get()->vm->error("implement me");
+            }
+            break;
+          }
+
+          case INITBLK : {
+            Value* three = pop();
+            Value* two = pop();
+            Value* one = pop();
+            std::vector<Value*> args;
+            args.push_back(one);
+            args.push_back(two);
+            args.push_back(three);
+            new CallInst(mvm::jit::llvm_memset_i32,
+                         args.begin(), args.end(), "", currentBlock);
+            break;
+          }
+      
+          case LDLOC : {
+            push(new LoadInst(locals[readU2(bytecodes, i)], "", currentBlock));
+            break;
+          }
+          
+          case LOCALLOC : {
+            push(new AllocaInst(Type::Int8Ty, pop(), "", currentBlock));
+            break;
+          }
+          
+          case STARG : {
+            new StoreInst(pop(), arguments[readU2(bytecodes, i)], false, currentBlock);
+            break;
+          }
+          
+          case STLOC : {
+            Value* val = pop();
+            Value* local = locals[readU2(bytecodes, i)];
+            store(val, local, false, currentBlock);
+            break;
+          }
+          
+          case LDLOCA : {
+            push(locals[readU2(bytecodes, i)]);
+            break;
+          }
+      
+          case ARGLIST : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+      
+          case INITOBJ : {
+            VMThread::get()->vm->error("implement me");
+            break;  
+          }
+          
+          case LDVIRTFTN : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          
+          case REFANYTYPE : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          
+          case RETHROW : {
+            std::vector<Value*> args;
+            if (opinfo->exception) {
+              args.push_back(opinfo->exception);
+            } else {
+              args.push_back(CLIJit::constantVMObjectNull);
+            }
+            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 SIZEOF : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          default :
+            VMThread::get()->vm->unknownError("unknown bytecode");
+        } 
+        break;
+      }
+
+      default :
+        VMThread::get()->vm->unknownError("unknown bytecode");
+    } 
+  }
+}
+
+void CLIJit::exploreOpcodes(uint8* bytecodes, uint32 codeLength) {
+  for(uint32 i = 0; i < codeLength; ++i) {
+    
+    if (bytecodes[i] != 0xFE) {
+      PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i,
+                  bytecodes[i]);
+      PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "exploring %s::", compilingMethod->printString());
+      PRINT_DEBUG(N3_COMPILE, 1, LIGHT_CYAN, OpcodeNames[bytecodes[i]]);
+      PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "\n");
+    }
+    
+    switch (bytecodes[i]) {
+      
+      case ADD:
+      case ADD_OVF:
+      case ADD_OVF_UN:
+      case AND: break;
+      
+#define TEST(name, read, offset) case name : { \
+        uint32 tmp = i; \
+        uint16 index = tmp + offset + read(bytecodes, i); \
+        if (!(opcodeInfos[index].newBlock)) \
+          opcodeInfos[index].newBlock = createBasicBlock("Branches"); \
+        break; \
+      }
+      
+      TEST(BEQ, readS4, 5);
+      TEST(BEQ_S, readS1, 2);
+      
+      TEST(BGE, readS4, 5);
+      TEST(BGE_S, readS1, 2);
+      TEST(BGE_UN, readS4, 5);
+      TEST(BGE_UN_S, readS1, 2);
+      
+      TEST(BGT, readS4, 5);
+      TEST(BGT_S, readS1, 2);
+      TEST(BGT_UN, readS4, 5);
+      TEST(BGT_UN_S, readS1, 2);
+
+      TEST(BLE, readS4, 5);
+      TEST(BLE_S, readS1, 2);
+      TEST(BLE_UN, readS4, 5);
+      TEST(BLE_UN_S, readS1, 2);
+      
+      TEST(BLT, readS4, 5);
+      TEST(BLT_S, readS1, 2);
+      TEST(BLT_UN, readS4, 5);
+      TEST(BLT_UN_S, readS1, 2);
+      
+      TEST(BNE_UN, readS4, 5);
+      TEST(BNE_UN_S, readS1, 2);
+
+      case BR : {
+        uint32 tmp = i;
+        uint16 index = tmp + 5 + readS4(bytecodes, i);
+        if (!(opcodeInfos[index].newBlock))
+          opcodeInfos[index].newBlock = createBasicBlock("BR");
+        break;
+      }
+      
+      case BR_S : {
+        uint32 tmp = i;
+        uint16 index = tmp + 2 + readS1(bytecodes, i);
+        if (!(opcodeInfos[index].newBlock))
+          opcodeInfos[index].newBlock = createBasicBlock("BR");
+        break;
+      }
+
+      case BREAK: break;
+
+      TEST(BRFALSE, readS4, 5);
+      TEST(BRFALSE_S, readS1, 2);
+      TEST(BRTRUE, readS4, 5);
+      TEST(BRTRUE_S, readS1, 2);
+
+#undef TEST
+      
+      case CALL: {
+        i+= 4;
+        break;
+      }
+
+      case CALLI: {
+        VMThread::get()->vm->unknownError("implement me");
+        break;
+      }
+
+      case CKFINITE : {
+        VMThread::get()->vm->unknownError("implement me");
+        break;
+      }
+
+      case CONV_I1 :
+      case CONV_I2 :
+      case CONV_I4 :
+      case CONV_I8 :
+      case CONV_R4 :
+      case CONV_R8 :
+      case CONV_U1 :
+      case CONV_U2 :
+      case CONV_U4 :
+      case CONV_U8 :
+      case CONV_I :
+      case CONV_U :
+      case CONV_R_UN :
+      case CONV_OVF_I1 :
+      case CONV_OVF_I2 :
+      case CONV_OVF_I4 :
+      case CONV_OVF_I8 :
+      case CONV_OVF_U1 :
+      case CONV_OVF_U2 :
+      case CONV_OVF_U4 :
+      case CONV_OVF_U8 :
+      case CONV_OVF_I :
+      case CONV_OVF_U :
+      case CONV_OVF_I1_UN :
+      case CONV_OVF_I2_UN :
+      case CONV_OVF_I4_UN :
+      case CONV_OVF_I8_UN :
+      case CONV_OVF_U1_UN :
+      case CONV_OVF_U2_UN :
+      case CONV_OVF_U4_UN :
+      case CONV_OVF_U8_UN :
+      case DIV:
+      case DIV_UN:
+      case DUP:
+      case ENDFINALLY : break;
+      
+      case JMP : {
+        VMThread::get()->vm->error("implement me"); 
+        break;
+      }
+ 
+      case LDARG_S : {
+        i+= 1;
+        break;
+      }
+
+      case LDARG_0 :
+      case LDARG_1 :
+      case LDARG_2 :
+      case LDARG_3 : break;
+
+      case LDARGA_S : {
+        i += 1;
+        break;
+      }
+
+      case LDC_I4 : {
+        i += 4;
+        break;
+      }
+      
+      case LDC_I8 : {
+        i += 8;
+        break;
+      }
+      
+      case LDC_R4 : {
+        i += 4;
+        break;
+      }
+      
+      case LDC_R8 : {
+        i += 8;
+        break;
+      }
+      
+      case LDC_I4_0 :
+      case LDC_I4_1 :
+      case LDC_I4_2 :
+      case LDC_I4_3 :
+      case LDC_I4_4 :
+      case LDC_I4_5 :
+      case LDC_I4_6 :
+      case LDC_I4_7 :
+      case LDC_I4_8 :
+      case LDC_I4_M1 : break;
+      
+      case LDC_I4_S : {
+        i += 1;
+        break;
+      }
+ 
+      case LDIND_U1 :
+      case LDIND_I1 :
+      case LDIND_U2 :
+      case LDIND_I2 :
+      case LDIND_U4 :
+      case LDIND_I4 :
+      case LDIND_I8 :
+      case LDIND_R4 :
+      case LDIND_R8 :
+      case LDIND_I : break;
+      
+      case LDIND_REF : {
+        break;
+      }
+ 
+      case LDLOC_S : {
+        i += 1;
+        break;
+      }
+      
+      case LDLOC_0 :
+      case LDLOC_1 :
+      case LDLOC_2 :
+      case LDLOC_3 : break;
+      
+      case LDLOCA_S : {
+        i += 1;
+        break;
+      }
+      
+      case LDNULL : break;
+
+      case LEAVE : {
+        uint32 tmp = i;
+        uint32 value = readS4(bytecodes, i);
+        uint32 index = tmp + 5 + value;
+        if (!(opcodeInfos[index].newBlock))
+          opcodeInfos[index].newBlock = createBasicBlock("LEAVE");
+        leaves.push_back(opcodeInfos[index].newBlock);
+        break;
+      }
+      
+      case LEAVE_S : {
+        uint32 tmp = i;
+        uint8 value = readS1(bytecodes, i);
+        uint32 index = tmp + 2 + value;
+        if (!(opcodeInfos[index].newBlock))
+          opcodeInfos[index].newBlock = createBasicBlock("LEAVE_S");
+        leaves.push_back(opcodeInfos[index].newBlock);
+        break;
+      }
+
+      case MUL :
+      case MUL_OVF :
+      case MUL_OVF_UN :
+      case NEG :
+      case NOP :
+      case NOT :
+      case OR :
+      case POP :
+      case REM :
+      case REM_UN :
+      case RET :
+      case SHL :
+      case SHR :
+      case SHR_UN : break;
+      
+      case STARG_S : {
+        i += 1;
+        break;
+      }
+
+      case STIND_I1 :
+      case STIND_I2 :
+      case STIND_I4 :
+      case STIND_I8 :
+      case STIND_R4 :
+      case STIND_R8 :
+      case STIND_I :
+      case STIND_REF : break;
+      
+      case STLOC_S : {
+        i += 1;
+        break;
+      }
+      
+      case STLOC_0 :
+      case STLOC_1 :
+      case STLOC_2 :
+      case STLOC_3 :
+      case SUB :
+      case SUB_OVF :
+      case SUB_OVF_UN : break;
+
+      case SWITCH : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case XOR : break;
+
+      case BOX : {
+        i += 4;
+        break; 
+      }
+
+      case CALLVIRT : {
+        i += 4;
+        break; 
+      }
+
+      case CASTCLASS : {
+        i += 4;
+        break;  
+      }
+
+      case CPOBJ : {
+        VMThread::get()->vm->error("implement me");
+        break;  
+      }
+       
+      case ISINST : {
+        i += 4;
+        break;  
+      }
+      
+      case LDELEM : {
+        VMThread::get()->vm->error("implement me");
+        break;  
+      }
+      
+      case LDELEM_I1 : {
+        VMThread::get()->vm->error("implement me");
+        break;  
+      }
+
+      case LDELEM_I2 :
+      case LDELEM_I4 :
+      case LDELEM_I8 :
+      case LDELEM_U1 :
+      case LDELEM_U2 :
+      case LDELEM_U4 :
+      case LDELEM_R4 :
+      case LDELEM_R8 :
+      case LDELEM_I :
+      case LDELEM_REF :
+      case LDELEMA : break;
+
+      case LDFLD : {
+        i += 4;
+        break;
+      }
+      
+      case LDFLDA : {
+        i += 4;
+        break;
+      }
+
+      case LDLEN : break;
+
+      case LDOBJ : {
+        i += 4;
+        break;
+      }
+
+      case LDSFLD : {
+        i += 4;
+        break;
+      }
+      
+      case LDSFLDA : {
+        i += 4;
+        break;
+      }
+
+      case LDSTR : {
+        i += 4;
+        break;
+      }
+
+      case LDTOKEN : {
+        i += 4;
+        break;
+      }
+      
+      case MKREFANY : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case NEWARR : {
+        i += 4;
+        break;
+      }
+
+      case NEWOBJ : {
+        i += 4;
+        break;
+      }
+      
+      case REFANYVAL : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+      
+      case STELEM : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case STELEM_I1 :
+      case STELEM_I2 :
+      case STELEM_I4 :
+      case STELEM_I8 :
+      case STELEM_R4 :
+      case STELEM_R8 :
+      case STELEM_I :
+      case STELEM_REF : break;
+
+      case STFLD : {
+        i += 4;
+        break;
+      }
+
+      case STOBJ : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case STSFLD : {
+        i += 4;
+        break;
+      }
+
+      case THROW : {
+        break;
+      }
+
+      case UNBOX : {
+        i += 4;
+        break;
+      }
+      
+      case UNBOX_ANY : {
+        VMThread::get()->vm->error("implement me");
+        break;
+      }
+
+      case 0xFE : {
+      
+        PRINT_DEBUG(N3_COMPILE, 1, COLOR_NORMAL, "\t[at %5d] %-5d ", i,
+                    bytecodes[i + 1]);
+        PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "exploring ");
+        PRINT_DEBUG(N3_COMPILE, 1, LIGHT_CYAN, OpcodeNamesFE[bytecodes[i + 1]]);
+        PRINT_DEBUG(N3_COMPILE, 1, LIGHT_BLUE, "\n");
+      
+        switch (bytecodes[++i]) {
+
+          case CEQ:
+          case CGT:
+          case CGT_UN:
+          case CLT:
+          case CLT_UN:
+          case CPBLK : break;
+      
+          case ENDFILTER: {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          
+          case LDARG : {
+            i += 2;
+            break;
+          }
+          
+          case LDARGA : {
+            i += 2;
+            break;
+          }
+          
+          case LDFTN : {
+            i += 4;
+            break;
+          }
+
+          case INITBLK : break;
+      
+          case LDLOC : {
+            i += 2;
+            break;
+          }
+          
+          case LOCALLOC : break;
+          
+          case STARG : {
+            i += 2;
+            break;
+          }
+          
+          case STLOC : {
+            i += 2;
+            break;
+          }
+          
+          case LDLOCA : {
+            i += 2;
+            break;
+          }
+      
+          case ARGLIST : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+      
+          case INITOBJ : {
+            VMThread::get()->vm->error("implement me");
+            break;  
+          }
+          
+          case LDVIRTFTN : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          
+          case REFANYTYPE : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          
+          case RETHROW : {
+            break;
+          }
+        
+          case SIZEOF : {
+            VMThread::get()->vm->error("implement me");
+            break;
+          }
+          default :
+            VMThread::get()->vm->unknownError("unknown bytecode");
+        } 
+        break;
+      }
+      
+      default :
+        VMThread::get()->vm->unknownError("unknown bytecode");
+    }
+  }
+}
diff --git a/vmkit/lib/N3/VMCore/PNetLib.cpp b/vmkit/lib/N3/VMCore/PNetLib.cpp
new file mode 100644
index 0000000..3bb69c4
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/PNetLib.cpp
@@ -0,0 +1,1180 @@
+//===--------------- PNetLib.cpp - PNetLib interface ----------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <math.h>
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+#include "mvm/JIT.h"
+
+#include "Assembly.h"
+#include "CLIAccess.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "NativeUtil.h"
+#include "N3.h"
+#include "PNetLib.h"
+#include "Reader.h"
+#include "VMArray.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+#define IL_CONSOLE_NORMAL 0
+
+
+#define MEMBER_TYPES_CONSTRUCTOR 0x1
+#define MEMBER_TYPES_EVENT 0x2
+#define MEMBER_TYPES_FIELD 0x4
+#define MEMBER_TYPES_METHOD 0x8
+#define MEMBER_TYPES_PROPERTY 0x10
+#define MEMBER_TYPES_TYPEINFO 0x20
+#define MEMBER_TYPES_CUSTOM 0x40
+#define MEMBER_TYPES_NESTEDTYPE 0x80
+#define MEMBER_TYPES_ALL 0xBF
+
+#define METHOD_SEMANTIC_ATTRIBUTES_SETTER   0x1
+#define METHOD_SEMANTIC_ATTRIBUTES_GETTER   0x2
+#define METHOD_SEMANTIC_ATTRIBUTES_OTHER    0x4
+#define METHOD_SEMANTIC_ATTRIBUTES_ADDON    0x8
+#define METHOD_SEMANTIC_ATTRIBUTES_REMOVEON 0x10
+#define METHOD_SEMANTIC_ATTRIBUTES_FIRE     0x20
+
+
+typedef uint32 (*uint32_void)(void);
+typedef sint32 (*sint32_sint32)(sint32);
+typedef char* (*string_void)(void);
+typedef sint32 (*sint32_ptr_sint32_ptr_sint32)(uint16*, sint32, uint8*, sint32);
+typedef void (*void_ptr_sint32)(void*, sint32);
+typedef char (*char_sint32)(sint32);
+typedef sint64 (*sint64_ptr)(void*);
+typedef uint32 (*uint32_ptr_ptr_uint32)(void*, void*, uint32);
+typedef sint32 (*sint32_ptr_ptr_sint32)(void*, void*, sint32);
+
+static void* pnetLibSupport;
+static void* pnetLibStdio;
+static void* pnetLibTime;
+static uint32_void ILGetCodePage;
+static uint32_void ILGetCultureID;
+static string_void ILGetCultureName;
+static sint32_sint32 ILAnsiGetMaxByteCount;
+static sint32_sint32 ILConsoleWriteChar;
+static uint32_void ILConsoleGetMode;
+static sint32_ptr_sint32_ptr_sint32 ILAnsiGetBytes;
+static void_ptr_sint32 StdFlush;
+static char_sint32 ILGetUnicodeCategory;
+static sint64_ptr ILTimeMethodsGetCurrentTime;
+static uint32_ptr_ptr_uint32 ILUnicodeStringToLower;
+static sint32_ptr_ptr_sint32 ILUnicodeStringCompareIgnoreCase;
+static sint32_ptr_ptr_sint32 ILUnicodeStringCompareNoIgnoreCase;
+
+extern "C" void System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray(
+                                               VMArray* array, VMField* field) {
+  if (!array || !field) return;
+
+  VMClass* type = field->classDef;
+  VMClassArray* ts = (VMClassArray*)array->classOf;
+  VMCommonClass* bs = ts->baseClass;
+  Assembly* ass = type->assembly;
+
+  uint32 rva = ass->getRVAFromField(field->token);
+  Section* rsrcSection = ass->rsrcSection;
+
+  uint32 size = array->size;
+  uint32 offset = rsrcSection->rawAddress + (rva - rsrcSection->virtualAddress);
+  ArrayUInt8* bytes = ass->bytes;
+
+  if (bs == N3::pChar) {
+    for (uint32 i = 0; i < size; ++i) {
+      ((uint16*)(void*)(array->elements))[i] = READ_U2(bytes, offset);
+    }
+  } else if (bs == N3::pSInt32) {
+    for (uint32 i = 0; i < size; ++i) {
+      ((sint32*)(void*)(array->elements))[i] = READ_U4(bytes, offset);
+    }
+  } else if (bs == N3::pDouble) {
+    for (uint32 i = 0; i < size; ++i) {
+      ((double*)(void*)(array->elements))[i] = READ_U8(bytes, offset);
+    }
+  } else {
+    VMThread::get()->vm->error("implement me");
+  }
+}
+
+extern "C" VMObject* System_Type_GetTypeFromHandle(VMCommonClass* cl) {
+  return cl->getClassDelegatee();
+}
+
+extern "C" void System_Threading_Monitor_Enter(VMObject* obj) {
+  obj->aquire();
+}
+
+extern "C" void System_Threading_Monitor_Exit(VMObject* obj) {
+  obj->unlock();
+}
+
+extern "C" uint32 System_Text_DefaultEncoding_InternalCodePage() {
+  return ILGetCodePage();
+}
+
+extern "C" VMObject* System_Reflection_Assembly_GetCallingAssembly() {
+  Assembly* ass = Assembly::getCallingAssembly();
+  assert(ass);
+  return ass->getAssemblyDelegatee();
+}
+
+extern "C" VMObject* System_Reflection_Assembly_GetExecutingAssembly() {
+  Assembly* ass = Assembly::getExecutingAssembly();
+  assert(ass);
+  return ass->getAssemblyDelegatee();
+}
+
+extern "C" uint32 System_Globalization_CultureInfo_InternalCultureID() {
+  return ILGetCultureID();
+}
+
+extern "C" VMObject* System_Globalization_CultureInfo_InternalCultureName() {
+  char* val = ILGetCultureName();
+  N3* vm = (N3*)(VMThread::get()->vm);
+  if (val) {
+    VMObject* ret = vm->asciizToStr(val);
+    free(val);
+    return ret;
+  } else {
+    VMObject* ret = vm->asciizToStr("iv");
+    return ret;
+  }
+}
+
+extern "C" void System_Reflection_Assembly_LoadFromFile() {
+  VMThread::get()->vm->error("implement me");
+}
+
+static const UTF8* newBuilder(N3* vm, CLIString* value, uint32 length) {
+  uint32 valueLength = value ? value->length : 0;
+  const UTF8* utf8 = value ? value->value : 0;
+  uint32 roundLength = (7 + length) & 0xfffffff8;
+  uint16* buf = (uint16*)alloca(roundLength * sizeof(uint16));
+  uint32 strLength = 0;
+
+  if (value != 0) {
+    if (valueLength <= roundLength) {
+      memcpy(buf, utf8->elements, valueLength * sizeof(uint16));
+      strLength = valueLength;
+    } else {
+      memcpy(buf, utf8->elements, roundLength * sizeof(uint16));
+      strLength = roundLength;
+    }
+  }
+
+  return vm->readerConstructUTF8(buf, strLength);
+
+}
+
+extern "C" VMObject* System_String_NewBuilder(CLIString* value, 
+                                               uint32 length) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  CLIString* str = (CLIString*)vm->UTF8ToStr(newBuilder(vm, value, length));
+  return str;
+}
+
+extern "C" VMObject* Platform_SysCharInfo_GetNewLine() {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  return vm->asciizToStr("\n");
+}
+
+extern "C" void System_String_CopyToChecked(CLIString* str, sint32 sstart, 
+                                            ArrayUInt16* dest, sint32 dstart,
+                                            sint32 count) {
+  const UTF8* value = str->value;
+  memcpy(&dest->elements[dstart], &value->elements[sstart], count << 1);
+}
+
+extern "C" sint32 System_Text_DefaultEncoding_InternalGetMaxByteCount(sint32 val) {
+  return ILAnsiGetMaxByteCount(val);
+}
+
+extern "C" void Platform_Stdio_StdWrite(sint32 fd, ArrayUInt8* value, 
+                                        sint32 index, sint32 count) {
+  if (fd == 1) {
+    if (ILConsoleGetMode() == IL_CONSOLE_NORMAL) {
+      fwrite(&value->elements[index], 1, count, stdout);
+    } else {
+      char* buf = (char*)(&value->elements[index]);
+      while (count > 0) {
+        ILConsoleWriteChar(*buf);
+        ++buf;
+        --count;
+      }
+      fflush(stdout);
+    }
+  } else {
+    fwrite(&value->elements[index], 1, count, stderr);
+  }
+}
+
+extern "C" sint32 System_Text_DefaultEncoding_InternalGetBytes(ArrayUInt16* chars,
+            sint32 charIndex, sint32 charCount, ArrayUInt8* bytes, sint32 byteIndex) {
+  
+  return ILAnsiGetBytes(&chars->elements[charIndex], charCount, &bytes->elements[byteIndex], bytes->size - byteIndex);
+}
+
+extern "C" void Platform_Stdio_StdFlush(sint32 fd) {
+  StdFlush(0, fd);
+}
+
+extern "C" void System_Array_InternalCopy(VMArray* src, sint32 sstart, 
+                                          VMArray* dst, sint32 dstart, 
+                                          sint32 len) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  verifyNull(src);
+  verifyNull(dst);
+  
+  if (!(src->classOf->isArray && dst->classOf->isArray)) {
+    vm->arrayStoreException();
+  }
+  
+  VMClassArray* ts = (VMClassArray*)src->classOf;
+  VMClassArray* td = (VMClassArray*)dst->classOf;
+  VMCommonClass* dstType = td->baseClass;
+  VMCommonClass* srcType = ts->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);
+  } 
+  
+  bool doThrow = false;
+  
+  if (srcType->super == N3::pValue && srcType != dstType) {
+    vm->arrayStoreException();
+  } else if (srcType->super != N3::pValue && srcType->super != N3::pEnum) {
+    sint32 i = sstart;
+    while (i < sstart + len && !doThrow) {
+      VMObject* cur = ((ArrayObject*)src)->at(i);
+      if (cur) {
+        if (!(cur->classOf->isAssignableFrom(dstType))) {
+          doThrow = true;
+          len = i;
+        }
+      }
+      ++i;
+    }
+  }
+  
+  
+  uint32 size = srcType->naturalType->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();
+  
+}
+
+extern "C" sint32 System_Array_GetRank(VMObject* arr) {
+  verifyNull(arr);
+  if (arr->classOf->isArray) {
+    return ((VMClassArray*)(arr->classOf))->dims;
+  } else {
+    VMThread::get()->vm->error("implement me");
+    return 0;
+  }
+}
+
+extern "C" sint32 System_Array_GetLength(VMObject* arr) {
+  verifyNull(arr);
+  if (arr->classOf->isArray) {
+    return ((VMArray*)arr)->size;
+  } else {
+    VMThread::get()->vm->error("implement me");
+    return 0;
+  }
+}
+
+extern "C" sint32 System_Array_GetLowerBound(VMObject* arr, sint32 dim) {
+  return 0;
+}
+
+extern "C" VMObject* System_Object_GetType(VMObject* obj) {
+  verifyNull(obj);
+  return obj->classOf->getClassDelegatee();
+}
+
+extern "C" VMObject* System_Reflection_ClrType_GetElementType(VMObject* Klass) {
+  VMCommonClass* cl = (VMCommonClass*)((*Klass)(N3::typeClrType).PointerVal);
+  if (!cl->isArray) {
+    VMThread::get()->vm->error("implement me");
+    return 0;
+  } else {
+    return ((VMClassArray*)cl)->baseClass->getClassDelegatee();
+  }
+}
+
+extern "C" CLIString* System_String_NewString(uint32 size) {
+  CLIString* str = (CLIString*)(N3::pString->doNew());
+  str->length = size;
+  return str;
+}
+
+extern "C" void System_String_Copy_3(CLIString* dest, sint32 pos, 
+                                     CLIString* src) {
+  ArrayUInt16* arr = ArrayUInt16::acons(pos + src->value->size, 
+                                        (VMClassArray*)N3::pChar);
+  
+  for (sint32 i = 0; i < pos; ++i) {
+    arr->setAt(i, dest->value->at(i));
+  }
+
+  for (sint32 i = 0; i < src->length; ++i) {
+    arr->setAt(pos + i, src->value->at(i));
+  }
+
+  dest->value = ((UTF8*)arr)->extract(VMThread::get()->vm, 0, pos + src->value->size);
+  dest->length = dest->value->size;
+}
+
+extern "C" void System_String_Copy_5(CLIString* dest, sint32 destPos, 
+                                     CLIString* src, sint32 srcPos, 
+                                     sint32 length) {
+  const UTF8* utf8Src = src->value->extract(VMThread::get()->vm, srcPos, 
+                                            srcPos + length);
+  if (destPos == 0) {
+    dest->value = utf8Src;
+    dest->length = dest->value->size;
+  } else {
+    const UTF8* utf8Dest = dest->value->extract(VMThread::get()->vm, 0, 
+                                                destPos);
+    sint32 len1 = utf8Dest->size;
+    sint32 len2 = utf8Src->size;
+    uint16* buf = (uint16*)alloca((len1 + len2) * sizeof(uint16));
+
+    memcpy(buf, utf8Dest->elements, len1 * sizeof(uint16));
+    memcpy(buf + len1, utf8Dest->elements, len2 * sizeof(uint16));
+
+    const UTF8* utf8 = VMThread::get()->vm->readerConstructUTF8(buf, 
+                                                                len1 + len2);
+    dest->value = utf8;
+    dest->length = dest->value->size;
+  }
+}
+
+extern "C" bool System_String_Equals(CLIString* str1, CLIString* str2) {
+  return str1->value == str2->value;
+}
+
+extern "C" VMObject* System_Threading_Thread_InternalCurrentThread() {
+  return VMThread::get()->vmThread;
+}
+
+extern "C" sint32 Platform_SysCharInfo_GetUnicodeCategory(char c) {
+  return ILGetUnicodeCategory(c);
+}
+
+extern "C" uint16 System_String_GetChar(CLIString* str, sint32 index) {
+  return str->value->at(index);
+}
+
+extern "C" sint32 System_String_IndexOf(CLIString* str, uint16 value, 
+                                        sint32 startIndex, sint32 count) {
+  if (startIndex < 0) {
+    VMThread::get()->vm->error("shoud throw arg range");
+  }
+
+  if ((count < 0) || (str->length - startIndex < count)) {
+    VMThread::get()->vm->error("shoud throw arg range");
+  }
+
+  sint32 i = startIndex;
+  const UTF8* utf8 = str->value;
+  while (i < startIndex + count) {
+    if (utf8->at(i) == value) return i;
+    else ++i;
+  }
+
+  return -1;
+}
+
+extern "C" sint32 System_String_GetHashCode(CLIString* str) {
+  sint32 hash = 0;
+  const UTF8* utf8 = str->value;
+  for (sint32 i = 0; i < utf8->size; ++i) {
+    hash += ((hash << 5) + utf8->elements[i]);
+  }
+  return hash;
+}
+
+extern "C" double System_Decimal_ToDouble(void* ptr) {
+  VMThread::get()->vm->error("implement me");
+  return 0.0;
+}
+
+extern "C" double System_Math_Log10(double val) {
+  return log10(val);
+}
+
+extern "C" double System_Math_Floor(double val) {
+  return floor(val);
+}
+
+extern "C" VMObject* System_Text_StringBuilder_Insert_System_Text_StringBuilder_System_Int32_System_Char(
+                                                      StringBuilder* obj,
+                                                      sint32 index, 
+                                                      uint16 value) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  CLIString* buildString = obj->buildString;
+  const UTF8* utf8 = buildString->value;
+  sint32 strLength = buildString->length;
+  sint32 length = (index + 1) > strLength ? index + 1 : strLength + 1;
+  uint16* buf = (uint16*)alloca(length * sizeof(uint16));
+
+  if (index != 0) {
+    memcpy(buf, utf8->elements, index * sizeof(uint16));
+  }
+
+  if (strLength > index) {
+    memcpy(&(buf[index + 1]), &(utf8->elements[index]), 
+               (strLength - index) * sizeof(uint16));
+  }
+
+  buf[index] = value;
+  CLIString* str = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length));
+  obj->buildString = str;
+  
+  return obj;
+}
+
+extern "C" VMObject* System_Text_StringBuilder_Insert_System_Text_StringBuilder_System_Int32_System_String(
+                                                      StringBuilder* obj,
+                                                      sint32 index, 
+                                                      CLIString* str) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  CLIString* buildString = obj->buildString;
+  const UTF8* strUtf8 = str->value;
+  const UTF8* buildUtf8 = buildString->value;
+  sint32 strLength = str->length;
+  sint32 buildLength = buildString->length;
+  sint32 length = strLength + buildLength;
+  uint16* buf = (uint16*)alloca(length * sizeof(uint16));
+
+  if (index != 0) {
+    memcpy(buf, buildUtf8->elements, index * sizeof(uint16));
+  }
+
+  if (strLength != 0) {
+    memcpy(&(buf[index]), strUtf8->elements, strLength * sizeof(uint16));
+  }
+    
+  if (buildLength - index > 0) {
+    memcpy(&(buf[strLength + index]), &(buildUtf8->elements[index]), 
+               (buildLength - index) * sizeof(uint16));
+  }
+
+  CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length));
+  obj->buildString = val;
+
+  return obj;
+}
+
+extern "C" VMObject* System_Text_StringBuilder_Append_System_Text_StringBuilder_System_Char(
+                                                StringBuilder* obj,
+                                                uint16 value) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  CLIString* buildString = obj->buildString;
+  const UTF8* utf8 = buildString->value;
+  sint32 length = buildString->length;
+  uint16* buf = (uint16*)alloca((length + 1) * sizeof(uint16));
+
+  memcpy(buf, utf8->elements, length * sizeof(uint16));
+
+  buf[length] = value;
+  CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length + 1));
+  obj->buildString = val;
+  return obj;
+}
+
+
+extern "C" VMObject* System_Text_StringBuilder_Append_System_Text_StringBuilder_System_String(
+                                                StringBuilder* obj,
+                                                CLIString* str) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  CLIString* buildString = obj->buildString;
+  const UTF8* buildUtf8 = buildString->value;
+  const UTF8* strUtf8 = str->value;
+  sint32 buildLength = buildString->length;
+  sint32 strLength = str->length;
+  sint32 length = buildLength + strLength;
+  uint16* buf = (uint16*)alloca(length * sizeof(uint16));
+
+  memcpy(buf, buildUtf8->elements, buildLength * sizeof(uint16));
+  memcpy(&(buf[buildLength]), strUtf8->elements, strLength * sizeof(uint16));
+
+  CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length));
+  obj->buildString = val;
+  return obj;
+}
+
+extern "C" sint32 System_String_FindInRange(CLIString* obj, sint32 srcFirst, 
+                                            sint32 srcLast, sint32 step,
+                                            CLIString* dest) {
+  uint16* buf1 = (uint16*)&(obj->value->elements[srcFirst]);
+  uint16* buf2 = (uint16*)(dest->value->elements);
+  sint32 destLength = dest->length;
+  sint32 size = destLength * sizeof(uint16);
+  
+  if (step > 0) {
+    if (destLength == 1) {
+      while (srcFirst <= srcLast) {
+        if (buf1[0]  == buf2[0]) {
+          return srcFirst;
+        } else {
+          buf1 = &(buf1[1]);
+          ++srcFirst; 
+        }
+      } 
+    } else {
+      while (srcFirst <= srcLast) {
+        if ((buf1[0] == buf2[0]) && !memcmp(buf1, buf2, size)) {
+          return srcFirst;
+        } else {
+          buf1 = &(buf1[1]);
+          ++srcFirst;
+        }
+      }
+    }
+  } else {
+    if (destLength == 1) {
+      while (srcFirst >= srcLast) {
+        if (buf1[0] == buf2[0]) {
+          return srcFirst;
+        } else {
+          buf1 = buf1 - 1;
+          --srcFirst;
+        }
+      }
+    } else {
+      while (srcFirst >= srcLast) {
+        if ((buf1[0] == buf2[0]) && !memcmp(buf1, buf2, size)) {
+          return srcFirst;
+        } else {
+          buf1 = buf1 - 1;
+          --srcFirst;
+        }
+      }
+    }
+  }
+  return -1;
+}
+
+extern "C" VMObject* System_Reflection_Assembly_LoadFromName(CLIString* str, sint32 & error, VMObject* parent) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  Assembly* ass = vm->loadAssembly(str->value, "dll");
+  if (!ass) vm->error("unfound assembly %s\n", str->value->printString());
+  error = 0;
+  return ass->getAssemblyDelegatee();
+}
+
+extern "C" CLIString* System_String_Concat_2(CLIString* str1, CLIString* str2) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  const UTF8* u1 = str1->value;
+  const UTF8* u2 = str2->value;
+  sint32 len1 = str1->length;
+  sint32 len2 = str2->length;
+  uint16* buf = (uint16*)alloca((len1 + len2) * sizeof(uint16));
+
+  memcpy(buf, u1->elements, len1 * sizeof(uint16));
+  memcpy(&(buf[len1]), u2->elements, len2 * sizeof(uint16));
+  
+  CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, len1 + len2));
+  
+  return val;
+}
+
+extern "C" CLIString* System_String_Concat_3(CLIString* str1, CLIString* str2, CLIString* str3) {
+  N3* vm = (N3*)(VMThread::get()->vm);
+  const UTF8* u1 = str1->value;
+  const UTF8* u2 = str2->value;
+  const UTF8* u3 = str3->value;
+  sint32 len1 = str1->length;
+  sint32 len2 = str2->length;
+  sint32 len3 = str3->length;
+  uint16* buf = (uint16*)alloca((len1 + len2 + len3) * sizeof(uint16));
+
+  memcpy(buf, u1->elements, len1 * sizeof(uint16));
+  memcpy(&(buf[len1]), u2->elements, len2 * sizeof(uint16));
+  memcpy(&(buf[len1 + len2]), u3->elements, len3 * sizeof(uint16));
+  
+  CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, len1 + len2 + len3));
+  
+  return val;
+}
+
+extern "C" void System_String_RemoveSpace(CLIString* str, sint32 index, sint32 length) {
+  const UTF8* utf8 = str->value;
+  sint32 strLength = str->length;
+  uint16* buf = (uint16*)alloca(strLength * sizeof(uint16));
+  sint32 j = index;
+
+  if (index != 0) {
+    memcpy(buf, utf8->elements, index * sizeof(uint16));
+  }
+  
+  // 32 is space
+  for (sint32 i = 0; i < length; ++i) {
+    uint16 cur = utf8->elements[index + i];
+    if (cur != 32) {
+      buf[j] = cur;
+    } else {
+      ++j;
+    }
+  }
+
+  if (strLength > (index + length)) {
+    memcpy(&(buf[j]), &(utf8->elements[index + length]), (strLength - (index + length)) * sizeof(uint16));
+  }
+
+  const UTF8* res = VMThread::get()->vm->readerConstructUTF8(buf, j);
+  str->value = res;
+  str->length = j;
+}
+
+extern "C" void System_String__ctor_3(CLIString* str, uint16 ch, sint32 count) {
+  ArrayUInt16* array = ArrayUInt16::acons(count, N3::arrayChar);
+  for (sint32 i = 0; i < count; ++i) {
+    array->elements[i] = ch;
+  }
+
+  const UTF8* utf8 = VMThread::get()->vm->readerConstructUTF8(array->elements, array->size);
+  str->value = utf8;
+  str->length = array->size;
+  str->capacity = array->size;
+}
+
+extern "C" int64_t Platform_TimeMethods_GetCurrentTime() {
+  return ILTimeMethodsGetCurrentTime(0);
+}
+
+#define ASSEMBLY_VALUE(obj) ((Assembly**)obj)[3]
+
+extern "C" VMObject* System_Reflection_Assembly_GetType(VMObject* obj, CLIString* str, bool onError, bool ignoreCase) {
+  Assembly* ass = ASSEMBLY_VALUE(obj);
+  const UTF8* utf8 = str->value;
+  char* asciiz = utf8->UTF8ToAsciiz();
+  char* index = (char*)memrchr(asciiz, '.', strlen(asciiz));
+  N3* vm = ass->vm;
+  
+  index[0] = 0;
+  ++index;
+  VMCommonClass* cl = ass->loadTypeFromName(vm->asciizConstructUTF8(index), vm->asciizConstructUTF8(asciiz), true, true, true, onError);
+  if (!cl) VMThread::get()->vm->error("implement me");
+  return cl->getClassDelegatee();
+}
+
+static bool parameterMatch(std::vector<VMCommonClass*> params, ArrayObject* types, bool virt) {
+  uint32 v = virt ? 1 : 0;
+  if (types->size + v + 1 != params.size()) return false;
+  for (sint32 i = 0; i < types->size; ++i) {
+    VMCommonClass* cur = (VMCommonClass*)(*N3::typeClrType)(types->elements[i]).PointerVal;
+    if (cur != params[i + 1 + v]) return false;
+  }
+  return true;
+}
+
+extern "C" VMObject* System_Reflection_ClrType_GetMemberImpl(VMObject* Type, CLIString* str, sint32 memberTypes, sint32 bindingFlags, VMObject* binder, 
+                                                   sint32 callingConventions, ArrayObject* types, VMObject* modifiers) {
+  VMCommonClass* type = (VMCommonClass*)((*N3::typeClrType)(Type).PointerVal);
+  const UTF8* name = str->value;
+  if (memberTypes == MEMBER_TYPES_PROPERTY) {
+    std::vector<Property*> properties = type->properties;
+    Property *res = 0;
+    for (std::vector<Property*>::iterator i = properties.begin(), 
+            e = properties.end(); i!= e; ++i) {
+      if ((*i)->name == name) {
+        res = *i; 
+        break;
+      }
+    }
+    if (res == 0) VMThread::get()->vm->error("implement me");
+    return res->getPropertyDelegatee();
+  } else if (memberTypes == MEMBER_TYPES_METHOD) {
+    std::vector<VMMethod*> virtualMethods = type->virtualMethods;
+    std::vector<VMMethod*> staticMethods = type->staticMethods;
+    
+    for (std::vector<VMMethod*>::iterator i = virtualMethods.begin(), 
+            e = virtualMethods.end(); i!= e; ++i) {
+      VMMethod* meth = *i;
+      if (meth->name == name) {
+        if (parameterMatch(meth->parameters, types, true)) {
+          return meth->getMethodDelegatee();
+        }
+      }
+    }
+    
+    for (std::vector<VMMethod*>::iterator i = staticMethods.begin(), 
+            e = staticMethods.end(); i!= e; ++i) {
+      VMMethod* meth = *i;
+      if (meth->name == name) {
+        if (parameterMatch(meth->parameters, types, false)) {
+          return meth->getMethodDelegatee();
+        }
+      }
+    }
+
+  } else {
+    VMThread::get()->vm->error("implement me");
+  }
+  return 0;
+}
+
+extern "C" VMObject* System_Reflection_ClrHelpers_GetSemantics(mvm::Object* item, uint32 attributes, bool nonPublic) {
+  if (item->getVirtualTable() == Property::VT) {
+    Property* prop = (Property*)item;
+    if (attributes == METHOD_SEMANTIC_ATTRIBUTES_GETTER) {
+      char* asciiz = prop->name->UTF8ToAsciiz();
+      char* buf = (char*)alloca(strlen(asciiz) + 5);
+      sprintf(buf, "get_%s", asciiz);
+      VirtualMachine* vm = VMThread::get()->vm;
+      VMMethod* meth = prop->type->lookupMethod(vm->asciizConstructUTF8(buf), prop->parameters, true, false);
+      assert(meth);
+      return meth->getMethodDelegatee();
+    }
+  } else {
+    VMThread::get()->vm->error("implement me");
+  }
+  return 0;
+}
+
+static void decapsulePrimitive(VMObject* arg, const llvm::Type* type, std::vector<llvm::GenericValue>& args) {
+  if (type == llvm::Type::Int1Ty) {
+    llvm::GenericValue gv;
+    gv.IntVal = llvm::APInt(1, (bool)((uint32*)arg)[VALUE_OFFSET]);
+    args.push_back(gv);
+  } else if (type == llvm::Type::Int8Ty) {
+    llvm::GenericValue gv;
+    gv.IntVal = llvm::APInt(8, (uint8)((uint32*)arg)[VALUE_OFFSET]);
+    args.push_back(gv);
+  } else if (type == llvm::Type::Int16Ty) {
+    llvm::GenericValue gv;
+    gv.IntVal = llvm::APInt(16, (uint16)((uint32*)arg)[VALUE_OFFSET]);
+    args.push_back(gv);
+  } else if (type == llvm::Type::Int32Ty) {
+    llvm::GenericValue gv;
+    gv.IntVal = llvm::APInt(32, (uint32)((uint32*)arg)[VALUE_OFFSET]);
+    args.push_back(gv);
+  } else if (type == llvm::Type::Int64Ty) {
+    llvm::GenericValue gv;
+    uint32* ptr = &((uint32*)arg)[VALUE_OFFSET];
+    gv.IntVal = llvm::APInt(64, ((uint64*)ptr)[0]);
+    args.push_back(gv);
+  } else if (type == llvm::Type::FloatTy) {
+    llvm::GenericValue gv;
+    float* ptr = &((float*)arg)[VALUE_OFFSET];
+    gv.FloatVal = ((float*)ptr)[0];
+    args.push_back(gv);
+  } else if (type == llvm::Type::DoubleTy) {
+    llvm::GenericValue gv;
+    uint32* ptr = &((uint32*)arg)[VALUE_OFFSET];
+    gv.DoubleVal = ((double*)ptr)[0];
+    args.push_back(gv);
+  } else if (type == llvm::PointerType::getUnqual(llvm::Type::Int8Ty)) {
+    llvm::GenericValue gv(((void**)arg)[VALUE_OFFSET]);
+    args.push_back(gv);
+  } else {
+    VMThread::get()->vm->error("implement me");
+  }
+}
+
+extern "C" VMObject* System_Reflection_ClrMethod_Invoke(VMObject* Method, VMObject* obj, sint32 invokeAttr, VMObject* binder, ArrayObject* args, VMObject* culture) {
+  VMMethod* meth = (VMMethod*)(*N3::methodMethodType)(Method).PointerVal;
+  meth->getSignature();
+  meth->compiledPtr();
+  llvm::Function* func = CLIJit::compile(meth->classDef, meth);
+  VMClass* type = meth->classDef;
+  type->resolveStatic(true);
+  uint32 virt = meth->virt;
+
+  if ((obj != 0) && virt) {
+    if (!(obj->classOf->isAssignableFrom(type))) {
+      VMThread::get()->vm->illegalArgumentException(meth->name->printString());
+    }
+    verifyNull(obj);
+  }
+    
+  std::vector<llvm::GenericValue> gvargs;
+  uint32 index = 0;
+  
+  llvm::Function::arg_iterator i = func->arg_begin();
+  llvm::Function::arg_iterator e = func->arg_end();
+  if (virt) {
+    llvm::GenericValue gv(obj);
+    gvargs.push_back(gv);
+    ++i;
+  }
+  
+  for ( ;i != e; ++i, ++index) {
+    const llvm::Type* type = i->getType();
+    if (llvm::isa<llvm::PointerType>(type) && type != llvm::PointerType::getUnqual(llvm::Type::Int8Ty)) {
+      llvm::GenericValue gv(args->elements[index]);
+      gvargs.push_back(gv);
+    } else {
+      decapsulePrimitive(args->elements[index], type, gvargs);
+    }
+  }
+  
+  llvm::GenericValue gv;
+  try{
+    gv = (*meth)(gvargs);
+  }catch(...) {
+    assert(0);
+  }
+  
+  VMObject* res = 0;
+  VMCommonClass* retType = meth->parameters[0];
+  if (retType == N3::pVoid) {
+    res = (*N3::pVoid)();
+  } else if (retType == N3::pBoolean) {
+    res = (*N3::pBoolean)();
+    (*N3::ctorBoolean)(res, gv.IntVal.getBoolValue());
+  } else if (retType == N3::pUInt8) {
+    res = (*N3::pUInt8)();
+    (*N3::ctorUInt8)(res, (uint8)gv.IntVal.getZExtValue());
+  } else if (retType == N3::pSInt8) {
+    res = (*N3::pSInt8)();
+    (*N3::ctorSInt8)(res, (uint8)gv.IntVal.getSExtValue());
+  } else if (retType == N3::pChar) {
+    res = (*N3::pChar)();
+    (*N3::ctorChar)(res, (uint16)gv.IntVal.getZExtValue());
+  } else if (retType == N3::pSInt16) {
+    res = (*N3::pSInt16)();
+    (*N3::ctorSInt16)(res, (sint16)gv.IntVal.getSExtValue());
+  } else if (retType == N3::pUInt16) {
+    res = (*N3::pUInt16)();
+    (*N3::ctorUInt16)(res, (uint16)gv.IntVal.getZExtValue());
+  } else if (retType == N3::pSInt32) {
+    res = (*N3::pSInt32)();
+    (*N3::ctorSInt32)(res, (sint32)gv.IntVal.getSExtValue());
+  } else if (retType == N3::pUInt32) {
+    res = (*N3::pUInt32)();
+    (*N3::ctorUInt32)(res, (sint32)gv.IntVal.getZExtValue());
+  } else if (retType == N3::pSInt64) {
+    res = (*N3::pSInt64)();
+    (*N3::ctorSInt64)(res, (sint64)gv.IntVal.getSExtValue());
+  } else if (retType == N3::pUInt64) {
+    res = (*N3::pUInt64)();
+    (*N3::ctorUInt64)(res, (sint64)gv.IntVal.getZExtValue());
+  } else if (retType == N3::pIntPtr) {
+    res = (*N3::pIntPtr)();
+    (*N3::ctorIntPtr)(res, (void*)gv.IntVal.getSExtValue());
+  } else if (retType == N3::pUIntPtr) {
+    res = (*N3::pUIntPtr)();
+    (*N3::ctorUIntPtr)(res, (void*)gv.IntVal.getZExtValue());
+  } else if (retType == N3::pFloat) {
+    res = (*N3::pFloat)();
+    (*N3::ctorFloat)(res, gv.FloatVal);
+  } else if (retType == N3::pDouble) {
+    res = (*N3::pDouble)();
+    (*N3::ctorDouble)(res, gv.DoubleVal);
+  } else {
+    if (retType->super == N3::pValue || retType->super == N3::pEnum)
+      VMThread::get()->vm->error("implement me");
+    res = (VMObject*)gv.PointerVal;
+  }
+  
+  return res;
+}
+
+
+static VMObject* createResourceStream(Assembly* ass, sint32 posn) {
+  uint32 resSize = ass->resSize;
+  uint32 resRva = ass->resRva;
+  Section* textSection = ass->textSection;
+  uint32 sectionLen = resSize;
+  uint32 section = 0;
+  uint32 start = 0;
+  uint32 length = 0;
+  uint32 pad = 0;
+  
+  Reader* reader = Reader::allocateReader(ass->bytes);
+  section = textSection->rawAddress + (resRva - textSection->virtualAddress);
+
+  reader->seek(section, Reader::SeekSet);
+  while (posn > 0) {
+    if (sectionLen < 4) return 0;
+    length = reader->readU4();
+    if (length > (sectionLen - 4)) return 0;
+    if ((length % 4) != 0) {
+      pad = 4 - (length % 4);
+    } else {
+      pad = 0;
+    }
+    start = start + length + pad + 4;
+    section = section + length + pad + 4;
+    reader->seek(section + length + pad + 4, Reader::SeekSet);
+    sectionLen = sectionLen - (length + pad + 4);
+    posn = posn - 1;
+  }
+
+  start = start + 4;
+  if (sectionLen < 4) return 0;
+  length = reader->readU4();
+  if (length > (sectionLen - 4)) return 0;
+
+  VMObject* res = (*N3::resourceStreamType)();
+  (*N3::ctorResourceStreamType)(res, ass, (uint64)start, (uint64)length);
+
+  return res;
+}
+      
+extern "C" VMObject* System_Reflection_Assembly_GetManifestResourceStream(VMObject* Ass, CLIString* str) {
+  Assembly* ass = (Assembly*)(*N3::assemblyAssemblyReflection)(Ass).PointerVal;
+  const UTF8* utf8 = str->value;
+  Header* header = ass->CLIHeader;
+  uint32 stringOffset = header->stringStream->realOffset;
+  Table* manTable  = header->tables[CONSTANT_ManifestResource];
+  uint32 manRows   = manTable->rowsNumber;
+  sint32 pos = -1;
+  uint32 i = 0;
+  VirtualMachine* vm = VMThread::get()->vm;
+  
+  while ((pos == -1) && (i < manRows)) {
+    uint32 nameOffset = manTable->readIndexInRow(i + 1, CONSTANT_MANIFEST_RESOURCE_NAME, ass->bytes);
+    const UTF8* name = ass->readString(vm, stringOffset + nameOffset);
+
+    if (name == utf8) {
+      pos = i;
+    } else {
+      ++i;
+    }
+  }
+
+  if (pos != -1) {
+    return createResourceStream(ass, pos);
+  } else {
+    return 0;
+  }
+}
+
+
+extern "C" ArrayObject* System_Reflection_ClrHelpers_GetCustomAttributes(Assembly* ass, VMCommonClass* clrTypePrivate, bool inherit) {
+  return ass->getCustomAttributes(clrTypePrivate->token, clrTypePrivate);
+}
+
+extern "C" VMObject* System_Globalization_TextInfo_ToLower(VMObject* obj, CLIString* str) {
+  verifyNull(str);
+  const UTF8* utf8 = str->value;
+  uint32 length = str->length;
+
+  uint16* buf = (uint16*)alloca(length * sizeof(uint16));
+
+  VirtualMachine* vm = VMThread::get()->vm;
+
+  memcpy(buf, utf8->elements, length * sizeof(uint16));
+  ILUnicodeStringToLower((void*)buf, (void*)utf8->elements, length);
+  const UTF8* res = vm->readerConstructUTF8(buf, length);
+  return ((N3*)vm)->UTF8ToStr(res);
+}
+
+extern "C" VMObject* System_String_Replace(CLIString* str, uint16 c1, uint16 c2) {
+  const UTF8* utf8 = str->value;
+  uint32 length = str->length;
+  if ((c1 == c2) || length == 0) return str;
+
+  uint16* buf = (uint16*)alloca(length * sizeof(uint16));
+  memcpy(buf, utf8->elements, length * sizeof(uint16));
+  for (uint32 i = 0; i < length; ++i) {
+    if (buf[i] == c1) buf[i] = c2;
+  }
+  
+  N3* vm = (N3*)VMThread::get()->vm;
+  const UTF8* res = vm->readerConstructUTF8(buf, length);
+  return vm->UTF8ToStr(res);
+}
+
+// LLVM Bug
+#if defined (__PPC__) && !defined (__MACH__)
+extern "C" uint32 System_Reflection_ClrResourceStream_ResourceRead(Assembly* assembly, uint32 position1, uint32 position2, ArrayUInt8* buffer, uint32 offset, uint32 count) {
+  uint64 position = position1 << 32 + position2;
+#else
+extern "C" uint32 System_Reflection_ClrResourceStream_ResourceRead(Assembly* assembly, uint64 position, ArrayUInt8* buffer, uint32 offset, uint32 count) {
+#endif
+  uint32 resRva = assembly->resRva;
+  ArrayUInt8* bytes = assembly->bytes;
+  Section* textSection = assembly->textSection;
+  uint32 section = 0;
+
+  section = textSection->rawAddress + (resRva - textSection->virtualAddress);
+  memcpy(&(buffer->elements[offset]), &(bytes->elements[section + position]), count);
+
+  return count;
+}
+
+extern "C" sint32 System_String_CompareInternal(CLIString* strA, sint32 indexA, sint32 lengthA, CLIString* strB, sint32 indexB, sint32 lengthB, bool ignoreCase) {
+  if (strA == 0) {
+    if (strB == 0) {
+      return 0;
+    }
+    return -1;
+  } else if (strB == 0) {
+    return 1;
+  } else {
+    sint32 cmp = 0;
+    if (lengthA >= lengthB) {
+      if (ignoreCase) {
+        cmp = ILUnicodeStringCompareIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthB);
+      } else {
+        cmp = ILUnicodeStringCompareNoIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthB);
+      }
+
+      if (cmp != 0) return cmp;
+      else if (lengthA > lengthB) return 1;
+      else return 0;
+    } else {
+      if (ignoreCase) {
+        cmp = ILUnicodeStringCompareIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthA);
+      } else {
+        cmp = ILUnicodeStringCompareNoIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthA);
+      }
+
+      if (cmp != 0) return cmp;
+      else return -1;
+    }
+  }
+}
+
+extern "C" void System_String_CharFill(CLIString* str, sint32 start, sint32 count, char ch) {
+  const UTF8* utf8 = str->value;
+  sint32 length = start + count;
+  uint16* buf = (uint16*)alloca(length * sizeof(uint16));
+
+  memcpy(buf, utf8->elements, start * sizeof(uint16));
+  for (sint32 i = 0; i < count; ++i) {
+    buf[i + start] = ch;
+  }
+  
+  VirtualMachine* vm = VMThread::get()->vm;
+  const UTF8* val = vm->readerConstructUTF8(buf, length);
+  str->value = val;
+  str->length = length;
+}
+
+
+extern "C" sint32 System_String_InternalOrdinal(CLIString *strA, sint32 indexA, sint32 lengthA,
+						CLIString *strB, sint32 indexB, sint32 lengthB) {
+	const uint16 *bufA;
+	const uint16 *bufB;
+
+	/* Handle the easy cases first */
+	if(!strA)
+	{
+		if(!strB)
+		{
+			return 0;
+		}
+		else
+		{
+			return -1;
+		}
+	}
+	else if(!strB)
+	{
+		return 1;
+	}
+
+	/* Compare the two strings */
+	bufA = &(strA->value->elements[indexA]);
+	bufB = &(strB->value->elements[indexB]);
+	while(lengthA > 0 && lengthB > 0)
+	{
+		if(*bufA < *bufB)
+		{
+			return -1;
+		}
+		else if(*bufA > *bufB)
+		{
+			return 1;
+		}
+		++bufA;
+		++bufB;
+		--lengthA;
+		--lengthB;
+	}
+
+	/* Determine the ordering based on the tail sections */
+	if(lengthA > 0)
+	{
+		return 1;
+	}
+	else if(lengthB > 0)
+	{
+		return -1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+extern "C" void System_GC_Collect() {
+  gc::collect();
+}
+
+
+
+void NativeUtil::initialise() {
+  void* p;
+  p = (void*)&System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray;
+  p = (void*)&System_Type_GetTypeFromHandle;
+  pnetLibSupport  = dlopen("libILSupport.so", RTLD_LAZY | RTLD_GLOBAL);
+  if (!pnetLibSupport) {
+    printf("error = %s\n", dlerror());
+  }
+  pnetLibStdio    = dlopen("libStdio.so", RTLD_LAZY | RTLD_GLOBAL);
+  pnetLibTime  = dlopen("libTime.so", RTLD_LAZY | RTLD_GLOBAL);
+  ILGetCodePage = (uint32_void)dlsym(pnetLibSupport, "ILGetCodePage");
+  assert(ILGetCodePage);
+  ILGetCultureID = (uint32_void)dlsym(pnetLibSupport, "ILGetCultureID");
+  assert(ILGetCultureID);
+  ILGetCultureName = (string_void)dlsym(pnetLibSupport, "ILGetCultureName");
+  assert(ILGetCultureName);
+  ILAnsiGetMaxByteCount = (sint32_sint32)dlsym(pnetLibSupport, "ILAnsiGetMaxByteCount");
+  assert(ILAnsiGetMaxByteCount);
+  ILConsoleGetMode = (uint32_void)dlsym(pnetLibSupport, "ILConsoleGetMode");
+  assert(ILConsoleGetMode);
+  ILConsoleWriteChar = (sint32_sint32)dlsym(pnetLibSupport, "ILConsoleWriteChar");
+  assert(ILConsoleWriteChar);
+  ILUnicodeStringToLower = (uint32_ptr_ptr_uint32)dlsym(pnetLibSupport, "ILUnicodeStringToLower");
+  assert(ILUnicodeStringToLower);
+  ILAnsiGetBytes = (sint32_ptr_sint32_ptr_sint32)dlsym(pnetLibSupport, "ILAnsiGetBytes");
+  assert(ILAnsiGetBytes);
+  StdFlush = (void_ptr_sint32)dlsym(pnetLibStdio, "_IL_Stdio_StdFlush");
+  assert(StdFlush);
+  ILGetUnicodeCategory = (char_sint32)dlsym(pnetLibSupport, "ILGetUnicodeCategory");
+  assert(ILGetUnicodeCategory);
+  ILTimeMethodsGetCurrentTime = (sint64_ptr)dlsym(pnetLibTime, "_IL_TimeMethods_GetCurrentTime");
+  ILUnicodeStringCompareIgnoreCase = (sint32_ptr_ptr_sint32)dlsym(pnetLibSupport, "ILUnicodeStringCompareIgnoreCase");
+  ILUnicodeStringCompareNoIgnoreCase = (sint32_ptr_ptr_sint32)dlsym(pnetLibSupport, "ILUnicodeStringCompareNoIgnoreCase");
+  assert(ILUnicodeStringCompareIgnoreCase);
+  assert(ILUnicodeStringCompareNoIgnoreCase);
+}
diff --git a/vmkit/lib/N3/VMCore/PNetLib.h b/vmkit/lib/N3/VMCore/PNetLib.h
new file mode 100644
index 0000000..4ce31fa
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/PNetLib.h
@@ -0,0 +1,30 @@
+//===----------------- PNetLib.h - PNetLib interface ----------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef N3_PNETLIB_H
+#define N3_PNETLIB_H
+
+#include "VMObject.h"
+
+
+namespace n3 {
+
+class CLIString;
+
+class StringBuilder : public VMObject {
+public:
+  CLIString* buildString;
+  sint32 maxCapactiy;
+  sint32 needsCopy;
+};
+
+}
+
+#endif 
diff --git a/vmkit/lib/N3/VMCore/Reader.cpp b/vmkit/lib/N3/VMCore/Reader.cpp
new file mode 100644
index 0000000..7567816
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/Reader.cpp
@@ -0,0 +1,144 @@
+//===--------------- Reader.cpp - Open and read files ---------------------===//
+//
+//                                N3
+//
+// 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 "N3.h"
+#include "VMArray.h"
+#include "VMThread.h"
+#include "Reader.h"
+
+using namespace n3;
+
+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, N3::arrayByte);
+    fread(res->elements, nbb, 1, fp);
+    fclose(fp);
+  }
+  return res;
+}
+
+uint8 Reader::readU1() {
+  return bytes->at(cursor++);
+}
+
+sint8 Reader::readS1() {
+  return readU1();
+}
+
+uint16 Reader::readU2() {
+  uint16 tmp = ((uint16)(readU1()));
+  return tmp | (((uint16)(readU1())) << 8);
+}
+
+sint16 Reader::readS2() {
+  sint16 tmp = ((sint16)(readS1()));
+  return tmp | (((sint16)(readS1())) << 8);
+}
+
+uint32 Reader::readU4() {
+  uint32 tmp = ((uint32)(readU2()));
+  return tmp | (((uint32)(readU2())) << 16);
+}
+
+sint32 Reader::readS4() {
+  sint32 tmp = ((sint32)(readS2()));
+  return tmp | (((sint32)(readS2())) << 16);
+}
+
+uint64 Reader::readU8() {
+  uint64 tmp = ((uint64)(readU4()));
+  return tmp | (((uint64)(readU4())) << 32);
+}
+
+sint64 Reader::readS8() {
+  sint64 tmp = ((sint64)(readS8()));
+  return tmp | (((sint64)(readS8())) << 32);
+}
+
+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))
+    VMThread::get()->vm->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/N3/VMCore/Reader.h b/vmkit/lib/N3/VMCore/Reader.h
new file mode 100644
index 0000000..8636e50
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/Reader.h
@@ -0,0 +1,98 @@
+//===----------------- Reader.h - Open and read files ---------------------===//
+//
+//                                N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_READER_H
+#define N3_READER_H
+
+#include "mvm/Object.h"
+
+#include "types.h"
+
+#include "VMArray.h"
+
+namespace n3 {
+
+
+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);
+  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);
+};
+
+static sint8 inline READ_S1(ArrayUInt8* bytes, uint32& offset) {
+  return (sint8)(bytes->elements[offset++]);
+}
+
+static uint8 inline READ_U1(ArrayUInt8* bytes, uint32& offset) {
+  return(uint8)(bytes->elements[offset++]);
+}
+
+static sint16 inline READ_S2(ArrayUInt8* bytes, uint32& offset) {
+  sint16 val = READ_S1(bytes, offset);
+  return val | (READ_U1(bytes, offset) << 8);
+}
+
+static uint16 inline READ_U2(ArrayUInt8* bytes, uint32& offset) {
+  uint16 val = READ_U1(bytes, offset);
+  return val | (READ_U1(bytes, offset) << 8);
+}
+
+static sint32 inline READ_S4(ArrayUInt8* bytes, uint32& offset) {
+  sint32 val = READ_U2(bytes, offset);
+  return val | (READ_U2(bytes, offset) << 16);
+}
+
+static uint32 inline READ_U3(ArrayUInt8* bytes, uint32& offset) {
+  uint32 val = READ_U2(bytes, offset);
+  return val | (READ_U1(bytes, offset) << 16);
+}
+
+
+static uint32 inline READ_U4(ArrayUInt8* bytes, uint32& offset) {
+  return READ_S4(bytes, offset);
+}
+
+static uint32 inline READ_U8(ArrayUInt8* bytes, uint32& offset) {
+  uint64 val1 = READ_U4(bytes, offset);
+  uint64 val2 = READ_U4(bytes, offset);
+  return (val2 << 32) + val1;
+}
+
+
+} // end namespace jnjvm
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/SignatureNames.def b/vmkit/lib/N3/VMCore/SignatureNames.def
new file mode 100644
index 0000000..89dfea5
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/SignatureNames.def
@@ -0,0 +1,85 @@
+//===---------- SignatureNames.def - Names of signature -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SIGNATURE_NAMES_DEF
+#define SIGNATURE_NAMES_DEF
+
+const char* n3::Assembly::signatureNames[0x46] = {
+  "ElementTypeEnd",           // 0x00
+  "ElementTypeVoid",          // 0x01
+  "ElementTypeBoolean",       // 0x02
+  "ElementTypeChar",          // 0x03
+  "ElementTypeI1",            // 0x04
+  "ElementTypeU1",            // 0x05
+  "ElementTypeI2",            // 0x06
+  "ElementTypeU2",            // 0x07
+  "ElementTypeI4",            // 0x08
+  "ElementTypeU4",            // 0x09
+  "ElementTypeI8",            // 0x0A
+  "ElementTypeU8",            // 0x0B
+  "ElementTypeR4",            // 0x0C
+  "ElementTypeR8",            // 0x0D
+  "ElementTypeString",        // 0x0E
+  "ElementTypePtr",           // 0x1F
+  "ElementTypeByRef",         // 0x10
+  "ElementTypeValueType",     // 0x11
+  "ElementTypeClass",         // 0x12
+  "ElementTypeVar",           // 0x13
+  "ElementTypeArray",         // 0x14
+  "ElementTypeGenericInst",   // 0x15
+  "ElementTypedByRef",        // 0x16
+  "Undefined 0x17",           // 0x17
+  "ElementTypeI",             // 0x18
+  "ElementTypeU",             // 0x19
+  "Undefined 0x1a",           // 0x1A
+  "ElementTypeFnptr",         // 0x1B
+  "ElementTypeObject",        // 0x1C
+  "ElementTypeSzarray",       // 0x1D
+  "ElementTypeMvar",          // 0x1E
+  "ElementTypeCmodReqd",      // 0x1F
+  "ElementTypeCmodOpt",       // 0x20
+  "ElementTypeInternal",      // 0x21
+  "ElementTypeModifier",      // 0x22
+  "Undefined",                // 0x23
+  "Undefined",                // 0x24
+  "Undefined",                // 0x25
+  "Undefined",                // 0x26
+  "Undefined",                // 0x27
+  "Undefined",                // 0x28
+  "Undefined",                // 0x29
+  "Undefined",                // 0x2A
+  "Undefined",                // 0x2B
+  "Undefined",                // 0x2C
+  "Undefined",                // 0x2D
+  "Undefined",                // 0x2E
+  "Undefined",                // 0x2F
+  "Undefined",                // 0x30
+  "Undefined",                // 0x31
+  "Undefined",                // 0x32
+  "Undefined",                // 0x33
+  "Undefined",                // 0x34
+  "Undefined",                // 0x35
+  "Undefined",                // 0x36
+  "Undefined",                // 0x37
+  "Undefined",                // 0x38
+  "Undefined",                // 0x39
+  "Undefined",                // 0x3A
+  "Undefined",                // 0x3B
+  "Undefined",                // 0x3C
+  "Undefined",                // 0x3D
+  "Undefined",                // 0x3E
+  "Undefined",                // 0x3F
+  "ElementTypeSentinel",      // 0x41
+  "Undefined",                // 0x42
+  "Undefined",                // 0x43
+  "Undefined",                // 0x44
+  "ElementTypePinned"         // 0x45
+};
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VMArray.cpp b/vmkit/lib/N3/VMCore/VMArray.cpp
new file mode 100644
index 0000000..ab66e0b
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMArray.cpp
@@ -0,0 +1,219 @@
+//===----------------- VMArray.cpp - VM arrays ------------------------===//
+//
+//                               N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+
+using namespace n3;
+
+const sint32 VMArray::MaxArraySize = 268435455;
+
+#define ACONS(name, elmt, size)                                             \
+  name *name::acons(sint32 n, VMClassArray* atype) {                        \
+    if (n < 0)                                                              \
+      VMThread::get()->vm->negativeArraySizeException(n);                   \
+    else if (n > VMArray::MaxArraySize)                                     \
+      VMThread::get()->vm->outOfMemoryError(n);                             \
+    name* res = (name*)                                                     \
+      Object::gcmalloc(sizeof(name) + n * size, VMObject::VT);              \
+    res->initialise(atype, n);                                              \
+    res->setVT(name::VT);                                                   \
+    return res;                                                             \
+  }
+
+#define INITIALISE(name)                                                    \
+  void name::initialise(VMCommonClass* atype, sint32 n) {                   \
+    VMObject::initialise(atype);                                            \
+    this->size = n;                                                         \
+    for (int i = 0; i < n; i++)                                             \
+      elements[i] = 0;                                                      \
+  }                                                                         \
+
+#define AT(name, elmt)                                                      \
+  elmt name::at(sint32 offset) const {                                      \
+    if (offset >= size)                                                     \
+      VMThread::get()->vm->indexOutOfBounds(this, offset);                  \
+    return elements[offset];                                                \
+  }                                                                         \
+  void name::setAt(sint32 offset, elmt value) {                             \
+    if (offset >= size)                                                     \
+      VMThread::get()->vm->indexOutOfBounds(this, offset);                  \
+    elements[offset] = value;                                               \
+  }
+
+#define ARRAYCLASS(name, elmt, size)                                        \
+  ACONS(name, elmt, size)                                                   \
+  INITIALISE(name)                                                          \
+  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(ArrayObject, VMObject*, 4)
+
+void VMArray::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(">");
+}
+
+
+AT(UTF8, uint16)
+INITIALISE(UTF8)
+
+#undef AT
+#undef INITIALISE
+#undef ACONS
+#undef ARRAYCLASS
+
+UTF8* UTF8::acons(sint32 n, VMClassArray* atype) {
+  if (n < 0)
+    VMThread::get()->vm->negativeArraySizeException(n);
+  else if (n > VMArray::MaxArraySize)
+    VMThread::get()->vm->outOfMemoryError(n);
+  UTF8* res = (UTF8*)Object::gcmalloc(sizeof(UTF8) + n * sizeof(uint16),
+                                      UTF8::VT);
+  res->initialise(atype, n);
+  return res;
+}
+
+void UTF8::print(mvm::PrintBuffer* buf) const {
+  for (int i = 0; i < size; i++)
+    buf->writeChar((char)elements[i]);
+}
+
+const UTF8* UTF8::extract(VirtualMachine *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(VirtualMachine* vm, char* asciiz) {
+  return vm->asciizConstructUTF8(asciiz);
+}
+
+const UTF8* UTF8::readerConstruct(VirtualMachine* 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();
+}
+
diff --git a/vmkit/lib/N3/VMCore/VMArray.h b/vmkit/lib/N3/VMCore/VMArray.h
new file mode 100644
index 0000000..e64b987
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMArray.h
@@ -0,0 +1,108 @@
+//===-------------------- VMArray.h - VM arrays ---------------------------===//
+//
+//                               N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_VM_ARRAY_H
+#define N3_VM_ARRAY_H
+
+#include "mvm/PrintBuffer.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Type.h"
+
+#include "types.h"
+
+#include "VMObject.h"
+
+namespace n3 {
+
+class VMClassArray;
+class VMCommonClass;
+class VMObject;
+class VirtualMachine;
+
+class VMArray : public VMObject {
+public:
+  static VirtualTable* VT;
+  sint32 size;
+  void* elements[0];
+  static const sint32 MaxArraySize;
+  static const llvm::Type* llvmType;
+
+  static llvm::ConstantInt* sizeOffset();
+  static llvm::ConstantInt* elementsOffset();
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+};
+
+typedef VMArray* (*arrayCtor_t)(uint32 len, VMCommonClass* cl);
+
+#define ARRAYCLASS(name, elmt)                                        \
+class name : public VMArray {                                         \
+public:                                                               \
+  static VirtualTable* VT;                                            \
+  static const llvm::Type* llvmType;                                  \
+  elmt elements[0];                                                   \
+  static name *acons(sint32 n, VMClassArray* cl);                     \
+  void initialise(VMCommonClass* atype, sint32 n);                    \
+  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 VMArray {
+public:
+  static VirtualTable* VT;
+  static const llvm::Type* llvmType;
+  VMObject* elements[0];
+  static ArrayObject *acons(sint32 n, VMClassArray* cl);
+  void initialise(VMCommonClass* atype, sint32 n);
+  VMObject* at(sint32) const;
+  void setAt(sint32, VMObject*);
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+};
+
+class UTF8 : public VMArray {
+public:
+  static VirtualTable* VT;
+  uint16 elements[0];
+
+  static const llvm::Type* llvmType;
+  static UTF8* acons(sint32 n, VMClassArray* cl);
+  void initialise(VMCommonClass* atype, sint32 n);
+  
+  unsigned short int at(sint32) const;
+  void setAt(sint32, uint16);
+  
+  virtual void print(mvm::PrintBuffer* buf) const;
+
+  char* UTF8ToAsciiz() const;
+  static const UTF8* asciizConstruct(VirtualMachine *vm, char* asciiz);
+  static const UTF8* readerConstruct(VirtualMachine *vm, uint16* buf, uint32 n);
+
+  const UTF8* extract(VirtualMachine *vm, uint32 start, uint32 len) const;
+};
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VMCache.cpp b/vmkit/lib/N3/VMCore/VMCache.cpp
new file mode 100644
index 0000000..3f2c8f9
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMCache.cpp
@@ -0,0 +1,223 @@
+//===------- VMCache.cpp - Inline cache for virtual calls -----------------===//
+//
+//                              N3
+//
+// 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 "Assembly.h"
+#include "CLIJit.h"
+#include "N3.h"
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMCache.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+#include "types.h"
+
+using namespace n3;
+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(VMMethod* meth) {
+  Enveloppe* enveloppe = gc_new(Enveloppe)();
+  enveloppe->firstCache = CacheNode::allocate();
+  enveloppe->firstCache->enveloppe = enveloppe;
+  enveloppe->cacheLock = mvm::Lock::allocNormal();
+  enveloppe->originalMethod = meth;
+  return enveloppe;
+}
+
+void CLIJit::invokeInterfaceOrVirtual(uint32 value) {
+  
+  VMMethod* origMeth = compilingClass->assembly->getMethodFromToken(value);
+  const llvm::FunctionType* funcType = origMeth->getSignature();
+  
+  std::vector<Value*> args;
+  makeArgs(funcType, args, origMeth->structReturn);
+
+  BasicBlock* callBlock = createBasicBlock("call virtual invoke");
+  PHINode* node = new PHINode(CacheNode::llvmType, "", callBlock);
+  
+  Value* argObj = args[0];
+  if (argObj->getType() != VMObject::llvmType) {
+    argObj = new BitCastInst(argObj, VMObject::llvmType, "", currentBlock);
+  }
+  JITVerifyNull(argObj);
+
+  // ok now the cache
+  Enveloppe* enveloppe = Enveloppe::allocate(origMeth);
+  compilingMethod->caches.push_back(enveloppe);
+  
+  Value* zero = mvm::jit::constantZero;
+  Value* one = mvm::jit::constantOne;
+  Value* two = mvm::jit::constantTwo;
+  Value* five = mvm::jit::constantFive;
+  
+  mvm::jit::protectConstants();
+  Value* llvmEnv = 
+    ConstantExpr::getIntToPtr(ConstantInt::get(Type::Int64Ty, uint64_t (enveloppe)),
+                  Enveloppe::llvmType);
+  mvm::jit::unprotectConstants();
+  
+  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(VMObject::classOffset());
+  Value* classPtr = new GetElementPtrInst(argObj, 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* ifFalse = createBasicBlock("cache not ok");
+  new BranchInst(callBlock, ifFalse, cmp, currentBlock);
+  node->addIncoming(cache, currentBlock);
+  
+  currentBlock = ifFalse;
+  Value* newCache = invoke(virtualLookupLLVM, cache, argObj, "", ifFalse, false);
+  node->addIncoming(newCache, currentBlock);
+  new BranchInst(callBlock, currentBlock);
+
+  currentBlock = callBlock;
+  Value* methPtr = new GetElementPtrInst(node, args1.begin(), args1.end(),
+                                         "", currentBlock);
+
+  Value* _meth = new LoadInst(methPtr, "", currentBlock);
+  Value* meth = new BitCastInst(_meth, PointerType::getUnqual(funcType), "", currentBlock);
+  
+
+  
+  std::vector<Value*> args4;
+  args4.push_back(zero);
+  args4.push_back(five);
+  Value* boxedptr = new GetElementPtrInst(node, args4.begin(), args4.end(), "", currentBlock);
+  Value* boxed = new LoadInst(boxedptr, "", currentBlock);
+  /* I put VMArray::llvmType here, but in should be something else... */
+  Value* unboxed = new BitCastInst(args[0], VMArray::llvmType, "", currentBlock);
+  Value* unboxedptr = new GetElementPtrInst(unboxed, args1.begin(), args1.end(), "", currentBlock);
+  Value* fakeunboxedptr = new BitCastInst(unboxedptr, args[0]->getType(), "", currentBlock);
+  args[0] = new SelectInst(boxed, fakeunboxedptr, args[0], "", currentBlock);
+  
+
+  Value* ret = invoke(meth, args, "", currentBlock, origMeth->structReturn);
+
+
+  if (ret->getType() != Type::VoidTy) {
+    push(ret);
+  }
+}
+
+extern "C" CacheNode* virtualLookup(CacheNode* cache, VMObject *obj) {
+  Enveloppe* enveloppe = cache->enveloppe;
+  VMCommonClass* ocl = obj->classOf;
+  VMMethod* orig = enveloppe->originalMethod;
+  
+  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) {
+    VMMethod* dmeth = ocl->lookupMethodDontThrow(orig->name,
+                                                 orig->parameters,
+                                                 false, true);
+    if (dmeth == 0) {
+      char* methAsciiz = orig->name->UTF8ToAsciiz();
+      char* nameAsciiz = orig->classDef->name->UTF8ToAsciiz();
+      char* nameSpaceAsciiz = orig->classDef->nameSpace->UTF8ToAsciiz();
+
+      char *buf = (char*)alloca(3 + strlen(methAsciiz) + 
+                                    strlen(nameAsciiz) + 
+                                    strlen(nameSpaceAsciiz));
+      sprintf(buf, "%s.%s.%s", nameSpaceAsciiz, nameAsciiz, methAsciiz);
+      const UTF8* newName = VMThread::get()->vm->asciizConstructUTF8(buf);
+      dmeth = ocl->lookupMethod(newName, orig->parameters, false, true);
+    }
+    
+    if (cache->methPtr) {
+      rcache = CacheNode::allocate();
+      rcache->enveloppe = enveloppe;
+    } else {
+      rcache = cache;
+    }
+    
+    Function* func = dmeth->compiledPtr();
+    rcache->methPtr = mvm::jit::executionEngine->getPointerToGlobal(func);
+    rcache->lastCible = (VMClass*)ocl;
+    rcache->box = (dmeth->classDef->super == N3::pValue);
+  }
+
+  if (enveloppe->firstCache != rcache) {
+    CacheNode *f = enveloppe->firstCache;
+    enveloppe->firstCache = rcache;
+    last->next = rcache->next;
+    rcache->next = f;
+
+  }
+  
+  enveloppe->cacheLock->unlock();
+  
+  return rcache;
+}
diff --git a/vmkit/lib/N3/VMCore/VMCache.h b/vmkit/lib/N3/VMCore/VMCache.h
new file mode 100644
index 0000000..9745d2b
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMCache.h
@@ -0,0 +1,64 @@
+//===--------- VMCache.h - Inline cache for virtual calls -----------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_VM_CACHE_H
+#define N3_VM_CACHE_H
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+#include "llvm/DerivedTypes.h"
+
+#include "types.h"
+
+namespace n3 {
+
+class Assembly;
+class Enveloppe;
+class UTF8;
+class VMClass;
+
+class CacheNode : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  void* methPtr;
+  VMClass* lastCible;
+  CacheNode* next;
+  Enveloppe* enveloppe;
+  bool box;
+  
+  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;
+  mvm::Lock* cacheLock;
+  VMMethod* originalMethod;
+
+  static const llvm::Type* llvmType;
+
+  static Enveloppe* allocate(VMMethod* orig);
+
+};
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VMClass.cpp b/vmkit/lib/N3/VMCore/VMClass.cpp
new file mode 100644
index 0000000..8de1a6a
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMClass.cpp
@@ -0,0 +1,820 @@
+//===------------ VMClass.cpp - CLI class representation ------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdarg.h>
+#include <vector>
+
+#include "llvm/DerivedTypes.h"
+
+#include "debug.h"
+#include "types.h"
+#include "mvm/JIT.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Locks.h"
+
+
+#include "Assembly.h"
+#include "CLIAccess.h"
+#include "CLIJit.h"
+#include "N3.h"
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMClass.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+void VMCommonClass::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLIType<");
+  nameSpace->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write(">");
+}
+
+void VMCommonClass::aquire() {
+  lockVar->lock(); 
+}
+
+void VMCommonClass::release() {
+  lockVar->unlock();
+}
+
+void VMCommonClass::waitClass() {
+  condVar->wait(lockVar);
+}
+
+void VMCommonClass::broadcastClass() {
+  condVar->broadcast();
+}
+
+bool VMCommonClass::ownerClass() {
+  return mvm::Lock::selfOwner(lockVar);
+}
+
+
+void VMClass::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLIType<");
+  nameSpace->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write(">");
+}
+
+void VMClassArray::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLITypeArray<");
+  nameSpace->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write(">");
+}
+
+void VMClassPointer::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLITypePointer<");
+  nameSpace->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write(">");
+}
+
+void VMMethod::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLIMethod<");
+  classDef->nameSpace->print(buf);
+  buf->write(".");
+  classDef->name->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write("(");
+  std::vector<VMCommonClass*>::iterator i = ((VMMethod*)this)->parameters.begin();
+  std::vector<VMCommonClass*>::iterator e = ((VMMethod*)this)->parameters.end();
+
+  ++i;
+  if (i != e) {
+    while (true) {
+      (*i)->nameSpace->print(buf);
+      buf->write(".");
+      (*i)->name->print(buf);
+      ++i;
+      if (i == e) break;
+      else buf->write(" ,");
+    }
+  }
+  buf->write(")");
+  buf->write(">");
+}
+
+void VMField::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLIField<");
+  classDef->nameSpace->print(buf);
+  buf->write(".");
+  classDef->name->print(buf);
+  buf->write("::");
+  name->print(buf);
+  buf->write(">");
+}
+  
+void Param::print(mvm::PrintBuffer* buf) const {
+  buf->write("CLIParam<");
+  name->print(buf);
+  buf->write(">");
+}
+
+void Property::print(mvm::PrintBuffer* buf) const {
+  buf->write("Property def with name <");
+  name->print(buf);
+  buf->write(">");
+}
+
+
+void VMCommonClass::initialise(VirtualMachine* vm, bool isArray) {
+  this->lockVar = mvm::Lock::allocRecursive();
+  this->condVar = mvm::Cond::allocCond();
+  this->delegatee = 0;
+  this->status = hashed;
+  this->vm = vm;
+  this->isArray = isArray;
+  this->isPointer = false;
+  this->isPrimitive = false;
+  this->naturalType = llvm::OpaqueType::get();
+}
+
+const UTF8* VMClassArray::constructArrayName(const UTF8* name, uint32 dims) {
+  const char* asciiz = name->UTF8ToAsciiz();
+  char* res = (char*)alloca(strlen(asciiz) + (dims * 2) + 1);
+  sprintf(res, asciiz);
+
+  for (uint32 i = 0; i < dims; ++i) {
+    sprintf(res, "%s[]", res);
+  }
+
+  return VMThread::get()->vm->asciizConstructUTF8(res);
+}
+
+const UTF8* VMClassPointer::constructPointerName(const UTF8* name, uint32 dims) {
+  const char* asciiz = name->UTF8ToAsciiz();
+  char* res = (char*)alloca(strlen(asciiz) + (dims * 2) + 1);
+  sprintf(res, asciiz);
+
+  for (uint32 i = 0; i < dims; ++i) {
+    sprintf(res, "%s*", res);
+  }
+
+  return VMThread::get()->vm->asciizConstructUTF8(res);
+}
+
+
+void VMCommonClass::loadParents() {
+  if ((0xffff & superToken) == 0) {
+    depth = 0;
+    display.push_back(this);
+  } else {
+    super = assembly->loadType((N3*)vm, superToken, true, false, false, true);
+    depth = super->depth + 1;
+    for (uint32 i = 0; i < super->display.size(); ++i) {
+      display.push_back(super->display[i]);
+    }
+    display.push_back(this);
+  }
+  
+  for (std::vector<uint32>::iterator i = interfacesToken.begin(), 
+       e = interfacesToken.end(); i!= e; ++i) {
+    interfaces.push_back((VMClass*)assembly->loadType((N3*)vm, (*i), true, 
+                                                      false, false, true));
+  }
+
+}
+
+typedef void (*clinit_t)(void);
+
+void VMCommonClass::clinitClass() {
+  VMCommonClass* cl = this; 
+  if (cl->status < ready) {
+    cl->aquire();
+    int status = cl->status;
+    if (status == ready) {
+      cl->release();
+    } else if (status == unified) {
+      cl->status = clinitParent;
+      cl->release();
+      if (cl->super) {
+        cl->super->resolveStatic(true);
+      }
+      for (uint32 i = 0; i < cl->interfaces.size(); i++) {
+        cl->interfaces[i]->resolveStatic(true);
+      }
+      
+      cl->status = inClinit;
+      std::vector<VMCommonClass*> args;
+      args.push_back(N3::pVoid);
+      VMMethod* meth = cl->lookupMethodDontThrow(N3::clinitName, args,
+                                                 true, false);
+      
+      PRINT_DEBUG(N3_LOAD, 0, COLOR_NORMAL, "; ");
+      PRINT_DEBUG(N3_LOAD, 0, LIGHT_GREEN, "clinit ");
+      PRINT_DEBUG(N3_LOAD, 0, COLOR_NORMAL, "%s::%s\n", printString(),
+                  cl->printString());
+      
+      if (meth) {
+        llvm::Function* pred = meth->compiledPtr();
+        clinit_t res = (clinit_t)mvm::jit::executionEngine->getPointerToGlobal(pred);
+        res();
+      }
+
+      cl->status = ready;
+      cl->broadcastClass();
+    } else if (status < unified) {
+      cl->release();
+      VMThread::get()->vm->unknownError("try to clinit a not-readed class...");
+    } else {
+      if (!cl->ownerClass()) {
+        while (status < ready) cl->waitClass();
+      } 
+      cl->release();
+    }
+  }
+}
+
+void VMClass::resolveStaticFields() {
+  
+  VMClass* cl = this;
+
+  std::vector<const llvm::Type*> fields;
+  fields.push_back(VMObject::llvmType->getContainedType(0));
+  uint64 offset = 0;
+  mvm::jit::protectConstants();
+  for (std::vector<VMField*>::iterator i = cl->staticFields.begin(),
+            e = cl->staticFields.end(); i!= e; ++i) {
+    // preincrement because 0 is VMObject
+    (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset);
+  }
+  mvm::jit::unprotectConstants();
+  for (std::vector<VMField*>::iterator i = cl->staticFields.begin(),
+            e = cl->staticFields.end(); i!= e; ++i) {
+    (*i)->signature->resolveType(false, false);
+    fields.push_back((*i)->signature->naturalType);
+  }
+
+  cl->staticType = llvm::PointerType::getUnqual(llvm::StructType::get(fields, false));
+
+  VirtualTable* VT = CLIJit::makeVT(cl, true);
+
+  uint64 size = mvm::jit::getTypeSize(cl->staticType->getContainedType(0));
+  cl->staticInstance = (VMObject*)mvm::Object::gcmalloc(size, VT);
+  cl->staticInstance->initialise(cl);
+
+  for (std::vector<VMField*>::iterator i = cl->staticFields.begin(),
+            e = cl->staticFields.end(); i!= e; ++i) {
+    
+    (*i)->initField(cl->staticInstance);
+  }
+}
+
+void VMClass::unifyTypes() {
+  for (std::vector<VMField*>::iterator i = virtualFields.begin(), 
+       e = virtualFields.end(); i!= e; ++i) {
+    (*i)->signature->resolveType(false, false);
+  }
+  if (naturalType->isAbstract())
+    naturalType = naturalType->getForwardedType();
+  
+  assert(naturalType);
+}
+
+void VMClass::resolveVirtualFields() {
+  VMClass* cl = this;
+  if (hasExplicitLayout(flags)) {
+    explicitLayoutSize = assembly->getExplicitLayout(token);
+    const llvm::Type* type = llvm::IntegerType::get(explicitLayoutSize);
+    ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(type);
+    naturalType = type;
+  } else if (super != 0) {
+    if (super == N3::pValue) {
+      uint32 size = virtualFields.size();
+      if (size == 1) {
+        virtualFields[0]->offset = mvm::jit::constantZero;
+        if (naturalType->isAbstract()) {
+          ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(virtualFields[0]->signature->naturalType);
+          naturalType = virtualFields[0]->signature->naturalType;
+        }
+      } else if (size == 0) {
+        if (naturalType->isAbstract()) {
+          ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(llvm::Type::VoidTy);
+          naturalType = llvm::Type::VoidTy;
+        }
+      } else {
+        std::vector<const llvm::Type*> Elts;
+        uint32 offset = -1;
+        mvm::jit::protectConstants();
+        for (std::vector<VMField*>::iterator i = virtualFields.begin(), 
+          e = virtualFields.end(); i!= e; ++i) {
+          (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset);
+          const llvm::Type* type = (*i)->signature->naturalType;
+          Elts.push_back(type);
+        }
+        mvm::jit::unprotectConstants();
+        const llvm::Type* tmp = llvm::StructType::get(Elts);
+        ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(tmp);
+        naturalType = tmp;
+      }
+    } else if (super == N3::pEnum) {
+      ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(llvm::Type::Int32Ty); // TODO find max
+      naturalType = llvm::Type::Int32Ty;
+    } else {
+      std::vector<const llvm::Type*> Elts;
+      Elts.push_back(super->naturalType->getContainedType(0));
+      uint32 offset = 0;
+      mvm::jit::protectConstants();
+      for (std::vector<VMField*>::iterator i = virtualFields.begin(), 
+           e = virtualFields.end(); i!= e; ++i) {
+        (*i)->offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ++offset);
+        const llvm::Type* type = (*i)->signature->naturalType;
+        Elts.push_back(type);
+      }
+      mvm::jit::unprotectConstants();
+      const llvm::Type* tmp = llvm::PointerType::getUnqual(llvm::StructType::get(Elts));
+      ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(tmp);
+      naturalType = tmp;
+    }
+  } else {
+    if (naturalType->isAbstract()) { // interfaces
+      ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(VMObject::llvmType);
+      naturalType = VMObject::llvmType;
+    }
+  }
+
+  unifyTypes();
+  
+  if (super == N3::pValue) {
+    std::vector<const llvm::Type*> Elts;
+    Elts.push_back(VMObject::llvmType->getContainedType(0));
+    for (std::vector<VMField*>::iterator i = virtualFields.begin(), 
+         e = virtualFields.end(); i!= e; ++i) {
+      Elts.push_back((*i)->signature->naturalType);
+    }
+    virtualType = llvm::PointerType::getUnqual(llvm::StructType::get(Elts)); 
+  } else {
+    virtualType = naturalType;
+  }
+  
+  if (super != N3::pEnum) {
+    VirtualTable* VT = CLIJit::makeVT(this, false);
+  
+    uint64 size = mvm::jit::getTypeSize(cl->virtualType->getContainedType(0));
+    cl->virtualInstance = (VMObject*)mvm::Object::gcmalloc(size, VT);
+    cl->virtualInstance->initialise(cl);
+
+    for (std::vector<VMField*>::iterator i = cl->virtualFields.begin(),
+              e = cl->virtualFields.end(); i!= e; ++i) {
+    
+      (*i)->initField(cl->virtualInstance);
+    }
+  }
+
+}
+
+
+void VMClassArray::makeType() {
+  std::vector<const llvm::Type*> arrayFields;
+  arrayFields.push_back(VMObject::llvmType->getContainedType(0));
+  arrayFields.push_back(llvm::Type::Int32Ty);
+  arrayFields.push_back(llvm::ArrayType::get(baseClass->naturalType, 0));
+  ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(llvm::PointerType::getUnqual(llvm::StructType::get(arrayFields, false)));
+  naturalType = naturalType->getForwardedType();
+  virtualType = naturalType;
+  arrayVT = CLIJit::makeArrayVT(this);
+}
+
+void VMClassPointer::makeType() {
+  const llvm::Type* type = (baseClass->naturalType == llvm::Type::VoidTy) ? llvm::Type::Int8Ty : baseClass->naturalType;
+  ((llvm::OpaqueType*)naturalType)->refineAbstractTypeTo(llvm::PointerType::getUnqual(type));
+  naturalType = naturalType->getForwardedType();
+}
+
+void VMCommonClass::resolveType(bool stat, bool clinit) {
+  VMCommonClass* cl = this;
+  if (cl->status < resolved) {
+    cl->aquire();
+    int status = cl->status;
+    if (status >= resolved) {
+      cl->release();
+    } else if (status <  loaded) {
+      cl->release();
+      VMThread::get()->vm->unknownError("try to resolve a not-readed class");
+    } else if (status == loaded) {
+      if (cl->isArray) {
+        VMClassArray* arrayCl = (VMClassArray*)cl;
+        VMCommonClass* baseClass =  arrayCl->baseClass;
+        baseClass->resolveType(false, false);
+        arrayCl->makeType();
+        cl->status = resolved;
+      } else if (cl->isPointer) {
+        VMClassPointer* pointerCl = (VMClassPointer*)cl;
+        VMCommonClass* baseClass =  pointerCl->baseClass;
+        baseClass->resolveType(false, false);
+        pointerCl->makeType();
+        cl->status = resolved;
+      } else {
+        cl->release();
+        cl->loadParents();
+        cl->aquire();
+        cl->status = prepared;
+        assembly->readClass(cl);
+        cl->status = readed;
+        ((VMClass*)cl)->resolveVirtualFields();
+        cl->status = resolved;
+      }
+      cl->release();
+    } else {
+      if (!(cl->ownerClass())) {
+        while (status < resolved) {
+          cl->waitClass();
+        }
+      }
+      cl->release();
+    }
+  }
+  if (stat) cl->resolveStatic(clinit);
+}
+
+void VMCommonClass::resolveStatic(bool clinit) {
+  VMCommonClass* cl = this;
+  if (cl->status < unified) {
+    cl->aquire();
+    int status = cl->status;
+    if (status >= unified) {
+      cl->release();
+    } else if (status < resolved) {
+      cl->release();
+      VMThread::get()->vm->unknownError("try to resolve static of a not virtual-resolved class");
+    } else if (status == resolved) {
+      if (cl->isArray) {
+        VMClassArray* arrayCl = (VMClassArray*)cl;
+        VMCommonClass* baseClass =  arrayCl->baseClass;
+        baseClass->resolveStatic(false);
+        cl->status = unified;
+      } else if (cl->isPointer) {
+        VMClassPointer* pointerCl = (VMClassPointer*)cl;
+        VMCommonClass* baseClass =  pointerCl->baseClass;
+        baseClass->resolveStatic(false);
+        cl->status = unified;
+      } else {
+        ((VMClass*)cl)->resolveStaticFields();
+        cl->status = unified;
+      }
+      cl->release();
+    } else {
+      if (!(cl->ownerClass())) {
+        while (status < unified) {
+          cl->waitClass();
+        }
+      }
+      cl->release();
+    }
+  }
+  if (clinit) cl->clinitClass();
+}
+
+
+VMMethod* VMCommonClass::lookupMethodDontThrow(const UTF8* name,
+                                               std::vector<VMCommonClass*>& args, 
+                                               bool isStatic, bool recurse) {
+  
+  std::vector<VMMethod*>* meths = (isStatic? &staticMethods : 
+                                             &virtualMethods);
+  
+  VMMethod *cur, *res = 0;
+  int i = 0;
+  int nbm = meths->size();
+
+  while (!res && i < nbm) {
+    cur = meths->at(i);
+    if (cur->name == name && cur->signatureEquals(args)) {
+      return cur;
+    }
+    ++i;
+  }
+
+  if (recurse) {
+    if (super) res = super->lookupMethodDontThrow(name, args, isStatic,
+                                                  recurse);
+    if (!res && isStatic) {
+      int nbi = interfaces.size();
+      i = 0;
+      while (res == 0 && i < nbi) {
+        res = interfaces[i]->lookupMethodDontThrow(name, args, isStatic,
+                                                   recurse);
+        ++i;
+      }
+    }
+  }
+
+  return res;
+}
+
+VMMethod* VMCommonClass::lookupMethod(const UTF8* name, 
+                                      std::vector<VMCommonClass*>& args, 
+                                      bool isStatic, bool recurse) {
+  
+  VMMethod* res = lookupMethodDontThrow(name, args, isStatic, recurse);
+  if (!res) {
+    VMThread::get()->vm->error(VirtualMachine::MissingMethodException, 
+                               "unable to find %s in %s",
+                               name->printString(), this->printString());
+  }
+  return res;
+}
+
+VMField* VMCommonClass::lookupFieldDontThrow(const UTF8* name,
+                                             VMCommonClass* type,
+                                             bool isStatic, bool recurse) {
+  
+  std::vector<VMField*>* fields = (isStatic? &staticFields : &virtualFields);
+  
+  VMField *cur, *res = 0;
+  int i = 0;
+  int nbm = fields->size();
+
+  while (!res && i < nbm) {
+    cur = fields->at(i);
+    if (cur->name == name && cur->signature == 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;
+}
+
+VMField* VMCommonClass::lookupField(const UTF8* name, VMCommonClass* type,
+                                    bool isStatic, bool recurse) {
+  
+  VMField* res = lookupFieldDontThrow(name, type, isStatic, recurse);
+  if (!res) {
+    VMThread::get()->vm->error(VirtualMachine::MissingFieldException, 
+                               "unable to find %s in %s",
+                               name->printString(), this->printString());
+  }
+  return res;
+}
+
+VMObject* VMClass::initialiseObject(VMObject* obj) {
+  uint64 size = mvm::jit::getTypeSize(virtualType->getContainedType(0));
+  memcpy(obj, virtualInstance, size);
+  return obj;
+}
+
+VMObject* VMClass::doNew() {
+  uint64 size = mvm::jit::getTypeSize(virtualType->getContainedType(0));
+  VMObject* res = (VMObject*)
+    gc::operator new(size, virtualInstance->getVirtualTable());
+  memcpy(res, virtualInstance, size);
+  return res;
+}
+
+VMObject* VMClassArray::doNew(uint32 nb) {
+  uint64 size = mvm::jit::getTypeSize(baseClass->naturalType);
+  VMArray* res = (VMArray*)
+    gc::operator new(size * nb + sizeof(VMObject) + sizeof(sint32), arrayVT);
+  memset(res->elements, 0, size * nb);
+  res->initialise(this);
+  res->size = nb;
+  return res;
+}
+
+static VMObject* doMultiNewIntern(VMClassArray* cl, uint32 dim, sint32* buf) {
+  if (dim <= 0) VMThread::get()->vm->error("Can't happen");
+  sint32 n = buf[0];
+  if (n < 0) VMThread::get()->vm->negativeArraySizeException(n);
+  
+  VMArray* res = (VMArray*)cl->doNew(n);
+  if (dim > 1) {
+    VMCommonClass* base = cl->baseClass;
+    if (n > 0) {
+      for (sint32 i = 0; i < n; ++i) {
+        res->elements[i] = doMultiNewIntern((VMClassArray*)base, dim - 1, &(buf[1]));
+      }
+    }
+    for (uint32 i = 1; i < dim; ++i) {
+      if (buf[i] < 0) VMThread::get()->vm->negativeArraySizeException(buf[i]);
+    }
+  }
+  return res;
+}
+
+extern "C" VMObject* doMultiNew(VMClassArray* cl, ...) {
+  sint32* dimSizes = (sint32*)alloca(cl->dims * sizeof(sint32));
+  va_list ap;
+  va_start(ap, cl);
+  for (uint32 i = 0; i < cl->dims; ++i) {
+    dimSizes[i] = va_arg(ap, sint32);
+  }
+  va_end(ap);
+  return doMultiNewIntern(cl, cl->dims, dimSizes);
+}
+
+
+static void disassembleStruct(std::vector<const llvm::Type*> &args, 
+                              const llvm::Type* arg) {
+  const llvm::StructType* STy = llvm::dyn_cast<llvm::StructType>(arg);
+  for (llvm::StructType::element_iterator I = STy->element_begin(),
+       E = STy->element_end(); I != E; ++I) {
+    if ((*I)->isFirstClassType()) {
+      args.push_back(*I);
+    } else {
+      disassembleStruct(args, *I);
+    }
+  }
+}
+
+const llvm::FunctionType* VMMethod::resolveSignature(
+                  std::vector<VMCommonClass*> & parameters, bool isVirt,
+                  bool& structRet) {
+    const llvm::Type* ret;
+    std::vector<const llvm::Type*> args;
+    std::vector<VMCommonClass*>::iterator i = parameters.begin(),
+                                          e = parameters.end();
+    if ((*i)->naturalType->isAbstract()) {
+      (*i)->resolveType(false, false);
+    }
+    ret = (*i)->naturalType;
+    ++i;
+    
+    if (isVirt) {
+      VMCommonClass* cur = (*i);
+      ++i;
+      if (cur->naturalType->isAbstract()) {
+        cur->resolveType(false, false);
+      }
+      if (cur->super != N3::pValue && cur->super != N3::pEnum) {
+        args.push_back(cur->naturalType);
+      } else {
+        args.push_back(llvm::PointerType::getUnqual(cur->naturalType));
+      }
+    }
+    
+    for ( ; i!= e; ++i) {
+      VMCommonClass* cur = (*i);
+      if (cur->naturalType->isAbstract()) {
+        cur->resolveType(false, false);
+      }
+      if (cur->naturalType->isFirstClassType()) {
+        args.push_back(cur->naturalType);
+      } else {
+        args.push_back(llvm::PointerType::getUnqual(cur->naturalType));
+      }
+    }
+
+    if (!(ret->isFirstClassType()) && ret != llvm::Type::VoidTy) {
+      args.push_back(llvm::PointerType::getUnqual(ret));
+      ret = llvm::Type::VoidTy;
+      structRet = true;
+    } else {
+      structRet = false;
+    }
+    return llvm::FunctionType::get(ret, args, false);
+}
+
+const llvm::FunctionType* VMMethod::getSignature() {
+  if (!_signature) {
+    _signature = resolveSignature(parameters, !isStatic(flags), structReturn);
+  }
+  return _signature;
+}
+
+const llvm::FunctionType* Property::getSignature() {
+  if (!_signature) {
+    bool structReturn = false;
+    _signature = VMMethod::resolveSignature(parameters, virt, structReturn);
+  }
+  return _signature;
+}
+
+bool VMCommonClass::implements(VMCommonClass* cl) {
+  if (this == cl) return true;
+  else {
+    for (uint32 i = 0; i < interfaces.size(); i++) {
+      VMCommonClass* cur = interfaces[i];
+      if (cur == cl) return true;
+      else if (cur->implements(cl)) return true;
+    }
+    if (super) {
+      return super->implements(cl);
+    }
+  }
+  return false;
+}
+
+bool VMCommonClass::instantiationOfArray(VMCommonClass* cl) {
+  if (this == cl) return true;
+  else {
+    if (isArray && cl->isArray) {
+      VMCommonClass* baseThis = ((VMClassArray*)this)->baseClass;
+      VMCommonClass* baseCl = ((VMClassArray*)cl)->baseClass;
+
+      if (isInterface(baseThis->flags) && isInterface(baseCl->flags)) {
+        return baseThis->implements(baseCl);
+      } else {
+        return baseThis->isAssignableFrom(baseCl);
+      }
+    }
+  }
+  return false;
+}
+
+bool VMCommonClass::subclassOf(VMCommonClass* cl) {
+  if (cl->depth < display.size()) {
+    return display[cl->depth] == cl;
+  } else {
+    return false;
+  }
+}
+
+bool VMCommonClass::isAssignableFrom(VMCommonClass* cl) {
+  if (this == cl) {
+    return true;
+  } else if (isInterface(cl->flags)) {
+    return this->implements(cl);
+  } else if (cl->isArray) {
+    return this->instantiationOfArray(cl);
+  } else if (cl->isPointer){
+    VMThread::get()->vm->error("implement me");
+    return false;
+  } else {
+    return this->subclassOf(cl);
+  }
+}
+
+VMObject* Property::getPropertyDelegatee() {
+  if (!delegatee) {
+    delegatee = (*N3::propertyType)();
+    (*N3::ctorPropertyType)(delegatee);
+    (*N3::propertyPropertyType)(delegatee, (VMObject*)this);
+  }
+  return delegatee;
+}
+
+VMObject* VMMethod::getMethodDelegatee() {
+  if (!delegatee) {
+    delegatee = (*N3::methodType)();
+    (*N3::ctorMethodType)(delegatee);
+    (*N3::methodMethodType)(delegatee, (VMObject*)this);
+  }
+  return delegatee;
+}
+
+VMObject* VMCommonClass::getClassDelegatee() {
+  if (!delegatee) {
+    delegatee = (*N3::clrType)();
+    (*N3::ctorClrType)(delegatee);
+    (*N3::typeClrType)(delegatee, (VMObject*)this);
+  }
+  return delegatee;
+}
+
+VMObject* Assembly::getAssemblyDelegatee() {
+  if (!delegatee) {
+    delegatee = (*N3::assemblyReflection)();
+    (*N3::ctorAssemblyReflection)(delegatee);
+    (*N3::assemblyAssemblyReflection)(delegatee, (VMObject*)this);
+  }
+  return delegatee;
+}
+
+bool VMMethod::signatureEquals(std::vector<VMCommonClass*>& args) {
+  bool stat = isStatic(flags);
+  if (args.size() != parameters.size()) return false;
+  else {
+    std::vector<VMCommonClass*>::iterator i = parameters.begin(), 
+          a = args.begin(), e = args.end(); 
+    
+    if ((*i) != (*a)) return false;
+    ++i; ++a;
+    if (!stat) {
+      ++i; ++a;
+    }
+    for( ; a != e; ++i, ++a) {
+      if ((*i) != (*a)) return false;
+    }
+  }
+  return true;
+}
diff --git a/vmkit/lib/N3/VMCore/VMClass.h b/vmkit/lib/N3/VMCore/VMClass.h
new file mode 100644
index 0000000..1807dc4
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMClass.h
@@ -0,0 +1,293 @@
+//===------------- VMClass.h - CLI class representation -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_VM_CLASS_H
+#define N3_VM_CLASS_H
+
+#include "types.h"
+
+#include "mvm/Method.h"
+#include "mvm/Object.h"
+#include "mvm/Threads/Locks.h"
+#include "mvm/Threads/Cond.h"
+
+#include "llvm/Constants.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Function.h"
+#include "llvm/Type.h"
+
+namespace n3 {
+
+class ArraySInt32;
+class Assembly;
+class Enveloppe;
+class Param;
+class Property;
+class UTF8;
+class VirtualMachine;
+class VMClass;
+class VMField;
+class VMMethod;
+class VMObject;
+
+typedef enum VMClassState {
+  hashed = 0, loaded, prepared, readed, resolved, unified, clinitParent, inClinit, ready
+}VMClassState;
+
+
+class VMCommonClass : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  std::vector<VMMethod*> virtualMethods;
+  std::vector<VMMethod*> staticMethods;
+  std::vector<VMField*>  virtualFields;
+  std::vector<VMField*>  staticFields;
+  std::vector<VMClass*> interfaces;
+  std::vector<uint32> interfacesToken;
+  VMCommonClass* super;
+  VirtualMachine* vm;
+  const UTF8* name;
+  const UTF8* nameSpace;
+  mvm::Lock* lockVar;
+  mvm::Cond* condVar;
+  VMObject* delegatee;
+  std::vector<VMCommonClass*> display;
+  Assembly* assembly;
+  std::vector<Property*> properties;
+  
+  llvm::Function* virtualTracer;
+  llvm::Function* staticTracer;
+  mvm::Code* codeVirtualTracer;
+  mvm::Code* codeStaticTracer;
+
+  uint32 superToken;
+  uint32 token;
+  bool isArray;
+  bool isPointer;
+  bool isPrimitive;
+  uint32 depth;
+  VMClassState status;
+  uint32 flags;
+  
+  static const uint32 maxDisplay;
+
+  void aquire();
+  void release();
+  void waitClass();
+  void broadcastClass();
+  bool ownerClass();
+
+  void initialise(VirtualMachine* vm, bool isArray);
+
+  const llvm::Type* naturalType;  // true type
+  const llvm::Type* virtualType;  // true type or box
+  const llvm::Type* staticType;   // static type
+
+  bool inheritName(const UTF8* Tname);
+  bool isOfTypeName(const UTF8* Tname);
+  bool implements(VMCommonClass* cl);
+  bool instantiationOfArray(VMCommonClass* cl);
+  bool subclassOf(VMCommonClass* cl);
+  bool isAssignableFrom(VMCommonClass* cl);
+  
+  void assignType();
+  void clinitClass();
+  void resolveStatic(bool clinit);
+  void resolveType(bool stat, bool clinit);
+  void loadParents();
+  
+  VMMethod* lookupMethodDontThrow(const UTF8* name, 
+                                  std::vector<VMCommonClass*>& args,
+                                  bool isStatic, bool recurse);
+  
+  VMMethod* lookupMethod(const UTF8* name, std::vector<VMCommonClass*>& args,
+                         bool isStatic, bool recurse);
+  
+  VMField* lookupFieldDontThrow(const UTF8* name, VMCommonClass* type,
+                                bool isStatic, bool recurse);
+  
+  VMField* lookupField(const UTF8* name, VMCommonClass* type, bool isStatic,
+                       bool recurse);
+  
+  llvm::GlobalVariable* llvmVar();
+  llvm::GlobalVariable* _llvmVar;
+  
+  VMObject* getClassDelegatee();
+};
+
+
+
+class VMClass : public VMCommonClass {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+  
+  void resolveFields();
+  void resolveStaticFields();
+  void resolveVirtualFields();
+  void unifyTypes();
+  
+  VMObject* staticInstance;
+  VMObject* virtualInstance;
+  std::vector<VMClass*> innerClasses;
+  VMClass* outerClass;
+  
+  VMObject* operator()();
+  VMObject* doNew();
+  VMObject* initialiseObject(VMObject*);
+
+  uint32 explicitLayoutSize;
+};
+
+class VMClassArray : public VMCommonClass {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  uint32 dims;
+  VMCommonClass* baseClass;
+  
+  static VMCommonClass* SuperArray;
+  static std::vector<VMClass*>      InterfacesArray;
+  static std::vector<VMMethod*>     VirtualMethodsArray;
+  static std::vector<VMMethod*>     StaticMethodsArray;
+  static std::vector<VMField*>      VirtualFieldsArray;
+  static std::vector<VMField*>      StaticFieldsArray;
+  
+  static const UTF8* constructArrayName(const UTF8* name, uint32 dims);
+  void makeType();
+  VMObject* doNew(uint32 nb);
+  VirtualTable* arrayVT;
+};
+
+class VMClassPointer : public VMCommonClass {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  uint32 dims;
+  VMCommonClass* baseClass;
+  static const UTF8* constructPointerName(const UTF8* name, uint32 dims);
+  void makeType();
+};
+
+class VMMethod : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+  
+  uint32 flags;
+  uint32 offset;
+  uint32 implFlags;
+  uint32 token;
+
+  VMObject* delegatee;
+  VMObject* getMethodDelegatee();
+  std::vector<Param*> params;
+  std::vector<Enveloppe*> caches;
+  std::vector<VMCommonClass*> parameters;
+  VMClass* classDef;
+  llvm::Function* compiledPtr();
+  llvm::Function* methPtr;
+  const UTF8* name;
+  const llvm::FunctionType* _signature;
+  bool structReturn;
+  bool virt;
+  bool canBeInlined;
+
+  mvm::Code* code;
+  
+  llvm::GenericValue operator()(...);
+  llvm::GenericValue operator()(va_list ap);
+  llvm::GenericValue operator()(VMObject* obj, va_list ap);
+  llvm::GenericValue operator()(std::vector<llvm::GenericValue>& args);
+  llvm::GenericValue run(...);
+  
+  const llvm::FunctionType* getSignature();
+  static const llvm::FunctionType* resolveSignature(
+      std::vector<VMCommonClass*>& params, bool isVirt, bool &structRet);
+  bool signatureEquals(std::vector<VMCommonClass*>& args);
+  llvm::GlobalVariable* llvmVar();
+  llvm::GlobalVariable* _llvmVar;
+};
+
+class VMField : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+  
+  uint32 flags;
+  llvm::ConstantInt* offset;
+  uint32 token;
+  const UTF8* name;
+  VMClass* classDef;
+  VMCommonClass* signature;
+  uint64 ptrOffset;
+  
+  void initField(VMObject* obj);
+
+  llvm::GenericValue operator()(VMObject* obj = 0); 
+  void operator()(VMObject* obj, bool val);
+  void operator()(VMObject* obj, float val);
+  void operator()(VMObject* obj, double val);
+  void operator()(VMObject* obj, sint32 val);
+  void operator()(VMObject* obj, sint64 val);
+  void operator()(VMObject* obj, VMObject* val);
+  void operator()(bool val);
+  void operator()(float val);
+  void operator()(double val);
+  void operator()(sint32 val);
+  void operator()(sint64 val);
+
+  llvm::GlobalVariable* llvmVar();
+  llvm::GlobalVariable* _llvmVar;
+};
+
+class Param : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  uint32 flags;
+  uint32 sequence;
+  VMMethod* method;
+  const UTF8* name;
+};
+
+class Property : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+  
+  std::vector<VMCommonClass*> parameters;
+  VMCommonClass* type;
+  const llvm::FunctionType* _signature;
+  const llvm::FunctionType* getSignature();
+  bool virt;
+  const UTF8* name;
+  VMObject* delegatee;
+  uint32 flags;
+  VMObject* getPropertyDelegatee();
+};
+
+
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VMObject.cpp b/vmkit/lib/N3/VMCore/VMObject.cpp
new file mode 100644
index 0000000..8462960
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMObject.cpp
@@ -0,0 +1,206 @@
+//===------------- VMObject.cpp - VM object definition --------------------===//
+//
+//                                N3
+//
+// 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 "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+#include "VirtualMachine.h"
+
+using namespace n3;
+
+void VMObject::initialise(VMCommonClass* cl) {
+  this->classOf = cl;
+  this->lockObj = 0;
+}
+
+VMCond* VMCond::allocate() {
+  return gc_new(VMCond)();
+}
+
+void VMCond::notify() {
+  for (std::vector<VMThread*>::iterator i = threads.begin(), 
+            e = threads.end(); i!= e; ++i) {
+    VMThread* cur = *i;
+    cur->lock->lock();
+    if (cur->interruptFlag != 0) {
+      cur->lock->unlock();
+      continue;
+    } else if (cur->vmThread != 0) {
+      cur->varcond->signal();
+      cur->lock->unlock();
+      threads.erase(i);
+      break;
+    } else { // dead thread
+      threads.erase(i);
+    }
+  }
+}
+
+void VMCond::notifyAll() {
+  for (std::vector<VMThread*>::iterator i = threads.begin(),
+            e = threads.end(); i!= e; ++i) {
+    VMThread* cur = *i;
+    cur->lock->lock();
+    cur->varcond->signal();
+    cur->lock->unlock();
+    threads.erase(i);
+  }
+}
+
+void VMCond::wait(VMThread* th) {
+  threads.push_back(th);
+}
+
+void VMCond::remove(VMThread* th) {
+  for (std::vector<VMThread*>::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 = VMCond::allocate();
+  return res;
+}
+
+void LockObj::aquire() {
+  lock->lock();
+}
+
+void LockObj::release() {
+  lock->unlock();
+}
+
+bool LockObj::owner() {
+  return mvm::Lock::selfOwner(lock);
+}
+
+void VMObject::print(mvm::PrintBuffer* buf) const {
+  buf->write("VMObject<");
+  classOf->print(buf);
+  buf->write(">");
+}
+
+VMObject* VMObject::allocate(VMCommonClass* cl) {
+  VMObject* res = gc_new(VMObject)();
+  res->classOf = cl;
+  return res;
+}
+
+static LockObj* myLock(VMObject* obj) {
+  verifyNull(obj);
+  if (obj->lockObj == 0) {
+    VMObject::globalLock->lock();
+    if (obj->lockObj == 0) {
+      obj->lockObj = LockObj::allocate();
+    }
+    VMObject::globalLock->unlock();
+  }
+  return obj->lockObj;
+}
+
+void VMObject::aquire() {
+  myLock(this)->aquire();
+}
+
+void VMObject::unlock() {
+  verifyNull(this);
+  lockObj->release();
+}
+
+void VMObject::waitIntern(struct timeval* info, bool timed) {
+  LockObj * l = myLock(this);
+  bool owner = l->owner();
+
+  if (owner) {
+    VMThread* thread = VMThread::get();
+    mvm::Lock* mutexThread = thread->lock;
+    mvm::Cond* varcondThread = thread->varcond;
+
+    mutexThread->lock();
+    if (thread->interruptFlag != 0) {
+      mutexThread->unlock();
+      thread->interruptFlag = 0;
+      thread->vm->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 = VMThread::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 = VMThread::StateRunning;
+
+      if (interrupted) {
+        thread->interruptFlag = 0;
+        thread->vm->interruptedException(this);
+      }
+    }
+  } else {
+    VMThread::get()->vm->illegalMonitorStateException(this);
+  }
+}
+
+void VMObject::wait() {
+  waitIntern(0, false);
+}
+
+void VMObject::timedWait(struct timeval& info) {
+  waitIntern(&info, false);
+}
+
+void VMObject::notify() {
+  LockObj* l = myLock(this);
+  if (l->owner()) {
+    l->varcond->notify();
+  } else {
+    VMThread::get()->vm->illegalMonitorStateException(this);
+  }
+}
+
+void VMObject::notifyAll() {
+  LockObj* l = myLock(this);
+  if (l->owner()) {
+    l->varcond->notifyAll();
+  } else {
+    VMThread::get()->vm->illegalMonitorStateException(this);
+  } 
+}
+
+bool VMObject::instanceOf(VMCommonClass* cl) {
+  if (!this) return false;
+  else return this->classOf->isAssignableFrom(cl);
+}
diff --git a/vmkit/lib/N3/VMCore/VMObject.h b/vmkit/lib/N3/VMCore/VMObject.h
new file mode 100644
index 0000000..1459a84
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMObject.h
@@ -0,0 +1,112 @@
+//===---------------- VMObject.h - VM object definition -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_VM_OBJECT_H
+#define N3_VM_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 n3 {
+
+class VMCommonClass;
+class VMField;
+class VMObject;
+class VMThread;
+class UTF8;
+
+class VMCond : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  std::vector<VMThread*> threads;
+  
+  static VMCond* allocate();
+
+  void notify();
+  void notifyAll();
+  void wait(VMThread* th);
+  void remove(VMThread* th);
+
+  virtual void tracer(size_t sz);
+};
+
+
+class LockObj : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  mvm::Lock *lock;
+  VMCond* varcond;
+
+  virtual void print(mvm::PrintBuffer* buf) const;
+  virtual void tracer(size_t sz);
+
+  static LockObj* allocate();
+  void aquire();
+  void release();
+  bool owner();
+};
+
+#define VALUE_OFFSET 3
+
+class VMObject : public mvm::Object {
+public:
+  static VirtualTable* VT;
+  VMCommonClass* 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 VMObject* allocate(VMCommonClass* 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(VMCommonClass* cl);
+
+  static llvm::ConstantInt* classOffset();
+  
+  bool instanceOf(VMCommonClass* cl);
+
+
+#ifdef SIGSEGV_THROW_NULL
+  #define verifyNull(obj) {}
+#else
+  #define verifyNull(obj) \
+    if (obj == 0) VMThread::get()->vm->nullPointerException("");
+#endif
+  
+  llvm::GenericValue operator()(VMField* field);
+  void operator()(VMField* field, float val);
+  void operator()(VMField* field, double val);
+  void operator()(VMField* field, sint64 val);
+  void operator()(VMField* field, sint32 val);
+  void operator()(VMField* field, VMObject* val);
+  void operator()(VMField* field, bool val);
+
+};
+
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VMThread.cpp b/vmkit/lib/N3/VMCore/VMThread.cpp
new file mode 100644
index 0000000..4e1485e
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMThread.cpp
@@ -0,0 +1,104 @@
+//===------------ VMThread.cpp - VM thread description --------------------===//
+//
+//                                N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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 "Assembly.h"
+#include "CLIJit.h"
+#include "CLIString.h"
+#include "N3ModuleProvider.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+#include "VirtualMachine.h"
+
+using namespace n3;
+
+const unsigned int VMThread::StateRunning = 0;
+const unsigned int VMThread::StateWaiting = 1;
+const unsigned int VMThread::StateInterrupted = 2;
+
+void VMThread::print(mvm::PrintBuffer* buf) {
+  buf->write("Thread:");
+  vmThread->print(buf);
+}
+
+void VMThread::destroyer(size_t sz) {
+  delete perFunctionPasses;
+}
+
+VMThread* VMThread::get() {
+  return threadKey->get();
+}
+
+extern void AddStandardCompilePasses(llvm::FunctionPassManager*);
+
+VMThread* VMThread::allocate(VMObject* thread, VirtualMachine* vm) {
+  VMThread* key = gc_new(VMThread)();
+  key->vmThread = thread;
+  key->vm = vm;
+  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(vm->TheModuleProvider);
+  key->perFunctionPasses->add(new llvm::TargetData(vm->module)); 
+  AddStandardCompilePasses(key->perFunctionPasses);
+  return key;
+}
+
+VMObject* VMThread::currentThread() {
+  VMThread* result = get();
+  if (result != 0)
+    return result->vmThread;
+  else
+    return 0;
+}
+
+void* VMThread::getCppException() {
+  return (void*)((char*)VMThread::get()->internalPendingException - 8 * sizeof(void*));
+}
+
+VMObject* VMThread::getCLIException() {
+  VMThread* th = VMThread::get();
+  return th->pendingException;
+}
+
+extern "C" void* __cxa_allocate_exception(unsigned);
+extern "C" void __cxa_throw(void*, void*, void*);
+
+
+void VMThread::throwException(VMObject* obj) {
+  VMThread* th = VMThread::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 VMThread::clearException() {
+  VMThread* th = VMThread::get();
+  th->pendingException = 0;
+  th->internalPendingException = 0;
+}
+
+bool VMThread::compareException(VMClass* cl) {
+  VMObject* pe = VMThread::get()->pendingException;
+  assert(pe && "no pending exception?");
+  return pe->classOf->subclassOf(cl);
+}
diff --git a/vmkit/lib/N3/VMCore/VMThread.h b/vmkit/lib/N3/VMCore/VMThread.h
new file mode 100644
index 0000000..390b46c
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VMThread.h
@@ -0,0 +1,67 @@
+//===--------------- VMThread.h - VM thread description -------------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_VM_THREAD_H
+#define N3_VM_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 n3 {
+
+class VirtualMachine;
+class VMClass;
+class VMObject;
+
+class VMThread : public mvm::Object {
+public:
+  static VirtualTable *VT;
+  VMObject* vmThread;
+  VirtualMachine* vm;
+  mvm::Lock* lock;
+  mvm::Cond* varcond;
+  VMObject* pendingException;
+  void* internalPendingException;
+  unsigned int self;
+  unsigned int interruptFlag;
+  unsigned int state;
+
+  static const unsigned int StateRunning;
+  static const unsigned int StateWaiting;
+  static const unsigned int StateInterrupted;
+
+  virtual void print(mvm::PrintBuffer *buf);
+  virtual void tracer(size_t sz);
+  virtual void destroyer(size_t sz);
+  
+  static mvm::Key<VMThread>* threadKey;
+
+  static VMThread* get();
+  static VMThread* allocate(VMObject* thread, VirtualMachine* vm);
+  static VMObject* currentThread();
+  
+  static VMObject* getCLIException();
+  static void* getCppException();
+  static void throwException(VMObject*);
+  static void clearException();
+  static bool compareException(VMClass*);
+
+  llvm::FunctionPassManager* perFunctionPasses;
+  std::vector<jmp_buf*> sjlj_buffers;
+};
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VirtualMachine.cpp b/vmkit/lib/N3/VMCore/VirtualMachine.cpp
new file mode 100644
index 0000000..eeb6ab1
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VirtualMachine.cpp
@@ -0,0 +1,157 @@
+//===------ VirtualMachine.cpp - Virtual machine description --------------===//
+//
+//                                N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+#include <stdarg.h>
+
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+
+#include "types.h"
+
+#include "Assembly.h"
+#include "CLIString.h"
+#include "LockedMap.h"
+#include "N3ModuleProvider.h"
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMClass.h"
+
+using namespace n3;
+
+#define DECLARE_EXCEPTION(EXCP) \
+  const char* VirtualMachine::EXCP = #EXCP
+
+DECLARE_EXCEPTION(SystemException);
+DECLARE_EXCEPTION(OverFlowException);
+DECLARE_EXCEPTION(OutOfMemoryException);
+DECLARE_EXCEPTION(IndexOutOfRangeException);
+DECLARE_EXCEPTION(NullReferenceException);
+DECLARE_EXCEPTION(SynchronizationLocException);
+DECLARE_EXCEPTION(ThreadInterruptedException);
+DECLARE_EXCEPTION(MissingMethodException);
+DECLARE_EXCEPTION(MissingFieldException);
+DECLARE_EXCEPTION(ArrayTypeMismatchException);
+DECLARE_EXCEPTION(ArgumentException);
+
+/*
+DECLARE_EXCEPTION(ArithmeticException);
+DECLARE_EXCEPTION(InvocationTargetException);
+DECLARE_EXCEPTION(ArrayStoreException);
+DECLARE_EXCEPTION(ClassCastException);
+DECLARE_EXCEPTION(ArrayIndexOutOfBoundsException);
+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(StackOverflowError);
+DECLARE_EXCEPTION(ClassNotFoundException);
+*/
+
+#undef DECLARE_EXCEPTION
+void ThreadSystem::print(mvm::PrintBuffer* buf) const {
+  buf->write("ThreadSystem<>");
+}
+
+ThreadSystem* ThreadSystem::allocateThreadSystem() {
+  ThreadSystem* res = gc_new(ThreadSystem)();
+  res->nonDaemonThreads = 1;
+  res->nonDaemonLock = mvm::Lock::allocNormal();
+  res->nonDaemonVar  = mvm::Cond::allocCond();
+  return res;
+}
+
+const UTF8* VirtualMachine::asciizConstructUTF8(const char* asciiz) {
+  return hashUTF8->lookupOrCreateAsciiz(asciiz);
+}
+
+const UTF8* VirtualMachine::readerConstructUTF8(const uint16* buf, uint32 len) {
+  return hashUTF8->lookupOrCreateReader(buf, len);
+}
+
+void VirtualMachine::error(const char* className, const char* fmt, va_list ap) {
+  fprintf(stderr, "Internal exception of type %s during bootstrap: ", className);
+  vfprintf(stderr, fmt, ap);
+  abort();
+}
+
+void VirtualMachine::indexOutOfBounds(const VMObject* obj, sint32 entry) {
+  error(IndexOutOfRangeException, "%d", entry);
+}
+
+void VirtualMachine::negativeArraySizeException(sint32 size) {
+  error(OverFlowException, "%d", size);
+}
+
+void VirtualMachine::nullPointerException(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  error(NullReferenceException, fmt, va_arg(ap, char*));
+}
+
+
+void VirtualMachine::illegalMonitorStateException(const VMObject* obj) {
+  error(SynchronizationLocException, "");
+}
+
+void VirtualMachine::interruptedException(const VMObject* obj) {
+  error(ThreadInterruptedException, "");
+}
+
+void VirtualMachine::outOfMemoryError(sint32 n) {
+  error(OutOfMemoryException, "");
+}
+
+void VirtualMachine::arrayStoreException() {
+  error(ArrayTypeMismatchException, "");
+}
+
+void VirtualMachine::illegalArgumentException(const char* name) {
+  error(ArgumentException, name);
+}
+
+void VirtualMachine::unknownError(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  error(SystemException, fmt, ap);
+}
+
+void VirtualMachine::error(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  error(SystemException, fmt, ap);
+}
+
+void VirtualMachine::error(const char* name, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  error(name, fmt, ap);
+}
+
+void VirtualMachine::destroyer(size_t sz) {
+  delete module;
+  delete TheModuleProvider;
+}
diff --git a/vmkit/lib/N3/VMCore/VirtualMachine.h b/vmkit/lib/N3/VMCore/VirtualMachine.h
new file mode 100644
index 0000000..bf9a1c7
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VirtualMachine.h
@@ -0,0 +1,129 @@
+//===------- VirtualMachine.h - Virtual machine description ---------------===//
+//
+//                              N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef N3_VIRTUAL_MACHINE_H
+#define N3_VIRTUAL_MACHINE_H
+
+#include <vector>
+
+#include "llvm/Function.h"
+
+#include "mvm/Object.h"
+#include "mvm/PrintBuffer.h"
+#include "mvm/Threads/Cond.h"
+#include "mvm/Threads/Locks.h"
+
+#include "types.h"
+
+namespace n3 {
+
+class FunctionMap;
+class N3ModuleProvider;
+class UTF8;
+class UTF8Map;
+class VMObject;
+class VMThread;
+
+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 VirtualMachine : public mvm::Object{
+public:
+  static VirtualTable* VT;
+  ThreadSystem* threadSystem; 
+ 
+  const UTF8*   asciizConstructUTF8(const char* asciiz);
+  const UTF8*   readerConstructUTF8(const uint16* buf, uint32 len);
+  UTF8Map * hashUTF8;
+
+  
+  // Exceptions name
+  static const char* SystemException;
+  static const char* OverFlowException;
+  static const char* OutOfMemoryException;
+  static const char* IndexOutOfRangeException;
+  static const char* SynchronizationLocException;
+  static const char* NullReferenceException;
+  static const char* ThreadInterruptedException;
+  static const char* MissingMethodException;
+  static const char* MissingFieldException;
+  static const char* ArrayTypeMismatchException;
+  static const char* ArgumentException;
+  /*static const char* ArithmeticException;
+  static const char* ClassNotFoundException;
+  static const char* InvocationTargetException;
+  static const char* ClassCastException;
+  static const char* ArrayIndexOutOfBoundsException;
+  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* StackOverflowError;
+  */
+  // Exceptions
+  
+  /*
+  void illegalAccessException(const char* msg);
+  void initializerError(const VMObject* excp);
+  void invocationTargetException(const VMObject* obj);
+  void classCastException(const char* msg);
+  void errorWithExcp(const char* className, const VMObject* excp);*/
+  void illegalArgumentException(const char* msg);
+  void arrayStoreException();
+  void illegalMonitorStateException(const VMObject* obj);
+  void interruptedException(const VMObject* obj);
+  void nullPointerException(const char* fmt, ...);
+  void outOfMemoryError(sint32 n);
+  void indexOutOfBounds(const VMObject* obj, sint32 entry);
+  void negativeArraySizeException(int size);
+  void unknownError(const char* fmt, ...); 
+  void error(const char* fmt, ...);
+  void error(const char* className, const char* fmt, ...);
+  void error(const char* className, const char* fmt, va_list ap);
+
+  
+  virtual void tracer(size_t sz);
+  virtual void print(mvm::PrintBuffer* buf) const {
+    buf->write("Virtual Machine<>");
+  }
+
+  virtual void destroyer(size_t sz);
+  
+  mvm::Lock* protectModule;
+  FunctionMap* functions;
+  llvm::Module* module;
+  N3ModuleProvider* TheModuleProvider;
+  VMThread* bootstrapThread;
+};
+
+} // end namespace n3
+
+#endif
diff --git a/vmkit/lib/N3/VMCore/VirtualTables.cpp b/vmkit/lib/N3/VMCore/VirtualTables.cpp
new file mode 100644
index 0000000..bc7e92a
--- /dev/null
+++ b/vmkit/lib/N3/VMCore/VirtualTables.cpp
@@ -0,0 +1,292 @@
+//===----- VirtualTables.cpp - Virtual methods for N3 objects -------------===//
+//
+//                                N3
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mvm/Object.h"
+
+#include "Assembly.h"
+#include "CLIString.h"
+#include "CLIJit.h"
+#include "LockedMap.h"
+#include "N3.h"
+#include "Reader.h"
+#include "VirtualMachine.h"
+#include "VMArray.h"
+#include "VMCache.h"
+#include "VMClass.h"
+#include "VMObject.h"
+#include "VMThread.h"
+
+using namespace n3;
+
+#define INIT(X) VirtualTable* X::VT = 0
+
+  INIT(VMArray);
+  INIT(ArrayUInt8);
+  INIT(ArraySInt8);
+  INIT(ArrayUInt16);
+  INIT(ArraySInt16);
+  INIT(ArrayUInt32);
+  INIT(ArraySInt32);
+  INIT(ArrayLong);
+  INIT(ArrayFloat);
+  INIT(ArrayDouble);
+  INIT(ArrayObject);
+  INIT(UTF8);
+  INIT(VMCommonClass);
+  INIT(VMClass);
+  INIT(VMClassArray);
+  INIT(VMClassPointer);
+  INIT(VMMethod);
+  INIT(VMField);
+  INIT(VMCond);
+  INIT(LockObj);
+  INIT(VMObject);
+  INIT(VMThread);
+  INIT(VirtualMachine);
+  INIT(UTF8Map);
+  INIT(ClassNameMap);
+  INIT(ClassTokenMap);
+  INIT(FieldTokenMap);
+  INIT(MethodTokenMap);
+  INIT(StringMap);
+  INIT(FunctionMap);
+  INIT(N3);
+  INIT(Assembly);
+  INIT(Section);
+  INIT(Stream);
+  INIT(Table);
+  INIT(Header);
+  INIT(AssemblyMap);
+  INIT(ThreadSystem);
+  INIT(CLIString);
+  INIT(Property);
+  INIT(Param);
+  INIT(CacheNode);
+  INIT(Enveloppe);
+  INIT(Reader);
+  INIT(Opinfo);
+  INIT(CLIJit);
+  INIT(Exception);
+  
+#undef INIT
+
+void Opinfo::tracer(size_t sz) {
+}
+
+void CLIJit::tracer(size_t sz) {
+  compilingMethod->markAndTrace();
+  compilingClass->markAndTrace();
+}
+
+void ThreadSystem::tracer(size_t sz) {
+  //nonDaemonLock->markAndTrace();
+  //nonDaemonVar->markAndTrace();
+}
+
+void Reader::tracer(size_t sz) {
+  bytes->markAndTrace();
+}
+
+void CacheNode::tracer(size_t sz) {
+  ((mvm::Object*)methPtr)->markAndTrace();
+  lastCible->markAndTrace();
+  next->markAndTrace();
+  enveloppe->markAndTrace();
+}
+
+void Enveloppe::tracer(size_t sz) {
+  firstCache->markAndTrace();
+  //cacheLock->markAndTrace();
+  originalMethod->markAndTrace();
+}
+
+void VMArray::tracer(size_t sz) {
+  VMObject::tracer(sz);
+}
+
+void ArrayObject::tracer(size_t sz) {
+  VMObject::tracer(sz);
+  for (sint32 i = 0; i < size; i++) {
+    elements[i]->markAndTrace();
+  }
+}
+
+#define ARRAYTRACER(name)         \
+  void name::tracer(size_t sz) {  \
+    VMObject::tracer(sz);         \
+  }
+  
+
+ARRAYTRACER(ArrayUInt8);
+ARRAYTRACER(ArraySInt8);
+ARRAYTRACER(ArrayUInt16);
+ARRAYTRACER(ArraySInt16);
+ARRAYTRACER(ArrayUInt32);
+ARRAYTRACER(ArraySInt32);
+ARRAYTRACER(ArrayLong);
+ARRAYTRACER(ArrayFloat);
+ARRAYTRACER(ArrayDouble);
+
+#undef ARRAYTRACER
+
+
+#define TRACE_VECTOR(type,name) { \
+  for (std::vector<type>::iterator i = name.begin(), e = name.end(); \
+       i!= e; ++i) {                                                    \
+    (*i)->markAndTrace(); }}
+
+void VMCommonClass::tracer(size_t sz) {
+  name->markAndTrace();
+  nameSpace->markAndTrace();
+  super->markAndTrace();
+  TRACE_VECTOR(VMClass*, interfaces);
+  //lockVar->markAndTrace();
+  //condVar->markAndTrace();
+  TRACE_VECTOR(VMMethod*, virtualMethods);
+  TRACE_VECTOR(VMMethod*, staticMethods);
+  TRACE_VECTOR(VMField*, virtualFields);
+  TRACE_VECTOR(VMField*, staticFields);
+  delegatee->markAndTrace();
+  TRACE_VECTOR(VMCommonClass*, display);
+  vm->markAndTrace();
+
+  assembly->markAndTrace();
+  //funcs->markAndTrace();
+  TRACE_VECTOR(Property*, properties);
+  codeVirtualTracer->markAndTrace();
+  codeStaticTracer->markAndTrace();
+}
+
+void VMClass::tracer(size_t sz) {
+  VMCommonClass::tracer(sz);
+  staticInstance->markAndTrace();
+  virtualInstance->markAndTrace();
+  TRACE_VECTOR(VMClass*, innerClasses);
+  outerClass->markAndTrace();
+}
+
+void VMClassArray::tracer(size_t sz) {
+  VMCommonClass::tracer(sz);
+  baseClass->markAndTrace();
+}
+
+void VMClassPointer::tracer(size_t sz) {
+  VMCommonClass::tracer(sz);
+  baseClass->markAndTrace();
+}
+
+
+void VMMethod::tracer(size_t sz) {
+  delegatee->markAndTrace();
+  //signature->markAndTrace();
+  classDef->markAndTrace();
+  TRACE_VECTOR(Param*, params);
+  TRACE_VECTOR(Enveloppe*, caches);
+  name->markAndTrace();
+  code->markAndTrace();
+}
+
+void VMField::tracer(size_t sz) {
+  signature->markAndTrace();
+  classDef->markAndTrace();
+  name->markAndTrace();
+}
+
+void VMCond::tracer(size_t sz) {
+  TRACE_VECTOR(VMThread*, threads);
+}
+
+void LockObj::tracer(size_t sz) {
+  //lock->markAndTrace();
+  varcond->markAndTrace();
+}
+
+void VMObject::tracer(size_t sz) {
+  classOf->markAndTrace();
+  lockObj->markAndTrace();
+}
+
+void VMThread::tracer(size_t sz) {
+  vmThread->markAndTrace();
+  vm->markAndTrace();
+  //lock->markAndTrace();
+  //varcond->markAndTrace();
+  pendingException->markAndTrace();
+}
+
+void VirtualMachine::tracer(size_t sz) {
+  threadSystem->markAndTrace();
+  hashUTF8->markAndTrace();
+  functions->markAndTrace();
+  //protectModule->markAndTrace();
+  bootstrapThread->markAndTrace();
+}
+
+void Param::tracer(size_t sz) {
+  method->markAndTrace();
+  name->markAndTrace();
+}
+
+void Property::tracer(size_t sz) {
+  type->markAndTrace();
+  //signature->markAndTrace();
+  name->markAndTrace();
+  delegatee->markAndTrace();
+}
+
+void Assembly::tracer(size_t sz) {
+  loadedNameClasses->markAndTrace();
+  loadedTokenClasses->markAndTrace();
+  loadedTokenMethods->markAndTrace();
+  loadedTokenFields->markAndTrace();
+  //lockVar->markAndTrace();
+  //condVar->markAndTrace();
+  name->markAndTrace();
+  bytes->markAndTrace();
+  textSection->markAndTrace();
+  rsrcSection->markAndTrace();
+  relocSection->markAndTrace();
+  CLIHeader->markAndTrace();
+  vm->markAndTrace();
+  delegatee->markAndTrace();
+  // TODO trace assembly refs...
+}
+
+void N3::tracer(size_t sz) {
+  VirtualMachine::tracer(sz);
+  hashUTF8->markAndTrace();
+  hashStr->markAndTrace();
+  loadedAssemblies->markAndTrace();
+}
+
+void Section::tracer(size_t sz) {
+}
+
+void Stream::tracer(size_t sz) {
+}
+
+void Table::tracer(size_t sz) {
+}
+
+void Header::tracer(size_t sz) {
+  versionName->markAndTrace();
+  tildStream->markAndTrace();
+  stringStream->markAndTrace();
+  usStream->markAndTrace();
+  blobStream->markAndTrace();
+  guidStream->markAndTrace();
+  TRACE_VECTOR(Table*, tables);
+}
+
+void CLIString::tracer(size_t sz) {
+}
+
+void Exception::tracer(size_t sz) {
+  catchClass->markAndTrace();
+}
diff --git a/vmkit/lib/N3/pnet-0.7.4.patch b/vmkit/lib/N3/pnet-0.7.4.patch
new file mode 100644
index 0000000..dd806fb
--- /dev/null
+++ b/vmkit/lib/N3/pnet-0.7.4.patch
@@ -0,0 +1,72 @@
+--- pnet-0.7.4/configure.in	2006-01-15 06:17:01.000000000 +0100
++++ pnet-0.7.4/configure.in	2006-12-19 11:03:05.000000000 +0100
+@@ -19,6 +19,7 @@
+ AC_PROG_RANLIB
+ AC_PROG_YACC
+ AM_PROG_LEX
++AM_PROG_LIBTOOL
+ 
+ AC_PATH_PROG(TREECC, treecc,, ${prefix}/bin:$PATH)
+ if test -z "$TREECC" ; then
+ 
+--- pnet-0.7.4/engine/Makefile.am	2005-12-19 19:00:35.000000000 +0100
++++ /home/varth/project/pnet-0.7.4/engine/Makefile.am	2006-12-19 11:17:07.000000000 +0100
+@@ -1,4 +1,5 @@
+ bin_PROGRAMS = ilrun ilverify
++lib_LTLIBRARIES = libStdio.la libTime.la
+ lib_LIBRARIES = libILEngine.a
+ man_MANS = ilrun.1 ilverify.1
+ 
+@@ -76,6 +77,11 @@
+ 							  $(UNROLL_INCLUDES) \
+ 							  $(VERIFY_INCLUDES)
+ 
++
++libStdio_la_SOURCES = lib_stdio.c
++libTime_la_SOURCES = lib_time.c
++
++
+ BUILT_SOURCES = gen_marshal.c \
+ 				gen_marshal.h
+ 
+--- pnet-0.7.4/support/Makefile.am	2005-08-22 14:39:20.000000000 +0200
++++ pnet-0.7.4/support/Makefile.am	2006-12-19 19:18:10.000000000 +0100
+@@ -1,3 +1,4 @@
++lib_LTLIBRARIES = libILSupport.la
+ lib_LIBRARIES = libILSupport.a
+ noinst_PROGRAMS = mkcategory mknumber mkcase
+ EXTRA_DIST = gen_errno.sh
+@@ -8,7 +9,7 @@
+ 
+ BUILT_SOURCES = errno_map.c
+ 
+-libILSupport_a_SOURCES = aes.c \
++libILSupport_la_SOURCES = aes.c \
+ 						 allocate.c \
+ 						 ansi.c \
+ 						 bignum.c \
+@@ -30,7 +31,6 @@
+ 						 guid.c \
+ 						 hash.c \
+ 						 hashtab.c \
+-						 hb_gc.c \
+ 						 interlocked.h \
+ 						 interlocked_any.h \
+ 						 interlocked_x86.h \
+@@ -85,6 +85,8 @@
+ 						 write_float.c \
+ 						 xml.c
+ 
++libILSupport_a_SOURCES = $(libILSupport_la_SOURCES) hb_gc.c
++
+ mkcategory_SOURCES = mkcategory.c
+ 
+ mknumber_SOURCES = mknumber.c
+--- pnet-0.7.4/auto_gen.sh	2002-12-01 23:58:37.000000000 +0100
++++ pnet-0.7.4/auto_gen.sh	2006-12-19 11:05:39.000000000 +0100
+@@ -34,4 +34,5 @@
+ # Run automake and autoconf.
+ automake --add-missing --copy $AM_FLAGS
+ autoconf
++libtoolize --copy --force
+ exit 0
diff --git a/vmkit/vmkit-llvm-2.2.patch b/vmkit/vmkit-llvm-2.2.patch
new file mode 100644
index 0000000..914a85d
--- /dev/null
+++ b/vmkit/vmkit-llvm-2.2.patch
@@ -0,0 +1,2026 @@
+Index: include/llvm/Target/TargetOptions.h
+===================================================================
+--- include/llvm/Target/TargetOptions.h	(revision 46321)
++++ include/llvm/Target/TargetOptions.h	(working copy)
+@@ -74,10 +74,15 @@
+   /// be emitted.
+   extern bool ExceptionHandling;
+ 
++  /// SizedMemoryCode - This flags indicates that memory for code is allocated by
++  /// an external allocator which requires the size to allocate
++  extern bool SizedMemoryCode;
++
+   /// PerformTailCallOpt - This flag is enabled when -tailcallopt is specified
+   /// on the commandline. When the flag is on, the target will perform tail call
+   /// optimization (pop the caller's stack) providing it supports it.
+   extern bool PerformTailCallOpt;
++
+ } // End llvm namespace
+ 
+ #endif
+Index: include/llvm/ExecutionEngine/ExecutionEngine.h
+===================================================================
+--- include/llvm/ExecutionEngine/ExecutionEngine.h	(revision 46321)
++++ include/llvm/ExecutionEngine/ExecutionEngine.h	(working copy)
+@@ -85,6 +85,11 @@
+   /// pointer is invoked to create it. If this returns null, the JIT will abort.
+   void* (*LazyFunctionCreator)(const std::string &);
+   
++  /// ExceptionTableRegister - If Exception Handling is set, the JIT will 
++  /// register dwarf tables with this function
++  typedef void (*EERegisterFn)(void*);
++  static EERegisterFn ExceptionTableRegister;
++
+ public:
+   /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and
+   /// JITEmitter classes.  It must be held while changing the internal state of
+@@ -247,6 +252,14 @@
+     LazyFunctionCreator = P;
+   }
+ 
++  static void InstallExceptionTableRegister(void (*F)(void*)) {
++    ExceptionTableRegister = F;
++  }
++
++  static void RegisterTable(void* res) {
++    ExceptionTableRegister(res);
++  }
++
+ protected:
+   explicit ExecutionEngine(ModuleProvider *P);
+ 
+Index: include/llvm/ExecutionEngine/JITMemoryManager.h
+===================================================================
+--- include/llvm/ExecutionEngine/JITMemoryManager.h	(revision 46321)
++++ include/llvm/ExecutionEngine/JITMemoryManager.h	(working copy)
+@@ -89,6 +89,17 @@
+   /// deallocateMemForFunction - Free JIT memory for the specified function.
+   /// This is never called when the JIT is currently emitting a function.
+   virtual void deallocateMemForFunction(const Function *F) = 0;
++  
++  /// startExceptionTable - When we finished JITing the function, if exception
++  /// handling is set, we emit the exception table.
++  virtual unsigned char* startExceptionTable(const Function* F,
++                                             uintptr_t &ActualSize) = 0;
++  
++  /// endExceptionTable - This method is called when the JIT is done emitting
++  /// the exception table.
++  virtual void endExceptionTable(const Function *F, unsigned char *TableStart,
++                                 unsigned char *TableEnd, 
++                                 unsigned char* FrameRegister) = 0;
+ };
+ 
+ } // end namespace llvm.
+Index: include/llvm/CodeGen/SizeEmitter.h
+===================================================================
+--- include/llvm/CodeGen/SizeEmitter.h	(revision 0)
++++ include/llvm/CodeGen/SizeEmitter.h	(revision 0)
+@@ -0,0 +1,116 @@
++//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file was developed by the LLVM research group and is distributed under
++// the University of Illinois Open Source License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++//
++// This file defines an abstract interface that is used by the machine code
++// emission framework to output the code.  This allows machine code emission to
++// be separated from concerns such as resolution of call targets, and where the
++// machine code will be written (memory or disk, f.e.).
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef LLVM_CODEGEN_SIZEEMITTER_H
++#define LLVM_CODEGEN_SIZEEMITTER_H
++
++#include "llvm/CodeGen/MachineCodeEmitter.h"
++#include "llvm/CodeGen/MachineFunction.h"
++
++namespace llvm {
++  /// SizeEmitter - The JIT implementation of the MachineCodeEmitter, which is
++  /// used to output functions to memory for execution.
++class SizeEmitter : public MachineCodeEmitter {
++  MachineFunction * Fn;
++  void* ConstantPoolBase;
++  void* JumpTableBase;
++  MachineConstantPool *ConstantPool;
++  MachineJumpTableInfo *JumpTable;
++  std::vector<intptr_t> LabelLocations;
++  MachineCodeEmitter* MCE;
++
++public:
++  SizeEmitter(MachineCodeEmitter* mce) { 
++    CurBufferPtr = 0; 
++    BufferBegin = 0; 
++    BufferEnd = (unsigned char*)-1;
++    MCE = mce;
++  }
++
++  SizeEmitter(std::vector<intptr_t> locations) {
++    LabelLocations = locations;
++    CurBufferPtr = 0; 
++    BufferBegin = 0; 
++    BufferEnd = (unsigned char*)-1;
++  }
++  
++  void initConstantPool(MachineConstantPool *MCP);
++
++  void initJumpTableInfo(MachineJumpTableInfo *MJTI);
++
++
++  virtual void startFunction(MachineFunction &F) { 
++    CurBufferPtr = 0; 
++    Fn = &F;
++  
++    // Ensure the constant pool/jump table info is at least 4-byte aligned.
++    emitAlignment(16);
++
++    initConstantPool(F.getConstantPool());
++    initJumpTableInfo(F.getJumpTableInfo());
++   
++    ConstantPoolBase  = (void*)(((unsigned) ConstantPoolBase) + CurBufferPtr);
++    JumpTableBase     = (void*)(((unsigned) JumpTableBase) + CurBufferPtr);
++  }
++
++  virtual bool finishFunction(MachineFunction &F) { 
++    MCE->setCurrentPtr(CurBufferPtr);
++    return false;
++  }
++  virtual void startFunctionStub(unsigned StubSize, unsigned Alignment) {}
++  virtual void *finishFunctionStub(const Function *F) { return 0; }
++  virtual void addRelocation(const llvm::MachineRelocation&) { }
++  virtual void emitByte(unsigned char B) {
++    CurBufferPtr++;
++  }
++  virtual void emitWordLE(unsigned W) {
++    CurBufferPtr+=4;
++  }   
++  virtual void emitWordBE(unsigned W) {
++    CurBufferPtr+=4;
++  }
++  virtual void emitInt32(int Value) {
++    CurBufferPtr += 4;
++  }
++  virtual void emitInt64(uint64_t Value) {
++    CurBufferPtr += 8;
++  }
++  virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
++  }  
++
++
++
++  virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {}
++  virtual intptr_t getConstantPoolEntryAddress(unsigned ConstantNum) const;
++
++  virtual intptr_t getJumpTableEntryAddress(unsigned Index) const;
++
++  virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
++    assert(0 && "Should not be in getMachineBasicBlockAddress of SizeEmitter");
++  }
++  
++  virtual void EmitLabel(uint64_t) {}
++  virtual intptr_t getLabelAddress(uint64_t LabelID) const {
++    assert(LabelLocations.size() > (unsigned)LabelID && 
++             LabelLocations[LabelID] && "Label not emitted!");
++      return LabelLocations[LabelID];
++  }
++  virtual void setModuleInfo(llvm::MachineModuleInfo*) {}
++};
++
++} // end llvm namespace
++
++#endif
+Index: include/llvm/CodeGen/MachineCodeEmitter.h
+===================================================================
+--- include/llvm/CodeGen/MachineCodeEmitter.h	(revision 46321)
++++ include/llvm/CodeGen/MachineCodeEmitter.h	(working copy)
+@@ -18,6 +18,7 @@
+ #define LLVM_CODEGEN_MACHINECODEEMITTER_H
+ 
+ #include "llvm/Support/DataTypes.h"
++#include <string>
+ #include <vector>
+ 
+ namespace llvm {
+@@ -26,6 +27,7 @@
+ class MachineConstantPool;
+ class MachineJumpTableInfo;
+ class MachineFunction;
++class MachineModuleInfo;
+ class MachineRelocation;
+ class Value;
+ class GlobalValue;
+@@ -91,7 +93,7 @@
+   /// emitByte - This callback is invoked when a byte needs to be written to the
+   /// output stream.
+   ///
+-  void emitByte(unsigned char B) {
++  virtual void emitByte(unsigned char B) {
+     if (CurBufferPtr != BufferEnd)
+       *CurBufferPtr++ = B;
+   }
+@@ -99,7 +101,7 @@
+   /// emitWordLE - This callback is invoked when a 32-bit word needs to be
+   /// written to the output stream in little-endian format.
+   ///
+-  void emitWordLE(unsigned W) {
++  virtual void emitWordLE(unsigned W) {
+     if (CurBufferPtr+4 <= BufferEnd) {
+       *CurBufferPtr++ = (unsigned char)(W >>  0);
+       *CurBufferPtr++ = (unsigned char)(W >>  8);
+@@ -113,7 +115,7 @@
+   /// emitWordBE - This callback is invoked when a 32-bit word needs to be
+   /// written to the output stream in big-endian format.
+   ///
+-  void emitWordBE(unsigned W) {
++  virtual void emitWordBE(unsigned W) {
+     if (CurBufferPtr+4 <= BufferEnd) {
+       *CurBufferPtr++ = (unsigned char)(W >> 24);
+       *CurBufferPtr++ = (unsigned char)(W >> 16);
+@@ -136,6 +138,64 @@
+       CurBufferPtr = BufferEnd;
+   }
+   
++  /// EmitULEB128Bytes - This callback is invoked when a ULEB128 needs to be
++  /// written to the output stream.
++  void emitULEB128Bytes(unsigned Value) {
++    do {
++      unsigned char Byte = Value & 0x7f;
++      Value >>= 7;
++      if (Value) Byte |= 0x80;
++      emitByte(Byte);
++    } while (Value);
++  }
++  
++  /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
++  /// written to the output stream.
++  void emitSLEB128Bytes(int Value) {
++    int Sign = Value >> (8 * sizeof(Value) - 1);
++    bool IsMore;
++  
++    do {
++      unsigned char Byte = Value & 0x7f;
++      Value >>= 7;
++      IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
++      if (IsMore) Byte |= 0x80;
++      emitByte(Byte);
++    } while (IsMore);
++  }
++
++  void emitString(const std::string &String) {
++    for (unsigned i = 0, N = String.size(); i < N; ++i) {
++      unsigned char C = String[i];
++      emitByte(C);
++    }
++    emitByte(0);
++  }
++  
++  virtual void emitInt32(int Value) {
++    if (CurBufferPtr+4 <= BufferEnd) {
++      *((uint32_t*)CurBufferPtr) = Value;
++      CurBufferPtr += 4;
++    } else {
++      CurBufferPtr = BufferEnd;
++    }
++  }
++
++  /// EmitInt64 - Emit a long long directive and value.
++  virtual void emitInt64(uint64_t Value) {
++    if (CurBufferPtr+8 <= BufferEnd) {
++      *((uint64_t*)CurBufferPtr) = Value;
++      CurBufferPtr += 8;
++    } else {
++      CurBufferPtr = BufferEnd;
++    }
++  }
++
++  virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
++    (*Addr) = Value;
++  }
++
++
+   /// allocateSpace - Allocate a block of space in the current output buffer,
+   /// returning null (and setting conditions to indicate buffer overflow) on
+   /// failure.  Alignment is the alignment in bytes of the buffer desired.
+@@ -159,6 +219,9 @@
+   /// start of the block is, and can implement getMachineBasicBlockAddress.
+   virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0;
+   
++  virtual void EmitLabel(uint64_t LabelID) = 0;
++
++
+   /// getCurrentPCValue - This returns the address that the next emitted byte
+   /// will be output to.
+   ///
+@@ -194,6 +257,17 @@
+   /// emitted.
+   ///
+   virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0;
++  
++  /// getLabelAddress - Return the address of the specified LabelID, only usable
++  /// after the LabelID has been emitted.
++  ///
++  virtual intptr_t getLabelAddress(uint64_t LabelID) const = 0;
++
++  virtual void setModuleInfo(MachineModuleInfo* Info) = 0;
++
++  void setCurrentPtr(unsigned char* Ptr) {
++    CurBufferPtr = Ptr;
++  }
+ };
+ 
+ } // End llvm namespace
+Index: lib/CodeGen/LLVMTargetMachine.cpp
+===================================================================
+--- lib/CodeGen/LLVMTargetMachine.cpp	(revision 46321)
++++ lib/CodeGen/LLVMTargetMachine.cpp	(working copy)
+@@ -17,6 +17,7 @@
+ #include "llvm/Assembly/PrintModulePass.h"
+ #include "llvm/Analysis/LoopPass.h"
+ #include "llvm/CodeGen/Passes.h"
++#include "llvm/CodeGen/SizeEmitter.h"
+ #include "llvm/CodeGen/Collector.h"
+ #include "llvm/Target/TargetOptions.h"
+ #include "llvm/Transforms/Scalar.h"
+@@ -187,7 +188,8 @@
+   PM.add(createGCLoweringPass());
+   
+   // FIXME: Implement the invoke/unwind instructions!
+-  PM.add(createLowerInvokePass(getTargetLowering()));
++  if (!ExceptionHandling)
++    PM.add(createLowerInvokePass(getTargetLowering()));
+   
+   // Make sure that no unreachable blocks are instruction selected.
+   PM.add(createUnreachableBlockEliminationPass());
+@@ -251,7 +253,13 @@
+   
+   if (addPreEmitPass(PM, Fast) && PrintMachineCode)
+     PM.add(createMachineFunctionPrinterPass(cerr));
++  
++  if (SizedMemoryCode) {
++    SizeEmitter * SE = new SizeEmitter(&MCE);
++    addSimpleCodeEmitter(PM, Fast, false, *SE);
++  }
+ 
++
+   addCodeEmitter(PM, Fast, PrintEmittedAsm, MCE);
+   
+   PM.add(createCollectorMetadataDeleter());
+Index: lib/CodeGen/ELFWriter.cpp
+===================================================================
+--- lib/CodeGen/ELFWriter.cpp	(revision 46321)
++++ lib/CodeGen/ELFWriter.cpp	(working copy)
+@@ -98,6 +98,18 @@
+       return 0;
+     }
+ 
++    virtual intptr_t getLabelAddress(uint64_t Label) const {
++      assert(0 && "JT not implementated yet!");
++      return 0;
++    }
++
++    virtual void EmitLabel(uint64_t LabelID) {
++    }
++
++
++    virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
++
++
+     /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
+     void startFunctionStub(unsigned StubSize, unsigned Alignment = 1) {
+       assert(0 && "JIT specific function called!");
+Index: lib/CodeGen/SizeEmitter.cpp
+===================================================================
+--- lib/CodeGen/SizeEmitter.cpp	(revision 0)
++++ lib/CodeGen/SizeEmitter.cpp	(revision 0)
+@@ -0,0 +1,77 @@
++#include "llvm/CodeGen/SizeEmitter.h"
++#include "llvm/Constant.h"
++#include "llvm/Constants.h"
++#include "llvm/DerivedTypes.h"
++#include "llvm/Module.h"
++#include "llvm/Type.h"
++#include "llvm/CodeGen/MachineCodeEmitter.h"
++#include "llvm/CodeGen/MachineFunction.h"
++#include "llvm/CodeGen/MachineConstantPool.h"
++#include "llvm/CodeGen/MachineJumpTableInfo.h"
++#include "llvm/CodeGen/MachineRelocation.h"
++#include "llvm/ExecutionEngine/GenericValue.h"
++#include "llvm/Target/TargetData.h"
++#include "llvm/Target/TargetJITInfo.h"
++#include "llvm/Target/TargetMachine.h"
++#include "llvm/Target/TargetOptions.h"
++#include "llvm/Support/Debug.h"
++#include "llvm/Support/MutexGuard.h"
++#include "llvm/System/Disassembler.h"
++#include "llvm/ADT/Statistic.h"
++#include "llvm/System/Memory.h"
++#include <algorithm>
++using namespace llvm;
++
++
++void SizeEmitter::initConstantPool(MachineConstantPool *MCP) {
++  const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
++  if (Constants.empty()) return;
++
++  MachineConstantPoolEntry CPE = Constants.back();
++  unsigned Size = CPE.Offset;
++  const Type *Ty = CPE.isMachineConstantPoolEntry()
++    ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
++  Size += Fn->getTarget().getTargetData()->getABITypeSize(Ty);
++  ConstantPoolBase = allocateSpace(Size, 1 << MCP->getConstantPoolAlignment());
++  ConstantPool = MCP;
++}
++
++void SizeEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) {
++  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
++  if (JT.empty()) return;
++  
++  unsigned NumEntries = 0;
++  for (unsigned i = 0, e = JT.size(); i != e; ++i)
++    NumEntries += JT[i].MBBs.size();
++
++  unsigned EntrySize = MJTI->getEntrySize();
++
++  // Just allocate space for all the jump tables now.  We will fix up the actual
++  // MBB entries in the tables after we emit the code for each block, since then
++  // we will know the final locations of the MBBs in memory.
++  JumpTable = MJTI;
++  JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment());
++}
++
++intptr_t SizeEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const {
++  assert(ConstantNum < ConstantPool->getConstants().size() &&
++         "Invalid ConstantPoolIndex!");
++  return (intptr_t)ConstantPoolBase +
++         ConstantPool->getConstants()[ConstantNum].Offset;
++}
++
++intptr_t SizeEmitter::getJumpTableEntryAddress(unsigned Index) const {
++  const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables();
++  assert(Index < JT.size() && "Invalid jump table index!");
++  
++  unsigned Offset = 0;
++  unsigned EntrySize = JumpTable->getEntrySize();
++  
++  for (unsigned i = 0; i < Index; ++i)
++    Offset += JT[i].MBBs.size();
++  
++   Offset *= EntrySize;
++  
++  return (intptr_t)((char *)JumpTableBase + Offset);
++}
++
+Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+===================================================================
+--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	(revision 46321)
++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	(working copy)
+@@ -148,6 +148,7 @@
+                                       SelectionDAG *DAG,
+                                       MachineBasicBlock *BB) {
+     TargetLowering &TLI = IS->getTargetLowering();
++      return createBURRListDAGScheduler(IS, DAG, BB);
+     
+     if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency) {
+       return createTDListDAGScheduler(IS, DAG, BB);
+Index: lib/CodeGen/MachOWriter.cpp
+===================================================================
+--- lib/CodeGen/MachOWriter.cpp	(revision 46321)
++++ lib/CodeGen/MachOWriter.cpp	(working copy)
+@@ -125,6 +125,20 @@
+       return MBBLocations[MBB->getNumber()];
+     }
+ 
++    virtual intptr_t getLabelAddress(uint64_t Label) const {
++      assert(0 && "Implement me");
++      abort();
++      return 0;
++    }
++
++    virtual void EmitLabel(uint64_t LabelID) {
++      assert(0 && "Implement me");
++      abort();
++    }
++
++
++    virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
++
+     /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
+     virtual void startFunctionStub(unsigned StubSize, unsigned Alignment = 1) {
+       assert(0 && "JIT specific function called!");
+Index: lib/Target/PowerPC/PPCCodeEmitter.cpp
+===================================================================
+--- lib/Target/PowerPC/PPCCodeEmitter.cpp	(revision 46321)
++++ lib/Target/PowerPC/PPCCodeEmitter.cpp	(working copy)
+@@ -20,6 +20,7 @@
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/CodeGen/MachineFunctionPass.h"
+ #include "llvm/CodeGen/MachineInstrBuilder.h"
++#include "llvm/CodeGen/MachineModuleInfo.h"
+ #include "llvm/CodeGen/Passes.h"
+ #include "llvm/Support/Debug.h"                   
+ #include "llvm/Support/Compiler.h"
+@@ -38,6 +39,11 @@
+     /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
+     ///
+     int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
++    
++    void getAnalysisUsage(AnalysisUsage &AU) const {
++      AU.addRequired<MachineModuleInfo>();
++      MachineFunctionPass::getAnalysisUsage(AU);
++    }
+ 
+   public:
+     static char ID;
+@@ -82,6 +88,8 @@
+   assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
+           MF.getTarget().getRelocationModel() != Reloc::Static) &&
+          "JIT relocation model must be set to static or default!");
++
++  MCE.setModuleInfo(&getAnalysis<MachineModuleInfo>());
+   do {
+     MovePCtoLROffset = 0;
+     MCE.startFunction(MF);
+@@ -101,6 +109,9 @@
+     default:
+       MCE.emitWordBE(getBinaryCodeForInstr(*I));
+       break;
++    case TargetInstrInfo::LABEL:
++      MCE.EmitLabel(MI.getOperand(0).getImm());
++      break;
+     case PPC::IMPLICIT_DEF_GPRC:
+     case PPC::IMPLICIT_DEF_G8RC:
+     case PPC::IMPLICIT_DEF_F8:
+Index: lib/Target/PowerPC/PPCInstrInfo.td
+===================================================================
+--- lib/Target/PowerPC/PPCInstrInfo.td	(revision 46321)
++++ lib/Target/PowerPC/PPCInstrInfo.td	(working copy)
+@@ -1179,6 +1179,8 @@
+           (BL_ELF texternalsym:$dst)>;
+ 
+ // Hi and Lo for Darwin Global Addresses.
++def : Pat<(PPChi texternalsym:$in, 0), (LIS texternalsym:$in)>;
++def : Pat<(PPClo texternalsym:$in, 0), (LI texternalsym:$in)>;
+ def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
+ def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
+ def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>;
+Index: lib/Target/PowerPC/PPCJITInfo.cpp
+===================================================================
+--- lib/Target/PowerPC/PPCJITInfo.cpp	(revision 46321)
++++ lib/Target/PowerPC/PPCJITInfo.cpp	(working copy)
+@@ -13,11 +13,15 @@
+ 
+ #define DEBUG_TYPE "jit"
+ #include "PPCJITInfo.h"
++#include "PPCRegisterInfo.h"
+ #include "PPCRelocations.h"
+ #include "PPCTargetMachine.h"
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/Config/alloca.h"
++#include "llvm/ExecutionEngine/ExecutionEngine.h"
+ #include "llvm/Support/Debug.h"
++#include "llvm/Support/Dwarf.h"
++#include "llvm/Target/TargetOptions.h"
+ #include <set>
+ using namespace llvm;
+ 
+@@ -52,24 +56,38 @@
+   if (Offset >= -(1 << 23) && Offset < (1 << 23)) {   // In range?
+     AtI[0] = BUILD_B(Offset, isCall);     // b/bl target
+   } else if (!is64Bit) {
+-    AtI[0] = BUILD_LIS(12, To >> 16);     // lis r12, hi16(address)
++    AtI[0] = BUILD_B(0, false);           // thread safety
+     AtI[1] = BUILD_ORI(12, 12, To);       // ori r12, r12, lo16(address)
+     AtI[2] = BUILD_MTCTR(12);             // mtctr r12
+     AtI[3] = BUILD_BCTR(isCall);          // bctr/bctrl
++    AtI[0] = BUILD_LIS(12, To >> 16);     // lis r12, hi16(address)
+   } else {
+-    AtI[0] = BUILD_LIS(12, To >> 48);      // lis r12, hi16(address)
++    AtI[0] = BUILD_B(0, false);            // thread safety
+     AtI[1] = BUILD_ORI(12, 12, To >> 32);  // ori r12, r12, lo16(address)
+     AtI[2] = BUILD_SLDI(12, 12, 32);       // sldi r12, r12, 32
+     AtI[3] = BUILD_ORIS(12, 12, To >> 16); // oris r12, r12, hi16(address)
+     AtI[4] = BUILD_ORI(12, 12, To);        // ori r12, r12, lo16(address)
+     AtI[5] = BUILD_MTCTR(12);              // mtctr r12
+     AtI[6] = BUILD_BCTR(isCall);           // bctr/bctrl
++    AtI[0] = BUILD_LIS(12, To >> 48);      // lis r12, hi16(address)
+   }
+ }
+ 
+ extern "C" void PPC32CompilationCallback();
+ extern "C" void PPC64CompilationCallback();
+ 
++
++// This is needed for old/broken assemblers (for example, gas on
++// Darwin is pretty old and doesn't support these directives)
++#if defined(__APPLE__)
++# define CFI(x)
++#else
++// FIXME: Disable this until we really want to use it. Also, we will
++//        need to add some workarounds for compilers, which support
++//        only subset of these directives.
++# define CFI(x) x
++#endif
++
+ #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
+     !defined(__ppc64__)
+ // CompilationCallback stub - We can't use a C function with inline assembly in
+@@ -155,19 +173,29 @@
+     // FIXME Layout
+     //   8 double registers       -  64 bytes
+     //   8 int registers          -  32 bytes
++    CFI(".cfi_startproc\n")    
++    "stwu 1, -104(1)\n"
++    CFI(".cfi_adjust_cfa_offset 104\n")
+     "mflr 0\n"
+-    "stw 0,  4(1)\n"
+-    "stwu 1, -104(1)\n"
++    "stw 0,  108(1)\n"
++    CFI(".cfi_offset lr, 4\n")
+     // Save all int arg registers
+-    "stw 10, 100(1)\n"   "stw 9,  96(1)\n"
+-    "stw 8,  92(1)\n"    "stw 7,  88(1)\n"
+-    "stw 6,  84(1)\n"    "stw 5,  80(1)\n"
+-    "stw 4,  76(1)\n"    "stw 3,  72(1)\n"
++    "stw 10, 100(1)\n"   
++    "stw 9,  96(1)\n"
++    "stw 8,  92(1)\n"    
++    "stw 7,  88(1)\n"
++    "stw 6,  84(1)\n"    
++    "stw 5,  80(1)\n"
++    "stw 4,  76(1)\n"    
++    "stw 3,  72(1)\n"
+     // Save all call-clobbered FP regs.
+     "stfd 8,  64(1)\n"
+-    "stfd 7,  56(1)\n"   "stfd 6,  48(1)\n"
+-    "stfd 5,  40(1)\n"   "stfd 4,  32(1)\n"
+-    "stfd 3,  24(1)\n"   "stfd 2,  16(1)\n"
++    "stfd 7,  56(1)\n"   
++    "stfd 6,  48(1)\n"
++    "stfd 5,  40(1)\n"   
++    "stfd 4,  32(1)\n"
++    "stfd 3,  24(1)\n"   
++    "stfd 2,  16(1)\n"
+     "stfd 1,  8(1)\n"
+     // Arguments to Compilation Callback:
+     // r3 - our lr (address of the call instruction in stub plus 4)
+@@ -180,21 +208,29 @@
+     "bl PPCCompilationCallbackC\n"
+     "mtctr 3\n"
+     // Restore all int arg registers
+-    "lwz 10, 100(1)\n"   "lwz 9,  96(1)\n"
+-    "lwz 8,  92(1)\n"    "lwz 7,  88(1)\n"
+-    "lwz 6,  84(1)\n"    "lwz 5,  80(1)\n"
+-    "lwz 4,  76(1)\n"    "lwz 3,  72(1)\n"
++    "lwz 10, 100(1)\n"   
++    "lwz 9,  96(1)\n"
++    "lwz 8,  92(1)\n"    
++    "lwz 7,  88(1)\n"
++    "lwz 6,  84(1)\n"    
++    "lwz 5,  80(1)\n"
++    "lwz 4,  76(1)\n"    
++    "lwz 3,  72(1)\n"
+     // Restore all FP arg registers
+     "lfd 8,  64(1)\n"
+-    "lfd 7,  56(1)\n"    "lfd 6,  48(1)\n"
+-    "lfd 5,  40(1)\n"    "lfd 4,  32(1)\n"
+-    "lfd 3,  24(1)\n"    "lfd 2,  16(1)\n"
++    "lfd 7,  56(1)\n"    
++    "lfd 6,  48(1)\n"
++    "lfd 5,  40(1)\n"    
++    "lfd 4,  32(1)\n"
++    "lfd 3,  24(1)\n"    
++    "lfd 2,  16(1)\n"
+     "lfd 1,  8(1)\n"
+     // Pop 3 frames off the stack and branch to target
+     "lwz  1, 104(1)\n"
+     "lwz  0, 4(1)\n"
+     "mtlr 0\n"
+     "bctr\n"
++    CFI(".cfi_endproc\n")    
+     );
+ #else
+ void PPC32CompilationCallback() {
+@@ -324,6 +360,31 @@
+   return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
+ }
+ 
++static const char* GetCommonFrame32() {
++    /*
++    // Size of common frame
++    MCE.emitWordBE(16);
++    // Common frame
++    MCE.emitWordBE(0);
++    MCE.emitByte(1);
++    MCE.emitByte('z');
++    MCE.emitByte('R');
++    MCE.emitByte(0);
++    MCE.emitByte(1);
++    MCE.emitByte(-4 & 0x7f);
++    MCE.emitByte(0x41);
++    MCE.emitByte(1);
++    MCE.emitByte(16);
++    MCE.emitByte(0xc);
++    MCE.emitByte(1);
++    MCE.emitByte(0);*/
++  static const char CF[] = {
++    0, 0, 0, 16, 0, 0, 0, 0, 1, 'z', 'R', 0, 1, -4 & 0x7f, 
++    0x41, 1, 16, 0xc, 1, 0
++  };
++  return CF;
++}
++
+ void *PPCJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
+   // If this is just a call to an external function, emit a branch instead of a
+   // call.  The code is the same except for one bit of the last instruction.
+@@ -341,20 +402,25 @@
+     EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit);
+     return MCE.finishFunctionStub(0);
+   }
+-
+-  MCE.startFunctionStub(10*4);
++  
++  if (ExceptionHandling && !is64Bit) {
++    MCE.startFunctionStub(10*4 + 44);
++  } else {
++    MCE.startFunctionStub(10*4);
++  }
++  intptr_t BeginAddr = (intptr_t)MCE.getCurrentPCValue();
+   if (is64Bit) {
++    MCE.emitWordBE(0x7d6802a6);     // mflr r11
++    MCE.emitWordBE(0xf9610010);     // std r11, 16(r1)
+     MCE.emitWordBE(0xf821ffb1);     // stdu r1,-80(r1)
++  } else if (TM.getSubtargetImpl()->isMachoABI()){
+     MCE.emitWordBE(0x7d6802a6);     // mflr r11
+-    MCE.emitWordBE(0xf9610060);     // std r11, 96(r1)
+-  } else if (TM.getSubtargetImpl()->isMachoABI()){
++    MCE.emitWordBE(0x91610008);     // stw r11, 8(r1)
+     MCE.emitWordBE(0x9421ffe0);     // stwu r1,-32(r1)
++  } else {
+     MCE.emitWordBE(0x7d6802a6);     // mflr r11
+-    MCE.emitWordBE(0x91610028);     // stw r11, 40(r1)
+-  } else {
++    MCE.emitWordBE(0x91610004);     // stw r11, 4(r1)
+     MCE.emitWordBE(0x9421ffe0);     // stwu r1,-32(r1)
+-    MCE.emitWordBE(0x7d6802a6);     // mflr r11
+-    MCE.emitWordBE(0x91610024);     // stw r11, 36(r1)
+   }
+   intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
+   MCE.emitWordBE(0);
+@@ -365,6 +431,41 @@
+   MCE.emitWordBE(0);
+   MCE.emitWordBE(0);
+   EmitBranchToAt(Addr, (intptr_t)Fn, true, is64Bit);
++  intptr_t EndAddr = (intptr_t)MCE.getCurrentPCValue();
++  
++  if (ExceptionHandling && !is64Bit) {
++    // Size of Eh section
++    MCE.emitWordBE(32);
++    // Eh section
++    MCE.emitWordBE(MCE.getCurrentPCValue() - (intptr_t)GetCommonFrame32());
++    MCE.emitWordBE(BeginAddr - MCE.getCurrentPCValue());
++    MCE.emitWordBE(EndAddr - BeginAddr);
++    MCE.emitByte(0);
++    MCE.emitByte(dwarf::DW_CFA_advance_loc4);
++    MCE.emitWordBE(8);
++    MCE.emitByte(dwarf::DW_CFA_def_cfa_offset);
++    MCE.emitByte(32);
++    MCE.emitByte(dwarf::DW_CFA_offset_extended_sf);
++    MCE.emitByte(TM.getRegisterInfo()->getDwarfRegNum(PPC::LR, true));
++    if (TM.getSubtargetImpl()->isMachoABI()){
++      MCE.emitByte(-2 & 0x7f);
++    } else {
++      MCE.emitByte(-1 & 0x7f);
++    }
++    MCE.emitByte(dwarf::DW_CFA_advance_loc4);
++    MCE.emitWordBE(4);
++    MCE.emitByte(dwarf::DW_CFA_def_cfa_register);
++    MCE.emitByte(1);
++    // Alignment
++    MCE.emitByte(0);
++    MCE.emitByte(0);
++    
++    // Two zero for the unwind runtime
++    MCE.emitWordBE(0);
++    MCE.emitWordBE(0);
++    
++    ExecutionEngine::RegisterTable((void*)EndAddr);
++  }
+   return MCE.finishFunctionStub(0);
+ }
+ 
+Index: lib/Target/PowerPC/PPCISelLowering.cpp
+===================================================================
+--- lib/Target/PowerPC/PPCISelLowering.cpp	(revision 46321)
++++ lib/Target/PowerPC/PPCISelLowering.cpp	(working copy)
+@@ -178,10 +178,12 @@
+   // We want to legalize GlobalAddress and ConstantPool nodes into the 
+   // appropriate instructions to materialize the address.
+   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
++  setOperationAction(ISD::ExternalSymbol  , MVT::i32  , Custom);
+   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
+   setOperationAction(ISD::ConstantPool,  MVT::i32, Custom);
+   setOperationAction(ISD::JumpTable,     MVT::i32, Custom);
+   setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
++  setOperationAction(ISD::ExternalSymbol  , MVT::i64  , Custom);
+   setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
+   setOperationAction(ISD::ConstantPool,  MVT::i64, Custom);
+   setOperationAction(ISD::JumpTable,     MVT::i64, Custom);
+@@ -1108,6 +1110,37 @@
+   return DAG.getLoad(PtrVT, DAG.getEntryNode(), Lo, NULL, 0);
+ }
+ 
++static SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
++  MVT::ValueType PtrVT = Op.getValueType();
++  ExternalSymbolSDNode *GSDB = dyn_cast<ExternalSymbolSDNode>(Op);
++  SDOperand GA = DAG.getTargetExternalSymbol(GSDB->getSymbol(), PtrVT);
++  SDOperand Zero = DAG.getConstant(0, PtrVT);
++  
++  const TargetMachine &TM = DAG.getTarget();
++
++  SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, GA, Zero);
++  SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, GA, Zero);
++
++  // If this is a non-darwin platform, we don't support non-static relo models
++  // yet.
++  if (TM.getRelocationModel() == Reloc::Static ||
++      !TM.getSubtarget<PPCSubtarget>().isDarwin()) {
++    // Generate non-pic code that has direct accesses to globals.
++    // The address of the global is just (hi(&g)+lo(&g)).
++    return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
++  }
++  
++  if (TM.getRelocationModel() == Reloc::PIC_) {
++    // With PIC, the first instruction is actually "GR+hi(&G)".
++    Hi = DAG.getNode(ISD::ADD, PtrVT,
++                     DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi);
++  }
++  
++  Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
++  
++  return Lo;
++}
++
+ static SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
+   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
+   
+@@ -1777,11 +1810,11 @@
+   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
+   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
+   // node so that legalize doesn't hack it.
+-  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+-  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+-    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
+-  else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
++  //if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
++  //  Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
++  //if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
++  //  Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
++  if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
+     // If this is an absolute destination address, use the munged value.
+     Callee = SDOperand(Dest, 0);
+   else {
+@@ -3064,6 +3097,7 @@
+   default: assert(0 && "Wasn't expecting to be able to lower this!"); 
+   case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
+   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
++  case ISD::ExternalSymbol:     return LowerExternalSymbol(Op, DAG);
+   case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG);
+   case ISD::JumpTable:          return LowerJumpTable(Op, DAG);
+   case ISD::SETCC:              return LowerSETCC(Op, DAG);
+Index: lib/Target/X86/X86CodeEmitter.cpp
+===================================================================
+--- lib/Target/X86/X86CodeEmitter.cpp	(revision 46321)
++++ lib/Target/X86/X86CodeEmitter.cpp	(working copy)
+@@ -23,6 +23,7 @@
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/CodeGen/MachineFunctionPass.h"
+ #include "llvm/CodeGen/MachineInstr.h"
++#include "llvm/CodeGen/MachineModuleInfo.h"
+ #include "llvm/CodeGen/Passes.h"
+ #include "llvm/Function.h"
+ #include "llvm/ADT/Statistic.h"
+@@ -61,6 +62,11 @@
+ 
+     void emitInstruction(const MachineInstr &MI,
+                          const TargetInstrDesc *Desc);
++    
++    void getAnalysisUsage(AnalysisUsage &AU) const {
++      AU.addRequired<MachineModuleInfo>();
++      MachineFunctionPass::getAnalysisUsage(AU);
++    }
+ 
+   private:
+     void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
+@@ -104,10 +110,13 @@
+   assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
+           MF.getTarget().getRelocationModel() != Reloc::Static) &&
+          "JIT relocation model must be set to static or default!");
++  
++  MCE.setModuleInfo(&getAnalysis<MachineModuleInfo>());
++  
+   II = ((X86TargetMachine&)TM).getInstrInfo();
+   TD = ((X86TargetMachine&)TM).getTargetData();
+   Is64BitMode = TM.getSubtarget<X86Subtarget>().is64Bit();
+-
++  
+   do {
+     MCE.startFunction(MF);
+     for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 
+@@ -596,13 +605,13 @@
+     // Remember the current PC offset, this is the PIC relocation
+     // base address.
+     switch (Opcode) {
+-#ifndef NDEBUG
+     default: 
+       assert(0 && "psuedo instructions should be removed before code emission");
+     case TargetInstrInfo::INLINEASM:
+       assert(0 && "JIT does not support inline asm!\n");
+     case TargetInstrInfo::LABEL:
+-      assert(0 && "JIT does not support meta labels!\n");
++      MCE.EmitLabel(MI.getOperand(0).getImm());
++      break;
+     case X86::IMPLICIT_DEF_GR8:
+     case X86::IMPLICIT_DEF_GR16:
+     case X86::IMPLICIT_DEF_GR32:
+@@ -613,7 +622,6 @@
+     case X86::IMPLICIT_DEF_VR128:
+     case X86::FP_REG_KILL:
+       break;
+-#endif
+     case X86::MOVPC32r: {
+       // This emits the "call" portion of this pseudo instruction.
+       MCE.emitByte(BaseOpcode);
+@@ -627,7 +635,6 @@
+     }
+     CurOp = NumOps;
+     break;
+-
+   case X86II::RawFrm:
+     MCE.emitByte(BaseOpcode);
+ 
+Index: lib/Target/TargetMachine.cpp
+===================================================================
+--- lib/Target/TargetMachine.cpp	(revision 46321)
++++ lib/Target/TargetMachine.cpp	(working copy)
+@@ -31,6 +31,7 @@
+   bool UseSoftFloat;
+   bool NoZerosInBSS;
+   bool ExceptionHandling;
++  bool SizedMemoryCode;
+   Reloc::Model RelocationModel;
+   CodeModel::Model CMModel;
+   bool PerformTailCallOpt;
+Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
+===================================================================
+--- lib/ExecutionEngine/JIT/JITEmitter.cpp	(revision 46321)
++++ lib/ExecutionEngine/JIT/JITEmitter.cpp	(working copy)
+@@ -14,18 +14,23 @@
+ 
+ #define DEBUG_TYPE "jit"
+ #include "JIT.h"
++#include "JITDwarfEmitter.h"
+ #include "llvm/Constant.h"
+ #include "llvm/Module.h"
+ #include "llvm/Type.h"
++#include "llvm/ADT/DenseMap.h"
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/CodeGen/MachineFunction.h"
+ #include "llvm/CodeGen/MachineConstantPool.h"
+ #include "llvm/CodeGen/MachineJumpTableInfo.h"
++#include "llvm/CodeGen/MachineModuleInfo.h"
+ #include "llvm/CodeGen/MachineRelocation.h"
++#include "llvm/CodeGen/SizeEmitter.h"
+ #include "llvm/ExecutionEngine/JITMemoryManager.h"
+ #include "llvm/Target/TargetData.h"
+ #include "llvm/Target/TargetJITInfo.h"
+ #include "llvm/Target/TargetMachine.h"
++#include "llvm/Target/TargetOptions.h"
+ #include "llvm/Support/Debug.h"
+ #include "llvm/Support/MutexGuard.h"
+ #include "llvm/System/Disassembler.h"
+@@ -344,6 +349,11 @@
+ 
+     /// Resolver - This contains info about the currently resolved functions.
+     JITResolver Resolver;
++    
++    JITDwarfEmitter *DE;
++    std::vector<intptr_t> LabelLocations;
++    MachineModuleInfo* MMI;
++
+   public:
+     JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit) {
+       MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
+@@ -351,9 +361,14 @@
+         MemMgr->AllocateGOT();
+         DOUT << "JIT is managing a GOT\n";
+       }
++      
++      if (ExceptionHandling)
++        DE = new JITDwarfEmitter(jit);
+     }
++   
+     ~JITEmitter() { 
+       delete MemMgr;
++      if (ExceptionHandling) delete DE;
+     }
+     
+     JITResolver &getJITResolver() { return Resolver; }
+@@ -361,6 +376,7 @@
+     virtual void startFunction(MachineFunction &F);
+     virtual bool finishFunction(MachineFunction &F);
+     
++    void initConstantPool(MachineConstantPool *MCP);
+     void emitConstantPool(MachineConstantPool *MCP);
+     void initJumpTableInfo(MachineJumpTableInfo *MJTI);
+     void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
+@@ -392,6 +408,26 @@
+     void deallocateMemForFunction(Function *F) {
+       MemMgr->deallocateMemForFunction(F);
+     }
++
++    virtual void EmitLabel(uint64_t LabelID) {
++      if (LabelLocations.size() <= LabelID)
++        LabelLocations.resize((LabelID+1)*2);
++      LabelLocations[LabelID] = getCurrentPCValue();
++    }
++
++    virtual intptr_t getLabelAddress(uint64_t LabelID) const {
++      assert(LabelLocations.size() > (unsigned)LabelID && 
++             LabelLocations[LabelID] && "Label not emitted!");
++      return LabelLocations[LabelID];
++    }
++    
++    virtual void setModuleInfo(MachineModuleInfo* Info) {
++      MMI = Info;
++      if (ExceptionHandling) DE->setModuleInfo(Info);
++    }
++
++
++
+   private:
+     void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
+     void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
+@@ -442,19 +478,47 @@
+ 
+ 
+ void JITEmitter::startFunction(MachineFunction &F) {
+-  uintptr_t ActualSize;
+-  BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
+-                                                         ActualSize);
+-  BufferEnd = BufferBegin+ActualSize;
++  MMI->BeginFunction(&F);
+   
+-  // Ensure the constant pool/jump table info is at least 4-byte aligned.
+-  emitAlignment(16);
++  if (SizedMemoryCode) {
++    BufferBegin = CurBufferPtr;
++    BufferEnd = (unsigned char*) 0xffffffff;
++  
++    // Ensure the constant pool/jump table info is at least 4-byte aligned.
++    emitAlignment(16);
+ 
+-  emitConstantPool(F.getConstantPool());
+-  initJumpTableInfo(F.getJumpTableInfo());
++    initConstantPool(F.getConstantPool());
++    initJumpTableInfo(F.getJumpTableInfo());
++    
++    
++    uintptr_t ActualSize = (uintptr_t)CurBufferPtr;
++    CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
++                                             ActualSize);
++  
++    ConstantPoolBase  = (void*)(((unsigned) ConstantPoolBase) + CurBufferPtr);
++    JumpTableBase     = (void*)(((unsigned) JumpTableBase) + CurBufferPtr);
+ 
+-  // About to start emitting the machine code for the function.
+-  emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
++    emitConstantPool(F.getConstantPool());
++
++  } else {
++    uintptr_t ActualSize;
++    BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
++                                                           ActualSize);
++    BufferEnd = BufferBegin+ActualSize;
++  
++    // Ensure the constant pool/jump table info is at least 4-byte aligned.
++    emitAlignment(16);
++
++    initConstantPool(F.getConstantPool());
++    emitConstantPool(F.getConstantPool());
++    initJumpTableInfo(F.getJumpTableInfo());
++  
++    // About to start emitting the machine code for the function.
++    emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
++
++  }
++  
++  
+   TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
+ 
+   MBBLocations.clear();
+@@ -553,10 +617,33 @@
+          << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart);
+ #endif
+   
++  if (ExceptionHandling) {
++    uintptr_t ActualSize;
++    if (SizedMemoryCode) {
++      SizeEmitter sz(LabelLocations);
++      DE->EmitDwarfTable(F, sz, FnStart, FnEnd);
++      ActualSize = sz.getCurrentPCValue();
++    }
++    SavedBufferBegin = BufferBegin;
++    SavedBufferEnd = BufferEnd;
++    SavedCurBufferPtr = CurBufferPtr;
++    
++    BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
++                                                             ActualSize);
++    BufferEnd = BufferBegin+ActualSize;
++    unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd);
++    MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, FrameRegister);
++    BufferBegin = SavedBufferBegin;
++    BufferEnd = SavedBufferEnd;
++    CurBufferPtr = SavedCurBufferPtr;
++
++    TheJIT->RegisterTable(FrameRegister);
++  }
++  MMI->EndFunction();
+   return false;
+ }
+ 
+-void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
++void JITEmitter::initConstantPool(MachineConstantPool *MCP) {
+   const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
+   if (Constants.empty()) return;
+ 
+@@ -565,12 +652,15 @@
+   const Type *Ty = CPE.isMachineConstantPoolEntry()
+     ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
+   Size += TheJIT->getTargetData()->getABITypeSize(Ty);
+-
++   
+   ConstantPoolBase = allocateSpace(Size, 1 << MCP->getConstantPoolAlignment());
+   ConstantPool = MCP;
++}
+ 
++void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
+   if (ConstantPoolBase == 0) return;  // Buffer overflow.
+ 
++  const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
+   // Initialize the memory for all of the constant pool entries.
+   for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
+     void *CAddr = (char*)ConstantPoolBase+Constants[i].Offset;
+Index: lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
+===================================================================
+--- lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp	(revision 0)
++++ lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp	(revision 0)
+@@ -0,0 +1,637 @@
++//===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++//
++// This file defines a JITDwarfEmitter object that is used by the JIT to
++// write dwarf tables to memory.
++//
++//===----------------------------------------------------------------------===//
++
++#include "JIT.h"
++#include "JITDwarfEmitter.h"
++#include "llvm/Function.h"
++#include "llvm/ADT/DenseMap.h"
++#include "llvm/CodeGen/AsmPrinter.h"
++#include "llvm/CodeGen/MachineCodeEmitter.h"
++#include "llvm/CodeGen/MachineFunction.h"
++#include "llvm/CodeGen/MachineLocation.h"
++#include "llvm/CodeGen/MachineModuleInfo.h"
++#include "llvm/ExecutionEngine/JITMemoryManager.h"
++#include "llvm/Target/MRegisterInfo.h"
++#include "llvm/Target/TargetAsmInfo.h"
++#include "llvm/Target/TargetData.h"
++#include "llvm/Target/TargetInstrInfo.h"
++#include "llvm/Target/TargetFrameInfo.h"
++#include "llvm/Target/TargetMachine.h"
++
++using namespace llvm;
++
++JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : Jit(theJit) {}
++
++
++unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, 
++                                               MachineCodeEmitter& mce,
++                                               unsigned char* StartFunction,
++                                               unsigned char* EndFunction) {
++  const TargetMachine& TM = F.getTarget();
++  TD = TM.getTargetData();
++  needsIndirectEncoding = TM.getTargetAsmInfo()->getNeedsIndirectEncoding();
++  stackGrowthDirection = TM.getFrameInfo()->getStackGrowthDirection();
++  RI = TM.getRegisterInfo();
++  MCE = &mce;
++  
++  unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction,
++                                                     EndFunction);
++      
++  unsigned char* Result = 0;
++  unsigned char* EHFramePtr = 0;
++
++  const std::vector<Function *> Personalities = MMI->getPersonalities();
++  EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]);
++
++  Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr,
++                       StartFunction, EndFunction, ExceptionTable);
++  
++  return Result;
++}
++
++
++void JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
++                                     const std::vector<MachineMove> &Moves) {
++  unsigned PointerSize = TD->getPointerSize();
++  int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ?
++          PointerSize : -PointerSize;
++  // TODO bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
++  bool IsLocal = BaseLabelPtr;
++
++  for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
++    const MachineMove &Move = Moves[i];
++    unsigned LabelID = Move.getLabelID();
++    
++    if (LabelID) {
++      LabelID = MMI->MappedLabel(LabelID);
++    
++      // Throw out move if the label is invalid.
++      if (!LabelID) continue;
++    }
++    
++    intptr_t LabelPtr = 0;
++    if (LabelID) LabelPtr = MCE->getLabelAddress(LabelID);
++
++    const MachineLocation &Dst = Move.getDestination();
++    const MachineLocation &Src = Move.getSource();
++    
++    // Advance row if new location.
++    if (BaseLabelPtr && LabelID && (BaseLabelPtr != LabelPtr || !IsLocal)) {
++      MCE->emitByte(dwarf::DW_CFA_advance_loc4);
++      if (PointerSize == 8) {
++        MCE->emitInt64(LabelPtr - BaseLabelPtr);
++      } else {
++        MCE->emitInt32(LabelPtr - BaseLabelPtr);
++      }
++      
++      BaseLabelPtr = LabelPtr;
++      IsLocal = true;
++    }
++    
++    // If advancing cfa.
++    if (Dst.isRegister() && Dst.getRegister() == MachineLocation::VirtualFP) {
++      if (!Src.isRegister()) {
++        if (Src.getRegister() == MachineLocation::VirtualFP) {
++          MCE->emitByte(dwarf::DW_CFA_def_cfa_offset);
++        } else {
++          MCE->emitByte(dwarf::DW_CFA_def_cfa);
++          MCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister(), true));
++        }
++        
++        int Offset = -Src.getOffset();
++        
++        MCE->emitULEB128Bytes(Offset);
++      } else {
++        assert(0 && "Machine move no supported yet.");
++      }
++    } else if (Src.isRegister() &&
++      Src.getRegister() == MachineLocation::VirtualFP) {
++      if (Dst.isRegister()) {
++        MCE->emitByte(dwarf::DW_CFA_def_cfa_register);
++        MCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getRegister(), true));
++      } else {
++        assert(0 && "Machine move no supported yet.");
++      }
++    } else {
++      unsigned Reg = RI->getDwarfRegNum(Src.getRegister(), true);
++      int Offset = Dst.getOffset() / stackGrowth;
++      
++      if (Offset < 0) {
++        MCE->emitByte(dwarf::DW_CFA_offset_extended_sf);
++        MCE->emitULEB128Bytes(Reg);
++        MCE->emitSLEB128Bytes(Offset);
++      } else if (Reg < 64) {
++        MCE->emitByte(dwarf::DW_CFA_offset + Reg);
++        MCE->emitULEB128Bytes(Offset);
++      } else {
++        MCE->emitByte(dwarf::DW_CFA_offset_extended);
++        MCE->emitULEB128Bytes(Reg);
++        MCE->emitULEB128Bytes(Offset);
++      }
++    }
++  }
++}
++
++/// SharedTypeIds - How many leading type ids two landing pads have in common.
++static unsigned SharedTypeIds(const LandingPadInfo *L,
++                              const LandingPadInfo *R) {
++  const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
++  unsigned LSize = LIds.size(), RSize = RIds.size();
++  unsigned MinSize = LSize < RSize ? LSize : RSize;
++  unsigned Count = 0;
++
++  for (; Count != MinSize; ++Count)
++    if (LIds[Count] != RIds[Count])
++      return Count;
++
++  return Count;
++}
++
++
++/// PadLT - Order landing pads lexicographically by type id.
++static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
++  const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
++  unsigned LSize = LIds.size(), RSize = RIds.size();
++  unsigned MinSize = LSize < RSize ? LSize : RSize;
++
++  for (unsigned i = 0; i != MinSize; ++i)
++    if (LIds[i] != RIds[i])
++      return LIds[i] < RIds[i];
++
++  return LSize < RSize;
++}
++
++struct KeyInfo {
++  static inline unsigned getEmptyKey() { return -1U; }
++  static inline unsigned getTombstoneKey() { return -2U; }
++  static unsigned getHashValue(const unsigned &Key) { return Key; }
++  static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
++  static bool isPod() { return true; }
++};
++
++/// ActionEntry - Structure describing an entry in the actions table.
++struct ActionEntry {
++  int ValueForTypeID; // The value to write - may not be equal to the type id.
++  int NextAction;
++  struct ActionEntry *Previous;
++};
++
++/// PadRange - Structure holding a try-range and the associated landing pad.
++struct PadRange {
++  // The index of the landing pad.
++  unsigned PadIndex;
++  // The index of the begin and end labels in the landing pad's label lists.
++  unsigned RangeIndex;
++};
++
++typedef DenseMap<unsigned, PadRange, KeyInfo> RangeMapType;
++
++/// CallSiteEntry - Structure describing an entry in the call-site table.
++struct CallSiteEntry {
++  unsigned BeginLabel; // zero indicates the start of the function.
++  unsigned EndLabel;   // zero indicates the end of the function.
++  unsigned PadLabel;   // zero indicates that there is no landing pad.
++  unsigned Action;
++};
++
++unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
++                                         unsigned char* StartFunction,
++                                         unsigned char* EndFunction) {
++  // Map all labels and get rid of any dead landing pads.
++  MMI->TidyLandingPads();
++
++  const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
++  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
++  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
++  if (PadInfos.empty()) return 0;
++
++  // Sort the landing pads in order of their type ids.  This is used to fold
++  // duplicate actions.
++  SmallVector<const LandingPadInfo *, 64> LandingPads;
++  LandingPads.reserve(PadInfos.size());
++  for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
++    LandingPads.push_back(&PadInfos[i]);
++  std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
++
++  // Negative type ids index into FilterIds, positive type ids index into
++  // TypeInfos.  The value written for a positive type id is just the type
++  // id itself.  For a negative type id, however, the value written is the
++  // (negative) byte offset of the corresponding FilterIds entry.  The byte
++  // offset is usually equal to the type id, because the FilterIds entries
++  // are written using a variable width encoding which outputs one byte per
++  // entry as long as the value written is not too large, but can differ.
++  // This kind of complication does not occur for positive type ids because
++  // type infos are output using a fixed width encoding.
++  // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
++  SmallVector<int, 16> FilterOffsets;
++  FilterOffsets.reserve(FilterIds.size());
++  int Offset = -1;
++  for(std::vector<unsigned>::const_iterator I = FilterIds.begin(),
++    E = FilterIds.end(); I != E; ++I) {
++    FilterOffsets.push_back(Offset);
++    Offset -= AsmPrinter::SizeULEB128(*I);
++  }
++
++  // Compute the actions table and gather the first action index for each
++  // landing pad site.
++  SmallVector<ActionEntry, 32> Actions;
++  SmallVector<unsigned, 64> FirstActions;
++  FirstActions.reserve(LandingPads.size());
++
++  int FirstAction = 0;
++  unsigned SizeActions = 0;
++  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
++    const LandingPadInfo *LP = LandingPads[i];
++    const std::vector<int> &TypeIds = LP->TypeIds;
++    const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
++    unsigned SizeSiteActions = 0;
++
++    if (NumShared < TypeIds.size()) {
++      unsigned SizeAction = 0;
++      ActionEntry *PrevAction = 0;
++
++      if (NumShared) {
++        const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
++        assert(Actions.size());
++        PrevAction = &Actions.back();
++        SizeAction = AsmPrinter::SizeSLEB128(PrevAction->NextAction) +
++          AsmPrinter::SizeSLEB128(PrevAction->ValueForTypeID);
++        for (unsigned j = NumShared; j != SizePrevIds; ++j) {
++          SizeAction -= AsmPrinter::SizeSLEB128(PrevAction->ValueForTypeID);
++          SizeAction += -PrevAction->NextAction;
++          PrevAction = PrevAction->Previous;
++        }
++      }
++
++      // Compute the actions.
++      for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) {
++        int TypeID = TypeIds[I];
++        assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
++        int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
++        unsigned SizeTypeID = AsmPrinter::SizeSLEB128(ValueForTypeID);
++
++        int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
++        SizeAction = SizeTypeID + AsmPrinter::SizeSLEB128(NextAction);
++        SizeSiteActions += SizeAction;
++
++        ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
++        Actions.push_back(Action);
++
++        PrevAction = &Actions.back();
++      }
++
++      // Record the first action of the landing pad site.
++      FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
++    } // else identical - re-use previous FirstAction
++
++    FirstActions.push_back(FirstAction);
++
++    // Compute this sites contribution to size.
++    SizeActions += SizeSiteActions;
++  }
++
++  // Compute the call-site table.  Entries must be ordered by address.
++  SmallVector<CallSiteEntry, 64> CallSites;
++
++  RangeMapType PadMap;
++  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
++    const LandingPadInfo *LandingPad = LandingPads[i];
++    for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
++      unsigned BeginLabel = LandingPad->BeginLabels[j];
++      assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
++      PadRange P = { i, j };
++      PadMap[BeginLabel] = P;
++    }
++  }
++
++  bool MayThrow = false;
++  unsigned LastLabel = 0;
++  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
++        I != E; ++I) {
++    for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
++          MI != E; ++MI) {
++      if (MI->getOpcode() != TargetInstrInfo::LABEL) {
++        MayThrow |= MI->getDesc().isCall();
++        continue;
++      }
++
++      unsigned BeginLabel = MI->getOperand(0).getImm();
++      assert(BeginLabel && "Invalid label!");
++
++      if (BeginLabel == LastLabel)
++        MayThrow = false;
++
++      RangeMapType::iterator L = PadMap.find(BeginLabel);
++
++      if (L == PadMap.end())
++        continue;
++
++      PadRange P = L->second;
++      const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
++
++      assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
++              "Inconsistent landing pad map!");
++
++      // If some instruction between the previous try-range and this one may
++      // throw, create a call-site entry with no landing pad for the region
++      // between the try-ranges.
++      if (MayThrow) {
++        CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
++        CallSites.push_back(Site);
++      }
++
++      LastLabel = LandingPad->EndLabels[P.RangeIndex];
++      CallSiteEntry Site = {BeginLabel, LastLabel,
++        LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};
++
++      assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
++              "Invalid landing pad!");
++
++      // Try to merge with the previous call-site.
++      if (CallSites.size()) {
++        CallSiteEntry &Prev = CallSites[CallSites.size()-1];
++        if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
++          // Extend the range of the previous entry.
++          Prev.EndLabel = Site.EndLabel;
++          continue;
++        }
++      }
++
++      // Otherwise, create a new call-site.
++      CallSites.push_back(Site);
++    }
++  }
++  // If some instruction between the previous try-range and the end of the
++  // function may throw, create a call-site entry with no landing pad for the
++  // region following the try-range.
++  if (MayThrow) {
++    CallSiteEntry Site = {LastLabel, 0, 0, 0};
++    CallSites.push_back(Site);
++  }
++
++  // Final tallies.
++  unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
++                                            sizeof(int32_t) + // Site length.
++                                            sizeof(int32_t)); // Landing pad.
++  for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
++    SizeSites += AsmPrinter::SizeULEB128(CallSites[i].Action);
++
++  unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();
++
++  unsigned TypeOffset = sizeof(int8_t) + // Call site format
++                        // Call-site table length
++                        AsmPrinter::SizeULEB128(SizeSites) + 
++                        SizeSites + SizeActions + SizeTypes;
++
++  unsigned TotalSize = sizeof(int8_t) + // LPStart format
++                       sizeof(int8_t) + // TType format
++                       AsmPrinter::SizeULEB128(TypeOffset) + // TType base offset
++                       TypeOffset;
++
++  unsigned SizeAlign = (4 - TotalSize) & 3;
++
++  // Begin the exception table.
++  MCE->emitAlignment(4);
++  for (unsigned i = 0; i != SizeAlign; ++i) {
++    MCE->emitByte(0);
++    // Asm->EOL("Padding");
++  }
++  
++  unsigned char* DwarfExceptionTable = (unsigned char*)MCE->getCurrentPCValue();
++
++  // Emit the header.
++  MCE->emitByte(dwarf::DW_EH_PE_omit);
++  // Asm->EOL("LPStart format (DW_EH_PE_omit)");
++  MCE->emitByte(dwarf::DW_EH_PE_absptr);
++  // Asm->EOL("TType format (DW_EH_PE_absptr)");
++  MCE->emitULEB128Bytes(TypeOffset);
++  // Asm->EOL("TType base offset");
++  MCE->emitByte(dwarf::DW_EH_PE_udata4);
++  // Asm->EOL("Call site format (DW_EH_PE_udata4)");
++  MCE->emitULEB128Bytes(SizeSites);
++  // Asm->EOL("Call-site table length");
++
++  // Emit the landing pad site information.
++  for (unsigned i = 0; i < CallSites.size(); ++i) {
++    CallSiteEntry &S = CallSites[i];
++    intptr_t BeginLabelPtr = 0;
++    intptr_t EndLabelPtr = 0;
++
++    if (!S.BeginLabel) {
++      BeginLabelPtr = (intptr_t)StartFunction;
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32(0);
++      else
++        MCE->emitInt64(0);
++    } else {
++      BeginLabelPtr = MCE->getLabelAddress(S.BeginLabel);
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction);
++      else
++        MCE->emitInt64(BeginLabelPtr - (intptr_t)StartFunction);
++    }
++
++    // Asm->EOL("Region start");
++
++    if (!S.EndLabel) {
++      EndLabelPtr = (intptr_t)EndFunction;
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32((intptr_t)EndFunction - BeginLabelPtr);
++      else
++        MCE->emitInt64((intptr_t)EndFunction - BeginLabelPtr);
++    } else {
++      EndLabelPtr = MCE->getLabelAddress(S.EndLabel);
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32(EndLabelPtr - BeginLabelPtr);
++      else
++        MCE->emitInt64(EndLabelPtr - BeginLabelPtr);
++    }
++    //Asm->EOL("Region length");
++
++    if (!S.PadLabel) {
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32(0);
++      else
++        MCE->emitInt64(0);
++    } else {
++      unsigned PadLabelPtr = MCE->getLabelAddress(S.PadLabel);
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction);
++      else
++        MCE->emitInt64(PadLabelPtr - (intptr_t)StartFunction);
++    }
++    // Asm->EOL("Landing pad");
++
++    MCE->emitULEB128Bytes(S.Action);
++    // Asm->EOL("Action");
++  }
++
++  // Emit the actions.
++  for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
++    ActionEntry &Action = Actions[I];
++
++    MCE->emitSLEB128Bytes(Action.ValueForTypeID);
++    //Asm->EOL("TypeInfo index");
++    MCE->emitSLEB128Bytes(Action.NextAction);
++    //Asm->EOL("Next action");
++  }
++
++  // Emit the type ids.
++  for (unsigned M = TypeInfos.size(); M; --M) {
++    GlobalVariable *GV = TypeInfos[M - 1];
++    
++    if (GV) {
++      if (TD->getPointerSize() == sizeof(int32_t)) {
++        MCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV));
++      } else {
++        MCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV));
++      }
++    } else {
++      if (TD->getPointerSize() == sizeof(int32_t))
++        MCE->emitInt32(0);
++      else
++        MCE->emitInt64(0);
++    }
++    // Asm->EOL("TypeInfo");
++  }
++
++  // Emit the filter typeids.
++  for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
++    unsigned TypeID = FilterIds[j];
++    MCE->emitULEB128Bytes(TypeID);
++    //Asm->EOL("Filter TypeInfo index");
++  }
++  
++  MCE->emitAlignment(4);
++
++  return DwarfExceptionTable;
++}
++
++unsigned char* JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) {
++  unsigned PointerSize = TD->getPointerSize();
++  int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ?
++          PointerSize : -PointerSize;
++  
++  unsigned char* StartCommonPtr = (unsigned char*)MCE->getCurrentPCValue();
++  // EH Common Frame header
++  MCE->allocateSpace(PointerSize, 0);
++  unsigned char* FrameCommonBeginPtr = (unsigned char*)MCE->getCurrentPCValue();
++  MCE->emitInt32((int)0);
++  MCE->emitByte(dwarf::DW_CIE_VERSION);
++  MCE->emitString(Personality ? "zPLR" : "zR");
++  MCE->emitULEB128Bytes(1);
++  MCE->emitSLEB128Bytes(stackGrowth);
++  MCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true));
++  
++  if (Personality) {
++    MCE->emitULEB128Bytes(7);
++    
++    if (needsIndirectEncoding)
++      MCE->emitByte(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 | 
++               dwarf::DW_EH_PE_indirect);
++    else
++      MCE->emitByte(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
++
++    if (PointerSize == 8)
++      MCE->emitInt64((intptr_t)Jit.getPointerToGlobal(Personality) - 
++                MCE->getCurrentPCValue());
++    else
++      MCE->emitInt32((intptr_t)Jit.getPointerToGlobal(Personality) - 
++                MCE->getCurrentPCValue());
++    
++    MCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel);
++    MCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel);
++      
++  } else {
++    MCE->emitULEB128Bytes(1);
++    MCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel);
++  }
++
++  std::vector<MachineMove> Moves;
++  RI->getInitialFrameState(Moves);
++  EmitFrameMoves(0, Moves);
++  MCE->emitAlignment(4);
++  
++  MCE->emitAt((uintptr_t*)StartCommonPtr, 
++              (uintptr_t)((unsigned char*)MCE->getCurrentPCValue() - 
++                          FrameCommonBeginPtr));
++
++  return StartCommonPtr;
++}
++
++
++unsigned char* JITDwarfEmitter::EmitEHFrame(const Function* Personality,
++                                            unsigned char* StartCommonPtr,
++                                            unsigned char* StartFunction, 
++                                            unsigned char* EndFunction,
++                                            unsigned char* ExceptionTable) {
++  unsigned PointerSize = TD->getPointerSize();
++  
++  // EH frame header.
++  unsigned char* StartEHPtr = (unsigned char*)MCE->getCurrentPCValue();
++  MCE->allocateSpace(PointerSize, 0);
++  unsigned char* FrameBeginPtr = (unsigned char*)MCE->getCurrentPCValue();
++  // FDE CIE Offset
++  if (PointerSize == 8) {
++    MCE->emitInt64(FrameBeginPtr - StartCommonPtr);
++    MCE->emitInt64(StartFunction - (unsigned char*)MCE->getCurrentPCValue());
++    MCE->emitInt64(EndFunction - StartFunction);
++  } else {
++    MCE->emitInt32(FrameBeginPtr - StartCommonPtr);
++    MCE->emitInt32(StartFunction - (unsigned char*)MCE->getCurrentPCValue());
++    MCE->emitInt32(EndFunction - StartFunction);
++  }
++
++  // If there is a personality and landing pads then point to the language
++  // specific data area in the exception table.
++  if (MMI->getPersonalityIndex()) {
++    MCE->emitULEB128Bytes(4);
++        
++    if (!MMI->getLandingPads().empty()) {
++      if (PointerSize == 8)
++        MCE->emitInt64(ExceptionTable - (unsigned char*)MCE->getCurrentPCValue());
++      else
++        MCE->emitInt32(ExceptionTable - (unsigned char*)MCE->getCurrentPCValue());
++    } else if (PointerSize == 8) {
++      MCE->emitInt64((int)0);
++    } else {
++      MCE->emitInt32((int)0);
++    }
++  } else {
++    MCE->emitULEB128Bytes(0);
++  }
++      
++  // Indicate locations of function specific  callee saved registers in
++  // frame.
++  EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves());
++      
++  MCE->emitAlignment(4);
++  
++  // Indicate the size of the table
++  MCE->emitAt((uintptr_t*)StartEHPtr, 
++              (uintptr_t)((unsigned char*)MCE->getCurrentPCValue() - 
++                          StartEHPtr));
++  
++  // Double zeroes for the unwind runtime
++  if (PointerSize == 8) {
++    MCE->emitInt64(0);
++    MCE->emitInt64(0);
++  } else {
++    MCE->emitInt32(0);
++    MCE->emitInt32(0);
++  }
++
++  
++  return StartEHPtr;
++}
+Index: lib/ExecutionEngine/JIT/JIT.cpp
+===================================================================
+--- lib/ExecutionEngine/JIT/JIT.cpp	(revision 46321)
++++ lib/ExecutionEngine/JIT/JIT.cpp	(working copy)
+@@ -314,8 +314,15 @@
+       abort();
+     }
+   }
++  
++  if (void *Addr = getPointerToGlobalIfAvailable(F)) {
++    return Addr;
++  }
+ 
+   if (F->isDeclaration()) {
++    if (void *Addr = getPointerToGlobalIfAvailable(F)) {
++      return Addr;
++    }
+     void *Addr = getPointerToNamedFunction(F->getName());
+     addGlobalMapping(F, Addr);
+     return Addr;
+Index: lib/ExecutionEngine/JIT/JITDwarfEmitter.h
+===================================================================
+--- lib/ExecutionEngine/JIT/JITDwarfEmitter.h	(revision 0)
++++ lib/ExecutionEngine/JIT/JITDwarfEmitter.h	(revision 0)
+@@ -0,0 +1,69 @@
++//===------ JITDwarfEmitter.h - Write dwarf tables into memory ------------===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++//
++// This file defines a JITDwarfEmitter object that is used by the JIT to
++// write dwarf tables to memory.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
++#define LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
++
++namespace llvm {
++
++class Function;
++class MachineCodeEmitter;
++class MachineFunction;
++class MachineModuleInfo;
++class MachineMove;
++class MRegisterInfo;
++class TargetData;
++class TargetMachine;
++
++class JITDwarfEmitter {
++  const TargetData* TD;
++  MachineCodeEmitter* MCE;
++  const MRegisterInfo* RI;
++  MachineModuleInfo* MMI;
++  JIT& Jit;
++  bool needsIndirectEncoding;
++  bool stackGrowthDirection;
++  
++public:
++  JITDwarfEmitter(JIT& jit);
++
++  unsigned char* EmitExceptionTable(MachineFunction* MF,
++                                    unsigned char* StartFunction, 
++                                    unsigned char* EndFunction);
++
++  void EmitFrameMoves(intptr_t BaseLabelPtr, 
++                      const std::vector<MachineMove> &Moves);
++    
++  unsigned char* EmitCommonEHFrame(const Function* Personality);
++
++  unsigned char* EmitEHFrame(const Function* Personality, 
++                             unsigned char* StartBufferPtr,
++                             unsigned char* StartFunction, 
++                             unsigned char* EndFunction,
++                             unsigned char* ExceptionTable);
++    
++
++  unsigned char* EmitDwarfTable(MachineFunction& F, 
++                                MachineCodeEmitter& MCE,
++                                unsigned char* StartFunction,
++                                unsigned char* EndFunction);
++  
++  void setModuleInfo(MachineModuleInfo* Info) {
++    MMI = Info;
++  }
++};
++
++} // end namespace llvm
++
++#endif // LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
+Index: lib/ExecutionEngine/JIT/JITMemoryManager.cpp
+===================================================================
+--- lib/ExecutionEngine/JIT/JITMemoryManager.cpp	(revision 46321)
++++ lib/ExecutionEngine/JIT/JITMemoryManager.cpp	(working copy)
+@@ -256,6 +256,7 @@
+     sys::MemoryBlock getNewMemoryBlock(unsigned size);
+     
+     std::map<const Function*, MemoryRangeHeader*> FunctionBlocks;
++    std::map<const Function*, MemoryRangeHeader*> TableBlocks;
+   public:
+     DefaultJITMemoryManager();
+     ~DefaultJITMemoryManager();
+@@ -290,6 +291,28 @@
+       FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
+     }
+     
++    /// startExceptionTable - Use startFunctionBody to allocate memory for the 
++    /// function's exception table.
++    unsigned char* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
++      return startFunctionBody(F, ActualSize);
++    }
++
++    /// endExceptionTable - The exception table of F is now allocated, 
++    /// and takes the memory in the range [TableStart,TableEnd).
++    void endExceptionTable(const Function *F, unsigned char *TableStart,
++                           unsigned char *TableEnd, 
++                           unsigned char* FrameRegister) {
++      assert(TableEnd > TableStart);
++      assert(TableStart == (unsigned char *)(CurBlock+1) &&
++             "Mismatched table start/end!");
++      
++      uintptr_t BlockSize = TableEnd - (unsigned char *)CurBlock;
++      TableBlocks[F] = CurBlock;
++
++      // Release the memory at the end of this block that isn't needed.
++      FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
++    }
++    
+     unsigned char *getGOTBase() const {
+       return GOTBase;
+     }
+@@ -315,6 +338,24 @@
+       
+       // Finally, remove this entry from FunctionBlocks.
+       FunctionBlocks.erase(I);
++      
++      I = TableBlocks.find(F);
++      if (I == TableBlocks.end()) return;
++      
++      // Find the block that is allocated for this function.
++      MemRange = I->second;
++      assert(MemRange->ThisAllocated && "Block isn't allocated!");
++      
++      // Fill the buffer with garbage!
++#ifndef NDEBUG
++      memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
++#endif
++      
++      // Free the memory.
++      FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
++      
++      // Finally, remove this entry from TableBlocks.
++      TableBlocks.erase(I);
+     }
+   };
+ }
+Index: lib/ExecutionEngine/ExecutionEngine.cpp
+===================================================================
+--- lib/ExecutionEngine/ExecutionEngine.cpp	(revision 46321)
++++ lib/ExecutionEngine/ExecutionEngine.cpp	(working copy)
+@@ -34,7 +34,9 @@
+ 
+ ExecutionEngine::EECtorFn ExecutionEngine::JITCtor = 0;
+ ExecutionEngine::EECtorFn ExecutionEngine::InterpCtor = 0;
++ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
+ 
++
+ ExecutionEngine::ExecutionEngine(ModuleProvider *P) : LazyFunctionCreator(0) {
+   LazyCompilationDisabled = false;
+   Modules.push_back(P);
+@@ -89,7 +91,7 @@
+   // If we are using the reverse mapping, add it too
+   if (!state.getGlobalAddressReverseMap(locked).empty()) {
+     const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr];
+-    assert((V == 0 || GV == 0) && "GlobalMapping already established!");
++    // assert((V == 0 || GV == 0) && "GlobalMapping already established!");
+     V = GV;
+   }
+ }
+@@ -125,7 +127,7 @@
+   // If we are using the reverse mapping, add it too
+   if (!state.getGlobalAddressReverseMap(locked).empty()) {
+     const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr];
+-    assert((V == 0 || GV == 0) && "GlobalMapping already established!");
++    // assert((V == 0 || GV == 0) && "GlobalMapping already established!");
+     V = GV;
+   }
+ }
+Index: lib/VMCore/AsmWriter.cpp
+===================================================================
+--- lib/VMCore/AsmWriter.cpp	(revision 46321)
++++ lib/VMCore/AsmWriter.cpp	(working copy)
+@@ -1052,8 +1052,9 @@
+   case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;      
+   case GlobalValue::ExternalLinkage: break;
+   case GlobalValue::GhostLinkage:
+-    cerr << "GhostLinkage not allowed in AsmWriter!\n";
+-    abort();
++    //cerr << "GhostLinkage not allowed in AsmWriter!\n";
++    //abort();
++    break;
+   }
+   switch (F->getVisibility()) {
+   default: assert(0 && "Invalid visibility style!");
diff --git a/vmkit/vmkit-llvm-svn.patch b/vmkit/vmkit-llvm-svn.patch
new file mode 100644
index 0000000..171b2fc
--- /dev/null
+++ b/vmkit/vmkit-llvm-svn.patch
@@ -0,0 +1,933 @@
+Index: include/llvm/Target/TargetOptions.h
+===================================================================
+--- include/llvm/Target/TargetOptions.h	(revision 48143)
++++ include/llvm/Target/TargetOptions.h	(working copy)
+@@ -74,10 +74,15 @@
+   /// be emitted.
+   extern bool ExceptionHandling;
+ 
++  /// SizedMemoryCode - This flags indicates that memory for code is allocated by
++  /// an external allocator which requires the size to allocate
++  extern bool SizedMemoryCode;
++
+   /// PerformTailCallOpt - This flag is enabled when -tailcallopt is specified
+   /// on the commandline. When the flag is on, the target will perform tail call
+   /// optimization (pop the caller's stack) providing it supports it.
+   extern bool PerformTailCallOpt;
++
+ } // End llvm namespace
+ 
+ #endif
+Index: include/llvm/CodeGen/SizeEmitter.h
+===================================================================
+--- include/llvm/CodeGen/SizeEmitter.h	(revision 0)
++++ include/llvm/CodeGen/SizeEmitter.h	(revision 0)
+@@ -0,0 +1,116 @@
++//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===//
++//
++//                     The LLVM Compiler Infrastructure
++//
++// This file was developed by the LLVM research group and is distributed under
++// the University of Illinois Open Source License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++//
++// This file defines an abstract interface that is used by the machine code
++// emission framework to output the code.  This allows machine code emission to
++// be separated from concerns such as resolution of call targets, and where the
++// machine code will be written (memory or disk, f.e.).
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef LLVM_CODEGEN_SIZEEMITTER_H
++#define LLVM_CODEGEN_SIZEEMITTER_H
++
++#include "llvm/CodeGen/MachineCodeEmitter.h"
++#include "llvm/CodeGen/MachineFunction.h"
++
++namespace llvm {
++  /// SizeEmitter - The JIT implementation of the MachineCodeEmitter, which is
++  /// used to output functions to memory for execution.
++class SizeEmitter : public MachineCodeEmitter {
++  MachineFunction * Fn;
++  void* ConstantPoolBase;
++  void* JumpTableBase;
++  MachineConstantPool *ConstantPool;
++  MachineJumpTableInfo *JumpTable;
++  std::vector<intptr_t> LabelLocations;
++  MachineCodeEmitter* MCE;
++
++public:
++  SizeEmitter(MachineCodeEmitter* mce) { 
++    CurBufferPtr = 0; 
++    BufferBegin = 0; 
++    BufferEnd = (unsigned char*)-1;
++    MCE = mce;
++  }
++
++  SizeEmitter(std::vector<intptr_t> locations) {
++    LabelLocations = locations;
++    CurBufferPtr = 0; 
++    BufferBegin = 0; 
++    BufferEnd = (unsigned char*)-1;
++  }
++  
++  void initConstantPool(MachineConstantPool *MCP);
++
++  void initJumpTableInfo(MachineJumpTableInfo *MJTI);
++
++
++  virtual void startFunction(MachineFunction &F) { 
++    CurBufferPtr = 0; 
++    Fn = &F;
++  
++    // Ensure the constant pool/jump table info is at least 4-byte aligned.
++    emitAlignment(16);
++
++    initConstantPool(F.getConstantPool());
++    initJumpTableInfo(F.getJumpTableInfo());
++   
++    ConstantPoolBase  = (void*)(((unsigned) ConstantPoolBase) + CurBufferPtr);
++    JumpTableBase     = (void*)(((unsigned) JumpTableBase) + CurBufferPtr);
++  }
++
++  virtual bool finishFunction(MachineFunction &F) { 
++    MCE->setCurrentPtr(CurBufferPtr);
++    return false;
++  }
++  virtual void startFunctionStub(unsigned StubSize, unsigned Alignment) {}
++  virtual void *finishFunctionStub(const Function *F) { return 0; }
++  virtual void addRelocation(const llvm::MachineRelocation&) { }
++  virtual void emitByte(unsigned char B) {
++    CurBufferPtr++;
++  }
++  virtual void emitWordLE(unsigned W) {
++    CurBufferPtr+=4;
++  }   
++  virtual void emitWordBE(unsigned W) {
++    CurBufferPtr+=4;
++  }
++  virtual void emitInt32(int Value) {
++    CurBufferPtr += 4;
++  }
++  virtual void emitInt64(uint64_t Value) {
++    CurBufferPtr += 8;
++  }
++  virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
++  }  
++
++
++
++  virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {}
++  virtual intptr_t getConstantPoolEntryAddress(unsigned ConstantNum) const;
++
++  virtual intptr_t getJumpTableEntryAddress(unsigned Index) const;
++
++  virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
++    assert(0 && "Should not be in getMachineBasicBlockAddress of SizeEmitter");
++  }
++  
++  virtual void emitLabel(uint64_t) {}
++  virtual intptr_t getLabelAddress(uint64_t LabelID) const {
++    assert(LabelLocations.size() > (unsigned)LabelID && 
++             LabelLocations[LabelID] && "Label not emitted!");
++      return LabelLocations[LabelID];
++  }
++  virtual void setModuleInfo(llvm::MachineModuleInfo*) {}
++};
++
++} // end llvm namespace
++
++#endif
+Index: include/llvm/CodeGen/MachineCodeEmitter.h
+===================================================================
+--- include/llvm/CodeGen/MachineCodeEmitter.h	(revision 48143)
++++ include/llvm/CodeGen/MachineCodeEmitter.h	(working copy)
+@@ -18,6 +18,7 @@
+ #define LLVM_CODEGEN_MACHINECODEEMITTER_H
+ 
+ #include "llvm/Support/DataTypes.h"
++#include <string>
+ #include <vector>
+ 
+ namespace llvm {
+@@ -92,7 +93,7 @@
+   /// emitByte - This callback is invoked when a byte needs to be written to the
+   /// output stream.
+   ///
+-  void emitByte(unsigned char B) {
++  virtual void emitByte(unsigned char B) {
+     if (CurBufferPtr != BufferEnd)
+       *CurBufferPtr++ = B;
+   }
+@@ -100,7 +101,7 @@
+   /// emitWordLE - This callback is invoked when a 32-bit word needs to be
+   /// written to the output stream in little-endian format.
+   ///
+-  void emitWordLE(unsigned W) {
++  virtual void emitWordLE(unsigned W) {
+     if (CurBufferPtr+4 <= BufferEnd) {
+       *CurBufferPtr++ = (unsigned char)(W >>  0);
+       *CurBufferPtr++ = (unsigned char)(W >>  8);
+@@ -114,7 +115,7 @@
+   /// emitWordBE - This callback is invoked when a 32-bit word needs to be
+   /// written to the output stream in big-endian format.
+   ///
+-  void emitWordBE(unsigned W) {
++  virtual void emitWordBE(unsigned W) {
+     if (CurBufferPtr+4 <= BufferEnd) {
+       *CurBufferPtr++ = (unsigned char)(W >> 24);
+       *CurBufferPtr++ = (unsigned char)(W >> 16);
+@@ -175,7 +176,7 @@
+   }
+   
+   /// emitInt32 - Emit a int32 directive.
+-  void emitInt32(int Value) {
++  virtual void emitInt32(int Value) {
+     if (CurBufferPtr+4 <= BufferEnd) {
+       *((uint32_t*)CurBufferPtr) = Value;
+       CurBufferPtr += 4;
+@@ -185,7 +186,7 @@
+   }
+ 
+   /// emitInt64 - Emit a int64 directive.
+-  void emitInt64(uint64_t Value) {
++  virtual void emitInt64(uint64_t Value) {
+     if (CurBufferPtr+8 <= BufferEnd) {
+       *((uint64_t*)CurBufferPtr) = Value;
+       CurBufferPtr += 8;
+@@ -195,7 +196,7 @@
+   }
+   
+   /// emitAt - Emit Value in Addr
+-  void emitAt(uintptr_t *Addr, uintptr_t Value) {
++  virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
+     if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd)
+       (*Addr) = Value;
+   }
+@@ -270,6 +271,11 @@
+   /// Specifies the MachineModuleInfo object. This is used for exception handling
+   /// purposes.
+   virtual void setModuleInfo(MachineModuleInfo* Info) = 0;
++
++  void setCurrentPtr(unsigned char* Ptr) {
++    CurBufferPtr = Ptr;
++  }
++
+ };
+ 
+ } // End llvm namespace
+Index: lib/CodeGen/LLVMTargetMachine.cpp
+===================================================================
+--- lib/CodeGen/LLVMTargetMachine.cpp	(revision 48143)
++++ lib/CodeGen/LLVMTargetMachine.cpp	(working copy)
+@@ -17,6 +17,7 @@
+ #include "llvm/Assembly/PrintModulePass.h"
+ #include "llvm/Analysis/LoopPass.h"
+ #include "llvm/CodeGen/Passes.h"
++#include "llvm/CodeGen/SizeEmitter.h"
+ #include "llvm/CodeGen/Collector.h"
+ #include "llvm/Target/TargetOptions.h"
+ #include "llvm/Transforms/Scalar.h"
+@@ -257,7 +258,13 @@
+   
+   if (addPreEmitPass(PM, Fast) && PrintMachineCode)
+     PM.add(createMachineFunctionPrinterPass(cerr));
++  
++  if (SizedMemoryCode) {
++    SizeEmitter * SE = new SizeEmitter(&MCE);
++    addSimpleCodeEmitter(PM, Fast, false, *SE);
++  }
+ 
++
+   addCodeEmitter(PM, Fast, PrintEmittedAsm, MCE);
+   
+   PM.add(createCollectorMetadataDeleter());
+Index: lib/CodeGen/SizeEmitter.cpp
+===================================================================
+--- lib/CodeGen/SizeEmitter.cpp	(revision 0)
++++ lib/CodeGen/SizeEmitter.cpp	(revision 0)
+@@ -0,0 +1,77 @@
++#include "llvm/CodeGen/SizeEmitter.h"
++#include "llvm/Constant.h"
++#include "llvm/Constants.h"
++#include "llvm/DerivedTypes.h"
++#include "llvm/Module.h"
++#include "llvm/Type.h"
++#include "llvm/CodeGen/MachineCodeEmitter.h"
++#include "llvm/CodeGen/MachineFunction.h"
++#include "llvm/CodeGen/MachineConstantPool.h"
++#include "llvm/CodeGen/MachineJumpTableInfo.h"
++#include "llvm/CodeGen/MachineRelocation.h"
++#include "llvm/ExecutionEngine/GenericValue.h"
++#include "llvm/Target/TargetData.h"
++#include "llvm/Target/TargetJITInfo.h"
++#include "llvm/Target/TargetMachine.h"
++#include "llvm/Target/TargetOptions.h"
++#include "llvm/Support/Debug.h"
++#include "llvm/Support/MutexGuard.h"
++#include "llvm/System/Disassembler.h"
++#include "llvm/ADT/Statistic.h"
++#include "llvm/System/Memory.h"
++#include <algorithm>
++using namespace llvm;
++
++
++void SizeEmitter::initConstantPool(MachineConstantPool *MCP) {
++  const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
++  if (Constants.empty()) return;
++
++  MachineConstantPoolEntry CPE = Constants.back();
++  unsigned Size = CPE.Offset;
++  const Type *Ty = CPE.isMachineConstantPoolEntry()
++    ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
++  Size += Fn->getTarget().getTargetData()->getABITypeSize(Ty);
++  ConstantPoolBase = allocateSpace(Size, 1 << MCP->getConstantPoolAlignment());
++  ConstantPool = MCP;
++}
++
++void SizeEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) {
++  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
++  if (JT.empty()) return;
++  
++  unsigned NumEntries = 0;
++  for (unsigned i = 0, e = JT.size(); i != e; ++i)
++    NumEntries += JT[i].MBBs.size();
++
++  unsigned EntrySize = MJTI->getEntrySize();
++
++  // Just allocate space for all the jump tables now.  We will fix up the actual
++  // MBB entries in the tables after we emit the code for each block, since then
++  // we will know the final locations of the MBBs in memory.
++  JumpTable = MJTI;
++  JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment());
++}
++
++intptr_t SizeEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const {
++  assert(ConstantNum < ConstantPool->getConstants().size() &&
++         "Invalid ConstantPoolIndex!");
++  return (intptr_t)ConstantPoolBase +
++         ConstantPool->getConstants()[ConstantNum].Offset;
++}
++
++intptr_t SizeEmitter::getJumpTableEntryAddress(unsigned Index) const {
++  const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables();
++  assert(Index < JT.size() && "Invalid jump table index!");
++  
++  unsigned Offset = 0;
++  unsigned EntrySize = JumpTable->getEntrySize();
++  
++  for (unsigned i = 0; i < Index; ++i)
++    Offset += JT[i].MBBs.size();
++  
++   Offset *= EntrySize;
++  
++  return (intptr_t)((char *)JumpTableBase + Offset);
++}
++
+Index: lib/Target/PowerPC/PPCInstrInfo.td
+===================================================================
+--- lib/Target/PowerPC/PPCInstrInfo.td	(revision 48143)
++++ lib/Target/PowerPC/PPCInstrInfo.td	(working copy)
+@@ -1189,6 +1189,8 @@
+           (BL_ELF texternalsym:$dst)>;
+ 
+ // Hi and Lo for Darwin Global Addresses.
++def : Pat<(PPChi texternalsym:$in, 0), (LIS texternalsym:$in)>;
++def : Pat<(PPClo texternalsym:$in, 0), (LI texternalsym:$in)>;
+ def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
+ def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
+ def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>;
+Index: lib/Target/PowerPC/PPCJITInfo.cpp
+===================================================================
+--- lib/Target/PowerPC/PPCJITInfo.cpp	(revision 48143)
++++ lib/Target/PowerPC/PPCJITInfo.cpp	(working copy)
+@@ -13,11 +13,15 @@
+ 
+ #define DEBUG_TYPE "jit"
+ #include "PPCJITInfo.h"
++#include "PPCRegisterInfo.h"
+ #include "PPCRelocations.h"
+ #include "PPCTargetMachine.h"
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/Config/alloca.h"
++#include "llvm/ExecutionEngine/ExecutionEngine.h"
+ #include "llvm/Support/Debug.h"
++#include "llvm/Support/Dwarf.h"
++#include "llvm/Target/TargetOptions.h"
+ #include <set>
+ using namespace llvm;
+ 
+@@ -52,24 +56,27 @@
+   if (Offset >= -(1 << 23) && Offset < (1 << 23)) {   // In range?
+     AtI[0] = BUILD_B(Offset, isCall);     // b/bl target
+   } else if (!is64Bit) {
+-    AtI[0] = BUILD_LIS(12, To >> 16);     // lis r12, hi16(address)
++    AtI[0] = BUILD_B(0, false);           // thread safety
+     AtI[1] = BUILD_ORI(12, 12, To);       // ori r12, r12, lo16(address)
+     AtI[2] = BUILD_MTCTR(12);             // mtctr r12
+     AtI[3] = BUILD_BCTR(isCall);          // bctr/bctrl
++    AtI[0] = BUILD_LIS(12, To >> 16);     // lis r12, hi16(address)
+   } else {
+-    AtI[0] = BUILD_LIS(12, To >> 48);      // lis r12, hi16(address)
++    AtI[0] = BUILD_B(0, false);            // thread safety
+     AtI[1] = BUILD_ORI(12, 12, To >> 32);  // ori r12, r12, lo16(address)
+     AtI[2] = BUILD_SLDI(12, 12, 32);       // sldi r12, r12, 32
+     AtI[3] = BUILD_ORIS(12, 12, To >> 16); // oris r12, r12, hi16(address)
+     AtI[4] = BUILD_ORI(12, 12, To);        // ori r12, r12, lo16(address)
+     AtI[5] = BUILD_MTCTR(12);              // mtctr r12
+     AtI[6] = BUILD_BCTR(isCall);           // bctr/bctrl
++    AtI[0] = BUILD_LIS(12, To >> 48);      // lis r12, hi16(address)
+   }
+ }
+ 
+ extern "C" void PPC32CompilationCallback();
+ extern "C" void PPC64CompilationCallback();
+ 
++
+ #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
+     !defined(__ppc64__)
+ // CompilationCallback stub - We can't use a C function with inline assembly in
+@@ -143,6 +150,9 @@
+ // it, because we the prolog/epilog inserted by GCC won't work for us.  Instead,
+ // write our own wrapper, which does things our way, so we have complete control
+ // over register saving and restoring.
++
++# define CFI(x) x
++
+ asm(
+     ".text\n"
+     ".align 2\n"
+@@ -155,19 +165,29 @@
+     // FIXME Layout
+     //   8 double registers       -  64 bytes
+     //   8 int registers          -  32 bytes
++    CFI(".cfi_startproc\n")    
++    "stwu 1, -104(1)\n"
++    CFI(".cfi_adjust_cfa_offset 104\n")
+     "mflr 0\n"
+-    "stw 0,  4(1)\n"
+-    "stwu 1, -104(1)\n"
++    "stw 0,  108(1)\n"
++    CFI(".cfi_offset lr, 4\n")
+     // Save all int arg registers
+-    "stw 10, 100(1)\n"   "stw 9,  96(1)\n"
+-    "stw 8,  92(1)\n"    "stw 7,  88(1)\n"
+-    "stw 6,  84(1)\n"    "stw 5,  80(1)\n"
+-    "stw 4,  76(1)\n"    "stw 3,  72(1)\n"
++    "stw 10, 100(1)\n"   
++    "stw 9,  96(1)\n"
++    "stw 8,  92(1)\n"    
++    "stw 7,  88(1)\n"
++    "stw 6,  84(1)\n"    
++    "stw 5,  80(1)\n"
++    "stw 4,  76(1)\n"    
++    "stw 3,  72(1)\n"
+     // Save all call-clobbered FP regs.
+     "stfd 8,  64(1)\n"
+-    "stfd 7,  56(1)\n"   "stfd 6,  48(1)\n"
+-    "stfd 5,  40(1)\n"   "stfd 4,  32(1)\n"
+-    "stfd 3,  24(1)\n"   "stfd 2,  16(1)\n"
++    "stfd 7,  56(1)\n"   
++    "stfd 6,  48(1)\n"
++    "stfd 5,  40(1)\n"   
++    "stfd 4,  32(1)\n"
++    "stfd 3,  24(1)\n"   
++    "stfd 2,  16(1)\n"
+     "stfd 1,  8(1)\n"
+     // Arguments to Compilation Callback:
+     // r3 - our lr (address of the call instruction in stub plus 4)
+@@ -180,21 +200,29 @@
+     "bl PPCCompilationCallbackC\n"
+     "mtctr 3\n"
+     // Restore all int arg registers
+-    "lwz 10, 100(1)\n"   "lwz 9,  96(1)\n"
+-    "lwz 8,  92(1)\n"    "lwz 7,  88(1)\n"
+-    "lwz 6,  84(1)\n"    "lwz 5,  80(1)\n"
+-    "lwz 4,  76(1)\n"    "lwz 3,  72(1)\n"
++    "lwz 10, 100(1)\n"   
++    "lwz 9,  96(1)\n"
++    "lwz 8,  92(1)\n"    
++    "lwz 7,  88(1)\n"
++    "lwz 6,  84(1)\n"    
++    "lwz 5,  80(1)\n"
++    "lwz 4,  76(1)\n"    
++    "lwz 3,  72(1)\n"
+     // Restore all FP arg registers
+     "lfd 8,  64(1)\n"
+-    "lfd 7,  56(1)\n"    "lfd 6,  48(1)\n"
+-    "lfd 5,  40(1)\n"    "lfd 4,  32(1)\n"
+-    "lfd 3,  24(1)\n"    "lfd 2,  16(1)\n"
++    "lfd 7,  56(1)\n"    
++    "lfd 6,  48(1)\n"
++    "lfd 5,  40(1)\n"    
++    "lfd 4,  32(1)\n"
++    "lfd 3,  24(1)\n"    
++    "lfd 2,  16(1)\n"
+     "lfd 1,  8(1)\n"
+     // Pop 3 frames off the stack and branch to target
+     "lwz  1, 104(1)\n"
+     "lwz  0, 4(1)\n"
+     "mtlr 0\n"
+     "bctr\n"
++    CFI(".cfi_endproc\n")    
+     );
+ #else
+ void PPC32CompilationCallback() {
+@@ -324,6 +352,31 @@
+   return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
+ }
+ 
++static const char* GetCommonFrame32() {
++    /*
++    // Size of common frame
++    MCE.emitWordBE(16);
++    // Common frame
++    MCE.emitWordBE(0);
++    MCE.emitByte(1);
++    MCE.emitByte('z');
++    MCE.emitByte('R');
++    MCE.emitByte(0);
++    MCE.emitByte(1);
++    MCE.emitByte(-4 & 0x7f);
++    MCE.emitByte(0x41);
++    MCE.emitByte(1);
++    MCE.emitByte(16);
++    MCE.emitByte(0xc);
++    MCE.emitByte(1);
++    MCE.emitByte(0);*/
++  static const char CF[] = {
++    0, 0, 0, 16, 0, 0, 0, 0, 1, 'z', 'R', 0, 1, -4 & 0x7f, 
++    0x41, 1, 16, 0xc, 1, 0
++  };
++  return CF;
++}
++
+ #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
+ defined(__APPLE__)
+ extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+@@ -356,21 +409,26 @@
+     SyncICache((void*)Addr, 7*4);
+     return MCE.finishFunctionStub(0);
+   }
+-
+-  MCE.startFunctionStub(10*4);
++  
++  if (ExceptionHandling && !is64Bit) {
++    MCE.startFunctionStub(10*4 + 44);
++  } else {
++    MCE.startFunctionStub(10*4);
++  }
++  intptr_t BeginAddr = (intptr_t)MCE.getCurrentPCValue();
+   intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
+   if (is64Bit) {
++    MCE.emitWordBE(0x7d6802a6);     // mflr r11
++    MCE.emitWordBE(0xf9610010);     // std r11, 16(r1)
+     MCE.emitWordBE(0xf821ffb1);     // stdu r1,-80(r1)
++  } else if (TM.getSubtargetImpl()->isMachoABI()){
+     MCE.emitWordBE(0x7d6802a6);     // mflr r11
+-    MCE.emitWordBE(0xf9610060);     // std r11, 96(r1)
+-  } else if (TM.getSubtargetImpl()->isMachoABI()){
++    MCE.emitWordBE(0x91610008);     // stw r11, 8(r1)
+     MCE.emitWordBE(0x9421ffe0);     // stwu r1,-32(r1)
++  } else {
+     MCE.emitWordBE(0x7d6802a6);     // mflr r11
+-    MCE.emitWordBE(0x91610028);     // stw r11, 40(r1)
+-  } else {
++    MCE.emitWordBE(0x91610004);     // stw r11, 4(r1)
+     MCE.emitWordBE(0x9421ffe0);     // stwu r1,-32(r1)
+-    MCE.emitWordBE(0x7d6802a6);     // mflr r11
+-    MCE.emitWordBE(0x91610024);     // stw r11, 36(r1)
+   }
+   intptr_t BranchAddr = (intptr_t)MCE.getCurrentPCValue();
+   MCE.emitWordBE(0);
+@@ -382,6 +440,42 @@
+   MCE.emitWordBE(0);
+   EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit);
+   SyncICache((void*)Addr, 10*4);
++  intptr_t EndAddr = (intptr_t)MCE.getCurrentPCValue();
++  
++  if (ExceptionHandling && !is64Bit) {
++    // Size of Eh section
++    MCE.emitWordBE(32);
++    // Eh section
++    MCE.emitWordBE(MCE.getCurrentPCValue() - (intptr_t)GetCommonFrame32());
++    MCE.emitWordBE(BeginAddr - MCE.getCurrentPCValue());
++    MCE.emitWordBE(EndAddr - BeginAddr);
++    MCE.emitByte(0);
++    MCE.emitByte(dwarf::DW_CFA_advance_loc4);
++    MCE.emitWordBE(8);
++    MCE.emitByte(dwarf::DW_CFA_def_cfa_offset);
++    MCE.emitByte(32);
++    MCE.emitByte(dwarf::DW_CFA_offset_extended_sf);
++    MCE.emitByte(TM.getRegisterInfo()->getDwarfRegNum(PPC::LR, true));
++    if (TM.getSubtargetImpl()->isMachoABI()){
++      MCE.emitByte(-2 & 0x7f);
++    } else {
++      MCE.emitByte(-1 & 0x7f);
++    }
++    MCE.emitByte(dwarf::DW_CFA_advance_loc4);
++    MCE.emitWordBE(4);
++    MCE.emitByte(dwarf::DW_CFA_def_cfa_register);
++    MCE.emitByte(1);
++    // Alignment
++    MCE.emitByte(0);
++    MCE.emitByte(0);
++    
++    // Two zero for the unwind runtime
++    MCE.emitWordBE(0);
++    MCE.emitWordBE(0);
++    
++    SyncICache((void*)EndAddr, 44);
++    ExecutionEngine::RegisterTable((void*)EndAddr);
++  }
+   return MCE.finishFunctionStub(0);
+ }
+ 
+Index: lib/Target/TargetMachine.cpp
+===================================================================
+--- lib/Target/TargetMachine.cpp	(revision 48143)
++++ lib/Target/TargetMachine.cpp	(working copy)
+@@ -31,6 +31,7 @@
+   bool UseSoftFloat;
+   bool NoZerosInBSS;
+   bool ExceptionHandling;
++  bool SizedMemoryCode;
+   Reloc::Model RelocationModel;
+   CodeModel::Model CMModel;
+   bool PerformTailCallOpt;
+Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
+===================================================================
+--- lib/ExecutionEngine/JIT/JITEmitter.cpp	(revision 48143)
++++ lib/ExecutionEngine/JIT/JITEmitter.cpp	(working copy)
+@@ -18,12 +18,14 @@
+ #include "llvm/Constant.h"
+ #include "llvm/Module.h"
+ #include "llvm/Type.h"
++#include "llvm/ADT/DenseMap.h"
+ #include "llvm/CodeGen/MachineCodeEmitter.h"
+ #include "llvm/CodeGen/MachineFunction.h"
+ #include "llvm/CodeGen/MachineConstantPool.h"
+ #include "llvm/CodeGen/MachineJumpTableInfo.h"
+ #include "llvm/CodeGen/MachineModuleInfo.h"
+ #include "llvm/CodeGen/MachineRelocation.h"
++#include "llvm/CodeGen/SizeEmitter.h"
+ #include "llvm/ExecutionEngine/JITMemoryManager.h"
+ #include "llvm/Target/TargetData.h"
+ #include "llvm/Target/TargetJITInfo.h"
+@@ -278,8 +280,10 @@
+     DOUT << "JIT: Lazily resolving function '" << F->getName()
+          << "' In stub ptr = " << Stub << " actual ptr = "
+          << I->first << "\n";
+-
++    
++    TheJIT->lock.release();
+     Result = TheJIT->getPointerToFunction(F);
++    TheJIT->lock.acquire();
+   }
+ 
+   // We don't need to reuse this stub in the future, as F is now compiled.
+@@ -357,9 +361,11 @@
+         MemMgr->AllocateGOT();
+         DOUT << "JIT is managing a GOT\n";
+       }
+-
+-      if (ExceptionHandling) DE = new JITDwarfEmitter(jit);
++      
++      if (ExceptionHandling)
++        DE = new JITDwarfEmitter(jit);
+     }
++   
+     ~JITEmitter() { 
+       delete MemMgr;
+       if (ExceptionHandling) delete DE;
+@@ -370,6 +376,7 @@
+     virtual void startFunction(MachineFunction &F);
+     virtual bool finishFunction(MachineFunction &F);
+     
++    void initConstantPool(MachineConstantPool *MCP);
+     void emitConstantPool(MachineConstantPool *MCP);
+     void initJumpTableInfo(MachineJumpTableInfo *MJTI);
+     void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
+@@ -469,19 +476,47 @@
+ 
+ 
+ void JITEmitter::startFunction(MachineFunction &F) {
+-  uintptr_t ActualSize;
+-  BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
+-                                                         ActualSize);
+-  BufferEnd = BufferBegin+ActualSize;
++  MMI->BeginFunction(&F);
+   
+-  // Ensure the constant pool/jump table info is at least 4-byte aligned.
+-  emitAlignment(16);
++  if (SizedMemoryCode) {
++    BufferBegin = CurBufferPtr;
++    BufferEnd = (unsigned char*) 0xffffffff;
++  
++    // Ensure the constant pool/jump table info is at least 4-byte aligned.
++    emitAlignment(16);
+ 
+-  emitConstantPool(F.getConstantPool());
+-  initJumpTableInfo(F.getJumpTableInfo());
++    initConstantPool(F.getConstantPool());
++    initJumpTableInfo(F.getJumpTableInfo());
++    
++    
++    uintptr_t ActualSize = (uintptr_t)CurBufferPtr;
++    CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
++                                             ActualSize);
++  
++    ConstantPoolBase  = (void*)(((unsigned) ConstantPoolBase) + CurBufferPtr);
++    JumpTableBase     = (void*)(((unsigned) JumpTableBase) + CurBufferPtr);
+ 
+-  // About to start emitting the machine code for the function.
+-  emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
++    emitConstantPool(F.getConstantPool());
++
++  } else {
++    uintptr_t ActualSize;
++    BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
++                                                           ActualSize);
++    BufferEnd = BufferBegin+ActualSize;
++  
++    // Ensure the constant pool/jump table info is at least 4-byte aligned.
++    emitAlignment(16);
++
++    initConstantPool(F.getConstantPool());
++    emitConstantPool(F.getConstantPool());
++    initJumpTableInfo(F.getJumpTableInfo());
++  
++    // About to start emitting the machine code for the function.
++    emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
++
++  }
++  
++  
+   TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
+ 
+   MBBLocations.clear();
+@@ -579,12 +614,18 @@
+     DOUT << "Disassembled code:\n"
+          << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart);
+ #endif
++ 
+   if (ExceptionHandling) {
+     uintptr_t ActualSize;
++    if (SizedMemoryCode) {
++      SizeEmitter sz(LabelLocations);
++      DE->EmitDwarfTable(F, sz, FnStart, FnEnd);
++      ActualSize = sz.getCurrentPCValue();
++    }
+     SavedBufferBegin = BufferBegin;
+     SavedBufferEnd = BufferEnd;
+     SavedCurBufferPtr = CurBufferPtr;
+-
++    
+     BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
+                                                              ActualSize);
+     BufferEnd = BufferBegin+ActualSize;
+@@ -598,11 +639,10 @@
+     TheJIT->RegisterTable(FrameRegister);
+   }
+   MMI->EndFunction();
+- 
+   return false;
+ }
+ 
+-void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
++void JITEmitter::initConstantPool(MachineConstantPool *MCP) {
+   const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
+   if (Constants.empty()) return;
+ 
+@@ -611,12 +651,15 @@
+   const Type *Ty = CPE.isMachineConstantPoolEntry()
+     ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
+   Size += TheJIT->getTargetData()->getABITypeSize(Ty);
+-
++   
+   ConstantPoolBase = allocateSpace(Size, 1 << MCP->getConstantPoolAlignment());
+   ConstantPool = MCP;
++}
+ 
++void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
+   if (ConstantPoolBase == 0) return;  // Buffer overflow.
+ 
++  const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
+   // Initialize the memory for all of the constant pool entries.
+   for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
+     void *CAddr = (char*)ConstantPoolBase+Constants[i].Offset;
+Index: lib/ExecutionEngine/JIT/JIT.cpp
+===================================================================
+--- lib/ExecutionEngine/JIT/JIT.cpp	(revision 48143)
++++ lib/ExecutionEngine/JIT/JIT.cpp	(working copy)
+@@ -289,10 +289,10 @@
+ /// specified function, compiling it if neccesary.
+ ///
+ void *JIT::getPointerToFunction(Function *F) {
+-  MutexGuard locked(lock);
+ 
+-  if (void *Addr = getPointerToGlobalIfAvailable(F))
+-    return Addr;   // Check if function already code gen'd
++  if (void *Addr = getPointerToGlobalIfAvailable(F)) {
++    return Addr;
++  }
+ 
+   // Make sure we read in the function if it exists in this Module.
+   if (F->hasNotBeenReadFromBitcode()) {
+@@ -314,13 +314,25 @@
+       abort();
+     }
+   }
++  
++  if (void *Addr = getPointerToGlobalIfAvailable(F)) {
++    return Addr;
++  }
+ 
+   if (F->isDeclaration()) {
++    if (void *Addr = getPointerToGlobalIfAvailable(F)) {
++      return Addr;
++    }
+     void *Addr = getPointerToNamedFunction(F->getName());
+     addGlobalMapping(F, Addr);
+     return Addr;
+   }
+ 
++  MutexGuard locked(lock);
++  
++  if (void *Addr = getPointerToGlobalIfAvailable(F))
++    return Addr;   // Check if function already code gen'd
++  
+   runJITOnFunction(F);
+ 
+   void *Addr = getPointerToGlobalIfAvailable(F);
+Index: lib/ExecutionEngine/ExecutionEngine.cpp
+===================================================================
+--- lib/ExecutionEngine/ExecutionEngine.cpp	(revision 48143)
++++ lib/ExecutionEngine/ExecutionEngine.cpp	(working copy)
+@@ -92,7 +92,7 @@
+   // If we are using the reverse mapping, add it too
+   if (!state.getGlobalAddressReverseMap(locked).empty()) {
+     const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr];
+-    assert((V == 0 || GV == 0) && "GlobalMapping already established!");
++    // assert((V == 0 || GV == 0) && "GlobalMapping already established!");
+     V = GV;
+   }
+ }
+@@ -128,7 +128,7 @@
+   // If we are using the reverse mapping, add it too
+   if (!state.getGlobalAddressReverseMap(locked).empty()) {
+     const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr];
+-    assert((V == 0 || GV == 0) && "GlobalMapping already established!");
++    // assert((V == 0 || GV == 0) && "GlobalMapping already established!");
+     V = GV;
+   }
+ }
+Index: lib/VMCore/AsmWriter.cpp
+===================================================================
+--- lib/VMCore/AsmWriter.cpp	(revision 48143)
++++ lib/VMCore/AsmWriter.cpp	(working copy)
+@@ -1053,8 +1053,9 @@
+   case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;      
+   case GlobalValue::ExternalLinkage: break;
+   case GlobalValue::GhostLinkage:
+-    cerr << "GhostLinkage not allowed in AsmWriter!\n";
+-    abort();
++    //cerr << "GhostLinkage not allowed in AsmWriter!\n";
++    //abort();
++    break;
+   }
+   switch (F->getVisibility()) {
+   default: assert(0 && "Invalid visibility style!");
+Index: lib/Target/X86/X86JITInfo.cpp
+===================================================================
+--- lib/Target/X86/X86JITInfo.cpp	(revision 48341)
++++ lib/Target/X86/X86JITInfo.cpp	(working copy)
+@@ -57,7 +57,7 @@
+ // FIXME: Disable this until we really want to use it. Also, we will
+ //        need to add some workarounds for compilers, which support
+ //        only subset of these directives.
+-# define CFI(x)
++# define CFI(x) x
+ #endif
+ 
+ // Provide a wrapper for X86CompilationCallback2 that saves non-traditional
+Index: lib/Target/PowerPC/PPCISelLowering.cpp
+===================================================================
+--- lib/Target/PowerPC/PPCISelLowering.cpp	(revision 48651)
++++ lib/Target/PowerPC/PPCISelLowering.cpp	(working copy)
+@@ -177,10 +177,12 @@
+   // We want to legalize GlobalAddress and ConstantPool nodes into the 
+   // appropriate instructions to materialize the address.
+   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
++  setOperationAction(ISD::ExternalSymbol  , MVT::i32  , Custom);
+   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
+   setOperationAction(ISD::ConstantPool,  MVT::i32, Custom);
+   setOperationAction(ISD::JumpTable,     MVT::i32, Custom);
+   setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
++  setOperationAction(ISD::ExternalSymbol  , MVT::i64  , Custom);
+   setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
+   setOperationAction(ISD::ConstantPool,  MVT::i64, Custom);
+   setOperationAction(ISD::JumpTable,     MVT::i64, Custom);
+@@ -735,6 +737,36 @@
+   return isIntS16Immediate(Op.Val, Imm);
+ }
+ 
++ static SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
++   MVT::ValueType PtrVT = Op.getValueType();
++   ExternalSymbolSDNode *GSDB = dyn_cast<ExternalSymbolSDNode>(Op);
++   SDOperand GA = DAG.getTargetExternalSymbol(GSDB->getSymbol(), PtrVT);
++   SDOperand Zero = DAG.getConstant(0, PtrVT);
++      
++   const TargetMachine &TM = DAG.getTarget();
++ 
++   SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, GA, Zero);
++   SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, GA, Zero);
++ 
++   // If this is a non-darwin platform, we don't support non-static relo models
++   // yet.
++   if (TM.getRelocationModel() == Reloc::Static || 
++       !TM.getSubtarget<PPCSubtarget>().isDarwin()) {
++     // Generate non-pic code that has direct accesses to globals.
++     // The address of the global is just (hi(&g)+lo(&g)).
++     return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
++   }  
++      
++   if (TM.getRelocationModel() == Reloc::PIC_) {
++     // With PIC, the first instruction is actually "GR+hi(&G)".
++     Hi = DAG.getNode(ISD::ADD, PtrVT,
++                      DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi);
++   }  
++      
++   Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
++      
++   return Lo;
++ }
+ 
+ /// SelectAddressRegReg - Given the specified addressed, check to see if it
+ /// can be represented as an indexed [r+r] operation.  Returns false if it
+@@ -2116,11 +2148,11 @@
+   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
+   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
+   // node so that legalize doesn't hack it.
+-  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+-    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+-  else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+-    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
+-  else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
++  //if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
++  //  Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
++  //if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
++  //  Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
++  if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
+     // If this is an absolute destination address, use the munged value.
+     Callee = SDOperand(Dest, 0);
+   else {
+@@ -3381,6 +3413,7 @@
+   default: assert(0 && "Wasn't expecting to be able to lower this!"); 
+   case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
+   case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
++  case ISD::ExternalSymbol:     return LowerExternalSymbol(Op, DAG);
+   case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG);
+   case ISD::JumpTable:          return LowerJumpTable(Op, DAG);
+   case ISD::SETCC:              return LowerSETCC(Op, DAG);