Fix mcs build to use Thread.Abort.
[mono.git] / mono / mini / aot-runtime.c
index ba9d698d3dbd97e271340832fd2602f7ceba87aa..3091cab90549320f868f5dc2f5c385c909fc21b8 100644 (file)
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/mono-endian.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-mmap.h>
-#include "mono/utils/mono-compiler.h"
+#include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-digest.h>
 
@@ -60,6 +60,7 @@
 #include "seq-points.h"
 #include "version.h"
 #include "debugger-agent.h"
+#include "aot-compiler.h"
 
 #ifndef DISABLE_AOT
 
@@ -68,7 +69,7 @@
 #endif
 
 /* Number of got entries shared between the JIT and LLVM GOT */
-#define N_COMMON_GOT_ENTRIES 4
+#define N_COMMON_GOT_ENTRIES 10
 
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
@@ -84,7 +85,7 @@ typedef struct MonoAotModule {
        /* Pointer to the Global Offset Table */
        gpointer *got;
        gpointer *llvm_got;
-       gpointer shared_got [N_COMMON_GOT_ENTRIES];
+       gpointer *shared_got;
        GHashTable *name_cache;
        GHashTable *extra_methods;
        /* Maps methods to their code */
@@ -98,6 +99,7 @@ typedef struct MonoAotModule {
        guint32 image_table_len;
        gboolean out_of_date;
        gboolean plt_inited;
+       gboolean got_initializing;
        guint8 *mem_begin;
        guint8 *mem_end;
        guint8 *jit_code_start;
@@ -212,11 +214,10 @@ static void
 compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **code_end);
 
 static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass);
+init_llvm_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context);
 
-/*****************************************************/
-/*                 AOT RUNTIME                       */
-/*****************************************************/
+static MonoJumpInfo*
+decode_patches (MonoAotModule *amodule, MonoMemPool *mp, int n_patches, gboolean llvm, guint32 *got_offsets);
 
 static inline void
 amodule_lock (MonoAotModule *amodule)
@@ -478,6 +479,7 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                MonoType *gshared_constraint = NULL;
                char *par_name = NULL;
 
+               t = NULL;
                if (has_container) {
                        gboolean is_method = decode_value (p, &p);
                        
@@ -501,44 +503,44 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
                } else {
                        gboolean has_gshared_constraint = decode_value (p, &p);
                        if (has_gshared_constraint) {
-                               int len;
+                               MonoClass *par_klass;
 
                                gshared_constraint = decode_type (module, p, &p);
                                if (!gshared_constraint)
                                        return NULL;
 
-                               len = decode_value (p, &p);
-                               if (len) {
-                                       par_name = mono_image_alloc (module->assembly->image, len + 1);
-                                       memcpy (par_name, p, len);
-                                       p += len;
-                                       par_name [len] = '\0';
-                               }
+                               par_klass = decode_klass_ref (module, p, &p);
+                               if (!par_klass)
+                                       return NULL;
+
+                               t = mini_get_shared_gparam (&par_klass->byval_arg, gshared_constraint);
                        }
                }
 
-               t = g_new0 (MonoType, 1);
-               t->type = type;
-               if (container) {
-                       t->data.generic_param = mono_generic_container_get_param (container, num);
-                       g_assert (gshared_constraint == NULL);
+               if (t) {
+                       klass = mono_class_from_mono_type (t);
                } else {
-                       /* Anonymous */
-                       MonoGenericParam *par = (MonoGenericParam*)mono_image_alloc0 (module->assembly->image, sizeof (MonoGenericParamFull));
-                       par->num = num;
-                       par->gshared_constraint = gshared_constraint;
-                       // FIXME:
-                       par->image = mono_defaults.corlib;
-                       t->data.generic_param = par;
-                       if (par_name)
-                               ((MonoGenericParamFull*)par)->info.name = par_name;
-               }
-
-               // FIXME: Maybe use types directly to avoid
-               // the overhead of creating MonoClass-es
-               klass = mono_class_from_mono_type (t);
+                       t = g_new0 (MonoType, 1);
+                       t->type = type;
+                       if (container) {
+                               t->data.generic_param = mono_generic_container_get_param (container, num);
+                               g_assert (gshared_constraint == NULL);
+                       } else {
+                               /* Anonymous */
+                               MonoGenericParam *par = (MonoGenericParam*)mono_image_alloc0 (module->assembly->image, sizeof (MonoGenericParamFull));
+                               par->num = num;
+                               par->gshared_constraint = gshared_constraint;
+                               par->image = module->assembly->image;
+                               t->data.generic_param = par;
+                               if (par_name)
+                                       ((MonoGenericParamFull*)par)->info.name = par_name;
+                       }
+                       // FIXME: Maybe use types directly to avoid
+                       // the overhead of creating MonoClass-es
+                       klass = mono_class_from_mono_type (t);
 
-               g_free (t);
+                       g_free (t);
+               }
                break;
        }
        case MONO_AOT_TYPEREF_ARRAY:
@@ -827,6 +829,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
        }
 
        if (image_index == MONO_AOT_METHODREF_WRAPPER) {
+               WrapperInfo *info;
                guint32 wrapper_type;
 
                wrapper_type = decode_value (p, &p);
@@ -892,9 +895,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                g_error ("Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
                        break;
                }
-               case MONO_WRAPPER_WRITE_BARRIER:
+               case MONO_WRAPPER_WRITE_BARRIER: {
                        ref->method = mono_gc_get_write_barrier ();
                        break;
+               }
                case MONO_WRAPPER_STELEMREF: {
                        int subtype = decode_value (p, &p);
 
@@ -902,7 +906,6 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                ref->method = mono_marshal_get_stelemref ();
                        } else if (subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF) {
                                int kind;
-                               WrapperInfo *info;
                                
                                kind = decode_value (p, &p);
 
@@ -986,7 +989,6 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
 
                                ref->method = mono_marshal_get_array_address (rank, elem_size);
                        } else if (subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
-                               WrapperInfo *info;
                                MonoMethod *m;
 
                                m = decode_resolve_method_ref (module, p, &p);
@@ -1047,6 +1049,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                }
                case MONO_WRAPPER_RUNTIME_INVOKE: {
                        int subtype = decode_value (p, &p);
+                       int pass_rgctx = decode_value (p, &p);
 
                        if (!target)
                                return FALSE;
@@ -1061,17 +1064,16 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
 
                                if (!m)
                                        return FALSE;
-                               ref->method = mono_marshal_get_runtime_invoke (m, FALSE);
+                               ref->method = mono_marshal_get_runtime_invoke (m, FALSE, pass_rgctx);
                        } else if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL) {
                                /* Virtual direct wrapper */
                                MonoMethod *m = decode_resolve_method_ref (module, p, &p);
 
                                if (!m)
                                        return FALSE;
-                               ref->method = mono_marshal_get_runtime_invoke (m, TRUE);
+                               ref->method = mono_marshal_get_runtime_invoke (m, TRUE, pass_rgctx);
                        } else {
                                MonoMethodSignature *sig;
-                               WrapperInfo *info;
 
                                sig = decode_signature_with_target (module, NULL, p, &p);
                                info = mono_marshal_get_wrapper_info (target);
@@ -1079,6 +1081,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
 
                                if (info->subtype != subtype)
                                        return FALSE;
+                               if (info->d.runtime_invoke.pass_rgctx != pass_rgctx)
+                                       return FALSE;
                                g_assert (info->d.runtime_invoke.sig);
                                if (mono_metadata_signature_equal (sig, info->d.runtime_invoke.sig))
                                        ref->method = target;
@@ -1130,8 +1134,6 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                                        return FALSE;
 
                                if (wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) {
-                                       WrapperInfo *info;
-
                                        subtype = decode_value (p, &p);
                                        info = mono_marshal_get_wrapper_info (target);
                                        if (info) {
@@ -1647,7 +1649,7 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, char **out_msg)
        char *build_info;
        char *msg = NULL;
        gboolean usable = TRUE;
-       gboolean full_aot;
+       gboolean full_aot, safepoints;
        guint8 *blob;
        guint32 excluded_cpu_optimizations;
 
@@ -1673,6 +1675,10 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, char **out_msg)
                msg = g_strdup_printf ("compiled with --aot=full");
                usable = FALSE;
        }
+       if (mono_llvm_only && !(info->flags & MONO_AOT_FILE_FLAG_LLVM_ONLY)) {
+               msg = g_strdup_printf ("not compiled with --aot=llvmonly");
+               usable = FALSE;
+       }
 #ifdef TARGET_ARM
        /* mono_arch_find_imt_method () requires this */
        if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
@@ -1712,6 +1718,13 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, char **out_msg)
                }
        }
 
+       safepoints = info->flags & MONO_AOT_FILE_FLAG_SAFEPOINTS;
+
+       if (!safepoints && mono_threads_is_coop_enabled ()) {
+               msg = g_strdup_printf ("not compiled with safepoints");
+               usable = FALSE;
+       }
+
        *out_msg = msg;
        return usable;
 }
@@ -1748,19 +1761,69 @@ get_call_table_entry (void *table, int index)
 #endif
 }
 
+/*
+ * init_amodule_got:
+ *
+ *   Initialize the shared got entries for AMODULE.
+ */
 static void
-init_gots (MonoAotModule *amodule)
+init_amodule_got (MonoAotModule *amodule)
 {
-       int i;
+       MonoJumpInfo *ji;
+       MonoMemPool *mp;
+       MonoJumpInfo *patches;
+       guint32 got_offsets [128];
+       int i, npatches;
+
+       /* These can't be initialized in load_aot_module () */
+       if (amodule->shared_got [0] || amodule->got_initializing)
+               return;
+
+       amodule->got_initializing = TRUE;
+
+       mp = mono_mempool_new ();
+       npatches = amodule->info.nshared_got_entries;
+       for (i = 0; i < npatches; ++i)
+               got_offsets [i] = i;
+       patches = decode_patches (amodule, mp, npatches, FALSE, got_offsets);
+       g_assert (patches);
+       for (i = 0; i < npatches; ++i) {
+               ji = &patches [i];
+
+               if (ji->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR && !mono_gc_is_moving ()) {
+                       amodule->shared_got [i] = NULL;
+               } else if (ji->type == MONO_PATCH_INFO_GC_NURSERY_START && !mono_gc_is_moving ()) {
+                       amodule->shared_got [i] = NULL;
+               } else if (ji->type == MONO_PATCH_INFO_GC_NURSERY_BITS && !mono_gc_is_moving ()) {
+                       amodule->shared_got [i] = NULL;
+               } else if (ji->type == MONO_PATCH_INFO_IMAGE) {
+                       amodule->shared_got [i] = amodule->assembly->image;
+               } else if (ji->type == MONO_PATCH_INFO_MSCORLIB_GOT_ADDR) {
+                       if (mono_defaults.corlib) {
+                               MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;
+
+                               if (mscorlib_amodule)
+                                       amodule->shared_got [i] = mscorlib_amodule->got;
+                       } else {
+                               amodule->shared_got [i] = amodule->got;
+                       }
+               } else if (ji->type == MONO_PATCH_INFO_AOT_MODULE) {
+                       amodule->shared_got [i] = amodule;
+               } else {
+                       amodule->shared_got [i] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, ji, FALSE);
+               }
+       }
 
        if (amodule->got) {
-               for (i = 0; i < N_COMMON_GOT_ENTRIES; ++i)
+               for (i = 0; i < npatches; ++i)
                        amodule->got [i] = amodule->shared_got [i];
        }
        if (amodule->llvm_got) {
-               for (i = 0; i < N_COMMON_GOT_ENTRIES; ++i)
+               for (i = 0; i < npatches; ++i)
                        amodule->llvm_got [i] = amodule->shared_got [i];
        }
+
+       mono_mempool_destroy (mp);
 }
 
 static void
@@ -1891,7 +1954,9 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        amodule->globals = globals;
        amodule->sofile = sofile;
        amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL);
+       amodule->extra_methods = g_hash_table_new (NULL, NULL);
        amodule->blob = blob;
+       amodule->shared_got = g_new0 (gpointer, info->nshared_got_entries);
 
        mono_mutex_init_recursive (&amodule->mutex);
 
@@ -1966,6 +2031,12 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        for (i = 0; i < amodule->info.nmethods; ++i) {
                void *addr = NULL;
 
+               if (amodule->info.llvm_get_method) {
+                       gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+
+                       addr = get_method (i);
+               }
+
                /* method_addresses () contains a table of branches, since the ios linker can update those correctly */
                if (!addr && amodule->info.method_addresses) {
                        addr = get_call_table_entry (amodule->info.method_addresses, i);
@@ -2024,37 +2095,13 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        assembly->image->aot_module = amodule;
 
-       amodule->shared_got [0] = assembly->image;
-
        if (mono_aot_only) {
                char *code;
                find_symbol (amodule->sofile, amodule->globals, "specific_trampolines_page", (gpointer *)&code);
                amodule->use_page_trampolines = code != NULL;
                /*g_warning ("using page trampolines: %d", amodule->use_page_trampolines);*/
-               if (mono_defaults.corlib) {
-                       /* The second got slot contains the mscorlib got addr */
-                       MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;
-
-                       amodule->shared_got [1] = mscorlib_amodule->got;
-               } else {
-                       amodule->shared_got [1] = amodule->got;
-               }
-       }
-
-       if (mono_gc_is_moving ()) {
-               MonoJumpInfo ji;
-
-               memset (&ji, 0, sizeof (ji));
-               ji.type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
-               amodule->shared_got [2] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
-
-               memset (&ji, 0, sizeof (ji));
-               ji.type = MONO_PATCH_INFO_GC_NURSERY_START;
-               amodule->shared_got [3] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
        }
 
-       init_gots (amodule);
-
        /*
         * Register the plt region as a single trampoline so we can unwind from this code
         */
@@ -2100,18 +2147,6 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: loaded AOT Module for %s.\n", assembly->image->name);
 }
 
-/*
- * mono_aot_register_globals:
- *
- *   This is called by the ctor function in AOT images compiled with the
- * 'no-dlsym' option.
- */
-void
-mono_aot_register_globals (gpointer *globals)
-{
-       g_assert_not_reached ();
-}
-
 /*
  * mono_aot_register_module:
  *
@@ -2393,6 +2428,16 @@ compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **c
        int version, fde_count;
        gint32 *table;
 
+       if (amodule->info.llvm_get_method) {
+               gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+
+               *code_start = get_method (-1);
+               *code_end = get_method (-2);
+
+               g_assert (*code_end > *code_start);
+               return;
+       }
+
        g_assert (amodule->mono_eh_frame);
 
        p = amodule->mono_eh_frame;
@@ -2446,7 +2491,7 @@ is_thumb_code (MonoAotModule *amodule, guint8 *code)
  */
 static MonoJitInfo*
 decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, 
-                                                  MonoMethod *method, guint8 *code, 
+                                                  MonoMethod *method, guint8 *code, guint32 code_len,
                                                   MonoJitExceptionInfo *clauses, int num_clauses,
                                                   MonoJitInfoFlags flags,
                                                   GSList **nesting,
@@ -2456,14 +2501,21 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
        guint8 *fde, *cie, *code_start, *code_end;
        int version, fde_count;
        gint32 *table;
-       int i, pos, left, right, code_len;
+       int i, pos, left, right;
        MonoJitExceptionInfo *ei;
        guint32 fde_len, ei_len, nested_len, nindex;
        gpointer *type_info;
        MonoJitInfo *jinfo;
        MonoLLVMFDEInfo info;
 
-       g_assert (amodule->mono_eh_frame);
+       if (!amodule->mono_eh_frame) {
+               jinfo = mono_domain_alloc0_lock_free (domain, mono_jit_info_size (flags, num_clauses, 0));
+               mono_jit_info_init (jinfo, method, code, code_len, flags, num_clauses, 0);
+               memcpy (jinfo->clauses, clauses, num_clauses * sizeof (MonoJitExceptionInfo));
+               return jinfo;
+       }
+
+       g_assert (amodule->mono_eh_frame && code);
 
        p = amodule->mono_eh_frame;
 
@@ -2516,7 +2568,8 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
        } else {
                code_end = amodule->methods [table [(pos + 1) * 2]];
        }
-       code_len = code_end - code_start;
+       if (!code_len)
+               code_len = code_end - code_start;
 
        g_assert (code >= code_start && code < code_end);
 
@@ -2631,7 +2684,7 @@ alloc0_jit_info_data (MonoDomain *domain, int size, gboolean async_context)
  */
 static MonoJitInfo*
 decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, 
-                                                        MonoMethod *method, guint8* ex_info, guint8 *addr,
+                                                        MonoMethod *method, guint8* ex_info,
                                                         guint8 *code, guint32 code_len)
 {
        int i, buf_len, num_clauses, len;
@@ -2710,6 +2763,13 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                        if (decode_value (p, &p))
                                ei->data.catch_class = decode_klass_ref (amodule, p, &p);
 
+                       ei->clause_index = i;
+
+                       ei->try_offset = decode_value (p, &p);
+                       ei->try_len = decode_value (p, &p);
+                       ei->handler_offset = decode_value (p, &p);
+                       ei->handler_len = decode_value (p, &p);
+
                        /* Read the list of nesting clauses */
                        while (TRUE) {
                                int nesting_index = decode_value (p, &p);
@@ -2719,7 +2779,7 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain,
                        }
                }
 
-               jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, flags, nesting, &this_reg, &this_offset);
+               jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, code_len, clauses, num_clauses, flags, nesting, &this_reg, &this_offset);
 
                g_free (clauses);
                for (i = 0; i < num_clauses; ++i)
@@ -3164,7 +3224,7 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 
        //printf ("F: %s\n", mono_method_full_name (method, TRUE));
 
-       jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, addr, code, code_len);
+       jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, code, code_len);
 
        g_assert ((guint8*)addr >= (guint8*)jinfo->code_start);
 
@@ -3274,7 +3334,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                        if (!ji->data.del_tramp->method)
                                goto cleanup;
                }
-               ji->data.del_tramp->virtual = decode_value (p, &p) ? TRUE : FALSE;
+               ji->data.del_tramp->is_virtual = decode_value (p, &p) ? TRUE : FALSE;
                break;
        case MONO_PATCH_INFO_IMAGE:
                ji->data.image = load_image (aot_module, decode_value (p, &p), TRUE);
@@ -3351,12 +3411,14 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
        case MONO_PATCH_INFO_GC_NURSERY_START:
+       case MONO_PATCH_INFO_GC_NURSERY_BITS:
        case MONO_PATCH_INFO_JIT_TLS_ID:
                break;
        case MONO_PATCH_INFO_CASTCLASS_CACHE:
                ji->data.index = decode_value (p, &p);
                break;
-       case MONO_PATCH_INFO_RGCTX_FETCH: {
+       case MONO_PATCH_INFO_RGCTX_FETCH:
+       case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
                gboolean res;
                MonoJumpInfoRgctxEntry *entry;
                guint32 offset, val;
@@ -3380,6 +3442,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                break;
        }
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
+       case MONO_PATCH_INFO_AOT_MODULE:
+       case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
                break;
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE: {
                MonoJumpInfoImtTramp *imt_tramp = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoImtTramp));
@@ -3464,6 +3528,9 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        }
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
                break;
+       case MONO_PATCH_INFO_AOT_JIT_INFO:
+               ji->data.index = decode_value (p, &p);
+               break;
        default:
                g_warning ("unhandled type %d", ji->type);
                g_assert_not_reached ();
@@ -3477,63 +3544,75 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        return FALSE;
 }
 
+/*
+ * decode_patches:
+ *
+ *    Decode a list of patches identified by the got offsets in GOT_OFFSETS. Return an array of
+ * MonoJumpInfo structures allocated from MP.
+ */
 static MonoJumpInfo*
-load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches,
-                                gboolean llvm, guint32 **got_slots,
-                                guint8 *buf, guint8 **endbuf)
+decode_patches (MonoAotModule *amodule, MonoMemPool *mp, int n_patches, gboolean llvm, guint32 *got_offsets)
 {
        MonoJumpInfo *patches;
-       int pindex;
-       guint8 *p;
+       MonoJumpInfo *ji;
        gpointer *got;
-       guint32 *got_offsets;
-
-       p = buf;
+       guint32 *got_info_offsets;
+       int i;
+       gboolean res;
 
        if (llvm) {
-               got = aot_module->llvm_got;
-               got_offsets = aot_module->info.llvm_got_info_offsets;
+               got = amodule->llvm_got;
+               got_info_offsets = amodule->info.llvm_got_info_offsets;
        } else {
-               got = aot_module->got;
-               got_offsets = aot_module->info.got_info_offsets;
+               got = amodule->got;
+               got_info_offsets = amodule->info.got_info_offsets;
        }
 
        patches = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo) * n_patches);
+       for (i = 0; i < n_patches; ++i) {
+               guint8 *p = amodule->blob + mono_aot_get_offset (got_info_offsets, got_offsets [i]);
 
-       *got_slots = g_malloc (sizeof (guint32) * n_patches);
-
-       for (pindex = 0; pindex < n_patches; ++pindex) {
-               MonoJumpInfo *ji = &patches [pindex];
-               guint8 *shared_p;
-               gboolean res;
-               guint32 got_offset;
-
-               got_offset = decode_value (p, &p);
-
-               shared_p = aot_module->blob + mono_aot_get_offset (got_offsets, got_offset);
-
-               ji->type = decode_value (shared_p, &shared_p);
+               ji = &patches [i];
+               ji->type = decode_value (p, &p);
 
                /* See load_method () for SFLDA */
-               if (got [got_offset] && ji->type != MONO_PATCH_INFO_SFLDA) {
+               if (got && got [got_offsets [i]] && ji->type != MONO_PATCH_INFO_SFLDA) {
                        /* Already loaded */
                } else {
-                       res = decode_patch (aot_module, mp, ji, shared_p, &shared_p);
+                       res = decode_patch (amodule, mp, ji, p, &p);
                        if (!res)
-                               goto cleanup;
+                               return NULL;
                }
-
-               (*got_slots) [pindex] = got_offset;
        }
 
-       *endbuf = p;
        return patches;
+}
 
- cleanup:
-       g_free (*got_slots);
-       *got_slots = NULL;
+static MonoJumpInfo*
+load_patch_info (MonoAotModule *amodule, MonoMemPool *mp, int n_patches,
+                                gboolean llvm, guint32 **got_slots,
+                                guint8 *buf, guint8 **endbuf)
+{
+       MonoJumpInfo *patches;
+       int pindex;
+       guint8 *p;
 
-       return NULL;
+       p = buf;
+
+       *got_slots = g_malloc (sizeof (guint32) * n_patches);
+       for (pindex = 0; pindex < n_patches; ++pindex) {
+               (*got_slots)[pindex] = decode_value (p, &p);
+       }
+
+       patches = decode_patches (amodule, mp, n_patches, llvm, *got_slots);
+       if (!patches) {
+               g_free (*got_slots);
+               *got_slots = NULL;
+               return NULL;
+       }
+
+       *endbuf = p;
+       return patches;
 }
 
 static void
@@ -3567,12 +3646,12 @@ register_jump_target_got_slot (MonoDomain *domain, MonoMethod *method, gpointer
 static gpointer
 load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
 {
-       MonoClass *klass;
-       gboolean from_plt = method == NULL;
        MonoJitInfo *jinfo = NULL;
        guint8 *code = NULL, *info;
        gboolean res;
 
+       init_amodule_got (amodule);
+
        if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) {
                if (mono_aot_only)
                        /* The caller cannot handle this */
@@ -3587,7 +3666,16 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
        if (amodule->out_of_date)
                return NULL;
 
+       if (amodule->info.llvm_get_method) {
+               /*
+                * Obtain the method address by calling a generated function in the LLVM module.
+                */
+               gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+               code = get_method (method_index);
+       }
+
        if (!code) {
+               /* JITted method */
                if (amodule->methods [method_index] == GINT_TO_POINTER (-1)) {
                        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
                                char *full_name;
@@ -3600,10 +3688,9 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                        }
                        return NULL;
                }
+               code = amodule->methods [method_index];
        }
 
-       code = amodule->methods [method_index];
-
        info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
 
        if (!amodule->methods_loaded) {
@@ -3637,9 +3724,11 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                }
        }
 
-       res = init_method (amodule, method_index, method, &klass);
-       if (!res)
-               goto cleanup;
+       if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY))) {
+               res = init_llvm_method (amodule, method_index, method, NULL, NULL);
+               if (!res)
+                       goto cleanup;
+       }
 
        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
                char *full_name;
@@ -3682,9 +3771,6 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
        }
 
-       if (from_plt && klass && !klass->generic_container)
-               mono_runtime_class_init (mono_class_vtable (domain, klass));
-
        return code;
 
  cleanup:
@@ -3754,7 +3840,7 @@ find_aot_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, guint32
                        MonoMethod *w1 = mono_marshal_method_from_wrapper (method);
                        MonoMethod *w2 = mono_marshal_method_from_wrapper (m);
 
-                       if (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2) {
+                       if ((w1 == w2) || (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2)) {
                                index = value;
                                break;
                        }
@@ -3840,10 +3926,12 @@ mono_aot_find_method_index (MonoMethod *method)
 }
 
 static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass)
+init_llvm_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context)
 {
        MonoDomain *domain = mono_domain_get ();
        MonoMemPool *mp;
+       MonoClass *klass;
+       gboolean from_plt = method == NULL;
        int pindex, n_patches;
        guint8 *p;
        MonoJitInfo *jinfo = NULL;
@@ -3855,10 +3943,10 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        p = info;
 
        if (method) {
-               *klass = method->klass;
+               klass = method->klass;
                decode_klass_ref (amodule, p, &p);
        } else {
-               *klass = decode_klass_ref (amodule, p, &p);
+               klass = decode_klass_ref (amodule, p, &p);
        }
 
        n_patches = decode_value (p, &p);
@@ -3881,8 +3969,10 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
                }
 
                patches = load_patch_info (amodule, mp, n_patches, llvm, &got_slots, p, &p);
-               if (patches == NULL)
+               if (patches == NULL) {
+                       mono_mempool_destroy (mp);
                        goto cleanup;
+               }
 
                for (pindex = 0; pindex < n_patches; ++pindex) {
                        MonoJumpInfo *ji = &patches [pindex];
@@ -3894,6 +3984,20 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
                         * finished executing (#23242).
                         */
                        if (!got [got_slots [pindex]] || ji->type == MONO_PATCH_INFO_SFLDA) {
+                               /* In llvm-only made, we might encounter shared methods */
+                               if (mono_llvm_only && ji->type == MONO_PATCH_INFO_METHOD && mono_method_check_context_used (ji->data.method)) {
+                                       MonoError error;
+
+                                       g_assert (context);
+                                       ji->data.method = mono_class_inflate_generic_method_checked (ji->data.method, context, &error);
+                               }
+                               /* This cannot be resolved in mono_resolve_patch_target () */
+                               if (ji->type == MONO_PATCH_INFO_AOT_JIT_INFO) {
+                                       // FIXME: Lookup using the index
+                                       jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
+                                       ji->type = MONO_PATCH_INFO_ABS;
+                                       ji->data.target = jinfo;
+                               }
                                addr = mono_resolve_patch_target (method, domain, code, ji, TRUE);
                                if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
                                        addr = mono_create_ftnptr (domain, addr);
@@ -3913,6 +4017,11 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        if (mini_get_debug_options ()->load_aot_jit_info_eagerly)
                jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
 
+       if (init_class)
+               mono_runtime_class_init (mono_class_vtable (domain, init_class));
+       else if (from_plt && klass && !klass->generic_container)
+               mono_runtime_class_init (mono_class_vtable (domain, klass));
+
        return TRUE;
 
  cleanup:
@@ -3922,6 +4031,60 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        return FALSE;
 }
 
+void
+mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+{
+       MonoAotModule *amodule = aot_module;
+       gboolean res;
+
+       // FIXME: Handle failure
+       res = init_llvm_method (amodule, method_index, NULL, NULL, NULL);
+       g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this)
+{
+       MonoAotModule *amodule = aot_module;
+       gboolean res;
+       MonoClass *klass;
+       MonoGenericContext *context;
+       MonoMethod *method;
+
+       // FIXME:
+       g_assert (this);
+       klass = this->vtable->klass;
+
+       amodule_lock (amodule);
+       method = g_hash_table_lookup (amodule->extra_methods, GUINT_TO_POINTER (method_index));
+       amodule_unlock (amodule);
+
+       g_assert (method);
+       context = mono_method_get_context (method);
+       g_assert (context);
+
+       res = init_llvm_method (amodule, method_index, NULL, klass, context);
+       g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_rgctx  (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+       MonoAotModule *amodule = aot_module;
+       gboolean res;
+       MonoGenericContext context = { NULL, NULL };
+       MonoClass *klass = rgctx->class_vtable->klass;
+
+       if (klass->generic_class)
+               context.class_inst = klass->generic_class->context.class_inst;
+       else if (klass->generic_container)
+               context.class_inst = klass->generic_container->context.class_inst;
+       context.method_inst = rgctx->method_inst;
+
+       res = init_llvm_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
+       g_assert (res);
+}
+
 /*
  * mono_aot_get_method:
  *
@@ -3971,12 +4134,21 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
        /* Find method index */
        method_index = 0xffffff;
        if (method->is_inflated && !method->wrapper_type && mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE)) {
+               MonoMethod *orig_method = method;
                /* 
                 * For generic methods, we store the fully shared instance in place of the
                 * original method.
                 */
                method = mono_method_get_declaring_generic_method (method);
                method_index = mono_metadata_token_index (method->token) - 1;
+
+               if (mono_llvm_only) {
+                       /* Needed by mono_aot_init_gshared_method_this () */
+                       /* orig_method is a random instance but it is enough to make init_llvm_method () work */
+                       amodule_lock (amodule);
+                       g_hash_table_insert (amodule->extra_methods, GUINT_TO_POINTER (method_index), orig_method);
+                       amodule_unlock (amodule);
+               }
        } else if (method->is_inflated || !method->token) {
                /* This hash table is used to avoid the slower search in the extra_method_table in the AOT image */
                amodule_lock (amodule);
@@ -4036,9 +4208,9 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
                /* Same for CompareExchange<T> and Exchange<T> */
                /* Same for Volatile.Read<T>/Write<T> */
                if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass->image == mono_defaults.corlib && 
-                       ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->params [1])) ||
-                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->ret))) ||
-                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->params [1]))))) {
+                       ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1]))) ||
+                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->ret)))) ||
+                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1])))))) {
                        MonoError error;
                        MonoMethod *m;
                        MonoGenericContext ctx;
@@ -4105,8 +4277,6 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
 
                /* Needed by find_jit_info */
                amodule_lock (amodule);
-               if (!amodule->extra_methods)
-                       amodule->extra_methods = g_hash_table_new (NULL, NULL);
                g_hash_table_insert (amodule->extra_methods, GUINT_TO_POINTER (method_index), method);
                amodule_unlock (amodule);
        } else {
@@ -4249,7 +4419,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
 
        ji.type = decode_value (p, &p);
 
-       mp = mono_mempool_new_size (512);
+       mp = mono_mempool_new ();
        res = decode_patch (module, mp, &ji, p, &p);
 
        if (!res) {
@@ -4326,6 +4496,11 @@ init_plt (MonoAotModule *amodule)
        if (amodule->plt_inited)
                return;
 
+       if (amodule->info.plt_size <= 1) {
+               amodule->plt_inited = TRUE;
+               return;
+       }
+
        tramp = mono_create_specific_trampoline (amodule, MONO_TRAMPOLINE_AOT_PLT, mono_get_root_domain (), NULL);
 
        /*
@@ -4596,6 +4771,12 @@ get_mscorlib_aot_module (void)
        return amodule;
 }
 
+static void
+no_trampolines (void)
+{
+       g_assert_not_reached ();
+}
+
 /*
  * Return the trampoline identified by NAME from the mscorlib AOT file.
  * On ppc64, this returns a function descriptor.
@@ -4605,6 +4786,11 @@ mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
 {
        MonoAotModule *amodule = get_mscorlib_aot_module ();
 
+       if (mono_llvm_only) {
+               *out_tinfo = NULL;
+               return no_trampolines;
+       }
+
        return mono_create_ftnptr_malloc (load_function_full (amodule, name, out_tinfo));
 }
 
@@ -4894,6 +5080,12 @@ get_numerous_trampoline (MonoAotTrampoline tramp_type, int n_got_slots, MonoAotM
        return amodule->trampolines [tramp_type] + (index * tramp_size);
 }
 
+static void
+no_specific_trampoline (void)
+{
+       g_assert_not_reached ();
+}
+
 /*
  * Return a specific trampoline from the AOT file.
  */
@@ -4907,6 +5099,11 @@ mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampo
        static gboolean inited;
        static guint32 num_trampolines;
 
+       if (mono_llvm_only) {
+               *code_len = 1;
+               return no_specific_trampoline;
+       }
+
        if (!inited) {
                mono_aot_lock ();
 
@@ -4994,6 +5191,14 @@ mono_aot_get_unbox_trampoline (MonoMethod *method)
                g_assert (amodule);
        }
 
+       if (amodule->info.llvm_get_unbox_tramp) {
+               gpointer (*get_tramp) (int) = amodule->info.llvm_get_unbox_tramp;
+               code = get_tramp (method_index);
+
+               if (code)
+                       return code;
+       }
+
        ut = amodule->unbox_trampolines;
        ut_end = amodule->unbox_trampolines_end;
 
@@ -5064,6 +5269,12 @@ mono_aot_get_lazy_fetch_trampoline (guint32 slot)
        return mono_create_ftnptr (mono_domain_get (), code);
 }
 
+static void
+no_imt_thunk (void)
+{
+       g_assert_not_reached ();
+}
+
 gpointer
 mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
 {
@@ -5073,6 +5284,9 @@ mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem
        int i, index, real_count;
        MonoAotModule *amodule;
 
+       if (mono_llvm_only)
+               return no_imt_thunk;
+
        real_count = 0;
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
@@ -5236,6 +5450,33 @@ mono_aot_init (void)
 {
 }
 
+void
+mono_aot_cleanup (void)
+{
+}
+
+guint32
+mono_aot_find_method_index (MonoMethod *method)
+{
+       g_assert_not_reached ();
+       return 0;
+}
+
+void
+mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+{
+}
+
+void
+mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this)
+{
+}
+
+void
+mono_aot_init_gshared_method_rgctx  (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+}
+
 gpointer
 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
 {
@@ -5317,6 +5558,13 @@ mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr)
        return NULL;
 }
 
+gpointer
+mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
 gpointer
 mono_aot_get_trampoline (const char *name)
 {
@@ -5345,6 +5593,29 @@ mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem
        return NULL;
 }      
 
+gpointer
+mono_aot_get_gsharedvt_arg_trampoline (gpointer arg, gpointer addr)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+void
+mono_aot_set_make_unreadable (gboolean unreadable)
+{
+}
+
+gboolean
+mono_aot_is_pagefault (void *ptr)
+{
+       return FALSE;
+}
+
+void
+mono_aot_handle_pagefault (void *ptr)
+{
+}
+
 guint8*
 mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
 {