Merge pull request #1991 from esdrubal/seq_test_fix
[mono.git] / mono / mini / mini-runtime.c
index 9ae1a99974d468ed9ee2635e154bb5ce9608ec01..8b454087638bef15f630ffa4446e8e57391fc72f 100644 (file)
@@ -59,6 +59,7 @@
 #include <mono/utils/dtrace.h>
 #include <mono/utils/mono-signal-handler.h>
 #include <mono/utils/mono-threads.h>
+#include <mono/utils/checked-build.h>
 #include <mono/io-layer/io-layer.h>
 
 #include "mini.h"
@@ -86,6 +87,7 @@ MONO_FAST_TLS_DECLARE(mono_jit_tls);
 gboolean mono_compile_aot = FALSE;
 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
 gboolean mono_aot_only = FALSE;
+MonoAotMode mono_aot_mode = MONO_AOT_MODE_NONE;
 
 const char *mono_build_date;
 gboolean mono_do_signal_chaining;
@@ -117,12 +119,14 @@ static void register_icalls (void);
 gboolean
 mono_running_on_valgrind (void)
 {
+#ifndef HOST_WIN32
        if (RUNNING_ON_VALGRIND){
 #ifdef VALGRIND_JIT_REGISTER_MAP
                valgrind_register = TRUE;
 #endif
                return TRUE;
        } else
+#endif
                return FALSE;
 }
 
@@ -154,7 +158,7 @@ get_method_from_ip (void *ip)
        if (!domain)
                domain = mono_get_root_domain ();
 
-       ji = mono_jit_info_table_find (domain, ip);
+       ji = mono_jit_info_table_find_internal (domain, ip, TRUE, TRUE);
        if (!ji) {
                user_data.ip = ip;
                user_data.method = NULL;
@@ -169,7 +173,11 @@ get_method_from_ip (void *ip)
                }
                else
                        return NULL;
+       } else if (ji->is_trampoline) {
+               res = g_strdup_printf ("<%p - %s trampoline>", ip, ((MonoTrampInfo*)ji->d.tramp_info)->name);
+               return res;
        }
+
        method = mono_method_full_name (jinfo_get_method (ji), TRUE);
        /* FIXME: unused ? */
        location = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
@@ -259,7 +267,7 @@ mono_print_method_from_ip (void *ip)
        gsctx = mono_jit_info_get_generic_sharing_context (ji);
        shared_type = "";
        if (gsctx) {
-               if (gsctx->var_is_vt || gsctx->mvar_is_vt)
+               if (gsctx->is_gsharedvt)
                        shared_type = "gsharedvt ";
                else
                        shared_type = "gshared ";
@@ -285,7 +293,7 @@ gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee)
 {
        MonoMethod *cmethod;
 
-       if (!caller || !callee)
+       if (!caller || caller->is_trampoline || !callee || callee->is_trampoline)
                return FALSE;
 
        /*
@@ -459,14 +467,10 @@ mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJ
 void
 mono_tramp_info_free (MonoTrampInfo *info)
 {
-       GSList *l;
-
        g_free (info->name);
 
        // FIXME: ji
-       for (l = info->unwind_ops; l; l = l->next)
-               g_free (l->data);
-       g_slist_free (info->unwind_ops);
+       mono_free_unwind_info (info->unwind_ops);
        g_free (info);
 }
 
@@ -479,7 +483,8 @@ register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
        mono_jit_info_init (ji, NULL, info->code, info->code_size, 0, 0, 0);
        ji->d.tramp_info = info;
        ji->is_trampoline = TRUE;
-       // FIXME: Unwind info
+
+       ji->unwind_info = mono_cache_unwind_info (info->uw_info, info->uw_info_len);
 
        mono_jit_info_table_add (domain, ji);
 }
@@ -492,26 +497,38 @@ register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
  * Frees INFO.
  */
 void
-mono_tramp_info_register (MonoTrampInfo *info)
+mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
 {
        MonoTrampInfo *copy;
 
        if (!info)
                return;
 
+       if (!domain)
+               domain = mono_get_root_domain ();
+
        copy = g_new0 (MonoTrampInfo, 1);
        copy->code = info->code;
        copy->code_size = info->code_size;
        copy->name = g_strdup (info->name);
 
+       if (info->unwind_ops) {
+               copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, &copy->uw_info_len);
+       } else {
+               /* Trampolines from aot have the unwind ops already encoded */
+               copy->uw_info = info->uw_info;
+               copy->uw_info_len = info->uw_info_len;
+       }
+
        mono_jit_lock ();
        tramp_infos = g_slist_prepend (tramp_infos, copy);
        mono_jit_unlock ();
 
        mono_save_trampoline_xdebug_info (info);
 
-       if (mono_get_root_domain ())
-               register_trampoline_jit_info (mono_get_root_domain (), copy);
+       /* Only register trampolines that have unwind infos */
+       if (mono_get_root_domain () && copy->uw_info)
+               register_trampoline_jit_info (domain, copy);
 
        if (mono_jit_map_is_enabled ())
                mono_emit_jit_tramp (info->code, info->code_size, info->name);
@@ -587,28 +604,14 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
        MonoMethod *wrapper;
        gconstpointer trampoline;
        MonoDomain *domain = mono_get_root_domain ();
-       gboolean check_exc = check_for_pending_exc;
+       gboolean check_exc = TRUE;
 
-       if (callinfo->wrapper) {
+       if (callinfo->wrapper)
                return callinfo->wrapper;
-       }
 
        if (callinfo->trampoline)
                return callinfo->trampoline;
 
-       /*
-        * We use the lock on the root domain instead of the JIT lock to protect
-        * callinfo->trampoline, since we do a lot of stuff inside the critical section.
-        */
-       mono_loader_lock (); /*FIXME mono_compile_method requires the loader lock, by large.*/
-       mono_domain_lock (domain);
-
-       if (callinfo->trampoline) {
-               mono_domain_unlock (domain);
-               mono_loader_unlock ();
-               return callinfo->trampoline;
-       }
-
        if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
                /* This icall is used to check for exceptions, so don't check in the wrapper */
                check_exc = FALSE;
@@ -621,11 +624,12 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
                trampoline = mono_compile_method (wrapper);
        else
                trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
-       mono_register_jit_icall_wrapper (callinfo, trampoline);
-
-       callinfo->trampoline = trampoline;
 
-       mono_domain_unlock (domain);
+       mono_loader_lock ();
+       if (!callinfo->trampoline) {
+               mono_register_jit_icall_wrapper (callinfo, trampoline);
+               callinfo->trampoline = trampoline;
+       }
        mono_loader_unlock ();
 
        return callinfo->trampoline;
@@ -652,7 +656,9 @@ mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
 static void
 register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
 {
-       return mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
+#ifndef DISABLE_JIT
+       mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
+#endif
 }
 
 /*
@@ -1029,6 +1035,7 @@ int
 mini_get_tls_offset (MonoTlsKey key)
 {
        int offset;
+       g_assert (MONO_ARCH_HAVE_TLS_GET);
 
        switch (key) {
        case TLS_KEY_THREAD:
@@ -1172,13 +1179,10 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_CLASS:
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
-       case MONO_PATCH_INFO_CLASS_INIT:
-       case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
        case MONO_PATCH_INFO_METHODCONST:
        case MONO_PATCH_INFO_METHOD:
        case MONO_PATCH_INFO_METHOD_JUMP:
        case MONO_PATCH_INFO_IMAGE:
-       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
        case MONO_PATCH_INFO_ICALL_ADDR:
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
@@ -1200,9 +1204,6 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
        case MONO_PATCH_INFO_GC_NURSERY_START:
        case MONO_PATCH_INFO_JIT_TLS_ID:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_GOT_OFFSET:
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
                return (ji->type << 8);
@@ -1224,6 +1225,8 @@ mono_patch_info_hash (gconstpointer data)
 
                return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
        }
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+               return (ji->type << 8) | g_str_hash (ji->data.target);
        default:
                printf ("info type: %d\n", ji->type);
                mono_print_ji (ji); printf ("\n");
@@ -1283,6 +1286,10 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
                return ji1->data.index == ji2->data.index;
        case MONO_PATCH_INFO_VIRT_METHOD:
                return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+               if (ji1->data.target == ji2->data.target)
+                       return 1;
+               return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
        default:
                if (ji1->data.target != ji2->data.target)
                        return 0;
@@ -1453,13 +1460,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_class_vtable (domain, patch_info->data.klass);
                g_assert (target);
                break;
-       case MONO_PATCH_INFO_CLASS_INIT: {
-               MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.klass);
-
-               g_assert (vtable);
-               target = mono_create_class_init_trampoline (vtable);
-               break;
-       }
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
                MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
 
@@ -1586,78 +1586,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        case MONO_PATCH_INFO_NONE:
                break;
        case MONO_PATCH_INFO_RGCTX_FETCH: {
-               MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
-               guint32 slot = -1;
-
-               switch (entry->data->type) {
-               case MONO_PATCH_INFO_CLASS:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_METHOD:
-               case MONO_PATCH_INFO_METHODCONST:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_FIELD:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_SIGNATURE:
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.sig, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               case MONO_PATCH_INFO_GSHAREDVT_CALL: {
-                       MonoJumpInfoGSharedVtCall *call_info = g_malloc0 (sizeof (MonoJumpInfoGSharedVtCall)); //mono_domain_alloc0 (domain, sizeof (MonoJumpInfoGSharedVtCall));
-
-                       memcpy (call_info, entry->data->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, call_info, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               }
-               case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
-                       MonoGSharedVtMethodInfo *info;
-                       MonoGSharedVtMethodInfo *oinfo = entry->data->data.gsharedvt_method;
-                       int i;
-
-                       /* Make a copy into the domain mempool */
-                       info = g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
-                       info->method = oinfo->method;
-                       info->num_entries = oinfo->num_entries;
-                       info->entries = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate) * info->num_entries);
-                       for (i = 0; i < oinfo->num_entries; ++i) {
-                               MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
-                               MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
-
-                               memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
-                       }
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               }
-               case MONO_PATCH_INFO_VIRT_METHOD: {
-                       MonoJumpInfoVirtMethod *info;
-                       MonoJumpInfoVirtMethod *oinfo = entry->data->data.virt_method;
-
-                       info = g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
-                       memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
-                       slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
-                       break;
-               }
-               default:
-                       g_assert_not_reached ();
-                       break;
-               }
+               int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
 
                target = mono_create_rgctx_lazy_fetch_trampoline (slot);
                break;
        }
-       case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
-               target = mono_create_generic_class_init_trampoline ();
-               break;
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-               target = mono_create_monitor_enter_trampoline ();
-               break;
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-               target = mono_create_monitor_enter_v4_trampoline ();
-               break;
-       case MONO_PATCH_INFO_MONITOR_EXIT:
-               target = mono_create_monitor_exit_trampoline ();
-               break;
 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
                if (!run_cctors)
@@ -1739,34 +1672,21 @@ mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *contex
 
        if (context && context->class_inst) {
                inst = context->class_inst;
-               if (domain)
-                       gsctx->var_is_vt = mono_domain_alloc0 (domain, sizeof (gboolean) * inst->type_argc);
-               else if (mp)
-                       gsctx->var_is_vt = mono_mempool_alloc0 (mp, sizeof (gboolean) * inst->type_argc);
-               else
-                       gsctx->var_is_vt = g_new0 (gboolean, inst->type_argc);
-
                for (i = 0; i < inst->type_argc; ++i) {
                        MonoType *type = inst->type_argv [i];
 
                        if (mini_is_gsharedvt_gparam (type))
-                               gsctx->var_is_vt [i] = TRUE;
+                               gsctx->is_gsharedvt = TRUE;
                }
        }
        if (context && context->method_inst) {
                inst = context->method_inst;
-               if (domain)
-                       gsctx->mvar_is_vt = mono_domain_alloc0 (domain, sizeof (gboolean) * inst->type_argc);
-               else if (mp)
-                       gsctx->mvar_is_vt = mono_mempool_alloc0 (mp, sizeof (gboolean) * inst->type_argc);
-               else
-                       gsctx->mvar_is_vt = g_new0 (gboolean, inst->type_argc);
 
                for (i = 0; i < inst->type_argc; ++i) {
                        MonoType *type = inst->type_argv [i];
 
                        if (mini_is_gsharedvt_gparam (type))
-                               gsctx->mvar_is_vt [i] = TRUE;
+                               gsctx->is_gsharedvt = TRUE;
                }
        }
 }
@@ -2042,6 +1962,8 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
        mono_internal_hash_table_remove (&domain->jit_code_hash, method);
        mono_domain_jit_code_hash_unlock (domain);
        g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
+
+       /* requires the domain lock - took above */
        mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
 
        /* Remove jump targets in this method */
@@ -2240,10 +2162,11 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                                        return NULL;
                                } else {
                                        mono_raise_exception (jit_ex);
+                                       /* coverity[unreachable] */
                                }
                        }
 
-                       info->compiled_method = mini_add_method_trampoline (NULL, callee, info->compiled_method, mono_method_needs_static_rgctx_invoke (callee, FALSE), FALSE);
+                       info->compiled_method = mini_add_method_trampoline (callee, info->compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
                } else {
                        info->compiled_method = NULL;
                }
@@ -2266,7 +2189,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                        for (i = 0; i < sig->param_count; ++i) {
                                MonoType *t = sig->params [i];
 
-                               if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
+                               if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
                                        supported = FALSE;
                        }
 
@@ -2324,7 +2247,9 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                if (!info->dyn_call_info)
                        info->runtime_invoke = mono_jit_compile_method (invoke);
 
+               mono_domain_lock (domain);
                info2 = mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
+               mono_domain_unlock (domain);
                if (info2) {
                        g_free (info);
                        info = info2;
@@ -2405,7 +2330,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
        MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
        MONO_SIG_HANDLER_GET_CONTEXT;
 
-       ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
+       ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
 
 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
        if (mono_arch_is_int_overflow (ctx, info))
@@ -2491,7 +2416,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
        }
 #endif
 
-       ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
+       ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
@@ -2631,10 +2556,6 @@ mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *met
        if (!method)
                return NULL;
 
-       /* FIXME Support more cases */
-       if (mono_aot_only)
-               return NULL;
-
        if (MONO_TYPE_ISSTRUCT (sig->ret))
                return NULL;
 
@@ -2672,7 +2593,19 @@ mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *met
        if (cache [idx])
                return cache [idx];
 
-       return cache [idx] = mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
+       /* FIXME Support more cases */
+       if (mono_aot_only) {
+               char tramp_name [256];
+               const char *imt = load_imt_reg ? "_imt" : "";
+               int ind = (load_imt_reg ? (-offset) : offset) / SIZEOF_VOID_P;
+
+               sprintf (tramp_name, "delegate_virtual_invoke%s_%d", imt, ind);
+               cache [idx] = mono_aot_get_trampoline (tramp_name);
+               g_assert (cache [idx]);
+       } else {
+               cache [idx] = mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
+       }
+       return cache [idx];
 }
 
 static gpointer
@@ -2725,6 +2658,8 @@ mini_parse_debug_options (void)
                        debug_options.gen_sdb_seq_points = TRUE;
                else if (!strcmp (arg, "gen-compact-seq-points"))
                        debug_options.gen_seq_points_compact_data = TRUE;
+               else if (!strcmp (arg, "single-imm-size"))
+                       debug_options.single_imm_size = TRUE;
                else if (!strcmp (arg, "init-stacks"))
                        debug_options.init_stacks = TRUE;
                else if (!strcmp (arg, "casts"))
@@ -2733,6 +2668,8 @@ mini_parse_debug_options (void)
                        debug_options.soft_breakpoints = TRUE;
                else if (!strcmp (arg, "check-pinvoke-callconv"))
                        debug_options.check_pinvoke_callconv = TRUE;
+               else if (!strcmp (arg, "arm-use-fallback-tls"))
+                       debug_options.arm_use_fallback_tls = TRUE;
                else if (!strcmp (arg, "debug-domain-unload"))
                        mono_enable_debug_domain_unload (TRUE);
                else if (!strcmp (arg, "partial-sharing"))
@@ -2741,7 +2678,7 @@ mini_parse_debug_options (void)
                        mono_align_small_structs = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'debug-domain-unload', 'partial-sharing', 'align-small-structs'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'arm-use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs'\n");
                        exit (1);
                }
        }
@@ -2844,12 +2781,11 @@ mini_create_jit_domain_info (MonoDomain *domain)
 {
        MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
 
-       info->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
        info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
-       info->runtime_invoke_hash = mono_conc_hashtable_new_full (&domain->lock, mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
+       info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
        info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
        info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jump_target_hash = g_hash_table_new (NULL, NULL);
@@ -2908,7 +2844,6 @@ mini_free_jit_domain_info (MonoDomain *domain)
        }
        if (info->method_code_hash)
                g_hash_table_destroy (info->method_code_hash);
-       g_hash_table_destroy (info->class_init_trampoline_hash);
        g_hash_table_destroy (info->jump_trampoline_hash);
        g_hash_table_destroy (info->jit_trampoline_hash);
        g_hash_table_destroy (info->delegate_trampoline_hash);
@@ -2976,6 +2911,8 @@ mini_init (const char *filename, const char *runtime_version)
 
        MONO_VES_INIT_BEGIN ();
 
+       CHECKED_MONO_INIT ();
+
 #if defined(__linux__) && !defined(__native_client__)
        if (access ("/proc/self/maps", F_OK) != 0) {
                g_print ("Mono requires /proc to be mounted.\n");
@@ -3029,6 +2966,7 @@ mini_init (const char *filename, const char *runtime_version)
        ticallbacks.setup_async_callback = mono_setup_async_callback;
        ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
        ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
+       ticallbacks.thread_state_init = mono_thread_state_init;
 
        mono_counters_init ();
 
@@ -3090,11 +3028,6 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
        mono_threads_install_cleanup (mini_thread_cleanup);
 
-#ifdef MONO_ARCH_HAVE_NOTIFY_PENDING_EXC
-       check_for_pending_exc = FALSE;
-       mono_threads_install_notify_pending_exc ((MonoThreadNotifyPendingExcFunc)mono_arch_notify_pending_exc);
-#endif
-
 #define JIT_TRAMPOLINES_WORK
 #ifdef JIT_TRAMPOLINES_WORK
        mono_install_compile_method (mono_jit_compile_method);
@@ -3202,8 +3135,6 @@ register_icalls (void)
                                ves_icall_get_frame_info);
        mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
                                ves_icall_get_trace);
-       mono_add_internal_call ("System.Exception::get_trace",
-                               ves_icall_System_Exception_get_trace);
        mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
                                mono_runtime_install_handlers);
 
@@ -3289,16 +3220,19 @@ register_icalls (void)
 #endif
 
        register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
+       register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
        register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
        register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
        register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
        register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
        register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
 
+
 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
        register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
        register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
 #endif
+
 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
        register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, "mono_conv_to_r8_un", FALSE);
 #endif
@@ -3314,6 +3248,7 @@ register_icalls (void)
 #ifdef MONO_ARCH_EMULATE_FREM
 #if defined(__default_codegen__)
        register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
+       register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
 #elif defined(__native_client_codegen__)
        register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
 #endif
@@ -3413,6 +3348,9 @@ register_icalls (void)
 
        register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
        register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
+       register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
+       register_icall (mono_fill_class_rgctx, "mono_class_fill_rgctx", "ptr ptr int", FALSE);
+       register_icall (mono_fill_method_rgctx, "mono_method_fill_rgctx", "ptr ptr int", FALSE);
 
        register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
 
@@ -3505,6 +3443,7 @@ mini_cleanup (MonoDomain *domain)
 
 #ifndef MONO_CROSS_COMPILE
        mono_domain_free (domain, TRUE);
+       mono_gc_mutex_cleanup ();
 #endif
 
 #ifdef ENABLE_LLVM
@@ -3542,8 +3481,6 @@ mini_cleanup (MonoDomain *domain)
 
        mono_mutex_destroy (&jit_mutex);
 
-       mono_mutex_destroy (&mono_delegate_section);
-
        mono_code_manager_cleanup ();
 
 #ifdef USE_JUMP_TABLES
@@ -3655,6 +3592,17 @@ void mono_precompile_assemblies ()
        g_hash_table_destroy (assemblies);
 }
 
+/*
+ * Used by LLVM.
+ * Have to export this for AOT.
+ */
+void
+mono_personality (void)
+{
+       /* Not used */
+       g_assert_not_reached ();
+}
+
 #ifdef USE_JUMP_TABLES
 #define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128