#include <mono/metadata/attach.h>
#include <mono/metadata/runtime.h>
#include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/monitor.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-counters.h>
mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name);
}
+static void
+register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr)
+{
+ MonoMethodSignature *sig;
+
+ if (sigstr)
+ sig = mono_create_icall_signature (sigstr);
+ else
+ sig = NULL;
+
+ mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL);
+}
+
static void
register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
{
* mono_get_lmf_addr, and mono_get_lmf_addr requires the thread to be attached.
*/
- mono_jit_thread_attach (NULL);
+ mono_thread_attach (mono_get_root_domain ());
+ mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id)))
return &jit_tls->lmf;
}
/*
- * mono_jit_thread_attach:
+ * mono_jit_thread_attach: called by native->managed wrappers
*
- * Called by native->managed wrappers. Returns the original domain which needs to be
- * restored, or NULL.
+ * In non-coop mode:
+ * - @dummy: is NULL
+ * - @return: the original domain which needs to be restored, or NULL.
+ *
+ * In coop mode:
+ * - @dummy: contains the original domain
+ * - @return: a cookie containing current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise
*/
-MonoDomain*
-mono_jit_thread_attach (MonoDomain *domain)
+gpointer
+mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy)
{
MonoDomain *orig;
- if (!domain)
- /*
- * Happens when called from AOTed code which is only used in the root
- * domain.
- */
+ if (!domain) {
+ /* Happens when called from AOTed code which is only used in the root domain. */
domain = mono_get_root_domain ();
+ }
+
+ g_assert (domain);
+
+ if (!mono_threads_is_coop_enabled ()) {
+ gboolean attached;
#ifdef MONO_HAVE_FAST_TLS
- if (!MONO_FAST_TLS_GET (mono_lmf_addr)) {
- mono_thread_attach (domain);
- // #678164
- mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
- }
+ attached = MONO_FAST_TLS_GET (mono_lmf_addr) != NULL;
#else
- if (!mono_native_tls_get_value (mono_jit_tls_id)) {
- mono_thread_attach (domain);
- mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
- }
+ attached = mono_native_tls_get_value (mono_jit_tls_id) != NULL;
#endif
- orig = mono_domain_get ();
- if (orig != domain)
- mono_domain_set (domain, TRUE);
- return orig != domain ? orig : NULL;
+ if (!attached) {
+ mono_thread_attach (domain);
+
+ // #678164
+ mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
+ }
+
+ orig = mono_domain_get ();
+ if (orig != domain)
+ mono_domain_set (domain, TRUE);
+
+ return orig != domain ? orig : NULL;
+ } else {
+ MonoThreadInfo *info;
+
+ info = mono_thread_info_current_unchecked ();
+ if (!info || !mono_thread_info_is_live (info)) {
+ /* thread state STARTING -> RUNNING */
+ mono_thread_attach (domain);
+
+ // #678164
+ mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
+
+ *dummy = NULL;
+
+ /* mono_threads_reset_blocking_start returns the current MonoThreadInfo
+ * if we were in BLOCKING mode */
+ return mono_thread_info_current ();
+ } else {
+ orig = mono_domain_get ();
+
+ /* orig might be null if we did an attach -> detach -> attach sequence */
+
+ if (orig != domain)
+ mono_domain_set (domain, TRUE);
+
+ *dummy = orig;
+
+ /* thread state (BLOCKING|RUNNING) -> RUNNING */
+ return mono_threads_reset_blocking_start (dummy);
+ }
+ }
}
-/* Called by native->managed wrappers */
+/*
+ * mono_jit_thread_detach: called by native->managed wrappers
+ *
+ * In non-coop mode:
+ * - @cookie: the original domain which needs to be restored, or NULL.
+ * - @dummy: is NULL
+ *
+ * In coop mode:
+ * - @cookie: contains current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise
+ * - @dummy: contains the original domain
+ */
void
-mono_jit_set_domain (MonoDomain *domain)
+mono_jit_thread_detach (gpointer cookie, gpointer *dummy)
{
- if (domain)
- mono_domain_set (domain, TRUE);
+ MonoDomain *domain, *orig;
+
+ if (!mono_threads_is_coop_enabled ()) {
+ orig = (MonoDomain*) cookie;
+
+ if (orig)
+ mono_domain_set (orig, TRUE);
+ } else {
+ orig = (MonoDomain*) *dummy;
+
+ domain = mono_domain_get ();
+ g_assert (domain);
+
+ /* it won't do anything if cookie is NULL
+ * thread state RUNNING -> (RUNNING|BLOCKING) */
+ mono_threads_reset_blocking_end (cookie, dummy);
+
+ if (orig != domain) {
+ if (!orig)
+ mono_domain_unset ();
+ else
+ mono_domain_set (orig, TRUE);
+ }
+ }
}
/**
}
gpointer
-mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors)
+mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors, MonoError *error)
{
unsigned char *ip = patch_info->ip.i + code;
gconstpointer target = NULL;
+ mono_error_init (error);
+
switch (patch_info->type) {
case MONO_PATCH_INFO_BB:
/*
case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
gpointer handle;
MonoClass *handle_class;
- MonoError error;
handle = mono_ldtoken_checked (patch_info->data.token->image,
- patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, &error);
- if (!mono_error_ok (&error))
- g_error ("Could not patch ldtoken due to %s", mono_error_get_message (&error));
+ patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
+ if (!mono_error_ok (error))
+ g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
mono_class_init (handle_class);
mono_class_init (mono_class_from_mono_type ((MonoType *)handle));
- target = mono_type_get_object_checked (domain, (MonoType *)handle, &error);
- mono_error_raise_exception (&error);
-
+ target = mono_type_get_object_checked (domain, (MonoType *)handle, error);
+ if (!mono_error_ok (error))
+ return NULL;
break;
}
case MONO_PATCH_INFO_LDTOKEN: {
gpointer handle;
MonoClass *handle_class;
- MonoError error;
handle = mono_ldtoken_checked (patch_info->data.token->image,
- patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, &error);
- if (!mono_error_ok (&error))
- g_error ("Could not patch ldtoken due to %s", mono_error_get_message (&error));
+ patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
+ if (!mono_error_ok (error))
+ g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
mono_class_init (handle_class);
target = handle;
if (run_cctors) {
target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
if (!target) {
- if (mono_aot_only)
- mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
+ if (mono_aot_only) {
+ mono_error_set_exception_instance (error, mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
+ return NULL;
+ }
g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
}
} else {
}
static MonoObject*
-mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc)
+mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error)
{
MonoMethodSignature *sig = info->sig;
MonoDomain *domain = mono_domain_get ();
gpointer *param_refs;
int i, pindex;
+ mono_error_init (error);
+
g_assert (info->gsharedvt_invoke);
/*
runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
runtime_invoke (NULL, args, exc, info->compiled_method);
+ if (exc && *exc)
+ mono_error_set_exception_instance (error, (MonoException*) *exc);
if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
return mono_value_box (domain, info->ret_box_class, retval);
* @method: the method to invoke
* @obj: this pointer
* @params: array of parameter values.
- * @error: error
- * @exc: used to catch exceptions objects
+ * @exc: Set to the exception raised in the managed method. If NULL, error is thrown instead.
+ * If coop is enabled, this argument is ignored - all exceptoins are caught and propagated
+ * through @error
+ * @error: error or caught exception object
*/
static MonoObject*
-mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoError *error, MonoObject **exc)
+mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
{
MonoMethod *invoke, *callee;
MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
*/
mono_class_setup_vtable (method->klass);
if (method->klass->exception_type != MONO_EXCEPTION_NONE) {
+ MonoException *fail_exc = mono_class_get_exception_for_failure (method->klass);
if (exc)
- *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
- else
- mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
+ *exc = (MonoObject*)fail_exc;
+ mono_error_set_exception_instance (error, fail_exc);
return NULL;
}
}
* We need this here because mono_marshal_get_runtime_invoke can place
* the helper method in System.Object and not the target class.
*/
- if (exc) {
+ if (exc)
+ {
*exc = (MonoObject*)mono_runtime_class_init_full (info->vtable, FALSE);
- if (*exc)
+ if (*exc) {
+ mono_error_set_exception_instance (error, (MonoException*) *exc);
return NULL;
+ }
} else {
mono_runtime_class_init (info->vtable);
}
+ /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
+ we always catch the exception and propagate it through the MonoError */
+ gboolean catchExcInMonoError =
+ (exc == NULL) && mono_threads_is_coop_enabled ();
+ MonoObject *invoke_exc = NULL;
+ if (catchExcInMonoError)
+ exc = &invoke_exc;
+
/* The wrappers expect this to be initialized to NULL */
if (exc)
*exc = NULL;
mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
dyn_runtime_invoke (buf, exc, info->compiled_method);
+ if (catchExcInMonoError && *exc != NULL)
+ mono_error_set_exception_instance (error, (MonoException*) *exc);
mono_arch_finish_dyn_call (info->dyn_call_info, buf);
#endif
if (mono_llvm_only)
- return mono_llvmonly_runtime_invoke (method, info, obj, params, exc);
+ return mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
- return runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+ MonoObject *result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
+ if (catchExcInMonoError && *exc != NULL)
+ mono_error_set_exception_instance (error, (MonoException*) *exc);
+ return result;
}
typedef struct {
mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
+ mono_counters_register ("JIT/method-to-IR (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
+ mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
+ mono_counters_register ("JIT/handle_out_of_line_bblock (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_out_of_line_bblock);
+ mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
+ mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop);
+ mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops);
+ mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches);
+ mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs);
+ mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce);
+ mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis);
+ mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion);
+ mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering);
+ mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info);
+ mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops);
+ mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints);
+ mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute);
+ mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop);
+ mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce);
+ mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal);
+ mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove);
+ mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2);
+ mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2);
+ mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2);
+ mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2);
+ mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts);
+ mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts);
+ mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2);
+ mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness);
+ mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
+ mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
+ mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
+ mono_counters_register ("JIT/jit_local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
+ mono_counters_register ("JIT/jit_local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
+ mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
+ mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
+ mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
+ mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info);
mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
MonoDomain *
mini_init (const char *filename, const char *runtime_version)
{
+ MonoError error;
MonoDomain *domain;
MonoRuntimeCallbacks callbacks;
MonoThreadInfoRuntimeCallbacks ticallbacks;
#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_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
+ mono_error_assert_ok (&error);
mono_thread_attach (domain);
#endif
register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
- register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
- register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
+ register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr ptr", TRUE);
+ register_icall (mono_jit_thread_detach, "mono_jit_thread_detach", "void ptr ptr", TRUE);
register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE);
register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE);
register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE);
register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE);
- register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", FALSE);
+ register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE);
#if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE);
register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
- register_icall_no_wrapper (mono_llvmonly_set_calling_assembly, "mono_llvmonly_set_calling_assembly", "void ptr");
- register_icall_no_wrapper (mono_llvmonly_get_calling_assembly, "mono_llvmonly_get_calling_assembly", "object");
/* This needs a wrapper so it can have a preserveall cconv */
register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE);
register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
+ register_icall_with_wrapper (mono_monitor_enter, "mono_monitor_enter", "void obj");
+ register_icall_with_wrapper (mono_monitor_enter_v4, "mono_monitor_enter_v4", "void obj ptr");
+ register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
+ register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
+
#ifdef TARGET_IOS
register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
#endif