* Dietmar Maurer (dietmar@ximian.com)
*
* Copyright 2002-2003 Ximian, Inc.
- * Coprygith 2003-2010 Novell, Inc.
+ * Copyright 2003-2010 Novell, Inc.
*/
#define MONO_LLVM_IN_MINI 1
MINI_FAST_TLS_DECLARE(mono_jit_tls);
#endif
+#ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
+#define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1
+#endif
+
MonoTraceSpec *mono_jit_trace_calls = NULL;
gboolean mono_break_on_exc = FALSE;
gboolean mono_compile_aot = FALSE;
* output. Unlike mono_pmip which returns a string, this routine
* prints the value on the standard output.
*/
+#ifdef __GNUC__
+/* Prevent the linker from optimizing this away in embedding setups to help debugging */
+ __attribute__((used))
+#endif
void
mono_print_method_from_ip (void *ip)
{
inst->backend.is_pinvoke = 0;
inst->dreg = vreg;
+ if (cfg->compute_gc_maps) {
+ if (type->byref) {
+ mono_mark_vreg_as_mp (cfg, vreg);
+ } else {
+ MonoType *t = mini_type_get_underlying_type (NULL, type);
+ if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || MONO_TYPE_IS_REFERENCE (t)) {
+ inst->flags |= MONO_INST_GC_TRACK;
+ mono_mark_vreg_as_ref (cfg, vreg);
+ }
+ }
+ }
+
cfg->varinfo [num] = inst;
MONO_INIT_VARINFO (&cfg->vars [num], num);
#endif
+void
+mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg)
+{
+ if (vreg >= cfg->vreg_is_ref_len) {
+ gboolean *tmp = cfg->vreg_is_ref;
+ int size = cfg->vreg_is_ref_len;
+
+ while (vreg >= cfg->vreg_is_ref_len)
+ cfg->vreg_is_ref_len = cfg->vreg_is_ref_len ? cfg->vreg_is_ref_len * 2 : 32;
+ cfg->vreg_is_ref = mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_ref_len);
+ if (size)
+ memcpy (cfg->vreg_is_ref, tmp, size * sizeof (gboolean));
+ }
+ cfg->vreg_is_ref [vreg] = TRUE;
+}
+
+void
+mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg)
+{
+ if (vreg >= cfg->vreg_is_mp_len) {
+ gboolean *tmp = cfg->vreg_is_mp;
+ int size = cfg->vreg_is_mp_len;
+
+ while (vreg >= cfg->vreg_is_mp_len)
+ cfg->vreg_is_mp_len = cfg->vreg_is_mp_len ? cfg->vreg_is_mp_len * 2 : 32;
+ cfg->vreg_is_mp = mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_mp_len);
+ if (size)
+ memcpy (cfg->vreg_is_mp, tmp, size * sizeof (gboolean));
+ }
+ cfg->vreg_is_mp [vreg] = TRUE;
+}
+
static MonoType*
type_from_stack_type (MonoInst *ins) {
switch (ins->type) {
if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
return jit_tls->lmf;
-
- g_assert_not_reached ();
+ /*
+ * We do not assert here because this function can be called from
+ * mini-gc.c on a thread that has not executed any managed code, yet
+ * (the thread object allocation can trigger a collection).
+ */
return NULL;
#endif
}
switch (ji->type) {
case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
- case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
case MONO_PATCH_INFO_DECLSEC:
return (ji->type << 8) | ji->data.token->token;
+ case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
+ return (ji->type << 8) | ji->data.token->token | (ji->data.token->has_context ? (gsize)ji->data.token->context.class_inst : 0);
case MONO_PATCH_INFO_INTERNAL_METHOD:
return (ji->type << 8) | g_str_hash (ji->data.name);
case MONO_PATCH_INFO_VTABLE:
target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
break;
}
+ case MONO_PATCH_INFO_CASTCLASS_CACHE: {
+ target = mono_domain_alloc0 (domain, sizeof (gpointer));
+ break;
+ }
default:
g_assert_not_reached ();
}
MonoBasicBlock *bb;
int max_epilog_size;
guint8 *code;
+ MonoDomain *code_domain;
+
+ if (mono_using_xdebug)
+ /*
+ * Recent gdb versions have trouble processing symbol files containing
+ * overlapping address ranges, so allocate all code from the code manager
+ * of the root domain. (#666152).
+ */
+ code_domain = mono_get_root_domain ();
+ else
+ code_domain = cfg->domain;
#if defined(__native_client_codegen__) && defined(__native_client__)
void *code_dest;
/* emit code all basic blocks */
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
bb->native_offset = cfg->code_len;
+ bb->real_native_offset = cfg->code_len;
//if ((bb == cfg->bb_entry) || !(bb->region == -1 && !bb->dfn))
mono_arch_output_basic_block (cfg, bb);
bb->native_length = cfg->code_len - bb->native_offset;
mono_dynamic_code_hash_insert (cfg->domain, cfg->method, cfg->dynamic_info);
mono_domain_unlock (cfg->domain);
- code = mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + unwindlen);
+ if (mono_using_xdebug)
+ /* See the comment for cfg->code_domain */
+ code = mono_domain_code_reserve (code_domain, cfg->code_size + unwindlen);
+ else
+ code = mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + unwindlen);
} else {
guint unwindlen = 0;
#ifdef MONO_ARCH_HAVE_UNWIND_TABLE
unwindlen = mono_arch_unwindinfo_get_size (cfg->arch.unwindinfo);
#endif
- code = mono_domain_code_reserve (cfg->domain, cfg->code_size + unwindlen);
+ code = mono_domain_code_reserve (code_domain, cfg->code_size + unwindlen);
}
#if defined(__native_client_codegen__) && defined(__native_client__)
nacl_allow_target_modification (TRUE);
mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->run_cctors);
if (cfg->method->dynamic) {
- mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
+ if (mono_using_xdebug)
+ mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
+ else
+ mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
} else {
- mono_domain_code_commit (cfg->domain, cfg->native_code, cfg->code_size, cfg->code_len);
+ mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
}
#if defined(__native_client_codegen__) && defined(__native_client__)
cfg->native_code = code_dest;
/*
* Extend the try block backwards to include parts of the previous call
* instruction.
- * FIXME: This is arch specific.
*/
- ei->try_start = (guint8*)ei->try_start - 1;
+ ei->try_start = (guint8*)ei->try_start - MONO_ARCH_MONITOR_ENTER_ADJUSTMENT;
}
tblock = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
g_assert (tblock);
else
InterlockedIncrement (&mono_jit_stats.methods_without_llvm);
- if (cfg->verbose_level >= 2) {
- char *id = mono_method_full_name (cfg->method, FALSE);
- mono_disassemble_code (cfg, cfg->native_code, cfg->code_len, id + 3);
- g_free (id);
- }
-
cfg->jit_info = create_jit_info (cfg, method_to_compile);
#ifdef MONO_ARCH_HAVE_LIVERANGE_OPS
mono_save_seq_point_info (cfg);
+ if (cfg->verbose_level >= 2) {
+ char *id = mono_method_full_name (cfg->method, FALSE);
+ mono_disassemble_code (cfg, cfg->native_code, cfg->code_len, id + 3);
+ g_free (id);
+ }
+
if (!cfg->compile_aot) {
mono_domain_lock (cfg->domain);
mono_jit_info_table_add (cfg->domain, cfg->jit_info);
}
#endif
- /* The hard-guard page has been hit: there is not much we can do anymore
- * Print a hopefully clear message and abort.
- */
if (jit_tls->stack_size &&
ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
- const char *method;
- /* we don't do much now, but we can warn the user with a useful message */
- fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), (gpointer)info->si_addr);
- if (ji && ji->method)
- method = mono_method_full_name (ji->method, TRUE);
- else
- method = "Unmanaged";
- fprintf (stderr, "At %s\n", method);
- _exit (1);
+ /*
+ * The hard-guard page has been hit: there is not much we can do anymore
+ * Print a hopefully clear message and abort.
+ */
+ mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
+ g_assert_not_reached ();
} else {
/* The original handler might not like that it is executed on an altstack... */
if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
debug_options.no_gdb_backtrace = TRUE;
else if (!strcmp (arg, "suspend-on-sigsegv"))
debug_options.suspend_on_sigsegv = TRUE;
+ else if (!strcmp (arg, "suspend-on-unhandled"))
+ debug_options.suspend_on_unhandled = TRUE;
else if (!strcmp (arg, "dont-free-domains"))
mono_dont_free_domains = TRUE;
else if (!strcmp (arg, "dyn-runtime-invoke"))
debug_options.better_cast_details = 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', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks'\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-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks'\n");
exit (1);
}
}
callbacks.create_ftnptr = mini_create_ftnptr;
callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
callbacks.get_runtime_build_info = mono_get_runtime_build_info;
+ callbacks.set_cast_details = mono_set_cast_details;
#ifdef MONO_ARCH_HAVE_IMT
if (mono_use_imt) {
mono_unwind_init ();
- mini_gc_init ();
-
if (getenv ("MONO_XDEBUG")) {
char *xdebug_opts = getenv ("MONO_XDEBUG");
mono_xdebug_init (xdebug_opts);
mono_icall_init ();
+ /* This should come after mono_init () too */
+ mini_gc_init ();
+
mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
ves_icall_get_frame_info);
mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",