2008-04-08 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / aot-runtime.c
index b610c2e6971e451a943a146ee801532553f3c9f7..51dc033bb0bf09cb76a2d37982346b4d6982e10a 100644 (file)
@@ -10,7 +10,9 @@
 
 #include "config.h"
 #include <sys/types.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <fcntl.h>
 #include <string.h>
 #ifndef PLATFORM_WIN32
 #include <windows.h>
 #endif
 
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
 #include <errno.h>
 #include <sys/stat.h>
 #include <limits.h>    /* for PAGESIZE */
 #define PAGESIZE 4096
 #endif
 
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>  /* for WIFEXITED, WEXITSTATUS */
+#endif
+
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/class.h>
 #include <mono/metadata/object.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
+#include <mono/metadata/gc-internal.h>
 #include <mono/utils/mono-logger.h>
 #include "mono/utils/mono-compiler.h"
 
 #include "mini.h"
+#include "version.h"
 
 #ifndef DISABLE_AOT
 
@@ -61,9 +73,11 @@ typedef struct MonoAotModule {
        /* Pointer to the Global Offset Table */
        gpointer *got;
        guint32 got_size;
+       GHashTable *name_cache;
        MonoAssemblyName *image_names;
        char **image_guids;
        MonoImage **image_table;
+       guint32 image_table_len;
        gboolean out_of_date;
        gboolean plt_inited;
        guint8 *mem_begin;
@@ -76,15 +90,18 @@ typedef struct MonoAotModule {
        guint8 *plt_jump_table;
        guint32 plt_jump_table_size;
        guint32 *code_offsets;
-       guint8 *method_infos;
+       guint8 *method_info;
        guint32 *method_info_offsets;
-       guint8 *ex_infos;
+       guint8 *got_info;
+       guint32 *got_info_offsets;
+       guint8 *ex_info;
        guint32 *ex_info_offsets;
        guint32 *method_order;
        guint32 *method_order_end;
-       guint8 *class_infos;
+       guint8 *class_info;
        guint32 *class_info_offsets;
        guint32 *methods_loaded;
+       guint16 *class_name_table;
 } MonoAotModule;
 
 static GHashTable *aot_modules;
@@ -99,11 +116,7 @@ static CRITICAL_SECTION aot_mutex;
  * code is in copy-on-write memory, this will not increase the memory usage
  * of the runtime.
  */
-#ifdef MONO_ARCH_HAVE_PIC_AOT
 static gboolean use_loaded_code = TRUE;
-#else
-static gboolean use_loaded_code = FALSE;
-#endif
 
 /*
  * Whenever to AOT compile loaded assemblies on demand and store them in
@@ -111,32 +124,33 @@ static gboolean use_loaded_code = FALSE;
  */
 static gboolean use_aot_cache = FALSE;
 
+/*
+ * Whenever to spawn a new process to AOT a file or do it in-process. Only relevant if
+ * use_aot_cache is TRUE.
+ */
+static gboolean spawn_compiler = TRUE;
+
 /* For debugging */
 static gint32 mono_last_aot_method = -1;
 
 static gboolean make_unreadable = FALSE;
 static guint32 n_pagefaults = 0;
+static guint32 name_table_accesses = 0;
 
 /* Used to speed-up find_aot_module () */
 static gsize aot_code_low_addr = (gssize)-1;
 static gsize aot_code_high_addr = 0;
 
-static MonoJitInfo*
-mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod *method, guint8 *code, guint8 *info, guint8 *ex_info);
+static gpointer
+mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod *method, guint8 *code, guint8 *info);
 
 static void
 init_plt (MonoAotModule *info);
 
-static gboolean 
+static inline gboolean 
 is_got_patch (MonoJumpInfoType patch_type)
 {
-#ifdef __x86_64__
-       return TRUE;
-#elif defined(__i386__)
        return TRUE;
-#else
-       return FALSE;
-#endif
 }
 
 /*****************************************************/
@@ -149,6 +163,8 @@ load_image (MonoAotModule *module, int index)
        MonoAssembly *assembly;
        MonoImageOpenStatus status;
 
+       g_assert (index < module->image_table_len);
+
        if (module->image_table [index])
                return module->image_table [index];
        if (module->out_of_date)
@@ -202,29 +218,62 @@ decode_value (guint8 *ptr, guint8 **rptr)
 }
 
 static MonoClass*
-decode_klass_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 {
        MonoImage *image;
-       MonoClass *klass;
-       guint32 token, rank, image_index;
+       MonoClass *klass, *eklass;
+       guint32 token, rank;
 
        token = decode_value (buf, &buf);
        if (token == 0) {
                *endbuf = buf;
                return NULL;
        }
-       image_index = decode_value (buf, &buf);
-       image = load_image (module, image_index);
-       if (!image)
-               return NULL;
-       if (mono_metadata_token_code (token) == 0) {
+       if (mono_metadata_token_table (token) == 0) {
+               image = load_image (module, decode_value (buf, &buf));
+               if (!image)
+                       return NULL;
                klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + token);
-       } else {
-               token = MONO_TOKEN_TYPE_DEF + decode_value (buf, &buf);
+       } else if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
+               if (token == MONO_TOKEN_TYPE_SPEC) {
+                       MonoClass *gclass;
+                       int i;
+                       MonoGenericContext ctx;
+                       MonoGenericInst inst;
+
+                       gclass = decode_klass_ref (module, buf, &buf);
+                       g_assert (gclass->generic_container);
+
+                       memset (&ctx, 0, sizeof (ctx));
+                       memset (&inst, 0, sizeof (inst));
+                       ctx.class_inst = &inst;
+                       inst.type_argc = decode_value (buf, &buf);
+                       inst.type_argv = g_new0 (MonoType*, inst.type_argc);
+                       for (i = 0; i < inst.type_argc; ++i) {
+                               MonoClass *pclass = decode_klass_ref (module, buf, &buf);
+                               if (!pclass) {
+                                       g_free (inst.type_argv);
+                                       return NULL;
+                               }
+                               inst.type_argv [i] = &pclass->byval_arg;
+                       }
+                       klass = mono_class_from_mono_type (mono_class_inflate_generic_type (&gclass->byval_arg, &ctx));
+               } else {
+                       image = load_image (module, decode_value (buf, &buf));
+                       if (!image)
+                               return NULL;
+                       klass = mono_class_get (image, token);
+               }
+       } else if (token == MONO_TOKEN_TYPE_DEF) {
+               /* Array */
+               image = load_image (module, decode_value (buf, &buf));
+               if (!image)
+                       return NULL;
                rank = decode_value (buf, &buf);
-               klass = mono_class_get (image, token);
-               g_assert (klass);
-               klass = mono_array_class_get (klass, rank);
+               eklass = decode_klass_ref (module, buf, &buf);
+               klass = mono_array_class_get (eklass, rank);
+       } else {
+               g_assert_not_reached ();
        }
        g_assert (klass);
        mono_class_init (klass);
@@ -236,7 +285,7 @@ decode_klass_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 static MonoClassField*
 decode_field_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
 {
-       MonoClass *klass = decode_klass_info (module, buf, &buf);
+       MonoClass *klass = decode_klass_ref (module, buf, &buf);
        guint32 token;
 
        if (!klass)
@@ -256,10 +305,17 @@ decode_method_ref (MonoAotModule *module, guint32 *token, guint8 *buf, guint8 **
        MonoImage *image;
 
        value = decode_value (buf, &buf);
-       *endbuf = buf;
        image_index = value >> 24;
        *token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
 
+       if (image_index == 255) {
+               /* Methodspec */
+               image_index = decode_value (buf, &buf);
+               *token = decode_value (buf, &buf);
+       }
+
+       *endbuf = buf;
+
        image = load_image (module, image_index);
        if (!image)
                return NULL;
@@ -342,15 +398,17 @@ create_cache_structure (void)
  * - Add options for excluding assemblies during development
  * - Maybe add a threshold after an assembly is AOT compiled
  * - invoking a new mono process is a security risk
+ * - recompile the AOT module if one of its dependencies changes
  */
-static GModule*
+static MonoDl*
 load_aot_module_from_cache (MonoAssembly *assembly, char **aot_name)
 {
-       char *fname, *cmd, *tmp2;
+       char *fname, *cmd, *tmp2, *aot_options;
        const char *home;
-       GModule *module;
+       MonoDl *module;
        gboolean res;
        gchar *out, *err;
+       gint exit_status;
 
        *aot_name = NULL;
 
@@ -367,26 +425,45 @@ load_aot_module_from_cache (MonoAssembly *assembly, char **aot_name)
        g_free (tmp2);
 
        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT trying to load from cache: '%s'.", fname);
-       module = g_module_open (fname, G_MODULE_BIND_LAZY);     
+       module = mono_dl_open (fname, MONO_DL_LAZY, NULL);
 
        if (!module) {
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT not found.");
 
                mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT precompiling assembly '%s'... ", assembly->image->name);
 
-               /* FIXME: security */
-               cmd = g_strdup_printf ("mono -O=all --aot=outfile=%s %s", fname, assembly->image->name);
+               aot_options = g_strdup_printf ("outfile=%s", fname);
 
-               res = g_spawn_command_line_sync (cmd, &out, &err, NULL, NULL);
-               g_free (cmd);
-               if (!res) {
-                       mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed.");
-                       return NULL;
+               if (spawn_compiler) {
+                       /* FIXME: security */
+                       /* FIXME: Has to pass the assembly loading path to the child process */
+                       cmd = g_strdup_printf ("mono -O=all --aot=%s %s", aot_options, assembly->image->name);
+
+                       res = g_spawn_command_line_sync (cmd, &out, &err, &exit_status, NULL);
+
+#if !defined(PLATFORM_WIN32) && !defined(__ppc__) && !defined(__powerpc__)
+                       if (res) {
+                               if (!WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) == 0))
+                                       mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed: %s.", err);
+                               else
+                                       mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
+                               g_free (out);
+                               g_free (err);
+                       }
+#endif
+                       g_free (cmd);
+               } else {
+                       res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options);
+                       if (!res) {
+                               mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed.");
+                       } else {
+                               mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
+                       }
                }
 
-               mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
+               module = mono_dl_open (fname, MONO_DL_LAZY, NULL);
 
-               module = g_module_open (fname, G_MODULE_BIND_LAZY);     
+               g_free (aot_options);
        }
 
        return module;
@@ -400,28 +477,36 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        gboolean usable = TRUE;
        char *saved_guid = NULL;
        char *aot_version = NULL;
+       char *runtime_version;
        char *opt_flags = NULL;
        gpointer *plt_jump_table_addr = NULL;
        guint32 *plt_jump_table_size = NULL;
-
-#ifdef MONO_ARCH_HAVE_PIC_AOT
        gpointer *got_addr = NULL;
        gpointer *got = NULL;
        guint32 *got_size_ptr = NULL;
-#endif
+       int i;
 
        if (mono_compile_aot)
                return;
-                                                       
+
+       if (assembly->aot_module)
+               /* 
+                * Already loaded. This can happen because the assembly loading code might invoke
+                * the assembly load hooks multiple times for the same assembly.
+                */
+               return;
+
        if (use_aot_cache)
                assembly->aot_module = load_aot_module_from_cache (assembly, &aot_name);
        else {
+               char *err;
                aot_name = g_strdup_printf ("%s%s", assembly->image->name, SHARED_EXT);
 
-               assembly->aot_module = g_module_open (aot_name, G_MODULE_BIND_LAZY);
+               assembly->aot_module = mono_dl_open (aot_name, MONO_DL_LAZY, &err);
 
                if (!assembly->aot_module) {
-                       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed to load AOT module %s: %s\n", aot_name, g_module_error ());
+                       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed to load AOT module %s: %s\n", aot_name, err);
+                       g_free (err);
                }
        }
 
@@ -430,9 +515,10 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                return;
        }
 
-       g_module_symbol (assembly->aot_module, "mono_assembly_guid", (gpointer *) &saved_guid);
-       g_module_symbol (assembly->aot_module, "mono_aot_version", (gpointer *) &aot_version);
-       g_module_symbol (assembly->aot_module, "mono_aot_opt_flags", (gpointer *)&opt_flags);
+       mono_dl_symbol (assembly->aot_module, "mono_assembly_guid", (gpointer *) &saved_guid);
+       mono_dl_symbol (assembly->aot_module, "mono_aot_version", (gpointer *) &aot_version);
+       mono_dl_symbol (assembly->aot_module, "mono_aot_opt_flags", (gpointer *)&opt_flags);
+       mono_dl_symbol (assembly->aot_module, "mono_runtime_version", (gpointer *)&runtime_version);
 
        if (!aot_version || strcmp (aot_version, MONO_AOT_FILE_VERSION)) {
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s has wrong file format version (expected %s got %s)\n", aot_name, MONO_AOT_FILE_VERSION, aot_version);
@@ -445,29 +531,31 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                }
        }
 
+       if (!runtime_version || ((strlen (runtime_version) > 0 && strcmp (runtime_version, FULL_VERSION)))) {
+               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is compiled against runtime version %s while this runtime has version %s.\n", aot_name, runtime_version, FULL_VERSION);
+               usable = FALSE;
+       }
+
        if (!usable) {
                g_free (aot_name);
-               g_module_close (assembly->aot_module);
+               mono_dl_close (assembly->aot_module);
                assembly->aot_module = NULL;
                return;
        }
 
-#ifdef MONO_ARCH_HAVE_PIC_AOT
-       g_module_symbol (assembly->aot_module, "got_addr", (gpointer *)&got_addr);
+       mono_dl_symbol (assembly->aot_module, "got_addr", (gpointer *)&got_addr);
        g_assert (got_addr);
        got = (gpointer*)*got_addr;
        g_assert (got);
-       g_module_symbol (assembly->aot_module, "got_size", (gpointer *)&got_size_ptr);
+       mono_dl_symbol (assembly->aot_module, "got_size", (gpointer *)&got_size_ptr);
        g_assert (got_size_ptr);
-#endif
 
        info = g_new0 (MonoAotModule, 1);
        info->aot_name = aot_name;
-#ifdef MONO_ARCH_HAVE_PIC_AOT
        info->got = got;
        info->got_size = *got_size_ptr;
        info->got [0] = assembly->image;
-#endif
+
        sscanf (opt_flags, "%d", &info->opts);
 
        /* Read image table */
@@ -475,7 +563,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                guint32 table_len, i;
                char *table = NULL;
 
-               g_module_symbol (assembly->aot_module, "mono_image_table", (gpointer *)&table);
+               mono_dl_symbol (assembly->aot_module, "mono_image_table", (gpointer *)&table);
                g_assert (table);
 
                table_len = *(guint32*)table;
@@ -483,6 +571,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                info->image_table = g_new0 (MonoImage*, table_len);
                info->image_names = g_new0 (MonoAssemblyName, table_len);
                info->image_guids = g_new0 (char*, table_len);
+               info->image_table_len = table_len;
                for (i = 0; i < table_len; ++i) {
                        MonoAssemblyName *aname = &(info->image_names [i]);
 
@@ -511,31 +600,34 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        }
 
        /* Read method and method_info tables */
-       g_module_symbol (assembly->aot_module, "method_offsets", (gpointer*)&info->code_offsets);
-       g_module_symbol (assembly->aot_module, "methods", (gpointer*)&info->code);
-       g_module_symbol (assembly->aot_module, "methods_end", (gpointer*)&info->code_end);
-       g_module_symbol (assembly->aot_module, "method_info_offsets", (gpointer*)&info->method_info_offsets);
-       g_module_symbol (assembly->aot_module, "method_infos", (gpointer*)&info->method_infos);
-       g_module_symbol (assembly->aot_module, "ex_info_offsets", (gpointer*)&info->ex_info_offsets);
-       g_module_symbol (assembly->aot_module, "ex_infos", (gpointer*)&info->ex_infos);
-       g_module_symbol (assembly->aot_module, "method_order", (gpointer*)&info->method_order);
-       g_module_symbol (assembly->aot_module, "method_order_end", (gpointer*)&info->method_order_end);
-       g_module_symbol (assembly->aot_module, "class_infos", (gpointer*)&info->class_infos);
-       g_module_symbol (assembly->aot_module, "class_info_offsets", (gpointer*)&info->class_info_offsets);
-       g_module_symbol (assembly->aot_module, "mem_end", (gpointer*)&info->mem_end);
+       mono_dl_symbol (assembly->aot_module, "method_offsets", (gpointer*)&info->code_offsets);
+       mono_dl_symbol (assembly->aot_module, "methods", (gpointer*)&info->code);
+       mono_dl_symbol (assembly->aot_module, "methods_end", (gpointer*)&info->code_end);
+       mono_dl_symbol (assembly->aot_module, "method_info_offsets", (gpointer*)&info->method_info_offsets);
+       mono_dl_symbol (assembly->aot_module, "method_info", (gpointer*)&info->method_info);
+       mono_dl_symbol (assembly->aot_module, "ex_info_offsets", (gpointer*)&info->ex_info_offsets);
+       mono_dl_symbol (assembly->aot_module, "ex_info", (gpointer*)&info->ex_info);
+       mono_dl_symbol (assembly->aot_module, "method_order", (gpointer*)&info->method_order);
+       mono_dl_symbol (assembly->aot_module, "method_order_end", (gpointer*)&info->method_order_end);
+       mono_dl_symbol (assembly->aot_module, "class_info", (gpointer*)&info->class_info);
+       mono_dl_symbol (assembly->aot_module, "class_info_offsets", (gpointer*)&info->class_info_offsets);
+       mono_dl_symbol (assembly->aot_module, "class_name_table", (gpointer *)&info->class_name_table);
+       mono_dl_symbol (assembly->aot_module, "got_info", (gpointer*)&info->got_info);
+       mono_dl_symbol (assembly->aot_module, "got_info_offsets", (gpointer*)&info->got_info_offsets);
+       mono_dl_symbol (assembly->aot_module, "mem_end", (gpointer*)&info->mem_end);
 
        info->mem_begin = info->code;
 
-       g_module_symbol (assembly->aot_module, "plt", (gpointer*)&info->plt);
-       g_module_symbol (assembly->aot_module, "plt_end", (gpointer*)&info->plt_end);
-       g_module_symbol (assembly->aot_module, "plt_info", (gpointer*)&info->plt_info);
+       mono_dl_symbol (assembly->aot_module, "plt", (gpointer*)&info->plt);
+       mono_dl_symbol (assembly->aot_module, "plt_end", (gpointer*)&info->plt_end);
+       mono_dl_symbol (assembly->aot_module, "plt_info", (gpointer*)&info->plt_info);
 
-       g_module_symbol (assembly->aot_module, "plt_jump_table_addr", (gpointer *)&plt_jump_table_addr);
+       mono_dl_symbol (assembly->aot_module, "plt_jump_table_addr", (gpointer *)&plt_jump_table_addr);
        g_assert (plt_jump_table_addr);
        info->plt_jump_table = (guint8*)*plt_jump_table_addr;
        g_assert (info->plt_jump_table);
 
-       g_module_symbol (assembly->aot_module, "plt_jump_table_size", (gpointer *)&plt_jump_table_size);
+       mono_dl_symbol (assembly->aot_module, "plt_jump_table_size", (gpointer *)&plt_jump_table_size);
        g_assert (plt_jump_table_size);
        info->plt_jump_table_size = *plt_jump_table_size;
 
@@ -566,7 +658,19 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        mono_jit_info_add_aot_module (assembly->image, info->code, info->code_end);
 
-       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT loaded AOT Module for %s.\n", assembly->image->name);
+       /*
+        * Since we store methoddef and classdef tokens when referring to methods/classes in
+        * referenced assemblies, we depend on the exact versions of the referenced assemblies.
+        * MS calls this 'hard binding'. This means we have to load all referenced assemblies
+        * non-lazily, since we can't handle out-of-date errors later.
+        */
+       for (i = 0; i < info->image_table_len; ++i)
+               load_image (info, i);
+
+       if (info->out_of_date)
+               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT Module %s is unusable because a dependency is out-of-date.\n", assembly->image->name);
+       else
+               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT loaded AOT Module for %s.\n", assembly->image->name);
 }
 
 void
@@ -589,6 +693,9 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
        guint32 flags;
 
        info->vtable_size = decode_value (buf, &buf);
+       if (info->vtable_size == -1)
+               /* Generic type */
+               return FALSE;
        flags = decode_value (buf, &buf);
        info->ghcimpl = (flags >> 0) & 0x1;
        info->has_finalize = (flags >> 1) & 0x1;
@@ -623,6 +730,7 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
 gboolean
 mono_aot_init_vtable (MonoVTable *vtable)
 {
+#ifdef MONO_ARCH_COMMON_VTABLE_TRAMPOLINE
        int i;
        MonoAotModule *aot_module;
        MonoClass *klass = vtable->klass;
@@ -641,7 +749,7 @@ mono_aot_init_vtable (MonoVTable *vtable)
                return FALSE;
        }
 
-       info = &aot_module->class_infos [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+       info = &aot_module->class_info [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
        p = info;
 
        err = decode_cached_class_info (aot_module, &class_info, p, &p);
@@ -650,43 +758,63 @@ mono_aot_init_vtable (MonoVTable *vtable)
                return FALSE;
        }
 
+       mono_aot_unlock ();
+
        //printf ("VT0: %s.%s %d\n", klass->name_space, klass->name, vtable_size);
        for (i = 0; i < class_info.vtable_size; ++i) {
-               guint32 image_index, token, value;
-               MonoImage *image;
-#ifndef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
-               MonoMethod *m;
+               vtable->vtable [i] = mini_get_vtable_trampoline ();
+       }
+
+       return TRUE;
+#else
+       return FALSE;
 #endif
+}
 
-               vtable->vtable [i] = 0;
+gpointer
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+{
+       int i;
+       MonoAotModule *aot_module;
+       MonoClass *klass = vtable->klass;
+       guint8 *info, *p;
+       MonoCachedClassInfo class_info;
+       gboolean err;
+       guint32 token;
+       MonoImage *image;
 
-               value = decode_value (p, &p);
-               if (!value)
-                       continue;
+       if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !klass->image->assembly->aot_module)
+               return NULL;
 
-               image_index = value >> 24;
-               token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
+       mono_aot_lock ();
 
-               image = load_image (aot_module, image_index);
-               if (!image) {
-                       mono_aot_unlock ();
-                       return FALSE;
-               }
+       aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
+       if (!aot_module) {
+               mono_aot_unlock ();
+               return NULL;
+       }
 
-#ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
-               vtable->vtable [i] = mono_create_jit_trampoline_from_token (image, token);
-#else
-               m = mono_get_method (image, token, NULL);
-               g_assert (m);
+       info = &aot_module->class_info [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+       p = info;
 
-               //printf ("M: %d %p %s\n", i, &(vtable->vtable [i]), mono_method_full_name (m, TRUE));
-               vtable->vtable [i] = mono_create_jit_trampoline (m);
-#endif
+       err = decode_cached_class_info (aot_module, &class_info, p, &p);
+       if (!err) {
+               mono_aot_unlock ();
+               return NULL;
+       }
+
+       for (i = 0; i < slot; ++i)
+               decode_method_ref (aot_module, &token, p, &p);
+
+       image = decode_method_ref (aot_module, &token, p, &p);
+       if (!image) {
+               mono_aot_unlock ();
+               return NULL;
        }
 
        mono_aot_unlock ();
 
-       return TRUE;
+       return mono_aot_get_method_from_token (domain, image, token);
 }
 
 gboolean
@@ -707,7 +835,7 @@ mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
                return FALSE;
        }
 
-       p = (guint8*)&aot_module->class_infos [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+       p = (guint8*)&aot_module->class_info [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
 
        err = decode_cached_class_info (aot_module, res, p, &p);
        if (!err) {
@@ -720,6 +848,120 @@ mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
        return TRUE;
 }
 
+/**
+ * mono_aot_get_class_from_name:
+ *
+ *  Obtains a MonoClass with a given namespace and a given name which is located in IMAGE,
+ * using a cache stored in the AOT file.
+ * Stores the resulting class in *KLASS if found, stores NULL otherwise.
+ *
+ * Returns: TRUE if the klass was found/not found in the cache, FALSE if no aot file was 
+ * found.
+ */
+gboolean
+mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
+{
+       MonoAotModule *aot_module;
+       guint16 *table, *entry;
+       guint16 table_size;
+       guint32 hash;
+       char full_name_buf [1024];
+       char *full_name;
+       const char *name2, *name_space2;
+       MonoTableInfo  *t;
+       guint32 cols [MONO_TYPEDEF_SIZE];
+       GHashTable *nspace_table;
+
+       if (!aot_modules)
+               return FALSE;
+
+       mono_aot_lock ();
+
+       aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, image->assembly);
+       if (!aot_module || !aot_module->class_name_table) {
+               mono_aot_unlock ();
+               return FALSE;
+       }
+
+       *klass = NULL;
+
+       /* First look in the cache */
+       if (!aot_module->name_cache)
+               aot_module->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+       nspace_table = g_hash_table_lookup (aot_module->name_cache, name_space);
+       if (nspace_table) {
+               *klass = g_hash_table_lookup (nspace_table, name);
+               if (*klass) {
+                       mono_aot_unlock ();
+                       return TRUE;
+               }
+       }
+
+       table_size = aot_module->class_name_table [0];
+       table = aot_module->class_name_table + 1;
+
+       if (name_space [0] == '\0')
+               full_name = g_strdup_printf ("%s", name);
+       else {
+               if (strlen (name_space) + strlen (name) < 1000) {
+                       sprintf (full_name_buf, "%s.%s", name_space, name);
+                       full_name = full_name_buf;
+               } else {
+                       full_name = g_strdup_printf ("%s.%s", name_space, name);
+               }
+       }
+       hash = g_str_hash (full_name) % table_size;
+       if (full_name != full_name_buf)
+               g_free (full_name);
+
+       entry = &table [hash * 2];
+
+       if (entry [0] != 0) {
+               t = &image->tables [MONO_TABLE_TYPEDEF];
+
+               while (TRUE) {
+                       guint32 index = entry [0];
+                       guint32 next = entry [1];
+                       guint32 token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, index);
+
+                       name_table_accesses ++;
+
+                       mono_metadata_decode_row (t, index - 1, cols, MONO_TYPEDEF_SIZE);
+
+                       name2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
+                       name_space2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
+
+                       if (!strcmp (name, name2) && !strcmp (name_space, name_space2)) {
+                               mono_aot_unlock ();
+                               *klass = mono_class_get (image, token);
+
+                               /* Add to cache */
+                               if (*klass) {
+                                       mono_aot_lock ();
+                                       nspace_table = g_hash_table_lookup (aot_module->name_cache, name_space);
+                                       if (!nspace_table) {
+                                               nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+                                               g_hash_table_insert (aot_module->name_cache, (char*)name_space2, nspace_table);
+                                       }
+                                       g_hash_table_insert (nspace_table, (char*)name2, *klass);
+                                       mono_aot_unlock ();
+                               }
+                               return TRUE;
+                       }
+
+                       if (next != 0) {
+                               entry = &table [next * 2];
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       mono_aot_unlock ();
+       
+       return TRUE;
+}
+
 static MonoJitInfo*
 decode_exception_debug_info (MonoAotModule *aot_module, MonoDomain *domain, 
                                                         MonoMethod *method, guint8* ex_info, guint8 *code)
@@ -768,11 +1010,7 @@ decode_exception_debug_info (MonoAotModule *aot_module, MonoDomain *domain,
        jinfo->used_regs = used_int_regs;
        jinfo->method = method;
        jinfo->code_start = code;
-#ifdef MONO_ARCH_HAVE_PIC_AOT
        jinfo->domain_neutral = 0;
-#else
-       jinfo->domain_neutral = (aot_module->opts & MONO_OPT_SHARED) != 0;
-#endif
 
        /* Load debug info */
        buf_len = decode_value (p, &p);
@@ -785,7 +1023,7 @@ MonoJitInfo *
 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 {
        MonoAssembly *ass = image->assembly;
-       GModule *module = ass->aot_module;
+       MonoDl *module = ass->aot_module;
        int pos, left, right, offset, offset1, offset2, last_offset, new_offset, page_index, method_index, table_len;
        guint32 token;
        MonoAotModule *aot_module;
@@ -891,7 +1129,7 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
        //printf ("F: %s\n", mono_method_full_name (method, TRUE));
 
        code = &aot_module->code [aot_module->code_offsets [method_index]];
-       ex_info = &aot_module->ex_infos [aot_module->ex_info_offsets [method_index]];
+       ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [method_index]];
 
        jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
 
@@ -905,7 +1143,7 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 }
 
 static gboolean
-decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guint8 *buf, guint8 **endbuf)
+decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guint8 *buf, guint8 **endbuf, guint32 *got_offset)
 {
        guint8 *p = buf;
        gpointer *table;
@@ -915,19 +1153,16 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
        switch (ji->type) {
        case MONO_PATCH_INFO_METHOD:
        case MONO_PATCH_INFO_METHODCONST:
-       case MONO_PATCH_INFO_METHOD_JUMP: {
-               guint32 image_index, token, value;
-
-               value = decode_value (p, &p);
-               image_index = value >> 24;
-               token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
+       case MONO_PATCH_INFO_METHOD_JUMP:
+       case MONO_PATCH_INFO_ICALL_ADDR: {
+               guint32 token;
 
-               image = load_image (aot_module, image_index);
+               image = decode_method_ref (aot_module, &token, p, &p);
                if (!image)
                        goto cleanup;
 
 #ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
-               if (ji->type == MONO_PATCH_INFO_METHOD) {
+               if ((ji->type == MONO_PATCH_INFO_METHOD) && (mono_metadata_token_table (token) == MONO_TABLE_METHOD)) {
                        ji->data.target = mono_create_jit_trampoline_from_token (image, token);
                        ji->type = MONO_PATCH_INFO_ABS;
                }
@@ -949,6 +1184,8 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
 
                wrapper_type = decode_value (p, &p);
 
+               ji->type = MONO_PATCH_INFO_METHOD;
+
                switch (wrapper_type) {
                case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: {
                        guint32 image_index, token, value;
@@ -964,46 +1201,48 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                        g_assert (ji->data.method);
                        mono_class_init (ji->data.method->klass);
 
-                       ji->type = MONO_PATCH_INFO_METHOD;
                        ji->data.method = mono_marshal_get_remoting_invoke_with_check (ji->data.method);
                        break;
                }
                case MONO_WRAPPER_PROXY_ISINST: {
-                       MonoClass *klass = decode_klass_info (aot_module, p, &p);
+                       MonoClass *klass = decode_klass_ref (aot_module, p, &p);
                        if (!klass)
                                goto cleanup;
-                       ji->type = MONO_PATCH_INFO_METHOD;
                        ji->data.method = mono_marshal_get_proxy_cancast (klass);
                        break;
                }
                case MONO_WRAPPER_LDFLD:
                case MONO_WRAPPER_LDFLDA:
                case MONO_WRAPPER_STFLD:
-               case MONO_WRAPPER_LDFLD_REMOTE:
-               case MONO_WRAPPER_STFLD_REMOTE:
                case MONO_WRAPPER_ISINST: {
-                       MonoClass *klass = decode_klass_info (aot_module, p, &p);
+                       MonoClass *klass = decode_klass_ref (aot_module, p, &p);
                        if (!klass)
                                goto cleanup;
-                       ji->type = MONO_PATCH_INFO_METHOD;
                        if (wrapper_type == MONO_WRAPPER_LDFLD)
                                ji->data.method = mono_marshal_get_ldfld_wrapper (&klass->byval_arg);
                        else if (wrapper_type == MONO_WRAPPER_LDFLDA)
                                ji->data.method = mono_marshal_get_ldflda_wrapper (&klass->byval_arg);
                        else if (wrapper_type == MONO_WRAPPER_STFLD)
                                ji->data.method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
-                       else if (wrapper_type == MONO_WRAPPER_LDFLD_REMOTE)
-                               ji->data.method = mono_marshal_get_ldfld_remote_wrapper (klass);
-                       else if (wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
-                               ji->data.method = mono_marshal_get_stfld_remote_wrapper (klass);
                        else if (wrapper_type == MONO_WRAPPER_ISINST)
                                ji->data.method = mono_marshal_get_isinst (klass);
                        else
                                g_assert_not_reached ();
                        break;
                }
+               case MONO_WRAPPER_LDFLD_REMOTE:
+                       ji->data.method = mono_marshal_get_ldfld_remote_wrapper (NULL);
+                       break;
+               case MONO_WRAPPER_STFLD_REMOTE:
+                       ji->data.method = mono_marshal_get_stfld_remote_wrapper (NULL);
+                       break;
+               case MONO_WRAPPER_ALLOC: {
+                       int atype = decode_value (p, &p);
+
+                       ji->data.method = mono_gc_get_managed_allocator_by_type (atype);
+                       break;
+               }
                case MONO_WRAPPER_STELEMREF:
-                       ji->type = MONO_PATCH_INFO_METHOD;
                        ji->data.method = mono_marshal_get_stelemref ();
                        break;
                default:
@@ -1018,12 +1257,25 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                p += len + 1;
                break;
        }
+       case MONO_PATCH_INFO_VTABLE:
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
-       case MONO_PATCH_INFO_VTABLE:
+               *got_offset = decode_value (p, &p);
+
+               if (aot_module->got [*got_offset]) {
+                       /* Already loaded */
+                       //printf ("HIT!\n");
+               } else {
+                       guint8 *tmp = aot_module->got_info + aot_module->got_info_offsets [*got_offset];
+                       ji->data.klass = decode_klass_ref (aot_module, tmp, &tmp);
+                       if (!ji->data.klass)
+                               goto cleanup;
+               }
+               break;
        case MONO_PATCH_INFO_CLASS_INIT:
-               ji->data.klass = decode_klass_info (aot_module, p, &p);
+       case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+               ji->data.klass = decode_klass_ref (aot_module, p, &p);
                if (!ji->data.klass)
                        goto cleanup;
                break;
@@ -1034,9 +1286,17 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                break;
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
-               ji->data.field = decode_field_info (aot_module, p, &p);
-               if (!ji->data.field)
-                       goto cleanup;
+               *got_offset = decode_value (p, &p);
+
+               if (aot_module->got [*got_offset]) {
+                       /* Already loaded */
+                       //printf ("HIT2!\n");
+               } else {
+                       guint8 *tmp = aot_module->got_info + aot_module->got_info_offsets [*got_offset];
+                       ji->data.field = decode_field_info (aot_module, tmp, &tmp);
+                       if (!ji->data.field)
+                               goto cleanup;
+               }
                break;
        case MONO_PATCH_INFO_SWITCH:
                ji->data.table = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoBBTable));
@@ -1070,16 +1330,24 @@ decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji,
                        goto cleanup;
                ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
                break;
+       case MONO_PATCH_INFO_RVA:
        case MONO_PATCH_INFO_DECLSEC:
        case MONO_PATCH_INFO_LDTOKEN:
        case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
-               image = load_image (aot_module, decode_value (p, &p));
-               if (!image)
-                       goto cleanup;
-               ji->data.token = mono_jump_info_token_new (mp, image, decode_value (p, &p));
+               *got_offset = decode_value (p, &p);
+
+               if (aot_module->got [*got_offset]) {
+                       /* Already loaded */
+               } else {
+                       guint8 *tmp = aot_module->got_info + aot_module->got_info_offsets [*got_offset];
+                       image = load_image (aot_module, decode_value (tmp, &tmp));
+                       if (!image)
+                               goto cleanup;
+                       ji->data.token = mono_jump_info_token_new (mp, image, decode_value (tmp, &tmp));
+               }
                break;
        case MONO_PATCH_INFO_EXC_NAME:
-               ji->data.klass = decode_klass_info (aot_module, p, &p);
+               ji->data.klass = decode_klass_ref (aot_module, p, &p);
                if (!ji->data.klass)
                        goto cleanup;
                ji->data.name = ji->data.klass->name;
@@ -1115,31 +1383,14 @@ load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches,
 
        /* First load the type + offset table */
        last_offset = 0;
-       patches = mono_mempool_alloc (mp, sizeof (MonoJumpInfo) * n_patches);
+       patches = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo) * n_patches);
 
        for (pindex = 0; pindex < n_patches; ++pindex) {                
                MonoJumpInfo *ji = &patches [pindex];
 
-#if defined(MONO_ARCH_HAVE_PIC_AOT)
                ji->type = *p;
                p ++;
-#else
-               guint8 b1, b2;
-
-               b1 = *(guint8*)p;
-               b2 = *((guint8*)p + 1);
-               p += 2;
 
-               ji->type = b1 >> 2;
-
-               if (((b1 & (1 + 2)) == 3) && (b2 == 255))
-                       ji->ip.i = decode_value (p, &p);
-               else
-                       ji->ip.i = (((guint32)(b1 & (1 + 2))) << 8) + b2;
-
-               ji->ip.i += last_offset;
-               last_offset = ji->ip.i;
-#endif
                //printf ("T: %d O: %d.\n", ji->type, ji->ip.i);
                ji->next = patch_info;
                patch_info = ji;
@@ -1152,13 +1403,11 @@ load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches,
        for (pindex = 0; pindex < n_patches; ++pindex) {
                MonoJumpInfo *ji = &patches [pindex];
 
-               if (!decode_patch_info (aot_module, mp, ji, p, &p))
+               if (!decode_patch_info (aot_module, mp, ji, p, &p, (*got_slots) + pindex))
                        goto cleanup;
 
-#if MONO_ARCH_HAVE_PIC_AOT
                if ((*got_slots) [pindex] == 0xffffffff)
                        (*got_slots) [pindex] = got_index ++;
-#endif
        }
 
        *endbuf = p;
@@ -1171,13 +1420,14 @@ load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches,
        return NULL;
 }
  
-static MonoJitInfo *
+static gpointer
 mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
 {
        MonoClass *klass = method->klass;
        MonoAssembly *ass = klass->image->assembly;
-       GModule *module = ass->aot_module;
-       guint8 *code, *info, *ex_info;
+       MonoDl *module = ass->aot_module;
+       guint32 method_index = mono_metadata_token_index (method->token) - 1;
+       guint8 *code, *info;
        MonoAotModule *aot_module;
 
        if (!module)
@@ -1206,7 +1456,13 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
        if (aot_module->out_of_date)
                return NULL;
 
-       if (aot_module->code_offsets [mono_metadata_token_index (method->token) - 1] == 0xffffffff) {
+       if (method->is_inflated) {
+               if (!mono_method_is_generic_sharable_impl (method))
+                       return NULL;
+               method = mono_method_get_declaring_generic_method (method);
+       }
+
+       if (aot_module->code_offsets [method_index] == 0xffffffff) {
                if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
                        char *full_name = mono_method_full_name (method, TRUE);
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
@@ -1215,9 +1471,14 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                return NULL;
        }
 
-       code = &aot_module->code [aot_module->code_offsets [mono_metadata_token_index (method->token) - 1]];
-       info = &aot_module->method_infos [aot_module->method_info_offsets [mono_metadata_token_index (method->token) - 1]];
-       ex_info = &aot_module->ex_infos [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
+       code = &aot_module->code [aot_module->code_offsets [method_index]];
+       info = &aot_module->method_info [aot_module->method_info_offsets [method_index]];
+
+       if (!aot_module->methods_loaded)
+               aot_module->methods_loaded = g_new0 (guint32, klass->image->tables [MONO_TABLE_METHOD].rows + 1);
+
+       if ((aot_module->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
+               return code;
 
        if (mono_last_aot_method != -1) {
                if (mono_jit_stats.methods_aot > mono_last_aot_method)
@@ -1227,27 +1488,32 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                                printf ("LAST AOT METHOD: %s.%s.%s.\n", klass->name_space, klass->name, method->name);
        }
 
-       return mono_aot_load_method (domain, aot_module, method, code, info, ex_info);
+       return mono_aot_load_method (domain, aot_module, method, code, info);
 }
 
-static MonoJitInfo*
-mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod *method, guint8 *code, guint8 *info, guint8* ex_info)
+static gpointer
+mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod *method, guint8 *code, guint8 *info)
 {
        MonoClass *klass = method->klass;
        MonoJumpInfo *patch_info = NULL;
-       MonoJitInfo *jinfo;
        MonoMemPool *mp;
        int i, pindex, got_index = 0, n_patches, used_strings;
        gboolean non_got_patches, keep_patches = TRUE;
-       guint8 *p;
-
-       jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
+       guint32 method_index = mono_metadata_token_index (method->token) - 1;
+       guint8 *p, *ex_info;
+       MonoJitInfo *jinfo = NULL;
 
        p = info;
-       decode_klass_info (aot_module, p, &p);
+       decode_klass_ref (aot_module, p, &p);
 
        if (!use_loaded_code) {
                guint8 *code2;
+
+               if (!jinfo) {
+                       ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
+                       jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
+               }
+
                code2 = mono_code_manager_reserve (domain->code_mp, jinfo->code_size);
                memcpy (code2, code, jinfo->code_size);
                mono_arch_flush_icache (code2, jinfo->code_size);
@@ -1269,9 +1535,7 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
 
        n_patches = decode_value (p, &p);
 
-#ifdef MONO_ARCH_HAVE_PIC_AOT
        keep_patches = FALSE;
-#endif
 
        if (n_patches) {
                MonoJumpInfo *patches;
@@ -1282,15 +1546,12 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                else
                        mp = mono_mempool_new ();
 
-#ifdef MONO_ARCH_HAVE_PIC_AOT
                got_index = decode_value (p, &p);
-#endif
 
                patches = load_patch_info (aot_module, mp, n_patches, got_index, &got_slots, p, &p);
                if (patches == NULL)
                        goto cleanup;
 
-#if MONO_ARCH_HAVE_PIC_AOT
                /* Do this outside the lock to avoid deadlocks */
                mono_aot_unlock ();
                non_got_patches = FALSE;
@@ -1306,21 +1567,17 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                                non_got_patches = TRUE;
                }
                if (non_got_patches) {
+                       if (!jinfo) {
+                               ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
+                               jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
+                       }
+
                        mono_arch_flush_icache (code, jinfo->code_size);
                        make_writable (code, jinfo->code_size);
                        mono_arch_patch_code (method, domain, code, patch_info, TRUE);
                }
                mono_aot_lock ();
-#else
-               if (use_loaded_code)
-                       /* disable write protection */
-                       make_writable (code, jinfo->code_size);
 
-               /* Do this outside the lock to avoid deadlocks */
-               mono_aot_unlock ();
-               mono_arch_patch_code (method, domain, code, patch_info, TRUE);
-               mono_aot_lock ();
-#endif
                g_free (got_slots);
 
                if (!keep_patches)
@@ -1331,13 +1588,21 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
 
        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
                char *full_name = mono_method_full_name (method, TRUE);
+
+               if (!jinfo) {
+                       ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
+                       jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
+               }
+
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", full_name, code, code + jinfo->code_size, info);
                g_free (full_name);
        }
 
+       aot_module->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
+
        init_plt (aot_module);
 
-       return jinfo;
+       return code;
 
  cleanup:
        /* FIXME: The space in domain->mp is wasted */  
@@ -1345,25 +1610,22 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                /* No need to cache patches */
                mono_mempool_destroy (mp);
 
+       if (jinfo)
+               g_free (jinfo);
+
        return NULL;
 }
 
-MonoJitInfo*
+gpointer
 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
 {
-       MonoJitInfo *info;
+       gpointer code;
 
        mono_aot_lock ();
-       info = mono_aot_get_method_inner (domain, method);
+       code = mono_aot_get_method_inner (domain, method);
        mono_aot_unlock ();
 
-       /* Do this outside the lock */
-       if (info) {
-               mono_jit_info_table_add (domain, info);
-               return info;
-       }
-       else
-               return NULL;
+       return code;
 }
 
 static gpointer
@@ -1374,7 +1636,7 @@ mono_aot_get_method_from_token_inner (MonoDomain *domain, MonoImage *image, guin
        int i, method_index, pindex, got_index, n_patches, used_strings;
        gboolean keep_patches = TRUE;
        guint8 *p;
-       GModule *module = ass->aot_module;
+       MonoDl *module = ass->aot_module;
        guint8 *code = NULL;
        guint8 *info;
        MonoAotModule *aot_module;
@@ -1401,7 +1663,7 @@ mono_aot_get_method_from_token_inner (MonoDomain *domain, MonoImage *image, guin
 
        method_index = mono_metadata_token_index (token) - 1;
        code = &aot_module->code [aot_module->code_offsets [method_index]];
-       info = &aot_module->method_infos [aot_module->method_info_offsets [method_index]];
+       info = &aot_module->method_info [aot_module->method_info_offsets [method_index]];
 
        if (!aot_module->methods_loaded)
                aot_module->methods_loaded = g_new0 (guint32, image->tables [MONO_TABLE_METHOD].rows + 1);
@@ -1420,7 +1682,7 @@ mono_aot_get_method_from_token_inner (MonoDomain *domain, MonoImage *image, guin
        }
 
        p = info;
-       *klass = decode_klass_info (aot_module, p, &p);
+       *klass = decode_klass_ref (aot_module, p, &p);
 
        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
                MonoMethod *method = mono_get_method (image, token, NULL);
@@ -1670,11 +1932,29 @@ mono_aot_handle_pagefault (void *ptr)
 
        n_pagefaults ++;
        mono_aot_unlock ();
+
+#if 0
+ {
+       void *array [256];
+       char **names;
+       int i, size;
+
+       printf ("\nNative stacktrace:\n\n");
+
+       size = backtrace (array, 256);
+       names = backtrace_symbols (array, size);
+       for (i =0; i < size; ++i) {
+               printf ("\t%s\n", names [i]);
+       }
+       free (names);
+ }
+#endif
+
 #endif
 }
 
 /*
- * aot_dyn_resolve:
+ * mono_aot_plt_resolve:
  *
  *   This function is called by the entries in the PLT to resolve the actual method that
  * needs to be called. It returns a trampoline to the method and patches the PLT entry.
@@ -1682,10 +1962,11 @@ mono_aot_handle_pagefault (void *ptr)
 gpointer
 mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
 {
-#ifdef MONO_ARCH_HAVE_PIC_AOT
+#ifdef MONO_ARCH_AOT_SUPPORTED
        guint8 *p, *target, *plt_entry;
        MonoJumpInfo ji;
        MonoAotModule *module = (MonoAotModule*)aot_module;
+       gboolean res;
 
        //printf ("DYN: %p %d\n", aot_module, plt_info_offset);
 
@@ -1693,8 +1974,9 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
 
        ji.type = decode_value (p, &p);
 
-       // FIXME: Error handling
-       decode_patch_info (module, NULL, &ji, p, &p);
+       res = decode_patch_info (module, NULL, &ji, p, &p, NULL);
+       // FIXME: Error handling (how ?)
+       g_assert (res);
 
        target = mono_resolve_patch_target (NULL, mono_domain_get (), NULL, &ji, TRUE);
 
@@ -1704,7 +1986,6 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
        mono_arch_patch_plt_entry (plt_entry, target);
 
        return target;
-
 #else
        g_assert_not_reached ();
        return NULL;
@@ -1721,11 +2002,12 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
 static void
 init_plt (MonoAotModule *info)
 {
-#ifdef MONO_ARCH_HAVE_PIC_AOT
+#ifdef MONO_ARCH_AOT_SUPPORTED
 #ifdef __i386__
        guint8 *buf = info->plt;
-#endif
-#if defined(__x86_64__)
+#elif defined(__x86_64__)
+       int i, n_entries;
+#elif defined(__arm__)
        int i, n_entries;
 #endif
        gpointer tramp;
@@ -1750,6 +2032,21 @@ init_plt (MonoAotModule *info)
         for (i = 1; i < n_entries; ++i)
                 /* Each PLT entry is 16 bytes long, the default entry begins at offset 6 */
                 ((gpointer*)info->plt_jump_table)[i] = info->plt + (i * 16) + 6;
+#elif defined(__arm__)
+        /* Initialize the first PLT entry */
+        make_writable (info->plt, info->plt_end - info->plt);
+        ((guint32*)info->plt)[1] = (guint32)tramp;
+
+        n_entries = ((guint8*)info->plt_end - (guint8*)info->plt) / 8;
+
+        /* 
+         * Initialize the jump targets embedded inside the PLT entries to the default
+         * targets.
+         */
+        for (i = 1; i < n_entries; ++i)
+                /* Each PLT entry is 8 bytes long, the jump target is at offset 4 */
+                /* Each default PLT target is 12 bytes long */
+                ((guint32*)info->plt)[(i * 2) + 1] = (guint8*)info->plt_end + ((i - 1) * 12);
 #else
        g_assert_not_reached ();
 #endif
@@ -1767,6 +2064,9 @@ guint8*
 mono_aot_get_plt_entry (guint8 *code)
 {
        MonoAotModule *aot_module = find_aot_module (code);
+#if defined(__arm__)
+       guint32 ins;
+#endif
 
        if (!aot_module)
                return NULL;
@@ -1779,6 +2079,19 @@ mono_aot_get_plt_entry (guint8 *code)
                if ((target >= (guint8*)(aot_module->plt)) && (target < (guint8*)(aot_module->plt_end)))
                        return target;
        }
+#elif defined(__arm__)
+       ins = ((guint32*)(gpointer)code) [-1];
+
+       /* Should be a 'bl' */
+       if ((((ins >> 25) & 0x7) == 0x5) && (((ins >> 24) & 0x1) == 0x1)) {
+               gint32 disp = ((gint32)ins) & 0xffffff;
+               guint8 *target = code - 4 + 8 + (disp * 4);
+
+               if ((target >= (guint8*)(aot_module->plt)) && (target < (guint8*)(aot_module->plt_end)))
+                       return target;
+       }               
+#else
+       g_assert_not_reached ();
 #endif
 
        return NULL;
@@ -1803,7 +2116,7 @@ mono_aot_init (void)
 {
 }
 
-MonoJitInfo*
+gpointer
 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
 {
        return NULL;
@@ -1827,6 +2140,12 @@ mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
        return FALSE;
 }
 
+gboolean
+mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
+{
+       return FALSE;
+}
+
 MonoJitInfo *
 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 {
@@ -1867,4 +2186,15 @@ mono_aot_get_plt_entry (guint8 *code)
        return NULL;
 }
 
+gpointer
+mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
+{
+       return NULL;
+}
+
+gpointer
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+{
+       return NULL;
+}
 #endif