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;
*/
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;
static GSList *tramp_infos;
+static void register_icalls (void);
+
gpointer
mono_realloc_native_code (MonoCompile *cfg)
{
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;
static MonoMethodSignature *
mono_get_array_new_va_signature (int arity)
{
- static GHashTable *sighash = NULL;
+ static GHashTable *sighash;
MonoMethodSignature *res;
int i;
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)))
} 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)
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)
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
#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)
{
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));
/* 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");
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;
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: {
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);
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) {
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;
}
}
- /*
- * 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;
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;
}
#if ENABLE_JIT_MAP
-static FILE* perf_map_file = NULL;
+static FILE* perf_map_file;
void
mono_enable_jit_map (void)
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 */
// 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;
mono_emit_jit_map (jinfo);
#endif
mono_domain_unlock (target_domain);
- mono_loader_unlock ();
vtable = mono_class_vtable (target_domain, method->klass);
if (!vtable) {
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);
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)
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 ()) {
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;
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);
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));
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);
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)
{
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);
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)
}
#endif
- InitializeCriticalSection (&jit_mutex);
+ mono_mutex_init_recursive (&jit_mutex);
+
+ mono_cross_helpers_run ();
/* Happens when using the embedding interface */
if (!default_opt_set)
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;
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);
mono_threads_runtime_init (&ticallbacks);
-
if (g_getenv ("MONO_DEBUG") != NULL)
mini_parse_debug_options ();
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)
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);
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 ();
/* 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",
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
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};
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 ();
#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
/* 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)
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);
}
}
current = prev;
}
g_jumptable = NULL;
- DeleteCriticalSection (&jumptable_mutex);
+ mono_mutex_destroy (&jumptable_mutex);
}
}