#include <sys/time.h>
#endif
-#ifdef PLATFORM_MACOSX
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <mach/exception.h>
-#include <mach/task.h>
-#include <pthread.h>
-#endif
-
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#include "debug-mini.h"
-static void setup_stat_profiler (void);
static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt);
static gpointer mono_jit_compile_method (MonoMethod *method);
int mono_break_at_bb_bb_num;
gboolean mono_do_x86_stack_align = TRUE;
const char *mono_build_date;
+gboolean mono_do_signal_chaining;
static int mini_verbose = 0;
return OP_STORER8_MEMBASE_REG;
case MONO_TYPE_VALUETYPE:
if (type->data.klass->enumtype) {
- type = type->data.klass->enum_basetype;
+ type = mono_class_enum_basetype (type->data.klass);
goto handle_enum;
}
if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (type)))
#define mono_type_is_long(type) (!(type)->byref && ((mono_type_get_underlying_type (type)->type == MONO_TYPE_I8) || (mono_type_get_underlying_type (type)->type == MONO_TYPE_U8)))
#define mono_type_is_float(type) (!(type)->byref && (((type)->type == MONO_TYPE_R8) || ((type)->type == MONO_TYPE_R4)))
+#ifdef DISABLE_JIT
+
+MonoInst*
+mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
+{
+ return NULL;
+}
+
+#else
+
MonoInst*
mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, int vreg)
{
cfg->varinfo [num] = inst;
MONO_INIT_VARINFO (&cfg->vars [num], num);
+ MONO_VARINFO (cfg, num)->vreg = vreg;
if (vreg != -1)
set_vreg_to_inst (cfg, vreg, inst);
dest->klass = dest->inst_i0->klass;
}
+#endif
+
static MonoType*
type_from_stack_type (MonoInst *ins) {
switch (ins->type) {
* 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;
}
callinfo->trampoline = trampoline;
mono_domain_unlock (domain);
+ mono_loader_unlock ();
return callinfo->trampoline;
}
return offsets;
}
-gint32*
-mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
-{
- return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align);
-}
-
#else
gint32*
#endif /* DISABLE_JIT */
+gint32*
+mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
+{
+ return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align);
+}
+
void
mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, gboolean no_throw)
{
if (thread)
thread->jit_data = jit_tls;
if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
- setup_stat_profiler ();
+ mono_runtime_setup_stat_profiler ();
}
static void
return mono_create_tls_get (cfg, mono_get_jit_tls_offset ());
}
+MonoInst*
+mono_get_domain_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_domain_get_tls_offset ());
+}
+
+MonoInst*
+mono_get_thread_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_thread_get_tls_offset ());
+}
+
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
if (method && method->dynamic) {
jump_table = mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
} else {
- mono_domain_lock (domain);
- if (mono_aot_only)
+ if (mono_aot_only) {
jump_table = mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
- else
- jump_table = mono_code_manager_reserve (domain->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
- mono_domain_unlock (domain);
+ } else {
+ jump_table = mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
+ }
}
for (i = 0; i < patch_info->data.table->table_size; i++)
#ifdef MONO_ARCH_HAVE_UNWIND_TABLE
unwindlen = mono_arch_unwindinfo_get_size (cfg->arch.unwindinfo);
#endif
- mono_domain_lock (cfg->domain);
- code = mono_code_manager_reserve (cfg->domain->code_mp, cfg->code_size + unwindlen);
- mono_domain_unlock (cfg->domain);
+ code = mono_domain_code_reserve (cfg->domain, cfg->code_size + unwindlen);
}
memcpy (code, cfg->native_code, cfg->code_len);
if (cfg->method->dynamic) {
table = mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
} else {
- mono_domain_lock (cfg->domain);
- table = mono_code_manager_reserve (cfg->domain->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
- mono_domain_unlock (cfg->domain);
+ table = mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
}
for (i = 0; i < patch_info->data.table->table_size; i++) {
if (cfg->method->dynamic) {
mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
} else {
- mono_domain_lock (cfg->domain);
- mono_code_manager_commit (cfg->domain->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
- mono_domain_unlock (cfg->domain);
+ mono_domain_code_commit (cfg->domain, cfg->native_code, cfg->code_size, cfg->code_len);
}
mono_arch_flush_icache (cfg->native_code, cfg->code_len);
#endif
}
-static MonoGenericInst*
-get_object_generic_inst (int type_argc)
-{
- MonoType **type_argv;
- int i;
-
- type_argv = alloca (sizeof (MonoType*) * type_argc);
-
- for (i = 0; i < type_argc; ++i)
- type_argv [i] = &mono_defaults.object_class->byval_arg;
-
- return mono_metadata_get_generic_inst (type_argc, type_argv);
-}
-
static void
compute_reachable (MonoBasicBlock *bb)
{
}
}
-static MonoGenericContext
-construct_object_context_for_method (MonoMethod *method)
-{
- MonoGenericContext object_context;
-
- g_assert (method->wrapper_type == MONO_WRAPPER_NONE);
- g_assert (!method->klass->generic_class);
- if (method->klass->generic_container) {
- int type_argc = method->klass->generic_container->type_argc;
-
- object_context.class_inst = get_object_generic_inst (type_argc);
- } else {
- object_context.class_inst = NULL;
- }
-
- if (mini_method_get_context (method)->method_inst) {
- int type_argc = mini_method_get_context (method)->method_inst->type_argc;
-
- object_context.method_inst = get_object_generic_inst (type_argc);
- } else {
- object_context.method_inst = NULL;
- }
-
- g_assert (object_context.class_inst || object_context.method_inst);
-
- return object_context;
-}
-
/*
* mini_method_compile:
* @method: the method to compile
jinfo = g_malloc0 (sizeof (MonoJitInfo) + (header->num_clauses * sizeof (MonoJitExceptionInfo)) +
generic_info_size);
} else {
- /* we access cfg->domain->mp */
- mono_domain_lock (cfg->domain);
jinfo = mono_domain_alloc0 (cfg->domain, sizeof (MonoJitInfo) +
(header->num_clauses * sizeof (MonoJitExceptionInfo)) +
generic_info_size);
- mono_domain_unlock (cfg->domain);
}
if (cfg->generic_sharing_context) {
- MonoGenericContext object_context = construct_object_context_for_method (method_to_compile);
+ MonoGenericContext object_context = mono_method_construct_object_context (method_to_compile);
method_to_register = mono_class_inflate_generic_method (method_to_compile, &object_context);
} else {
}
}
+ /*
+ * Its possible to generate dwarf unwind info for xdebug etc, but not actually
+ * using it during runtime, hence the define.
+ */
+#ifdef MONO_ARCH_HAVE_XP_UNWIND
+ if (cfg->unwind_ops) {
+ guint32 info_len;
+ guint8 *unwind_info = mono_unwind_ops_encode (cfg->unwind_ops, &info_len);
+
+ jinfo->used_regs = mono_cache_unwind_info (unwind_info, info_len);
+ g_free (unwind_info);
+ }
+#endif
+
cfg->jit_info = jinfo;
#if defined(__arm__)
mono_arch_fixup_jinfo (cfg);
#endif
- mono_save_xdebug_info (method_to_register, jinfo->code_start, jinfo->code_size, cfg->args, cfg->unwind_ops);
+ mono_save_xdebug_info (cfg);
if (!cfg->compile_aot) {
mono_domain_lock (cfg->domain);
#endif /* DISABLE_JIT */
-MonoJitInfo*
-mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *open_method)
-{
- static gboolean inited = FALSE;
- static int lookups = 0;
- static int failed_lookups = 0;
-
- MonoGenericContext object_context;
- MonoMethod *object_method;
- MonoJitInfo *ji;
-
- object_context = construct_object_context_for_method (open_method);
- object_method = mono_class_inflate_generic_method (open_method, &object_context);
-
- ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, object_method);
- if (ji && !ji->has_generic_jit_info)
- ji = NULL;
-
- if (!inited) {
- mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
- mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
- inited = TRUE;
- }
-
- ++lookups;
- if (!ji)
- ++failed_lookups;
-
- return ji;
-}
-
static MonoJitInfo*
lookup_generic_method (MonoDomain *domain, MonoMethod *method)
{
{
MonoJitInfo *info;
+ mono_loader_lock (); /*FIXME lookup_method_inner acquired it*/
mono_domain_jit_code_hash_lock (domain);
info = lookup_method_inner (domain, method);
mono_domain_jit_code_hash_unlock (domain);
+ mono_loader_unlock ();
return info;
}
g_assert_not_reached ();
}
+ mono_loader_lock (); /*FIXME lookup_method_inner requires the loader lock*/
mono_domain_lock (target_domain);
/* Check if some other thread already did the job. In this case, we can
}
mono_domain_unlock (target_domain);
+ mono_loader_unlock ();
vtable = mono_class_vtable (target_domain, method->klass);
if (!vtable) {
return runtime_invoke (obj, params, exc, compiled_method);
}
-#ifdef MONO_GET_CONTEXT
-#define GET_CONTEXT MONO_GET_CONTEXT
-#endif
-
-#ifndef GET_CONTEXT
-#ifdef PLATFORM_WIN32
-#define GET_CONTEXT \
- struct sigcontext *ctx = (struct sigcontext*)_dummy;
-#else
-#ifdef MONO_ARCH_USE_SIGACTION
-#define GET_CONTEXT \
- void *ctx = context;
-#elif defined(__sparc__)
-#define GET_CONTEXT \
- void *ctx = sigctx;
-#else
-#define GET_CONTEXT \
- void **_p = (void **)&_dummy; \
- struct sigcontext *ctx = (struct sigcontext *)++_p;
-#endif
-#endif
-#endif
-
-#ifdef MONO_ARCH_USE_SIGACTION
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context)
-#elif defined(__sparc__)
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *sigctx)
-#else
-#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy)
-#endif
-
-static void
-SIG_HANDLER_SIGNATURE (sigfpe_signal_handler)
+void
+SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler)
{
MonoException *exc = NULL;
#ifndef MONO_ARCH_USE_SIGACTION
mono_arch_handle_exception (ctx, exc, FALSE);
}
-static void
-SIG_HANDLER_SIGNATURE (sigill_signal_handler)
+void
+SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler)
{
MonoException *exc;
GET_CONTEXT;
mono_arch_handle_exception (ctx, exc, FALSE);
}
-static void
-SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
+void
+SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
{
#ifndef MONO_ARCH_SIGSEGV_ON_ALTSTACK
MonoException *exc = NULL;
GET_CONTEXT;
/* The thread might no be registered with the runtime */
- if (!mono_domain_get () || !jit_tls)
+ if (!mono_domain_get () || !jit_tls) {
+ if (mono_chain_signal (SIG_HANDLER_PARAMS))
+ return;
mono_handle_native_sigsegv (SIGSEGV, ctx);
+ }
ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
fprintf (stderr, "At %s\n", method);
_exit (1);
} else {
+ /* The original handler might not like that it is executed on an altstack... */
+ if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
+ return;
+
mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
}
#else
if (!ji) {
+ if (mono_chain_signal (SIG_HANDLER_PARAMS))
+ return;
+
mono_handle_native_sigsegv (SIGSEGV, ctx);
}
#endif
}
-#ifndef PLATFORM_WIN32
-
-static void
-SIG_HANDLER_SIGNATURE (sigabrt_signal_handler)
-{
- MonoJitInfo *ji;
- GET_CONTEXT;
-
- ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
- if (!ji) {
- mono_handle_native_sigsegv (SIGABRT, ctx);
- }
-}
-
-static void
-SIG_HANDLER_SIGNATURE (sigusr1_signal_handler)
-{
- gboolean running_managed;
- MonoException *exc;
- MonoThread *thread = mono_thread_current ();
- MonoDomain *domain = mono_domain_get ();
- void *ji;
-
- GET_CONTEXT;
-
- if (!thread || !domain)
- /* The thread might not have started up yet */
- /* FIXME: Specify the synchronization with start_wrapper () in threads.c */
- return;
-
- if (thread->thread_dump_requested) {
- thread->thread_dump_requested = FALSE;
-
- mono_print_thread_dump (ctx);
- }
-
- /*
- * FIXME:
- * This is an async signal, so the code below must not call anything which
- * is not async safe. That includes the pthread locking functions. If we
- * know that we interrupted managed code, then locking is safe.
- */
- ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
- running_managed = ji != NULL;
-
- exc = mono_thread_request_interruption (running_managed);
- if (!exc) return;
-
- mono_arch_handle_exception (ctx, exc, FALSE);
-}
-
-#if defined(__i386__) || defined(__x86_64__)
-#define FULL_STAT_PROFILER_BACKTRACE 1
-#define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
-#define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
-#if MONO_ARCH_STACK_GROWS_UP
-#define IS_BEFORE_ON_STACK <
-#define IS_AFTER_ON_STACK >
-#else
-#define IS_BEFORE_ON_STACK >
-#define IS_AFTER_ON_STACK <
-#endif
-#else
-#define FULL_STAT_PROFILER_BACKTRACE 0
-#endif
-
-#if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390)
-
-static void
-SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
-{
- NOT_IMPLEMENTED;
-}
-
-#else
-
-static void
-SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
-{
- int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
- GET_CONTEXT;
-
- if (call_chain_depth == 0) {
- mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
- } else {
- MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
- int current_frame_index = 1;
- MonoContext mono_context;
-#if FULL_STAT_PROFILER_BACKTRACE
- guchar *current_frame;
- guchar *stack_bottom;
- guchar *stack_top;
-#else
- MonoDomain *domain;
-#endif
- guchar *ips [call_chain_depth + 1];
-
- mono_arch_sigctx_to_monoctx (ctx, &mono_context);
- ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
-
- if (jit_tls != NULL) {
-#if FULL_STAT_PROFILER_BACKTRACE
- stack_bottom = jit_tls->end_of_stack;
- stack_top = MONO_CONTEXT_GET_SP (&mono_context);
- current_frame = MONO_CONTEXT_GET_BP (&mono_context);
-
- while ((current_frame_index <= call_chain_depth) &&
- (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
- ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
- ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
- current_frame_index ++;
- stack_top = current_frame;
- current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
- }
-#else
- domain = mono_domain_get ();
- if (domain != NULL) {
- MonoLMF *lmf = NULL;
- MonoJitInfo *ji;
- MonoJitInfo res;
- MonoContext new_mono_context;
- int native_offset;
- ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
- &new_mono_context, NULL, &lmf, &native_offset, NULL);
- while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
- ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
- current_frame_index ++;
- mono_context = new_mono_context;
- ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
- &new_mono_context, NULL, &lmf, &native_offset, NULL);
- }
- }
-#endif
- }
-
-
- mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
- }
-}
-
-#endif
-
-static void
-SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
-{
- gboolean res;
-
- GET_CONTEXT;
-
- /* We use this signal to start the attach agent too */
- res = mono_attach_start ();
- if (res)
- return;
-
- printf ("Full thread dump:\n");
-
- mono_threads_request_thread_dump ();
-
- /*
- * print_thread_dump () skips the current thread, since sending a signal
- * to it would invoke the signal handler below the sigquit signal handler,
- * and signal handlers don't create an lmf, so the stack walk could not
- * be performed.
- */
- mono_print_thread_dump (ctx);
-}
-
-static void
-SIG_HANDLER_SIGNATURE (sigusr2_signal_handler)
-{
- gboolean enabled = mono_trace_is_enabled ();
-
- mono_trace_enable (!enabled);
-}
-
-#endif
-
-static void
-SIG_HANDLER_SIGNATURE (sigint_signal_handler)
+void
+SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler)
{
MonoException *exc;
GET_CONTEXT;
mono_arch_handle_exception (ctx, exc, FALSE);
}
-#ifdef PLATFORM_MACOSX
-
-/*
- * This code disables the CrashReporter of MacOS X by installing
- * a dummy Mach exception handler.
- */
-
-/*
- * http://darwinsource.opendarwin.org/10.4.3/xnu-792.6.22/osfmk/man/exc_server.html
- */
-extern
-boolean_t
-exc_server (mach_msg_header_t *request_msg,
- mach_msg_header_t *reply_msg);
-
-/*
- * The exception message
- */
-typedef struct {
- mach_msg_base_t msg; /* common mach message header */
- char payload [1024]; /* opaque */
-} mach_exception_msg_t;
-
-/* The exception port */
-static mach_port_t mach_exception_port = VM_MAP_NULL;
-
-/*
- * Implicitly called by exc_server. Must be public.
- *
- * http://darwinsource.opendarwin.org/10.4.3/xnu-792.6.22/osfmk/man/catch_exception_raise.html
- */
-kern_return_t
-catch_exception_raise (
- mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t code_count)
-{
- /* consume the exception */
- return KERN_FAILURE;
-}
-
-/*
- * Exception thread handler.
- */
-static
-void *
-mach_exception_thread (void *arg)
-{
- for (;;) {
- mach_exception_msg_t request;
- mach_exception_msg_t reply;
- mach_msg_return_t result;
-
- /* receive from "mach_exception_port" */
- result = mach_msg (&request.msg.header,
- MACH_RCV_MSG | MACH_RCV_LARGE,
- 0,
- sizeof (request),
- mach_exception_port,
- MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
-
- g_assert (result == MACH_MSG_SUCCESS);
-
- /* dispatch to catch_exception_raise () */
- exc_server (&request.msg.header, &reply.msg.header);
-
- /* send back to sender */
- result = mach_msg (&reply.msg.header,
- MACH_SEND_MSG,
- reply.msg.header.msgh_size,
- 0,
- MACH_PORT_NULL,
- MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
-
- g_assert (result == MACH_MSG_SUCCESS);
- }
- return NULL;
-}
-
-static void
-macosx_register_exception_handler ()
-{
- mach_port_t task;
- pthread_attr_t attr;
- pthread_t thread;
-
- if (mach_exception_port != VM_MAP_NULL)
- return;
-
- task = mach_task_self ();
-
- /* create the "mach_exception_port" with send & receive rights */
- g_assert (mach_port_allocate (task, MACH_PORT_RIGHT_RECEIVE,
- &mach_exception_port) == KERN_SUCCESS);
- g_assert (mach_port_insert_right (task, mach_exception_port, mach_exception_port,
- MACH_MSG_TYPE_MAKE_SEND) == KERN_SUCCESS);
-
- /* create the exception handler thread */
- g_assert (!pthread_attr_init (&attr));
- g_assert (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED));
- g_assert (!pthread_create (&thread, &attr, mach_exception_thread, NULL));
- pthread_attr_destroy (&attr);
-
- /*
- * register "mach_exception_port" as a receiver for the
- * EXC_BAD_ACCESS exception
- *
- * http://darwinsource.opendarwin.org/10.4.3/xnu-792.6.22/osfmk/man/task_set_exception_ports.html
- */
- g_assert (task_set_exception_ports (task, EXC_MASK_BAD_ACCESS,
- mach_exception_port,
- EXCEPTION_DEFAULT,
- MACHINE_THREAD_STATE) == KERN_SUCCESS);
-}
-#endif
-
-#ifndef PLATFORM_WIN32
-static void
-add_signal_handler (int signo, gpointer handler)
-{
- struct sigaction sa;
-
-#ifdef MONO_ARCH_USE_SIGACTION
- sa.sa_sigaction = handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO;
-#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
- if (signo == SIGSEGV)
- sa.sa_flags |= SA_ONSTACK;
-#endif
-#else
- sa.sa_handler = handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
-#endif
- g_assert (sigaction (signo, &sa, NULL) != -1);
-}
-
-static void
-remove_signal_handler (int signo)
-{
- struct sigaction sa;
-
- sa.sa_handler = SIG_DFL;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
-
- sigaction (signo, &sa, NULL);
-}
-#endif
-
-static void
-mono_runtime_install_handlers (void)
-{
-#ifdef PLATFORM_WIN32
- win32_seh_init();
- win32_seh_set_handler(SIGFPE, sigfpe_signal_handler);
- win32_seh_set_handler(SIGILL, sigill_signal_handler);
- win32_seh_set_handler(SIGSEGV, sigsegv_signal_handler);
- if (debug_options.handle_sigint)
- win32_seh_set_handler(SIGINT, sigint_signal_handler);
-
-#else /* !PLATFORM_WIN32 */
-
- sigset_t signal_set;
-
-#if defined(PLATFORM_MACOSX) && !defined(__arm__)
- macosx_register_exception_handler ();
-#endif
-
- if (debug_options.handle_sigint)
- add_signal_handler (SIGINT, sigint_signal_handler);
-
- add_signal_handler (SIGFPE, sigfpe_signal_handler);
- add_signal_handler (SIGQUIT, sigquit_signal_handler);
- add_signal_handler (SIGILL, sigill_signal_handler);
- add_signal_handler (SIGBUS, sigsegv_signal_handler);
- if (mono_jit_trace_calls != NULL)
- add_signal_handler (SIGUSR2, sigusr2_signal_handler);
-
- add_signal_handler (mono_thread_get_abort_signal (), sigusr1_signal_handler);
- /* it seems to have become a common bug for some programs that run as parents
- * of many processes to block signal delivery for real time signals.
- * We try to detect and work around their breakage here.
- */
- sigemptyset (&signal_set);
- sigaddset (&signal_set, mono_thread_get_abort_signal ());
- sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
-
- signal (SIGPIPE, SIG_IGN);
-
- add_signal_handler (SIGABRT, sigabrt_signal_handler);
-
- /* catch SIGSEGV */
- add_signal_handler (SIGSEGV, sigsegv_signal_handler);
-#endif /* PLATFORM_WIN32 */
-}
-
-static void
-mono_runtime_cleanup_handlers (void)
-{
-#ifdef PLATFORM_WIN32
- win32_seh_cleanup();
-#else
- if (debug_options.handle_sigint)
- remove_signal_handler (SIGINT);
-
- remove_signal_handler (SIGFPE);
- remove_signal_handler (SIGQUIT);
- remove_signal_handler (SIGILL);
- remove_signal_handler (SIGBUS);
- if (mono_jit_trace_calls != NULL)
- remove_signal_handler (SIGUSR2);
-
- remove_signal_handler (mono_thread_get_abort_signal ());
-
- remove_signal_handler (SIGABRT);
-
- remove_signal_handler (SIGSEGV);
-#endif /* PLATFORM_WIN32 */
-}
-
-
-#ifdef HAVE_LINUX_RTC_H
-#include <linux/rtc.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-static int rtc_fd = -1;
-
-static int
-enable_rtc_timer (gboolean enable)
-{
- int flags;
- flags = fcntl (rtc_fd, F_GETFL);
- if (flags < 0) {
- perror ("getflags");
- return 0;
- }
- if (enable)
- flags |= FASYNC;
- else
- flags &= ~FASYNC;
- if (fcntl (rtc_fd, F_SETFL, flags) == -1) {
- perror ("setflags");
- return 0;
- }
- return 1;
-}
-#endif
-
-#ifdef PLATFORM_WIN32
-static HANDLE win32_main_thread;
-static MMRESULT win32_timer;
-
-static void CALLBACK
-win32_time_proc (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
-{
- CONTEXT context;
-
- context.ContextFlags = CONTEXT_CONTROL;
- if (GetThreadContext (win32_main_thread, &context)) {
-#ifdef _WIN64
- mono_profiler_stat_hit ((guchar *) context.Rip, &context);
-#else
- mono_profiler_stat_hit ((guchar *) context.Eip, &context);
-#endif
- }
-}
-#endif
-
-static void
-setup_stat_profiler (void)
-{
-#ifdef ITIMER_PROF
- struct itimerval itval;
- static int inited = 0;
-#ifdef HAVE_LINUX_RTC_H
- const char *rtc_freq;
- if (!inited && (rtc_freq = g_getenv ("MONO_RTC"))) {
- int freq = 0;
- inited = 1;
- if (*rtc_freq)
- freq = atoi (rtc_freq);
- if (!freq)
- freq = 1024;
- rtc_fd = open ("/dev/rtc", O_RDONLY);
- if (rtc_fd == -1) {
- perror ("open /dev/rtc");
- return;
- }
- add_signal_handler (SIGPROF, sigprof_signal_handler);
- if (ioctl (rtc_fd, RTC_IRQP_SET, freq) == -1) {
- perror ("set rtc freq");
- return;
- }
- if (ioctl (rtc_fd, RTC_PIE_ON, 0) == -1) {
- perror ("start rtc");
- return;
- }
- if (fcntl (rtc_fd, F_SETSIG, SIGPROF) == -1) {
- perror ("setsig");
- return;
- }
- if (fcntl (rtc_fd, F_SETOWN, getpid ()) == -1) {
- perror ("setown");
- return;
- }
- enable_rtc_timer (TRUE);
- return;
- }
- if (rtc_fd >= 0)
- return;
-#endif
-
- itval.it_interval.tv_usec = 999;
- itval.it_interval.tv_sec = 0;
- itval.it_value = itval.it_interval;
- setitimer (ITIMER_PROF, &itval, NULL);
- if (inited)
- return;
- inited = 1;
- add_signal_handler (SIGPROF, sigprof_signal_handler);
-#elif defined (PLATFORM_WIN32)
- static int inited = 0;
- TIMECAPS timecaps;
-
- if (inited)
- return;
-
- inited = 1;
- if (timeGetDevCaps (&timecaps, sizeof (timecaps)) != TIMERR_NOERROR)
- return;
-
- if ((win32_main_thread = OpenThread (READ_CONTROL | THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId ())) == NULL)
- return;
-
- if (timeBeginPeriod (1) != TIMERR_NOERROR)
- return;
-
- if ((win32_timer = timeSetEvent (1, 0, win32_time_proc, 0, TIME_PERIODIC)) == 0) {
- timeEndPeriod (1);
- return;
- }
-#endif
-}
-
/* mono_jit_create_remoting_trampoline:
* @method: pointer to the method info
*
debug_options.break_on_unverified = TRUE;
else if (!strcmp (arg, "no-gdb-backtrace"))
debug_options.no_gdb_backtrace = TRUE;
+ else if (!strcmp (arg, "suspend-on-sigsegv"))
+ debug_options.suspend_on_sigsegv = TRUE;
else if (!strcmp (arg, "dont-free-domains"))
mono_dont_free_domains = TRUE;
else {
fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
- fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains'\n");
+ fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv'\n");
exit (1);
}
}
mono_arch_init ();
+ mono_unwind_init ();
+
if (getenv ("MONO_XDEBUG")) {
mono_xdebug_init ();
/* So methods for multiple domains don't have the same address */
#endif
#ifdef MONO_ARCH_EMULATE_MUL_DIV
- mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
- mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
mono_register_opcode_emulation (CEE_MUL, "__emul_imul", "int32 int32 int32", mono_imul, TRUE);
mono_register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, TRUE);
+#endif
+
+#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
+ mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
+ mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
mono_register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
mono_register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
#endif
+
#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
mono_register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, FALSE);
#endif
mono_register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, FALSE);
mono_register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, FALSE);
mono_register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, FALSE);
+#if SIZEOF_VOID_P == 4
+ mono_register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, FALSE);
+#endif
mono_register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, FALSE);
mono_register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, FALSE);
register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
+ register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
#endif
#if SIZEOF_REGISTER == 4
g_print ("VTable data size: %ld\n", mono_stats.class_vtable_size);
g_print ("Mscorlib mempool size: %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
- g_print ("\nGeneric instances: %ld\n", mono_stats.generic_instance_count);
- g_print ("Initialized classes: %ld\n", mono_stats.generic_class_count);
- g_print ("Inflated methods: %ld / %ld\n", mono_stats.inflated_method_count_2,
- mono_stats.inflated_method_count);
+ g_print ("\nInitialized classes: %ld\n", mono_stats.generic_class_count);
g_print ("Inflated types: %ld\n", mono_stats.inflated_type_count);
- g_print ("Generics metadata size: %ld\n", mono_stats.generics_metadata_size);
g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
g_print ("Hazardous pointers: %ld\n", mono_stats.hazardous_pointer_count);
#ifdef HAVE_SGEN_GC
g_print ("Minor GC collections: %ld\n", mono_stats.minor_gc_count);
+#endif
g_print ("Major GC collections: %ld\n", mono_stats.major_gc_count);
+#ifdef HAVE_SGEN_GC
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);
#endif
+ 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);
void
mini_cleanup (MonoDomain *domain)
{
-#ifdef HAVE_LINUX_RTC_H
- if (rtc_fd >= 0)
- enable_rtc_timer (FALSE);
-#endif
-
+ mono_runtime_shutdown_stat_profiler ();
+
#ifndef DISABLE_COM
cominterop_release_all_rcws ();
#endif
mono_trampolines_cleanup ();
+ mono_unwind_cleanup ();
+
if (!mono_dont_free_global_codeman)
mono_code_manager_destroy (global_codeman);
g_hash_table_destroy (jit_icall_name_hash);