[runtime] Implement the new suspend infrastructure on windows.
[mono.git] / mono / mini / mini.c
index 035f975c9f80430359e947c8c006f77b01df0f1f..a31e9003a13596f56a2bff26c347a6bd75ae4be1 100644 (file)
@@ -88,15 +88,15 @@ MonoNativeTlsKey mono_jit_tls_id;
 MONO_FAST_TLS_DECLARE(mono_jit_tls);
 #endif
 
-MonoTraceSpec *mono_jit_trace_calls = NULL;
+MonoTraceSpec *mono_jit_trace_calls;
 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;
 /* Whenever to use IMT */
-gboolean mono_use_imt = ARCH_HAVE_IMT;
-MonoMethodDesc *mono_inject_async_exc_method = NULL;
+gboolean mono_use_imt = TRUE;
+MonoMethodDesc *mono_inject_async_exc_method;
 int mono_inject_async_exc_pos;
-MonoMethodDesc *mono_break_at_bb_method = NULL;
+MonoMethodDesc *mono_break_at_bb_method;
 int mono_break_at_bb_bb_num;
 gboolean mono_do_x86_stack_align = TRUE;
 const char *mono_build_date;
@@ -111,13 +111,13 @@ static int mini_verbose = 0;
  */
 gboolean mono_use_llvm = FALSE;
 
-#define mono_jit_lock() EnterCriticalSection (&jit_mutex)
-#define mono_jit_unlock() LeaveCriticalSection (&jit_mutex)
-static CRITICAL_SECTION jit_mutex;
+#define mono_jit_lock() mono_mutex_lock (&jit_mutex)
+#define mono_jit_unlock() mono_mutex_unlock (&jit_mutex)
+static mono_mutex_t jit_mutex;
 
-static MonoCodeManager *global_codeman = NULL;
+static MonoCodeManager *global_codeman;
 
-static GHashTable *jit_icall_name_hash = NULL;
+static GHashTable *jit_icall_name_hash;
 
 static MonoDebugOptions debug_options;
 
@@ -141,6 +141,8 @@ gboolean disable_vtypes_in_regs = FALSE;
 
 static GSList *tramp_infos;
 
+static void register_icalls (void);
+
 gpointer
 mono_realloc_native_code (MonoCompile *cfg)
 {
@@ -1135,6 +1137,8 @@ mono_op_imm_to_op (int opcode)
                return OP_IREM_UN;
        case OP_IREM_IMM:
                return OP_IREM;
+       case OP_LREM_IMM:
+               return OP_LREM;
        case OP_DIV_IMM:
 #if SIZEOF_REGISTER == 4
                return OP_IDIV;
@@ -1524,7 +1528,7 @@ mono_create_jump_table (MonoCompile *cfg, MonoInst *label, MonoBasicBlock **bbs,
 static MonoMethodSignature *
 mono_get_array_new_va_signature (int arity)
 {
-       static GHashTable *sighash = NULL;
+       static GHashTable *sighash;
        MonoMethodSignature *res;
        int i;
 
@@ -1858,7 +1862,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_
                else {
                        int ialign;
 
-                       size = mono_type_size (t, &ialign);
+                       size = mini_type_stack_size (NULL, t, &ialign);
                        align = ialign;
 
                        if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
@@ -2153,7 +2157,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
                } else {
                        int ialign;
 
-                       size = mono_type_size (t, &ialign);
+                       size = mini_type_stack_size (NULL, t, &ialign);
                        align = ialign;
 
                        if (mono_class_from_mono_type (t)->exception_type)
@@ -2360,8 +2364,8 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
 static mono_byte emul_opcode_hit_cache [(OP_LAST>>EMUL_HIT_SHIFT) + 1] = {0};
 static short emul_opcode_num = 0;
 static short emul_opcode_alloced = 0;
-static short *emul_opcode_opcodes = NULL;
-static MonoJitICallInfo **emul_opcode_map = NULL;
+static short *emul_opcode_opcodes;
+static MonoJitICallInfo **emul_opcode_map;
 
 MonoJitICallInfo *
 mono_find_jit_opcode_emulation (int opcode)
@@ -2950,9 +2954,6 @@ mini_get_tls_offset (MonoTlsKey key)
        case TLS_KEY_JIT_TLS:
 #ifdef HOST_WIN32
                offset = mono_get_jit_tls_key ();
-               /* Only 64 tls entries can be accessed using inline code */
-               if (offset >= 64)
-                       offset = -1;
 #else
                offset = mono_get_jit_tls_offset ();
 #endif
@@ -3062,6 +3063,16 @@ mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
 
 #endif /* !DISABLE_JIT */
 
+
+static gboolean
+mini_tls_key_supported (MonoTlsKey key)
+{
+       if (!MONO_ARCH_HAVE_TLS_GET)
+               return FALSE;
+
+       return mini_get_tls_offset (key) != -1;
+}
+
 void
 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
 {
@@ -3147,8 +3158,8 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
                res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
                break;
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
-               res->data.del_tramp = mono_mempool_alloc0 (mp, sizeof (MonoClassMethodPair));
-               memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoClassMethodPair));
+               res->data.del_tramp = mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
+               memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
                break;
        case MONO_PATCH_INFO_GSHAREDVT_CALL:
                res->data.gsharedvt = mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
@@ -3240,7 +3251,7 @@ mono_patch_info_hash (gconstpointer data)
                /* Hash on the selector name */
                return g_str_hash (ji->data.target);
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
-               return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method;
+               return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->virtual;
        default:
                printf ("info type: %d\n", ji->type);
                mono_print_ji (ji); printf ("\n");
@@ -3295,7 +3306,7 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
        case MONO_PATCH_INFO_GSHAREDVT_METHOD:
                return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
-               return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method;
+               return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->virtual == ji2->data.del_tramp->virtual;
        default:
                if (ji1->data.target != ji2->data.target)
                        return 0;
@@ -3465,9 +3476,12 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                break;
        }
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
-               MonoClassMethodPair *del_tramp = patch_info->data.del_tramp;
+               MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
 
-               target = mono_create_delegate_trampoline_with_method (domain, del_tramp->klass, del_tramp->method);
+               if (del_tramp->virtual)
+                       target = mono_create_delegate_virtual_trampoline (domain, del_tramp->klass, del_tramp->method);
+               else
+                       target = mono_create_delegate_trampoline_info (domain, del_tramp->klass, del_tramp->method);
                break;
        }
        case MONO_PATCH_INFO_SFLDA: {
@@ -4297,7 +4311,7 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
        jinfo->d.method = wrapper;
        jinfo->code_start = info->code;
        jinfo->code_size = info->code_size;
-       jinfo->used_regs = mono_cache_unwind_info (uw_info, info_len);
+       jinfo->unwind_info = mono_cache_unwind_info (uw_info, info_len);
 
        if (!info->uw_info)
                g_free (uw_info);
@@ -4340,6 +4354,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                if (stack_size)
                        arch_eh_info_size = sizeof (MonoArchEHJitInfo);
        }
+
+       if (cfg->has_unwind_info_for_epilog && !arch_eh_info_size)
+               arch_eh_info_size = sizeof (MonoArchEHJitInfo);
                
        if (cfg->try_block_holes) {
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
@@ -4380,7 +4397,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        jinfo->d.method = cfg->method_to_register;
        jinfo->code_start = cfg->native_code;
        jinfo->code_size = cfg->code_len;
-       jinfo->used_regs = cfg->used_int_regs;
        jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
        jinfo->num_clauses = num_clauses;
 
@@ -4626,19 +4642,28 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                }
        }
 
-       /* 
-        * Its possible to generate dwarf unwind info for xdebug etc, but not actually
-        * using it during runtime, hence the define.
-        */
        if (cfg->encoded_unwind_ops) {
-               jinfo->used_regs = mono_cache_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
+               /* Generated by LLVM */
+               jinfo->unwind_info = mono_cache_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
                g_free (cfg->encoded_unwind_ops);
        } else if (cfg->unwind_ops) {
                guint32 info_len;
                guint8 *unwind_info = mono_unwind_ops_encode (cfg->unwind_ops, &info_len);
+               guint32 unwind_desc;
 
-               jinfo->used_regs = mono_cache_unwind_info (unwind_info, info_len);
+               unwind_desc = mono_cache_unwind_info (unwind_info, info_len);
+
+               if (cfg->has_unwind_info_for_epilog) {
+                       MonoArchEHJitInfo *info;
+
+                       info = mono_jit_info_get_arch_eh_info (jinfo);
+                       g_assert (info);
+                       info->epilog_size = cfg->code_size - cfg->epilog_begin;
+               }
+               jinfo->unwind_info = unwind_desc;
                g_free (unwind_info);
+       } else {
+               jinfo->unwind_info = cfg->used_int_regs;
        }
 
        return jinfo;
@@ -4901,7 +4926,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        guint8 *ip;
        MonoCompile *cfg;
        int dfn, i, code_size_ratio;
+#ifndef DISABLE_SSA
        gboolean deadce_has_run = FALSE;
+#endif
        gboolean try_generic_shared, try_llvm = FALSE;
        MonoMethod *method_to_compile, *method_to_register;
        gboolean method_is_gshared = FALSE;
@@ -5816,7 +5843,7 @@ lookup_method (MonoDomain *domain, MonoMethod *method)
 }
 
 #if ENABLE_JIT_MAP
-static FILE* perf_map_file = NULL;
+static FILE* perf_map_file;
 
 void
 mono_enable_jit_map (void)
@@ -6093,18 +6120,11 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        else
                shared = NULL;
 
-       /*
-        * FIXME: lookup_method_inner requires the loader lock.
-        * FIXME: This is no longer true, can this be dropped ?
-        */
-       mono_loader_lock ();
        mono_domain_lock (target_domain);
 
        /* Check if some other thread already did the job. In this case, we can
        discard the code this thread generated. */
 
-       mono_domain_jit_code_hash_lock (target_domain);
-
        info = lookup_method_inner (target_domain, method, shared);
        if (info) {
                /* We can't use a domain specific method in another domain */
@@ -6113,18 +6133,18 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 //                     printf("Discarding code for method %s\n", method->name);
                }
        }
-       
        if (code == NULL) {
+               /* The lookup + insert is atomic since this is done inside the domain lock */
+               mono_domain_jit_code_hash_lock (target_domain);
                mono_internal_hash_table_insert (&target_domain->jit_code_hash, cfg->jit_info->d.method, cfg->jit_info);
                mono_domain_jit_code_hash_unlock (target_domain);
+
                code = cfg->native_code;
 
                if (cfg->generic_sharing_context && mono_method_is_generic_sharable (method, FALSE))
                        mono_stats.generics_shared_methods++;
                if (cfg->gsharedvt)
                        mono_stats.gsharedvt_methods++;
-       } else {
-               mono_domain_jit_code_hash_unlock (target_domain);
        }
 
        jinfo = cfg->jit_info;
@@ -6176,7 +6196,6 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        mono_emit_jit_map (jinfo);
 #endif
        mono_domain_unlock (target_domain);
-       mono_loader_unlock ();
 
        vtable = mono_class_vtable (target_domain, method->klass);
        if (!vtable) {
@@ -6359,9 +6378,11 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
 
        mono_domain_lock (domain);
        g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
+       mono_domain_jit_code_hash_lock (domain);
        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);
-       g_hash_table_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
+       mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
 
        /* Remove jump targets in this method */
        g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
@@ -6439,9 +6460,9 @@ mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *met
 
 gboolean mono_do_single_method_regression = FALSE;
 guint32 mono_single_method_regression_opt = 0;
-MonoMethod *mono_current_single_method = NULL;
-GSList *mono_single_method_list = NULL;
-GHashTable *mono_single_method_hash = NULL;
+MonoMethod *mono_current_single_method;
+GSList *mono_single_method_list;
+GHashTable *mono_single_method_hash;
 
 guint32
 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
@@ -6502,9 +6523,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
 
        domain_info = domain_jit_info (domain);
 
-       mono_domain_lock (domain);
-       info = g_hash_table_lookup (domain_info->runtime_invoke_hash, method);
-       mono_domain_unlock (domain);            
+       info = mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);
 
        if (!info) {
                if (mono_security_core_clr_enabled ()) {
@@ -6645,15 +6664,11 @@ 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 = g_hash_table_lookup (domain_info->runtime_invoke_hash, method);
+               info2 = mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
                if (info2) {
                        g_free (info);
                        info = info2;
-               } else {
-                       g_hash_table_insert (domain_info->runtime_invoke_hash, method, info);
                }
-               mono_domain_unlock (domain);
        }
 
        runtime_invoke = info->runtime_invoke;
@@ -6752,8 +6767,10 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
-               if (mono_do_crash_chaining)
+               if (mono_do_crash_chaining) {
                        mono_chain_signal (SIG_HANDLER_PARAMS);
+                       return;
+               }
        }
        
        mono_arch_handle_exception (ctx, exc);
@@ -6804,8 +6821,10 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
                        return;
                mono_handle_native_sigsegv (SIGSEGV, ctx);
-               if (mono_do_crash_chaining)
+               if (mono_do_crash_chaining) {
                        mono_chain_signal (SIG_HANDLER_PARAMS);
+                       return;
+               }
        }
 
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
@@ -6849,8 +6868,10 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
 
-               if (mono_do_crash_chaining)
+               if (mono_do_crash_chaining) {
                        mono_chain_signal (SIG_HANDLER_PARAMS);
+                       return;
+               }
        }
                        
        mono_arch_handle_exception (ctx, NULL);
@@ -6934,6 +6955,62 @@ mini_get_vtable_trampoline (int slot_index)
        return vtable_trampolines [index];
 }
 
+gpointer
+mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
+{
+       gboolean is_virtual_generic, is_interface, load_imt_reg;
+       int offset, idx;
+
+       static guint8 **cache = NULL;
+       static int cache_size = 0;
+
+       if (!method)
+               return NULL;
+
+       /* FIXME Support more cases */
+       if (mono_aot_only)
+               return NULL;
+
+       if (MONO_TYPE_ISSTRUCT (sig->ret))
+               return NULL;
+
+       is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
+       is_interface = method->klass->flags & TYPE_ATTRIBUTE_INTERFACE ? TRUE : FALSE;
+       load_imt_reg = is_virtual_generic || is_interface;
+
+       if (is_interface && !is_virtual_generic)
+               offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
+       else
+               offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
+
+       idx = (offset / SIZEOF_VOID_P + MONO_IMT_SIZE) * 2 + (load_imt_reg ? 1 : 0);
+       g_assert (idx >= 0);
+
+       /* Resize the cache to idx + 1 */
+       if (cache_size < idx + 1) {
+               mono_jit_lock ();
+               if (cache_size < idx + 1) {
+                       guint8 **new_cache;
+                       int new_cache_size = idx + 1;
+
+                       new_cache = g_new0 (guint8*, new_cache_size);
+                       if (cache)
+                               memcpy (new_cache, cache, cache_size * sizeof (guint8*));
+                       g_free (cache);
+
+                       mono_memory_barrier ();
+                       cache = new_cache;
+                       cache_size = new_cache_size;
+               }
+               mono_jit_unlock ();
+       }
+
+       if (cache [idx])
+               return cache [idx];
+
+       return cache [idx] = mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
+}
+
 static gpointer
 mini_get_imt_trampoline (int slot_index)
 {
@@ -7103,7 +7180,7 @@ mini_create_jit_domain_info (MonoDomain *domain)
        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 = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
+       info->runtime_invoke_hash = mono_conc_hashtable_new_full (&domain->lock, mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
        info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, 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);
@@ -7182,7 +7259,7 @@ mini_free_jit_domain_info (MonoDomain *domain)
        if (info->static_rgctx_trampoline_hash)
                g_hash_table_destroy (info->static_rgctx_trampoline_hash);
        g_hash_table_destroy (info->llvm_vcall_trampoline_hash);
-       g_hash_table_destroy (info->runtime_invoke_hash);
+       mono_conc_hashtable_destroy (info->runtime_invoke_hash);
        g_hash_table_destroy (info->seq_points);
        g_hash_table_destroy (info->arch_seq_points);
        if (info->agent_info)
@@ -7213,7 +7290,9 @@ mini_init (const char *filename, const char *runtime_version)
        }
 #endif
 
-       InitializeCriticalSection (&jit_mutex);
+       mono_mutex_init_recursive (&jit_mutex);
+
+       mono_cross_helpers_run ();
 
        /* Happens when using the embedding interface */
        if (!default_opt_set)
@@ -7236,7 +7315,6 @@ mini_init (const char *filename, const char *runtime_version)
 
        if (!global_codeman)
                global_codeman = mono_code_manager_new ();
-       jit_icall_name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
        memset (&callbacks, 0, sizeof (callbacks));
        callbacks.create_ftnptr = mini_create_ftnptr;
@@ -7245,13 +7323,12 @@ mini_init (const char *filename, const char *runtime_version)
        callbacks.set_cast_details = mono_set_cast_details;
        callbacks.debug_log = mono_debugger_agent_debug_log;
        callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
+       callbacks.tls_key_supported = mini_tls_key_supported;
 
-#ifdef MONO_ARCH_HAVE_IMT
        if (mono_use_imt) {
                callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
                callbacks.get_imt_trampoline = mini_get_imt_trampoline;
        }
-#endif
 
        mono_install_callbacks (&callbacks);
 
@@ -7262,7 +7339,6 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_threads_runtime_init (&ticallbacks);
 
-
        if (g_getenv ("MONO_DEBUG") != NULL)
                mini_parse_debug_options ();
 
@@ -7301,9 +7377,6 @@ mini_init (const char *filename, const char *runtime_version)
 
        mono_trampolines_init ();
 
-       if (!g_thread_supported ())
-               g_thread_init (NULL);
-
        mono_native_tls_alloc (&mono_jit_tls_id, NULL);
 
        if (default_opt & MONO_OPT_AOT)
@@ -7351,9 +7424,8 @@ mini_init (const char *filename, const char *runtime_version)
        mono_install_get_class_from_name (mono_aot_get_class_from_name);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
 
-       if (debug_options.collect_pagefault_stats) {
+       if (debug_options.collect_pagefault_stats)
                mono_aot_set_make_unreadable (TRUE);
-       }
 
        if (runtime_version)
                domain = mono_init_version (filename, runtime_version);
@@ -7366,14 +7438,12 @@ mini_init (const char *filename, const char *runtime_version)
                mono_marshal_use_aot_wrappers (TRUE);
        }
 
-#ifdef MONO_ARCH_HAVE_IMT
        if (mono_use_imt) {
                if (mono_aot_only)
                        mono_install_imt_thunk_builder (mono_aot_get_imt_thunk);
                else
                        mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
        }
-#endif
 
        /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
        mono_arch_finish_init ();
@@ -7386,6 +7456,58 @@ mini_init (const char *filename, const char *runtime_version)
        /* This should come after mono_init () too */
        mini_gc_init ();
 
+#ifndef DISABLE_JIT
+       mono_create_helper_signatures ();
+#endif
+
+       register_jit_stats ();
+
+#define JIT_CALLS_WORK
+#ifdef JIT_CALLS_WORK
+       /* Needs to be called here since register_jit_icall depends on it */
+       mono_marshal_init ();
+
+       jit_icall_name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+       mono_arch_register_lowlevel_calls ();
+
+       register_icalls ();
+
+       mono_generic_sharing_init ();
+#endif
+
+#ifdef MONO_ARCH_SIMD_INTRINSICS
+       mono_simd_intrinsics_init ();
+#endif
+
+#if MONO_SUPPORT_TASKLETS
+       mono_tasklets_init ();
+#endif
+
+       if (mono_compile_aot)
+               /*
+                * Avoid running managed code when AOT compiling, since the platform
+                * might only support aot-only execution.
+                */
+               mono_runtime_set_no_exec (TRUE);
+
+#define JIT_RUNTIME_WORKS
+#ifdef JIT_RUNTIME_WORKS
+       mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
+       mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb);
+       mono_thread_attach (domain);
+#endif
+
+       mono_profiler_runtime_initialized ();
+
+       MONO_VES_INIT_END ();
+
+       return domain;
+}
+
+static void
+register_icalls (void)
+{
        mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
                                ves_icall_get_frame_info);
        mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", 
@@ -7404,19 +7526,6 @@ mini_init (const char *filename, const char *runtime_version)
                                mono_debugger_agent_unhandled_exception);
 #endif
 
-#ifndef DISABLE_JIT
-       mono_create_helper_signatures ();
-#endif
-
-       register_jit_stats ();
-
-#define JIT_CALLS_WORK
-#ifdef JIT_CALLS_WORK
-       /* Needs to be called here since register_jit_icall depends on it */
-       mono_marshal_init ();
-
-       mono_arch_register_lowlevel_calls ();
-
        /*
         * It's important that we pass `TRUE` as the last argument here, as
         * it causes the JIT to omit a wrapper for these icalls. If the JIT
@@ -7617,41 +7726,10 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
 
        register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
-#endif
 
 #ifdef TARGET_IOS
        register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
 #endif
-
-       mono_generic_sharing_init ();
-
-#ifdef MONO_ARCH_SIMD_INTRINSICS
-       mono_simd_intrinsics_init ();
-#endif
-
-#if MONO_SUPPORT_TASKLETS
-       mono_tasklets_init ();
-#endif
-
-       if (mono_compile_aot)
-               /* 
-                * Avoid running managed code when AOT compiling, since the platform
-                * might only support aot-only execution.
-                */
-               mono_runtime_set_no_exec (TRUE);
-
-#define JIT_RUNTIME_WORKS
-#ifdef JIT_RUNTIME_WORKS
-       mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
-       mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb);
-       mono_thread_attach (domain);
-#endif
-
-       mono_profiler_runtime_initialized ();
-
-       MONO_VES_INIT_END ();
-       
-       return domain;
 }
 
 MonoJitStats mono_jit_stats = {0};
@@ -7783,9 +7861,9 @@ mini_cleanup (MonoDomain *domain)
 
        mono_native_tls_free (mono_jit_tls_id);
 
-       DeleteCriticalSection (&jit_mutex);
+       mono_mutex_destroy (&jit_mutex);
 
-       DeleteCriticalSection (&mono_delegate_section);
+       mono_mutex_destroy (&mono_delegate_section);
 
        mono_code_manager_cleanup ();
 
@@ -7955,16 +8033,6 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
 
 #endif
 
-#ifndef MONO_ARCH_HAVE_OPCODE_SUPPORTED
-
-gboolean
-mono_arch_opcode_supported (int opcode)
-{
-       return TRUE;
-}
-
-#endif
-
 #if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(ENABLE_GSHAREDVT)
 
 gboolean
@@ -7992,10 +8060,10 @@ typedef struct MonoJumpTableChunk {
        /* gpointer entries[total]; */
 } MonoJumpTableChunk;
 
-static MonoJumpTableChunk* g_jumptable = NULL;
-#define mono_jumptable_lock() EnterCriticalSection (&jumptable_mutex)
-#define mono_jumptable_unlock() LeaveCriticalSection (&jumptable_mutex)
-static CRITICAL_SECTION jumptable_mutex;
+static MonoJumpTableChunk* g_jumptable;
+#define mono_jumptable_lock() mono_mutex_lock (&jumptable_mutex)
+#define mono_jumptable_unlock() mono_mutex_unlock (&jumptable_mutex)
+static mono_mutex_t jumptable_mutex;
 
 static  MonoJumpTableChunk*
 mono_create_jumptable_chunk (guint32 max_entries)
@@ -8010,7 +8078,7 @@ void
 mono_jumptable_init (void)
 {
        if (g_jumptable == NULL) {
-               InitializeCriticalSection (&jumptable_mutex);
+               mono_mutex_init_recursive (&jumptable_mutex);
                g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS);
        }
 }
@@ -8066,7 +8134,7 @@ mono_jumptable_cleanup (void)
                        current = prev;
                }
                g_jumptable = NULL;
-               DeleteCriticalSection (&jumptable_mutex);
+               mono_mutex_destroy (&jumptable_mutex);
        }
 }