#include <mono/utils/dtrace.h>
#include <mono/utils/mono-signal-handler.h>
#include <mono/utils/mono-threads.h>
+#include <mono/utils/checked-build.h>
#include <mono/io-layer/io-layer.h>
#include "mini.h"
gboolean
mono_running_on_valgrind (void)
{
+#ifndef HOST_WIN32
if (RUNNING_ON_VALGRIND){
#ifdef VALGRIND_JIT_REGISTER_MAP
valgrind_register = TRUE;
#endif
return TRUE;
} else
+#endif
return FALSE;
}
if (!domain)
domain = mono_get_root_domain ();
- ji = mono_jit_info_table_find (domain, ip);
+ ji = mono_jit_info_table_find_internal (domain, ip, TRUE, TRUE);
if (!ji) {
user_data.ip = ip;
user_data.method = NULL;
}
else
return NULL;
+ } else if (ji->is_trampoline) {
+ res = g_strdup_printf ("<%p - %s trampoline>", ip, ((MonoTrampInfo*)ji->d.tramp_info)->name);
+ return res;
}
+
method = mono_method_full_name (jinfo_get_method (ji), TRUE);
/* FIXME: unused ? */
location = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
{
MonoMethod *cmethod;
- if (!caller || !callee)
+ if (!caller || caller->is_trampoline || !callee || callee->is_trampoline)
return FALSE;
/*
void
mono_tramp_info_free (MonoTrampInfo *info)
{
- GSList *l;
-
g_free (info->name);
// FIXME: ji
- for (l = info->unwind_ops; l; l = l->next)
- g_free (l->data);
- g_slist_free (info->unwind_ops);
+ mono_free_unwind_info (info->unwind_ops);
g_free (info);
}
mono_jit_info_init (ji, NULL, info->code, info->code_size, 0, 0, 0);
ji->d.tramp_info = info;
ji->is_trampoline = TRUE;
- // FIXME: Unwind info
+
+ ji->unwind_info = mono_cache_unwind_info (info->uw_info, info->uw_info_len);
mono_jit_info_table_add (domain, ji);
}
* Frees INFO.
*/
void
-mono_tramp_info_register (MonoTrampInfo *info)
+mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
{
MonoTrampInfo *copy;
if (!info)
return;
+ if (!domain)
+ domain = mono_get_root_domain ();
+
copy = g_new0 (MonoTrampInfo, 1);
copy->code = info->code;
copy->code_size = info->code_size;
copy->name = g_strdup (info->name);
+ if (info->unwind_ops) {
+ copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, ©->uw_info_len);
+ } else {
+ /* Trampolines from aot have the unwind ops already encoded */
+ copy->uw_info = info->uw_info;
+ copy->uw_info_len = info->uw_info_len;
+ }
+
mono_jit_lock ();
tramp_infos = g_slist_prepend (tramp_infos, copy);
mono_jit_unlock ();
mono_save_trampoline_xdebug_info (info);
- if (mono_get_root_domain ())
- register_trampoline_jit_info (mono_get_root_domain (), copy);
+ /* Only register trampolines that have unwind infos */
+ if (mono_get_root_domain () && copy->uw_info)
+ register_trampoline_jit_info (domain, copy);
if (mono_jit_map_is_enabled ())
mono_emit_jit_tramp (info->code, info->code_size, info->name);
MonoMethod *wrapper;
gconstpointer trampoline;
MonoDomain *domain = mono_get_root_domain ();
- gboolean check_exc = check_for_pending_exc;
+ gboolean check_exc = TRUE;
- if (callinfo->wrapper) {
+ if (callinfo->wrapper)
return callinfo->wrapper;
- }
if (callinfo->trampoline)
return callinfo->trampoline;
- /*
- * We use the lock on the root domain instead of the JIT lock to protect
- * callinfo->trampoline, since we do a lot of stuff inside the critical section.
- */
- mono_loader_lock (); /*FIXME mono_compile_method requires the loader lock, by large.*/
- mono_domain_lock (domain);
-
- if (callinfo->trampoline) {
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- return callinfo->trampoline;
- }
-
if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
/* This icall is used to check for exceptions, so don't check in the wrapper */
check_exc = FALSE;
trampoline = mono_compile_method (wrapper);
else
trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
- mono_register_jit_icall_wrapper (callinfo, trampoline);
-
- callinfo->trampoline = trampoline;
- mono_domain_unlock (domain);
+ mono_loader_lock ();
+ if (!callinfo->trampoline) {
+ mono_register_jit_icall_wrapper (callinfo, trampoline);
+ callinfo->trampoline = trampoline;
+ }
mono_loader_unlock ();
return callinfo->trampoline;
static void
register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
{
- return mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
+#ifndef DISABLE_JIT
+ mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
+#endif
}
/*
mini_get_tls_offset (MonoTlsKey key)
{
int offset;
+ g_assert (MONO_ARCH_HAVE_TLS_GET);
switch (key) {
case TLS_KEY_THREAD:
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IID:
case MONO_PATCH_INFO_ADJUSTED_IID:
- case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_METHODCONST:
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_METHOD_JUMP:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_JIT_TLS_ID:
- case MONO_PATCH_INFO_MONITOR_ENTER:
- case MONO_PATCH_INFO_MONITOR_ENTER_V4:
- case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GOT_OFFSET:
case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
return (ji->type << 8);
target = mono_class_vtable (domain, patch_info->data.klass);
g_assert (target);
break;
- case MONO_PATCH_INFO_CLASS_INIT: {
- MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.klass);
-
- g_assert (vtable);
- target = mono_create_class_init_trampoline (vtable);
- break;
- }
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
target = mono_create_rgctx_lazy_fetch_trampoline (slot);
break;
}
- case MONO_PATCH_INFO_MONITOR_ENTER:
- target = mono_create_monitor_enter_trampoline ();
- break;
- case MONO_PATCH_INFO_MONITOR_ENTER_V4:
- target = mono_create_monitor_enter_v4_trampoline ();
- break;
- case MONO_PATCH_INFO_MONITOR_EXIT:
- target = mono_create_monitor_exit_trampoline ();
- break;
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
case MONO_PATCH_INFO_SEQ_POINT_INFO:
if (!run_cctors)
mono_internal_hash_table_remove (&domain->jit_code_hash, method);
mono_domain_jit_code_hash_unlock (domain);
g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
+
+ /* requires the domain lock - took above */
mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
/* Remove jump targets in this method */
return NULL;
} else {
mono_raise_exception (jit_ex);
+ /* coverity[unreachable] */
}
}
- info->compiled_method = mini_add_method_trampoline (NULL, callee, info->compiled_method, mono_method_needs_static_rgctx_invoke (callee, FALSE), FALSE);
+ info->compiled_method = mini_add_method_trampoline (callee, info->compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
} else {
info->compiled_method = NULL;
}
if (!info->dyn_call_info)
info->runtime_invoke = mono_jit_compile_method (invoke);
+ mono_domain_lock (domain);
info2 = mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
+ mono_domain_unlock (domain);
if (info2) {
g_free (info);
info = info2;
MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
MONO_SIG_HANDLER_GET_CONTEXT;
- ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
+ ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
#if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
if (mono_arch_is_int_overflow (ctx, info))
}
#endif
- ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
+ ji = mono_jit_info_table_find_internal (mono_domain_get (), mono_arch_ip_from_context (ctx), TRUE, TRUE);
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
/* FIXME Support more cases */
if (mono_aot_only) {
char tramp_name [256];
+ const char *imt = load_imt_reg ? "_imt" : "";
+ int ind = (load_imt_reg ? (-offset) : offset) / SIZEOF_VOID_P;
- sprintf (tramp_name, "delegate_virtual_invoke%s_%d", load_imt_reg ? "_imt" : "", offset / SIZEOF_VOID_P);
+ sprintf (tramp_name, "delegate_virtual_invoke%s_%d", imt, ind);
cache [idx] = mono_aot_get_trampoline (tramp_name);
g_assert (cache [idx]);
} else {
debug_options.gen_sdb_seq_points = TRUE;
else if (!strcmp (arg, "gen-compact-seq-points"))
debug_options.gen_seq_points_compact_data = TRUE;
+ else if (!strcmp (arg, "single-imm-size"))
+ debug_options.single_imm_size = TRUE;
else if (!strcmp (arg, "init-stacks"))
debug_options.init_stacks = TRUE;
else if (!strcmp (arg, "casts"))
debug_options.soft_breakpoints = TRUE;
else if (!strcmp (arg, "check-pinvoke-callconv"))
debug_options.check_pinvoke_callconv = TRUE;
+ else if (!strcmp (arg, "arm-use-fallback-tls"))
+ debug_options.arm_use_fallback_tls = TRUE;
else if (!strcmp (arg, "debug-domain-unload"))
mono_enable_debug_domain_unload (TRUE);
else if (!strcmp (arg, "partial-sharing"))
mono_align_small_structs = TRUE;
else {
fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
- fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'debug-domain-unload', 'partial-sharing', 'align-small-structs'\n");
+ fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'arm-use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs'\n");
exit (1);
}
}
{
MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
- info->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
- info->runtime_invoke_hash = mono_conc_hashtable_new_full (&domain->lock, mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
+ info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->jump_target_hash = g_hash_table_new (NULL, NULL);
}
if (info->method_code_hash)
g_hash_table_destroy (info->method_code_hash);
- g_hash_table_destroy (info->class_init_trampoline_hash);
g_hash_table_destroy (info->jump_trampoline_hash);
g_hash_table_destroy (info->jit_trampoline_hash);
g_hash_table_destroy (info->delegate_trampoline_hash);
MONO_VES_INIT_BEGIN ();
+ CHECKED_MONO_INIT ();
+
#if defined(__linux__) && !defined(__native_client__)
if (access ("/proc/self/maps", F_OK) != 0) {
g_print ("Mono requires /proc to be mounted.\n");
ticallbacks.setup_async_callback = mono_setup_async_callback;
ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
+ ticallbacks.thread_state_init = mono_thread_state_init;
mono_counters_init ();
#endif
mono_threads_install_cleanup (mini_thread_cleanup);
-#ifdef MONO_ARCH_HAVE_NOTIFY_PENDING_EXC
- check_for_pending_exc = FALSE;
- mono_threads_install_notify_pending_exc ((MonoThreadNotifyPendingExcFunc)mono_arch_notify_pending_exc);
-#endif
-
#define JIT_TRAMPOLINES_WORK
#ifdef JIT_TRAMPOLINES_WORK
mono_install_compile_method (mono_jit_compile_method);
ves_icall_get_frame_info);
mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
ves_icall_get_trace);
- mono_add_internal_call ("System.Exception::get_trace",
- ves_icall_System_Exception_get_trace);
mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
mono_runtime_install_handlers);
#endif
register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
+ register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
+
#ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
#endif
+
#ifdef MONO_ARCH_EMULATE_CONV_R8_UN
register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, "mono_conv_to_r8_un", FALSE);
#endif
register_icall (mono_fill_method_rgctx, "mono_method_fill_rgctx", "ptr ptr int", FALSE);
register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
- register_dyn_icall (mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL),
- "specific_trampoline_generic_class_init", "void", TRUE);
#ifdef TARGET_IOS
register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
#ifndef MONO_CROSS_COMPILE
mono_domain_free (domain, TRUE);
+ mono_gc_mutex_cleanup ();
#endif
#ifdef ENABLE_LLVM
mono_mutex_destroy (&jit_mutex);
- mono_mutex_destroy (&mono_delegate_section);
-
mono_code_manager_cleanup ();
#ifdef USE_JUMP_TABLES
g_hash_table_destroy (assemblies);
}
+/*
+ * Used by LLVM.
+ * Have to export this for AOT.
+ */
+void
+mono_personality (void)
+{
+ /* Not used */
+ g_assert_not_reached ();
+}
+
#ifdef USE_JUMP_TABLES
#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128