Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mono / mini / mini.c
index 7e74ffcda5ab52ff1a50018b98c990dca711cb2f..534c2e20499304b2ee34e405ba8e95a110f53d12 100644 (file)
@@ -60,6 +60,7 @@
 #include <mono/utils/mono-hwcap.h>
 #include <mono/utils/dtrace.h>
 #include <mono/utils/mono-signal-handler.h>
+#include <mono/utils/mono-threads.h>
 
 #include "mini.h"
 #include "mini-llvm.h"
@@ -670,9 +671,9 @@ mono_tramp_info_register (MonoTrampInfo *info)
        copy->code_size = info->code_size;
        copy->name = g_strdup (info->name);
 
-       mono_loader_lock_if_inited ();
+       mono_jit_lock ();
        tramp_infos = g_slist_prepend (tramp_infos, copy);
-       mono_loader_unlock_if_inited ();
+       mono_jit_unlock ();
 
        mono_save_trampoline_xdebug_info (info);
 
@@ -682,6 +683,19 @@ mono_tramp_info_register (MonoTrampInfo *info)
        mono_tramp_info_free (info);
 }
 
+static void
+mono_tramp_info_cleanup (void)
+{
+       GSList *l;
+
+       for (l = tramp_infos; l; l = l->next) {
+               MonoTrampInfo *info = l->data;
+
+               mono_tramp_info_free (info);
+       }
+       g_slist_free (tramp_infos);
+}
+
 G_GNUC_UNUSED static void
 break_count (void)
 {
@@ -897,6 +911,8 @@ mono_type_to_store_membase (MonoCompile *cfg, MonoType *type)
        if (type->byref)
                return OP_STORE_MEMBASE_REG;
 
+       type = mini_replace_type (type);
+
 handle_enum:
        switch (type->type) {
        case MONO_TYPE_I1:
@@ -959,7 +975,7 @@ mono_type_to_load_membase (MonoCompile *cfg, MonoType *type)
        if (type->byref)
                return OP_LOAD_MEMBASE;
 
-       type = mono_type_get_underlying_type (type);
+       type = mini_replace_type (type);
 
        switch (type->type) {
        case MONO_TYPE_I1:
@@ -1037,6 +1053,8 @@ mini_type_to_ldind (MonoCompile* cfg, MonoType *type)
 guint
 mini_type_to_stind (MonoCompile* cfg, MonoType *type)
 {
+       type = mini_replace_type (type);
+
        if (cfg->generic_sharing_context && !type->byref) {
                if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
                        if (mini_type_var_is_vt (cfg, type))
@@ -1216,6 +1234,8 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
        int num = cfg->num_varinfo;
        gboolean regpair;
 
+       type = mini_replace_type (type);
+
        if ((num + 1) >= cfg->varinfo_count) {
                int orig_count = cfg->varinfo_count;
                cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64;
@@ -1242,7 +1262,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                if (type->byref) {
                        mono_mark_vreg_as_mp (cfg, vreg);
                } else {
-                       MonoType *t = mini_type_get_underlying_type (NULL, type);
+                       MonoType *t = mini_replace_type (type);
                        if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || mini_type_is_reference (cfg, t)) {
                                inst->flags |= MONO_INST_GC_TRACK;
                                mono_mark_vreg_as_ref (cfg, vreg);
@@ -1324,6 +1344,7 @@ MonoInst*
 mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
 {
        int dreg;
+       type = mini_replace_type (type);
 
        if (mono_type_is_long (type))
                dreg = mono_alloc_dreg (cfg, STACK_I8);
@@ -2696,22 +2717,42 @@ mono_set_lmf (MonoLMF *lmf)
        (*mono_get_lmf_addr ()) = lmf;
 }
 
+MonoJitTlsData*
+mono_get_jit_tls (void)
+{
+       return mono_native_tls_get_value (mono_jit_tls_id);
+}
+
 static void
 mono_set_jit_tls (MonoJitTlsData *jit_tls)
 {
+       MonoThreadInfo *info;
+
        mono_native_tls_set_value (mono_jit_tls_id, jit_tls);
 
 #ifdef MONO_HAVE_FAST_TLS
        MONO_FAST_TLS_SET (mono_jit_tls, jit_tls);
 #endif
+
+       /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
+       info = mono_thread_info_current ();
+       if (info)
+               mono_thread_info_tls_set (info, TLS_KEY_JIT_TLS, jit_tls);
 }
 
 static void
 mono_set_lmf_addr (gpointer lmf_addr)
 {
+       MonoThreadInfo *info;
+
 #ifdef MONO_HAVE_FAST_TLS
        MONO_FAST_TLS_SET (mono_lmf_addr, lmf_addr);
 #endif
+
+       /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
+       info = mono_thread_info_current ();
+       if (info)
+               mono_thread_info_tls_set (info, TLS_KEY_LMF_ADDR, lmf_addr);
 }
 
 /*
@@ -2922,6 +2963,7 @@ mini_get_tls_offset (MonoTlsKey key)
                g_assert (offset != -1);
                break;
        }
+
        return offset;
 }
 
@@ -2944,6 +2986,18 @@ mono_create_tls_get_offset (MonoCompile *cfg, int offset)
        return ins;
 }
 
+gboolean
+mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key)
+{
+       if (!MONO_ARCH_HAVE_TLS_GET)
+               return FALSE;
+
+       if (cfg->compile_aot)
+               return ARCH_HAVE_TLS_GET_REG;
+       else
+               return mini_get_tls_offset (key) != -1;
+}
+
 MonoInst*
 mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
 {
@@ -3003,7 +3057,7 @@ mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
 void
 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
 {
-       MonoJumpInfo *ji = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
+       MonoJumpInfo *ji = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
 
        ji->ip.i = ip;
        ji->type = type;
@@ -3016,7 +3070,7 @@ mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpoin
 void
 mono_add_patch_info_rel (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target, int relocation)
 {
-       MonoJumpInfo *ji = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
+       MonoJumpInfo *ji = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
 
        ji->ip.i = ip;
        ji->type = type;
@@ -3097,15 +3151,12 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
                info = mono_mempool_alloc (mp, sizeof (MonoGSharedVtMethodInfo));
                res->data.gsharedvt_method = info;
                memcpy (info, oinfo, sizeof (MonoGSharedVtMethodInfo));
-               info->entries = g_ptr_array_new ();
-               if (oinfo->entries) {
-                       for (i = 0; i < oinfo->entries->len; ++i) {
-                               MonoRuntimeGenericContextInfoTemplate *otemplate = g_ptr_array_index (oinfo->entries, i);
-                               MonoRuntimeGenericContextInfoTemplate *template = mono_mempool_alloc0 (mp, sizeof (MonoRuntimeGenericContextInfoTemplate));
+               info->entries = mono_mempool_alloc (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
+               for (i = 0; i < oinfo->num_entries; ++i) {
+                       MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
+                       MonoRuntimeGenericContextInfoTemplate *template = &info->entries [i];
 
-                               memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
-                               g_ptr_array_add (info->entries, template);
-                       }
+                       memcpy (template, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
                }
                //info->locals_types = mono_mempool_alloc0 (mp, info->nlocals * sizeof (MonoType*));
                //memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
@@ -3152,6 +3203,7 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
        case MONO_PATCH_INFO_SIGNATURE:
        case MONO_PATCH_INFO_TLS_OFFSET:
+       case MONO_PATCH_INFO_METHOD_CODE_SLOT:
                return (ji->type << 8) | (gssize)ji->data.target;
        case MONO_PATCH_INFO_GSHAREDVT_CALL:
                return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
@@ -3316,6 +3368,21 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                }
 #endif
                break;
+       case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
+               gpointer code_slot;
+
+               mono_domain_lock (domain);
+               if (!domain_jit_info (domain)->method_code_hash)
+                       domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
+               code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
+               if (!code_slot) {
+                       code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
+                       g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
+               }
+               mono_domain_unlock (domain);
+               target = code_slot;
+               break;
+       }
        case MONO_PATCH_INFO_SWITCH: {
                gpointer *jump_table;
                int i;
@@ -3528,13 +3595,13 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                        /* Make a copy into the domain mempool */
                        info = g_malloc0 (sizeof (MonoGSharedVtMethodInfo)); //mono_domain_alloc0 (domain, sizeof (MonoGSharedVtMethodInfo));
                        info->method = oinfo->method;
-                       info->entries = g_ptr_array_new ();
-                       for (i = 0; i < oinfo->entries->len; ++i) {
-                               MonoRuntimeGenericContextInfoTemplate *otemplate = g_ptr_array_index (oinfo->entries, i);
-                               MonoRuntimeGenericContextInfoTemplate *template = g_malloc0 (sizeof (MonoRuntimeGenericContextInfoTemplate));
+                       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));
-                               g_ptr_array_add (info->entries, template);
                        }
                        slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
                        break;
@@ -3588,9 +3655,16 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = (gpointer) (size_t) mono_jit_tls_id;
                break;
        }
-       case MONO_PATCH_INFO_TLS_OFFSET:
-               target = GINT_TO_POINTER (mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target)));
+       case MONO_PATCH_INFO_TLS_OFFSET: {
+               int offset;
+
+               offset = mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target));
+#ifdef MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET
+               offset = mono_arch_translate_tls_offset (offset);
+#endif
+               target = GINT_TO_POINTER (offset);
                break;
+       }
        case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
                target = NULL;
                break;
@@ -4218,6 +4292,9 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
        jinfo->code_size = info->code_size;
        jinfo->used_regs = mono_cache_unwind_info (uw_info, info_len);
 
+       if (!info->uw_info)
+               g_free (uw_info);
+
        return jinfo;
 }
 
@@ -4317,7 +4394,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
                else
                        gi->generic_sharing_context = mono_domain_alloc0 (cfg->domain, sizeof (MonoGenericSharingContext));
-               memcpy (gi->generic_sharing_context, cfg->generic_sharing_context, sizeof (MonoGenericSharingContext));
+               mini_init_gsctx (cfg->method->dynamic ? NULL : cfg->domain, NULL, cfg->gsctx_context, gi->generic_sharing_context);
 
                if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
                                mini_method_get_context (method_to_compile)->method_inst ||
@@ -4435,12 +4512,24 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        MonoExceptionClause *ec = &header->clauses [i];
                        MonoJitExceptionInfo *ei = &jinfo->clauses [i];
                        MonoBasicBlock *tblock;
-                       MonoInst *exvar;
+                       MonoInst *exvar, *spvar;
 
                        ei->flags = ec->flags;
 
-                       exvar = mono_find_exvar_for_offset (cfg, ec->handler_offset);
-                       ei->exvar_offset = exvar ? exvar->inst_offset : 0;
+                       /*
+                        * The spvars are needed by mono_arch_install_handler_block_guard ().
+                        */
+                       if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
+                               int region;
+
+                               region = ((i + 1) << 8) | MONO_REGION_FINALLY | ec->flags;
+                               spvar = mono_find_spvar_for_region (cfg, region);
+                               g_assert (spvar);
+                               ei->exvar_offset = spvar->inst_offset;
+                       } else {
+                               exvar = mono_find_exvar_for_offset (cfg, ec->handler_offset);
+                               ei->exvar_offset = exvar ? exvar->inst_offset : 0;
+                       }
 
                        if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                tblock = cfg->cil_offset_to_bb [ec->data.filter_offset];
@@ -4553,20 +4642,43 @@ static MonoType*
 get_gsharedvt_type (MonoType *t)
 {
        MonoGenericParam *par = t->data.generic_param;
+       MonoGenericParam *copy;
        MonoType *res;
+       MonoImage *image = NULL;
 
        /* 
         * Create an anonymous gparam with a different serial so normal gshared and gsharedvt methods have
         * a different instantiation.
         */
        g_assert (mono_generic_param_info (par));
-       par = g_memdup (par, sizeof (MonoGenericParamFull));
-       par->owner = NULL;
+       if (par->owner) {
+               image = par->owner->image;
+
+               mono_image_lock (image);
+               if (!image->gsharedvt_types)
+                       image->gsharedvt_types = g_hash_table_new (NULL, NULL);
+               res = g_hash_table_lookup (image->gsharedvt_types, par);
+               mono_image_unlock (image);
+               if (res)
+                       return res;
+               copy = mono_image_alloc0 (image, sizeof (MonoGenericParamFull));
+               memcpy (copy, par, sizeof (MonoGenericParamFull));
+       } else {
+               copy = g_memdup (par, sizeof (MonoGenericParamFull));
+       }
+       copy->owner = NULL;
        // FIXME:
-       par->image = mono_defaults.corlib;
-       par->serial = 1;
+       copy->image = mono_defaults.corlib;
+       copy->serial = 1;
        res = mono_metadata_type_dup (NULL, t);
-       res->data.generic_param = par;
+       res->data.generic_param = copy;
+
+       if (par->owner) {
+               mono_image_lock (image);
+               /* Duplicates are ok */
+               g_hash_table_insert (image->gsharedvt_types, par, res);
+               mono_image_unlock (image);
+       }
 
        return res;
 }
@@ -4720,16 +4832,21 @@ mini_get_shared_method (MonoMethod *method)
 }
 
 void
-mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
+mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
 {
        MonoGenericInst *inst;
        int i;
 
        memset (gsctx, 0, sizeof (MonoGenericSharingContext));
 
-       if (context->class_inst) {
+       if (context && context->class_inst) {
                inst = context->class_inst;
-               gsctx->var_is_vt = g_new0 (gboolean, inst->type_argc);
+               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];
@@ -4738,9 +4855,14 @@ mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
                                gsctx->var_is_vt [i] = TRUE;
                }
        }
-       if (context->method_inst) {
+       if (context && context->method_inst) {
                inst = context->method_inst;
-               gsctx->mvar_is_vt = g_new0 (gboolean, inst->type_argc);
+               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];
@@ -4757,15 +4879,14 @@ mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
  * @method: the method to compile
  * @opts: the optimization flags to use
  * @domain: the domain where the method will be compiled in
- * @run_cctors: whether we should run type ctors if possible
- * @compile_aot: whether this is an AOT compilation
+ * @flags: compilation flags
  * @parts: debug flag
  *
  * Returns: a MonoCompile* pointer. Caller must check the exception_type
  * field in the returned struct to see if compilation succeded.
  */
 MonoCompile*
-mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, gboolean compile_aot, int parts)
+mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts)
 {
        MonoMethodHeader *header;
        MonoMethodSignature *sig;
@@ -4777,6 +4898,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        gboolean try_generic_shared, try_llvm = FALSE;
        MonoMethod *method_to_compile, *method_to_register;
        gboolean method_is_gshared = FALSE;
+       gboolean run_cctors = (flags & JIT_FLAG_RUN_CCTORS) ? 1 : 0;
+       gboolean compile_aot = (flags & JIT_FLAG_AOT) ? 1 : 0;
+       gboolean full_aot = (flags & JIT_FLAG_FULL_AOT) ? 1 : 0;
 
        InterlockedIncrement (&mono_jit_stats.methods_compiled);
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
@@ -4843,6 +4967,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        cfg->domain = domain;
        cfg->verbose_level = mini_verbose;
        cfg->compile_aot = compile_aot;
+       cfg->full_aot = full_aot;
        cfg->skip_visibility = method->skip_visibility;
        cfg->orig_method = method;
        cfg->gen_seq_points = debug_options.gen_seq_points;
@@ -4865,7 +4990,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                MonoMethodInflated *inflated;
                MonoGenericContext *context;
 
-               // FIXME: Free the contents of gsctx if compilation fails
                if (method_is_gshared) {
                        g_assert (method->is_inflated);
                        inflated = (MonoMethodInflated*)method;
@@ -4879,7 +5003,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                        context = &inflated->context;
                }
 
-               mini_init_gsctx (context, &cfg->gsctx);
+               mini_init_gsctx (NULL, cfg->mempool, context, &cfg->gsctx);
+               cfg->gsctx_context = context;
 
                cfg->gsharedvt = TRUE;
                // FIXME:
@@ -5623,7 +5748,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 #else
 
 MonoCompile*
-mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, gboolean compile_aot, int parts)
+mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts)
 {
        g_assert_not_reached ();
        return NULL;
@@ -5868,7 +5993,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        jit_timer = g_timer_new ();
 
-       cfg = mini_method_compile (method, opt, target_domain, TRUE, FALSE, 0);
+       cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0);
        prof_method = cfg->method;
 
        g_timer_stop (jit_timer);
@@ -6950,6 +7075,13 @@ delete_jump_list (gpointer key, gpointer value, gpointer user_data)
        g_slist_free (jlist->list);
 }
 
+static void
+delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
+{
+       GSList *list = value;
+       g_slist_free (list);
+}
+
 static void
 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
 {
@@ -6991,7 +7123,7 @@ mini_free_jit_domain_info (MonoDomain *domain)
        g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
        g_hash_table_destroy (info->jump_target_hash);
        if (info->jump_target_got_slot_hash) {
-               g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL);
+               g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
                g_hash_table_destroy (info->jump_target_got_slot_hash);
        }
        if (info->dynamic_code_hash) {
@@ -7035,6 +7167,8 @@ mini_init (const char *filename, const char *runtime_version)
        }
 #endif
 
+       InitializeCriticalSection (&jit_mutex);
+
        /* Happens when using the embedding interface */
        if (!default_opt_set)
                default_opt = mono_parse_default_optimizations (NULL);
@@ -7044,8 +7178,6 @@ mini_init (const char *filename, const char *runtime_version)
                mono_set_generic_sharing_vt_supported (TRUE);
 #endif
 
-       InitializeCriticalSection (&jit_mutex);
-
 #ifdef MONO_HAVE_FAST_TLS
        MONO_FAST_TLS_INIT (mono_jit_tls);
        MONO_FAST_TLS_INIT (mono_lmf_addr);
@@ -7200,11 +7332,11 @@ mini_init (const char *filename, const char *runtime_version)
        /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
        mono_arch_finish_init ();
 
+       mono_icall_init ();
+
        /* This must come after mono_init () in the aot-only case */
        mono_exceptions_init ();
 
-       mono_icall_init ();
-
        /* This should come after mono_init () too */
        mini_gc_init ();
 
@@ -7383,6 +7515,8 @@ mini_init (const char *filename, const char *runtime_version)
 
 #if SIZEOF_REGISTER == 4
        register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
+#else
+       register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
 #endif
 
        /* other jit icalls */
@@ -7419,7 +7553,7 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
        register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
        register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
-       register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", TRUE);
+       register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
        register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
 
        register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);
@@ -7583,6 +7717,8 @@ mini_cleanup (MonoDomain *domain)
        g_free (emul_opcode_opcodes);
        g_free (vtable_trampolines);
 
+       mono_tramp_info_cleanup ();
+
        mono_arch_cleanup ();
 
        mono_generic_sharing_cleanup ();
@@ -7770,7 +7906,7 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
 
 #endif
 
-#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(MONOTOUCH) && !defined(MONO_EXTENSIONS)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(ENABLE_GSHAREDVT)
 
 gboolean
 mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig)
@@ -7881,3 +8017,15 @@ mono_jumptable_get_entry (guint8 *code_ptr)
        return mono_arch_jumptable_entry_from_code (code_ptr);
 }
 #endif
+
+/*
+ * mini_replace_type:
+ *
+ * Replace the type used in the metadata stream with what the JIT will actually use during compilation.
+*/
+MonoType*
+mini_replace_type (MonoType *type)
+{
+       type = mono_type_get_underlying_type (type);
+       return mini_native_type_replace_type (type);
+}