#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;
-/* Enable xdebug mode. See aot-compiler.c for documentation */
-static gboolean enable_xdebug = FALSE;
-
#define mono_jit_lock() EnterCriticalSection (&jit_mutex)
#define mono_jit_unlock() LeaveCriticalSection (&jit_mutex)
static CRITICAL_SECTION jit_mutex;
}
}
+/**
+ * mono_create_unwind_op:
+ *
+ * Create an unwind op with the given parameters.
+ */
+MonoUnwindOp*
+mono_create_unwind_op (int when, int tag, int reg, int val)
+{
+ MonoUnwindOp *op = g_new0 (MonoUnwindOp, 1);
+
+ op->op = tag;
+ op->reg = reg;
+ op->val = val;
+ op->when = when;
+
+ return op;
+}
+
/**
* mono_emit_unwind_op:
*
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)))
{
switch (opcode) {
case OP_ADD_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IADD;
#else
return OP_LADD;
case OP_IMUL_IMM:
return OP_IMUL;
case OP_AND_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IAND;
#else
return OP_LAND;
case OP_IREM_IMM:
return OP_IREM;
case OP_DIV_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IDIV;
#else
return OP_LDIV;
#endif
case OP_REM_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IREM;
#else
return OP_LREM;
#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);
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
#ifdef MONO_ARCH_SOFT_FLOAT
regpair = mono_type_is_long (type) || mono_type_is_float (type);
#else
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;
}
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
* pinvoke wrappers when they call functions returning structures */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (inst->inst_vtype->data.klass, &align);
+ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF) {
+ size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
+ }
else {
int ialign;
case MONO_TYPE_PTR:
case MONO_TYPE_I:
case MONO_TYPE_U:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
case MONO_TYPE_I4:
#else
case MONO_TYPE_I8:
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
* pinvoke wrappers when they call functions returning structures */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (inst->inst_vtype->data.klass, &align);
- else {
+ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF) {
+ size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
+ } else {
int ialign;
size = mono_type_size (inst->inst_vtype, &ialign);
case MONO_TYPE_PTR:
case MONO_TYPE_I:
case MONO_TYPE_U:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
case MONO_TYPE_I4:
#else
case MONO_TYPE_I8:
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
g_free (jit_tls->first_lmf);
g_free (jit_tls);
thread->jit_data = NULL;
- TlsSetValue (mono_jit_tls_id, NULL);
+
+ /* 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_current ()) {
+ TlsSetValue (mono_jit_tls_id, NULL);
+
+#ifdef HAVE_KW_THREAD
+ mono_jit_tls = NULL;
+ mono_lmf_addr = NULL;
+#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+ mono_lmf = NULL;
+#endif
+#endif
+ }
}
}
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++)
target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
break;
case MONO_PATCH_INFO_ICALL_ADDR:
- target = mono_lookup_internal_call (patch_info->data.method);
/* run_cctors == 0 -> AOT */
- if (!target && run_cctors)
- g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
+ if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ if (run_cctors) {
+ target = mono_lookup_pinvoke_call (patch_info->data.method, NULL, NULL);
+ if (!target)
+ g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
+ } else {
+ target = NULL;
+ }
+ } else {
+ target = mono_lookup_internal_call (patch_info->data.method);
+
+ if (!target && run_cctors)
+ g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
+ }
break;
case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
#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)
{
/* The debugger needs all locals to be on the stack or in a global register */
cfg->disable_vreg_to_lvreg = TRUE;
+ /* Don't remove unused variables when running inside the debugger since the user
+ * may still want to view them. */
+ cfg->disable_deadce_vars = TRUE;
+
// cfg->opt |= MONO_OPT_SHARED;
cfg->opt &= ~MONO_OPT_DEADCE;
cfg->opt &= ~MONO_OPT_INLINE;
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;
-
- g_assert (!method_to_compile->klass->generic_class);
- if (method_to_compile->klass->generic_container) {
- int type_argc = method_to_compile->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_to_compile)->method_inst) {
- int type_argc = mini_method_get_context (method_to_compile)->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);
+ 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
- if (enable_xdebug) {
-#ifndef DISABLE_AOT
- mono_save_xdebug_info (method_to_register, jinfo->code_start, jinfo->code_size, cfg->args, cfg->unwind_ops);
-#endif
- }
+ mono_save_xdebug_info (cfg);
if (!cfg->compile_aot) {
mono_domain_lock (cfg->domain);
if (!mono_method_is_generic_sharable_impl (method, FALSE))
return NULL;
- open_method = mono_method_get_declaring_generic_method (method);
+ open_method = mono_method_get_declaring_generic_method (method);
return mono_domain_lookup_shared_generic (domain, open_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;
}
mono_class_init (method->klass);
- mono_domain_lock (domain);
if ((code = mono_aot_get_method (domain, method))) {
- mono_domain_unlock (domain);
vtable = mono_class_vtable (domain, method->klass);
g_assert (vtable);
mono_runtime_class_init (vtable);
return code;
}
-
- mono_domain_unlock (domain);
}
#endif
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_jit_code_hash_unlock (target_domain);
code = cfg->native_code;
- if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl (method, FALSE)) {
- /* g_print ("inserting method %s.%s.%s\n", method->klass->name_space, method->klass->name, method->name); */
- mono_domain_register_shared_generic (target_domain,
- mono_method_get_declaring_generic_method (method), cfg->jit_info);
+ if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl (method, FALSE))
mono_stats.generics_shared_methods++;
- }
} else {
mono_domain_jit_code_hash_unlock (target_domain);
}
}
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 ();
- void *ji;
-
- GET_CONTEXT;
-
- 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 */
+ mono_dont_free_domains = TRUE;
+ }
+
mono_trampolines_init ();
if (!g_thread_supported ())
}
#endif
- if (getenv ("MONO_XDEBUG"))
- enable_xdebug = TRUE;
-
#define JIT_TRAMPOLINES_WORK
#ifdef JIT_TRAMPOLINES_WORK
mono_install_compile_method (mono_jit_compile_method);
#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_VOID_P == 4
+#if SIZEOF_REGISTER == 4
mono_register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, TRUE);
#endif
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);
+ mono_runtime_shutdown_stat_profiler ();
+
+#ifndef DISABLE_COM
+ cominterop_release_all_rcws ();
#endif
-
+
/*
* mono_runtime_cleanup() and mono_domain_finalize () need to
* be called early since they need the execution engine still
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);