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] = ∅
+ (*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] = ∅
+ }
+ 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] = ∅
+}
+
+void GCHash::initialise() {
+ if(!inited) {
+ inited = 1;
+ GCMinAlloc::initialise();
+
+ unsigned int i;
+
+ for(i=0; i<GCHashConst::nb_set_per_hash; i++) {
+ sets[i] = ∅
+ 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 = ∅
+ _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*> ¶ms);
+ 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);