g_free (info);
}
+G_GNUC_UNUSED static void
+break_count (void)
+{
+}
+
+/*
+ * Runtime debugging tool, use if (debug_count ()) <x> else <y> to do <x> the first COUNT times, then do <y> afterwards.
+ * Set a breakpoint in break_count () to break the last time <x> is done.
+ */
+G_GNUC_UNUSED gboolean
+mono_debug_count (void)
+{
+ static int count = 0;
+ count ++;
+
+ if (!getenv ("COUNT"))
+ return TRUE;
+
+ if (count == atoi (getenv ("COUNT"))) {
+ break_count ();
+ }
+
+ if (count > atoi (getenv ("COUNT"))) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
#define MONO_INIT_VARINFO(vi,id) do { \
(vi)->range.first_use.pos.bid = 0xffff; \
(vi)->reg = -1; \
(obj->vtable->klass == mono_defaults.threadabortexception_class)) {
mono_thread_exit ();
} else {
- MonoObject *other = NULL;
- MonoString *str = mono_object_to_string (obj, &other);
- if (str) {
- char *msg = mono_string_to_utf8 (str);
- fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg);
- fflush (stderr);
- g_free (msg);
- }
-
- exit (mono_environment_exitcode_get ());
+ mono_invoke_unhandled_exception_hook (obj);
}
}
switch (entry->data->type) {
case MONO_PATCH_INFO_CLASS:
- slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method));
break;
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_METHODCONST:
- slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method));
break;
case MONO_PATCH_INFO_FIELD:
- slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
+ slot = mono_method_lookup_or_register_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method));
break;
default:
g_assert_not_reached ();
last = ins;
}
+
+ if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY) {
+ MonoBasicBlock *bb2;
+ MonoInst *endfinally_seq_point = NULL;
+
+ /*
+ * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
+ */
+ l = g_slist_last (bb->seq_points);
+ g_assert (l);
+ endfinally_seq_point = l->data;
+
+ for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
+ GSList *l = g_slist_last (bb2->seq_points);
+
+ if (l) {
+ MonoInst *ins = l->data;
+
+ if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point)
+ next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
+ }
+ }
+ }
}
if (cfg->verbose_level > 2) {
sp->next = g_new (int, sp->next_len);
j = 0;
if (cfg->verbose_level > 2 && next [i]) {
- printf ("\t0x%x ->", sp->il_offset);
+ printf ("\tIL0x%x ->", sp->il_offset);
for (l = next [i]; l; l = l->next) {
next_index = GPOINTER_TO_UINT (l->data);
- printf (" 0x%x", info->seq_points [next_index].il_offset);
+ printf (" IL0x%x", info->seq_points [next_index].il_offset);
}
printf ("\n");
}
MonoJitInfo *jinfo;
int num_clauses;
int generic_info_size, arch_eh_info_size = 0;
- int holes_size = 0, num_holes = 0;
+ int holes_size = 0, num_holes = 0, cas_size = 0;
guint32 stack_size = 0;
g_assert (method_to_compile == cfg->method);
* mono_arch_get_argument_info () is not signal safe.
*/
arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1);
- stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
+ stack_size = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info);
if (stack_size)
arch_eh_info_size = sizeof (MonoArchEHJitInfo);
printf ("Number of try block holes %d\n", num_holes);
}
+ if (mono_method_has_declsec (cfg->method_to_register)) {
+ cas_size = sizeof (MonoMethodCasInfo);
+ }
+
if (COMPILE_LLVM (cfg))
num_clauses = cfg->llvm_ex_info_len;
else
if (cfg->method->dynamic) {
jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) +
- generic_info_size + holes_size + arch_eh_info_size);
+ generic_info_size + holes_size + arch_eh_info_size + cas_size);
} else {
jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
(num_clauses * sizeof (MonoJitExceptionInfo)) +
- generic_info_size + holes_size + arch_eh_info_size);
+ generic_info_size + holes_size + arch_eh_info_size + cas_size);
}
jinfo->method = cfg->method_to_register;
jinfo->code_size = cfg->code_len;
jinfo->used_regs = cfg->used_int_regs;
jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
- jinfo->cas_inited = FALSE; /* initialization delayed at the first stalk walk using this method */
jinfo->num_clauses = num_clauses;
+
if (COMPILE_LLVM (cfg))
jinfo->from_llvm = TRUE;
info->stack_size = stack_size;
}
+ if (cas_size) {
+ jinfo->has_cas_info = 1;
+ }
+
if (COMPILE_LLVM (cfg)) {
if (num_clauses)
memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
InterlockedIncrement (&mono_jit_stats.methods_compiled);
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
mono_profiler_method_jit (method);
- if (MONO_PROBE_METHOD_COMPILE_BEGIN_ENABLED ())
+ if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
MONO_PROBE_METHOD_COMPILE_BEGIN (method);
if (compile_aot)
cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD;
cfg->exception_message = g_strdup (mono_error_get_message (&err));
mono_error_cleanup (&err);
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
return cfg;
}
cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
}
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
return cfg;
}
if (i < 0) {
if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
if (compile_aot) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
return cfg;
}
}
g_assert (cfg->exception_type != MONO_EXCEPTION_GENERIC_SHARING_FAILED);
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
/* cfg contains the details of the failure, so let the caller cleanup */
return cfg;
/* after method_to_ir */
if (parts == 1) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
}
/* after SSA translation */
if (parts == 2) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
}
/* after SSA removal */
if (parts == 3) {
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
}
}
/* collect statistics */
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->jit_methods++;
mono_perfcounters->jit_bytes += header->code_size;
+#endif
mono_jit_stats.allocated_code_size += cfg->code_len;
code_size_ratio = cfg->code_len;
if (code_size_ratio > mono_jit_stats.biggest_method_size && mono_jit_stats.enabled) {
}
mono_jit_stats.native_code_size += cfg->code_len;
- if (MONO_PROBE_METHOD_COMPILE_END_ENABLED ())
+ if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
return cfg;
if (mono_aot_only) {
char *fullname = mono_method_full_name (method, TRUE);
- char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only.\n", fullname);
+ char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n", fullname);
*jit_ex = mono_get_exception_execution_engine (msg);
g_free (fullname);
invalidated_delegate_trampoline (char *desc)
{
g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
- "See http://www.go-mono.com/delegate.html for an explanation and ways to fix this.",
+ "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
desc);
}
#endif
MonoRuntimeCallbacks callbacks;
MonoThreadInfoRuntimeCallbacks ticallbacks;
- MONO_PROBE_VES_INIT_BEGIN ();
+ MONO_VES_INIT_BEGIN ();
#if defined(__linux__) && !defined(__native_client__)
if (access ("/proc/self/maps", F_OK) != 0) {
g_thread_init (NULL);
mono_native_tls_alloc (&mono_jit_tls_id, NULL);
- setup_jit_tls_data ((gpointer)-1, mono_thread_abort);
if (default_opt & MONO_OPT_AOT)
mono_aot_init ();
mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
mono_runtime_install_handlers);
+#ifdef PLATFORM_ANDROID
+ mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
+ mono_debugger_agent_unhandled_exception);
+#endif
+
mono_create_helper_signatures ();
register_jit_stats ();
mono_profiler_runtime_initialized ();
- MONO_PROBE_VES_INIT_END ();
+ MONO_VES_INIT_END ();
return domain;
}
g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
g_print ("Hazardous pointers: %ld\n", mono_stats.hazardous_pointer_count);
- g_print ("Minor GC collections: %ld\n", mono_stats.minor_gc_count);
- g_print ("Major GC collections: %ld\n", mono_stats.major_gc_count);
- g_print ("Minor GC time in msecs: %lf\n", (double)mono_stats.minor_gc_time_usecs / 1000.0);
- g_print ("Major GC time in msecs: %lf\n", (double)mono_stats.major_gc_time_usecs / 1000.0);
if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) {
g_print ("\nDecl security check : %ld\n", mono_jit_stats.cas_declsec_check);
g_print ("LinkDemand (user) : %ld\n", mono_jit_stats.cas_linkdemand);
mini_verbose = level;
}
-/*
+/**
* mono_get_runtime_build_info:
*
- * Return the runtime version + build date in string format.
- * The returned string is owned by the caller.
+ * Return the runtime version + build date in string format.
+ * The returned string is owned by the caller. The returned string
+ * format is "VERSION (FULL_VERSION BUILD_DATE)" and build date is optional.
*/
char*
mono_get_runtime_build_info (void)