2009-03-02 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini.c
index 586ceaa0e6275c54bacba7c3d6f716170c039b24..ddb9f6929b1854b87cd7c7625fd5685132271e81 100644 (file)
 #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
@@ -72,7 +64,6 @@
 
 #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);
 
@@ -110,12 +101,10 @@ MonoMethodDesc *mono_break_at_bb_method = NULL;
 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;
@@ -334,6 +323,24 @@ void *mono_global_codeman_reserve (int size)
        }
 }
 
+/**
+ * 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:
  *
@@ -545,7 +552,7 @@ handle_enum:
                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)))
@@ -667,7 +674,7 @@ mono_op_imm_to_op (int opcode)
 {
        switch (opcode) {
        case OP_ADD_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
                return OP_IADD;
 #else
                return OP_LADD;
@@ -683,7 +690,7 @@ mono_op_imm_to_op (int opcode)
        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;
@@ -721,13 +728,13 @@ mono_op_imm_to_op (int opcode)
        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;
@@ -799,6 +806,16 @@ set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst)
 #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)
 {
@@ -828,11 +845,12 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
        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
@@ -927,6 +945,8 @@ mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index)
        dest->klass = dest->inst_i0->klass;
 }
 
+#endif
+
 static MonoType*
 type_from_stack_type (MonoInst *ins) {
        switch (ins->type) {
@@ -1227,10 +1247,12 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
         * 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;
        }
 
@@ -1247,6 +1269,7 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
        callinfo->trampoline = trampoline;
 
        mono_domain_unlock (domain);
+       mono_loader_unlock ();
        
        return callinfo->trampoline;
 }
@@ -1365,8 +1388,9 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s
 
                /* 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;
 
@@ -1405,7 +1429,7 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s
                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:
@@ -1626,9 +1650,9 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
 
                /* 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);
@@ -1669,7 +1693,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
                        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:
@@ -1785,12 +1809,6 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
        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*
@@ -1802,6 +1820,12 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
 
 #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)
 {
@@ -2199,7 +2223,7 @@ mono_thread_attach_cb (gsize tid, gpointer stack_start)
        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
@@ -2215,7 +2239,24 @@ mini_thread_cleanup (MonoThread *thread)
                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         
+               }
        }
 }
 
@@ -2243,6 +2284,18 @@ mono_get_jit_tls_intrinsic (MonoCompile *cfg)
        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)
 {
@@ -2442,12 +2495,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                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++)
@@ -2777,9 +2829,7 @@ mono_codegen (MonoCompile *cfg)
 #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);
@@ -2840,9 +2890,7 @@ mono_codegen (MonoCompile *cfg)
                        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++) {
@@ -2914,9 +2962,7 @@ if (valgrind_register){
        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);
@@ -2927,20 +2973,6 @@ if (valgrind_register){
 #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)
 {
@@ -3062,6 +3094,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                /* 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;
@@ -3502,35 +3538,13 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                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 {
@@ -3638,16 +3652,26 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                }
        }
 
+       /* 
+        * 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);
@@ -3703,7 +3727,7 @@ lookup_generic_method (MonoDomain *domain, MonoMethod *method)
        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);
 }
@@ -3727,9 +3751,11 @@ lookup_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;
 }
@@ -3748,16 +3774,12 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
                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
 
@@ -3911,6 +3933,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                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
@@ -3932,12 +3955,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                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);
        }
@@ -3961,6 +3980,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        }
 
        mono_domain_unlock (target_domain);
+       mono_loader_unlock ();
 
        vtable = mono_class_vtable (target_domain, method->klass);
        if (!vtable) {
@@ -4170,39 +4190,8 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        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
@@ -4222,8 +4211,8 @@ SIG_HANDLER_SIGNATURE (sigfpe_signal_handler)
        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;
@@ -4233,8 +4222,8 @@ SIG_HANDLER_SIGNATURE (sigill_signal_handler)
        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;
@@ -4245,8 +4234,11 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
        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));
 
@@ -4269,11 +4261,18 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
                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);
        }
                        
@@ -4281,179 +4280,8 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
 #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;
@@ -4463,357 +4291,6 @@ SIG_HANDLER_SIGNATURE (sigint_signal_handler)
        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
  *
@@ -4889,11 +4366,13 @@ mini_parse_debug_options (void)
                        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);
                }
        }
@@ -4990,6 +4469,14 @@ mini_init (const char *filename, const char *runtime_version)
 
        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 ())
@@ -5019,9 +4506,6 @@ mini_init (const char *filename, const char *runtime_version)
        }
 #endif
 
-       if (getenv ("MONO_XDEBUG"))
-               enable_xdebug = TRUE;
-
 #define JIT_TRAMPOLINES_WORK
 #ifdef JIT_TRAMPOLINES_WORK
        mono_install_compile_method (mono_jit_compile_method);
@@ -5146,13 +4630,17 @@ mini_init (const char *filename, const char *runtime_version)
 #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
@@ -5197,6 +4685,9 @@ mini_init (const char *filename, const char *runtime_version)
        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);
@@ -5218,9 +4709,10 @@ mini_init (const char *filename, const char *runtime_version)
        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
 
@@ -5320,12 +4812,8 @@ print_jit_stats (void)
                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);
@@ -5352,10 +4840,12 @@ print_jit_stats (void)
                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);
@@ -5375,11 +4865,12 @@ print_jit_stats (void)
 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
@@ -5405,6 +4896,8 @@ mini_cleanup (MonoDomain *domain)
 
        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);