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 = TRUE;
+
const char *mono_build_date;
gboolean mono_do_signal_chaining;
gboolean mono_do_crash_chaining;
FindTrampUserData user_data;
MonoGenericSharingContext*gsctx;
const char *shared_type;
- GSList *l;
- ji = mini_jit_info_table_find (domain, ip, &target_domain);
+ ji = mini_jit_info_table_find_ext (domain, ip, TRUE, &target_domain);
+ if (ji && ji->is_trampoline) {
+ MonoTrampInfo *tinfo = ji->d.tramp_info;
+
+ printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
+ return;
+ }
+
if (!ji) {
user_data.ip = ip;
user_data.method = NULL;
mono_domain_lock (domain);
g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
mono_domain_unlock (domain);
+
if (user_data.method) {
char *mname = mono_method_full_name (user_data.method, TRUE);
printf ("IP %p is a JIT trampoline for %s\n", ip, mname);
g_free (mname);
return;
}
- for (l = tramp_infos; l; l = l->next) {
- MonoTrampInfo *tinfo = l->data;
-
- if ((guint8*)ip >= tinfo->code && (guint8*)ip <= tinfo->code + tinfo->code_size) {
- printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
- return;
- }
- }
g_print ("No method at %p\n", ip);
fflush (stdout);
g_free (info);
}
+static void
+register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
+{
+ MonoJitInfo *ji;
+
+ ji = mono_domain_alloc0 (domain, mono_jit_info_size (0, 0, 0));
+ 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
+
+ mono_jit_info_table_add (domain, ji);
+}
+
/*
* mono_tramp_info_register:
*
mono_save_trampoline_xdebug_info (info);
+ if (mono_get_root_domain ())
+ register_trampoline_jit_info (mono_get_root_domain (), copy);
+
if (mono_jit_map_is_enabled ())
mono_emit_jit_tramp (info->code, info->code_size, info->name);
g_slist_free (tramp_infos);
}
+/* Register trampolines created before the root domain was created in the jit info tables */
+static void
+register_trampolines (MonoDomain *domain)
+{
+ GSList *l;
+
+ for (l = tramp_infos; l; l = l->next) {
+ MonoTrampInfo *info = l->data;
+
+ register_trampoline_jit_info (domain, info);
+ }
+}
+
G_GNUC_UNUSED static void
break_count (void)
{
static void
mono_thread_start_cb (intptr_t tid, gpointer stack_start, gpointer func)
{
- MonoInternalThread *thread;
+ MonoThreadInfo *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
- thread = mono_thread_internal_current ();
+ thread = mono_thread_info_current_unchecked ();
if (thread)
thread->jit_data = jit_tls;
static void
mono_thread_attach_cb (intptr_t tid, gpointer stack_start)
{
- MonoInternalThread *thread;
+ MonoThreadInfo *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
- thread = mono_thread_internal_current ();
+ thread = mono_thread_info_current_unchecked ();
if (thread)
thread->jit_data = jit_tls;
if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
}
static void
-mini_thread_cleanup (MonoInternalThread *thread)
+mini_thread_cleanup (MonoNativeThreadId tid)
{
- MonoJitTlsData *jit_tls = thread->jit_data;
+ MonoJitTlsData *jit_tls = NULL;
+ MonoThreadInfo *info;
- if (jit_tls) {
- /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
- * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
- * not a trivial thing.
- *
- * The current offender is mono_thread_manage which cleanup threads from the outside.
- */
- if (thread == mono_thread_internal_current ())
- mono_set_jit_tls (NULL);
+ info = mono_thread_info_current_unchecked ();
+
+ /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
+ * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
+ * not a trivial thing.
+ *
+ * The current offender is mono_thread_manage which cleanup threads from the outside.
+ */
+ if (info && mono_thread_info_get_tid (info) == tid) {
+ jit_tls = info->jit_data;
+ info->jit_data = NULL;
+
+ mono_set_jit_tls (NULL);
/* If we attach a thread but never call into managed land, we might never get an lmf.*/
if (mono_get_lmf ()) {
mono_set_lmf (NULL);
mono_set_lmf_addr (NULL);
}
+ } else {
+ info = mono_thread_info_lookup (tid);
+ if (info) {
+ jit_tls = info->jit_data;
+ info->jit_data = NULL;
+ }
+ mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
+ }
+ if (jit_tls)
free_jit_tls_data (jit_tls);
-
- thread->jit_data = NULL;
- }
}
int
//memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
break;
}
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info;
+ MonoJumpInfoVirtMethod *oinfo;
+
+ oinfo = patch_info->data.virt_method;
+ info = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
+ res->data.virt_method = info;
+ memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
+ break;
+ }
default:
break;
}
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
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);
case MONO_PATCH_INFO_CASTCLASS_CACHE:
return (ji->type << 8) | (ji->data.index);
return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->virtual;
case MONO_PATCH_INFO_LDSTR_LIT:
return g_str_hash (ji->data.target);
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info = ji->data.virt_method;
+
+ return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
+ }
default:
printf ("info type: %d\n", ji->type);
mono_print_ji (ji); printf ("\n");
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;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
return ji1->data.index == ji2->data.index;
+ case MONO_PATCH_INFO_VIRT_METHOD:
+ return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
default:
if (ji1->data.target != ji2->data.target)
return 0;
target = code_slot;
break;
}
+ case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+#if defined(__native_client_codegen__)
+ target = (gpointer)&__nacl_thread_suspension_needed;
+#elif defined (USE_COOP_GC)
+ target = (gpointer)&mono_polling_required;
+#else
+ g_error ("Unsuported patch target");
+#endif
+ break;
case MONO_PATCH_INFO_SWITCH: {
gpointer *jump_table;
int i;
slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
break;
}
+ case MONO_PATCH_INFO_VIRT_METHOD: {
+ MonoJumpInfoVirtMethod *info;
+ MonoJumpInfoVirtMethod *oinfo = entry->data->data.virt_method;
+
+ info = g_malloc0 (sizeof (MonoJumpInfoVirtMethod));
+ memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, info, entry->info_type, mono_method_get_context (entry->method));
+ break;
+ }
default:
g_assert_not_reached ();
break;
target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
break;
}
+ case MONO_PATCH_INFO_GC_NURSERY_START: {
+ int shift_bits;
+ size_t size;
+
+ target = mono_gc_get_nursery (&shift_bits, &size);
+ break;
+ }
case MONO_PATCH_INFO_CASTCLASS_CACHE: {
target = mono_domain_alloc0 (domain, sizeof (gpointer));
break;
return (gpointer)target;
}
-static gboolean
-is_gsharedvt_type (MonoType *t)
-{
- return (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->gshared_constraint == MONO_TYPE_VALUETYPE;
-}
-
void
mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
{
for (i = 0; i < inst->type_argc; ++i) {
MonoType *type = inst->type_argv [i];
- if (is_gsharedvt_type (type))
+ if (mini_is_gsharedvt_gparam (type))
gsctx->var_is_vt [i] = TRUE;
}
}
for (i = 0; i < inst->type_argc; ++i) {
MonoType *type = inst->type_argv [i];
- if (is_gsharedvt_type (type))
+ if (mini_is_gsharedvt_gparam (type))
gsctx->mvar_is_vt [i] = TRUE;
}
}
return ji;
}
+MonoJitInfo *
+mono_get_jit_info_from_method (MonoDomain *domain, MonoMethod *method)
+{
+ return lookup_method (domain, method);
+}
+
#if ENABLE_JIT_MAP
static FILE* perf_map_file;
else if (!strcmp (arg, "explicit-null-checks"))
debug_options.explicit_null_checks = TRUE;
else if (!strcmp (arg, "gen-seq-points"))
- debug_options.gen_seq_points_debug_data = TRUE;
+ 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, "init-stacks"))
debug_options.check_pinvoke_callconv = TRUE;
else if (!strcmp (arg, "debug-domain-unload"))
mono_enable_debug_domain_unload (TRUE);
+ else if (!strcmp (arg, "partial-sharing"))
+ mono_set_partial_sharing_supported (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'\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', 'debug-domain-unload', 'partial-sharing'\n");
exit (1);
}
}
callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
callbacks.tls_key_supported = mini_tls_key_supported;
- if (mono_use_imt) {
- callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
- callbacks.get_imt_trampoline = mini_get_imt_trampoline;
- }
+ callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
+ callbacks.get_imt_trampoline = mini_get_imt_trampoline;
mono_install_callbacks (&callbacks);
mono_unwind_init ();
+#ifdef XDEBUG_ENABLED
if (g_getenv ("MONO_XDEBUG")) {
const char *xdebug_opts = g_getenv ("MONO_XDEBUG");
mono_xdebug_init (xdebug_opts);
mono_dont_free_domains = TRUE;
mono_using_xdebug = TRUE;
}
+#endif
#ifdef ENABLE_LLVM
if (mono_use_llvm) {
mono_marshal_use_aot_wrappers (TRUE);
}
- 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);
- }
+ 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);
/*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_tasklets_init ();
#endif
+ register_trampolines (domain);
+
if (mono_compile_aot)
/*
* Avoid running managed code when AOT compiling, since the platform
#if defined(__native_client__) || defined(__native_client_codegen__)
register_icall (mono_nacl_gc, "mono_nacl_gc", "void", TRUE);
#endif
+#if defined(USE_COOP_GC)
+ register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", TRUE);
+#endif
+
#ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", TRUE);
register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);