2005-12-11 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini.c
index 9a490fac56875f3c500a7576ad4a8b6d81665d9e..194f58b034e674dbdd99a0030631e4628cb27110 100644 (file)
@@ -48,6 +48,8 @@
 #include <mono/metadata/mono-debug-debugger.h>
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/security-manager.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/rawbuffer.h>
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/os/gc_wrapper.h>
@@ -60,6 +62,8 @@
 
 #include "jit-icalls.c"
 
+#include "aliasing.h"
+
 /* 
  * this is used to determine when some branch optimizations are possible: we exclude FP compares
  * because they have weird semantics with NaNs.
@@ -101,6 +105,8 @@ gboolean mono_use_security_manager = FALSE;
 
 static int mini_verbose = 0;
 
+#define mono_jit_lock() EnterCriticalSection (&jit_mutex)
+#define mono_jit_unlock() LeaveCriticalSection (&jit_mutex)
 static CRITICAL_SECTION jit_mutex;
 
 static GHashTable *class_init_hash_addr = NULL;
@@ -180,6 +186,12 @@ get_method_from_ip (void *ip)
        return res;
 }
 
+G_GNUC_UNUSED char *
+mono_pmip (void *ip)
+{
+       return get_method_from_ip (ip);
+}
+
 /* debug function */
 G_GNUC_UNUSED static void
 print_method_from_ip (void *ip)
@@ -254,9 +266,9 @@ void *mono_global_codeman_reserve (int size)
                return mono_code_manager_reserve (global_codeman, size);
        }
        else {
-               EnterCriticalSection (&jit_mutex);
+               mono_jit_lock ();
                ptr = mono_code_manager_reserve (global_codeman, size);
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
                return ptr;
        }
 }
@@ -439,7 +451,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_LOCLOADA(cfg,dest,num) do {        \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->ssa_op = MONO_SSA_MAYBE_LOAD;   \
+               (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN;        \
                (dest)->inst_i0 = (cfg)->varinfo [locals_offset + (num)];       \
                (dest)->inst_i0->flags |= MONO_INST_INDIRECT;   \
                (dest)->opcode = OP_LDADDR;     \
@@ -451,7 +463,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_RETLOADA(cfg,dest) do {    \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->ssa_op = MONO_SSA_MAYBE_LOAD;   \
+               (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN;        \
                (dest)->inst_i0 = (cfg)->ret;   \
                (dest)->inst_i0->flags |= MONO_INST_INDIRECT;   \
                (dest)->opcode = cfg->ret_var_is_local ? OP_LDADDR : CEE_LDIND_I;       \
@@ -463,7 +475,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 #define NEW_ARGLOADA(cfg,dest,num) do {        \
                 if (arg_array [(num)]->opcode == OP_ICONST) goto inline_failure; \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->ssa_op = MONO_SSA_MAYBE_LOAD;   \
+               (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN;        \
                (dest)->inst_i0 = arg_array [(num)];    \
                (dest)->inst_i0->flags |= MONO_INST_INDIRECT;   \
                (dest)->opcode = OP_LDADDR;     \
@@ -483,7 +495,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_TEMPLOADA(cfg,dest,num) do {       \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->ssa_op = MONO_SSA_MAYBE_LOAD;   \
+               (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN;        \
                (dest)->inst_i0 = (cfg)->varinfo [(num)];       \
                (dest)->inst_i0->flags |= MONO_INST_INDIRECT;   \
                (dest)->opcode = OP_LDADDR;     \
@@ -848,7 +860,7 @@ df_visit (MonoBasicBlock *start, int *dfn, MonoBasicBlock **array)
        int i;
 
        array [*dfn] = start;
-       /*g_print ("visit %d at %p\n", *dfn, start->cil_code);*/
+       /*g_print ("visit %d at %p (BB%ld)\n", *dfn, start->cil_code, start->block_num);*/
        for (i = 0; i < start->out_count; ++i) {
                if (start->out_bb [i]->dfn)
                        continue;
@@ -1798,6 +1810,9 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                found = FALSE;
                for (i = 0; i < bb->out_count; ++i) {
                        outb = bb->out_bb [i];
+                       /* exception handlers are linked, but they should not be considered for stack args */
+                       if (outb->flags & BB_EXCEPTION_HANDLER)
+                               continue;
                        //g_print (" %d", outb->block_num);
                        if (outb->in_stack) {
                                found = TRUE;
@@ -1831,8 +1846,14 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
 
        for (i = 0; i < bb->out_count; ++i) {
                outb = bb->out_bb [i];
-               if (outb->in_scount)
+               /* exception handlers are linked, but they should not be considered for stack args */
+               if (outb->flags & BB_EXCEPTION_HANDLER)
+                       continue;
+               if (outb->in_scount) {
+                       if (outb->in_scount != bb->out_scount)
+                               G_BREAKPOINT ();
                        continue; /* check they are the same locals */
+               }
                outb->in_scount = count;
                outb->in_stack = bb->out_stack;
        }
@@ -1865,6 +1886,11 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                found = FALSE;
                while (bindex < bb->out_count) {
                        outb = bb->out_bb [bindex];
+                       /* exception handlers are linked, but they should not be considered for stack args */
+                       if (outb->flags & BB_EXCEPTION_HANDLER) {
+                               bindex++;
+                               continue;
+                       }
                        if (outb->in_stack != locals) {
                                /* 
                                 * Instead of storing sp [i] to locals [i], we need to store
@@ -2337,7 +2363,7 @@ mono_get_element_address_signature (int arity)
        MonoMethodSignature *res;
        int i;
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (!sighash) {
                sighash = g_hash_table_new (NULL, NULL);
        }
@@ -2361,7 +2387,7 @@ mono_get_element_address_signature (int arity)
        res->ret = &mono_defaults.int_class->byval_arg;
 
        g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
 
        return res;
 }
@@ -2373,12 +2399,12 @@ mono_get_array_new_va_signature (int arity)
        MonoMethodSignature *res;
        int i;
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (!sighash) {
                sighash = g_hash_table_new (NULL, NULL);
        }
        else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
                return res;
        }
 
@@ -2397,7 +2423,7 @@ mono_get_array_new_va_signature (int arity)
        res->ret = &mono_defaults.int_class->byval_arg;
 
        g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
 
        return res;
 }
@@ -2542,13 +2568,35 @@ handle_alloc (MonoCompile *cfg, MonoBasicBlock *bblock, MonoClass *klass, gboole
 
        return mono_emit_jit_icall (cfg, bblock, alloc_ftn, iargs, ip);
 }
+
+/**
+ * Handles unbox of a Nullable<T>, returning a temp variable
+ * where the result is stored
+ */
+static int
+handle_unbox_nullable (MonoCompile* cfg, MonoBasicBlock* bblock, MonoInst* val, const guchar *ip, MonoClass* klass)
+{
+       MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1);
+       return mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
        
+}
+
+
+
 static MonoInst *
 handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip, MonoClass *klass)
 {
        MonoInst *dest, *vtoffset, *add, *vstore;
        int temp;
 
+       if (mono_class_is_nullable (klass)) {
+               MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1);
+               temp = mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
+               NEW_TEMPLOAD (cfg, dest, temp);
+               return dest;
+       }
+
+
        temp = handle_alloc (cfg, bblock, klass, TRUE, ip);
        NEW_TEMPLOAD (cfg, dest, temp);
        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
@@ -2589,9 +2637,9 @@ handle_array_new (MonoCompile *cfg, MonoBasicBlock *bblock, int rank, MonoInst *
                name = g_strdup (icall_name);
                info = mono_register_jit_icall (mono_array_new_va, name, esig, FALSE);
 
-               EnterCriticalSection (&jit_mutex);
+               mono_jit_lock ();
                g_hash_table_insert (jit_icall_name_hash, name, name);
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
        }
 
        cfg->flags |= MONO_CFG_HAS_VARARGS;
@@ -2777,9 +2825,9 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
                name = g_strdup (icall_name);
                info = mono_register_jit_icall (ves_array_element_address, name, esig, FALSE);
 
-               EnterCriticalSection (&jit_mutex);
+               mono_jit_lock ();
                g_hash_table_insert (jit_icall_name_hash, name, name);
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
        }
 
        temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE, FALSE);
@@ -2800,6 +2848,38 @@ mono_find_jit_opcode_emulation (int opcode)
                return NULL;
 }
 
+static MonoException*
+mini_loader_error_to_exception (MonoLoaderError *error)
+{
+       MonoException *ex = NULL;
+
+       switch (error->kind) {
+       case MONO_LOADER_ERROR_TYPE: {
+               MonoString *class_name = mono_string_new (mono_domain_get (), error->class_name);
+               
+               ex = mono_get_exception_type_load (class_name, error->assembly_name);
+               break;
+       }
+       case MONO_LOADER_ERROR_METHOD:
+       case MONO_LOADER_ERROR_FIELD: {
+               char *class_name;
+               
+               class_name = g_strdup_printf ("%s%s%s", error->klass->name_space, *error->klass->name_space ? "." : "", error->klass->name);
+
+               if (error->kind == MONO_LOADER_ERROR_METHOD)
+                       ex = mono_get_exception_missing_method (class_name, error->member_name);
+               else
+                       ex = mono_get_exception_missing_field (class_name, error->member_name);
+               g_free (class_name);
+               break;
+       }
+       default:
+               g_assert_not_reached ();
+       }
+
+       return ex;
+}
+
 static MonoInst*
 mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
@@ -2838,9 +2918,12 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                        ins->inst_i0 = args [0];
                        return ins;
 #endif
+               } else if (strcmp (cmethod->name, ".ctor") == 0) {
+                       MONO_INST_NEW (cfg, ins, CEE_NOP);
+                       return ins;
                } else
                        return NULL;
-       } else if (mini_class_is_system_array (cmethod->klass)) {
+       } else if (cmethod->klass == mono_defaults.array_class) {
                if (cmethod->name [0] != 'g')
                        return NULL;
 
@@ -2863,7 +2946,6 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
        } else if (cmethod->klass == mono_defaults.thread_class) {
                if (strcmp (cmethod->name, "get_CurrentThread") == 0 && (ins = mono_arch_get_thread_intrinsic (cfg)))
                        return ins;
-               return NULL;
        }
 
        return mono_arch_get_inst_for_method (cfg, cmethod, fsig, args);
@@ -3127,8 +3209,7 @@ emit_tree (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ins, const guint8
        MonoInst *store, *temp, *load;
        
        if (ip_in_bb (cfg, bblock, ip_next) &&
-               (CODE_IS_STLOC (ip_next) || *ip_next == CEE_BRTRUE || *ip_next == CEE_BRFALSE ||
-               *ip_next == CEE_BRTRUE_S || *ip_next == CEE_BRFALSE_S || *ip_next == CEE_RET))
+               (CODE_IS_STLOC (ip_next) || *ip_next == CEE_RET))
                        return ins;
        
        temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
@@ -3151,12 +3232,26 @@ mini_get_method (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericCont
 
        method = mono_get_method_full (m->klass->image, token, klass, context);
 
-       if (method->is_inflated)
+       if (method && method->is_inflated)
                method = mono_get_inflated_method (method);
 
        return method;
 }
 
+static inline MonoClass*
+mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
+{
+       MonoClass *klass;
+
+       if (method->wrapper_type != MONO_WRAPPER_NONE)
+               klass = mono_method_get_wrapper_data (method, token);
+       else
+               klass = mono_class_get_full (method->klass->image, token, context);
+       if (klass)
+               mono_class_init (klass);
+       return klass;
+}
+
 static
 void check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee, MonoBasicBlock *bblock, unsigned char *ip)
 {
@@ -3221,7 +3316,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
        image = method->klass->image;
        header = mono_method_get_header (method);
-       generic_container = ((MonoMethodNormal *)method)->generic_container;
+       generic_container = method->generic_container;
        sig = mono_method_signature (method);
        num_args = sig->hasthis + sig->param_count;
        ip = (unsigned char*)header->code;
@@ -3279,19 +3374,30 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
                /* handle exception clauses */
                for (i = 0; i < header->num_clauses; ++i) {
-                       //unsigned char *p = ip;
+                       MonoBasicBlock *try_bb;
                        MonoExceptionClause *clause = &header->clauses [i];
-                       GET_BBLOCK (cfg, bbhash, tblock, ip + clause->try_offset);
-                       tblock->real_offset = clause->try_offset;
+                       GET_BBLOCK (cfg, bbhash, try_bb, ip + clause->try_offset);
+                       try_bb->real_offset = clause->try_offset;
                        GET_BBLOCK (cfg, bbhash, tblock, ip + clause->handler_offset);
                        tblock->real_offset = clause->handler_offset;
+                       tblock->flags |= BB_EXCEPTION_HANDLER;
+
+                       link_bblock (cfg, try_bb, tblock);
+
+                       if (*(ip + clause->handler_offset) == CEE_POP)
+                               tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
 
                        if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
                            clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
                                MONO_ADD_INS (tblock, ins);
+
+                               /* todo: is a fault block unsafe to optimize? */
+                               if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
+                                       tblock->flags |= BB_EXCEPTION_UNSAFE;
                        }
 
+
                        /*g_print ("clause try IL_%04x to IL_%04x handler %d at IL_%04x to IL_%04x\n", clause->try_offset, clause->try_offset + clause->try_len, clause->flags, clause->handler_offset, clause->handler_offset + clause->handler_len);
                          while (p < end) {
                          g_print ("%s", mono_disasm_code_one (NULL, method, p, &p));
@@ -3807,6 +3913,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* FIXME: check the signature matches */
                        cmethod = mini_get_method (method, token, NULL, generic_context);
 
+                       if (!cmethod)
+                               goto load_error;
+
                        if (mono_use_security_manager) {
                                check_linkdemand (cfg, method, cmethod, bblock, ip);
                        }
@@ -3848,7 +3957,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        cmethod = mini_get_method (method, token, NULL, generic_context);
                                }
 
-                               g_assert (cmethod);
+                               if (!cmethod)
+                                       goto load_error;
 
                                if (!virtual && (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT))
                                        /* MS.NET seems to silently convert this to a callvirt */
@@ -3893,7 +4003,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 
                        if (cmethod && cmethod->klass->generic_container) {
-                               G_BREAKPOINT ();
+                               // G_BREAKPOINT ();
                                goto unverified;
                        }
 
@@ -3941,7 +4051,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 
                        if (*ip != CEE_CALLI && check_call_signature (cfg, fsig, sp)) {
-                               G_BREAKPOINT ();
+                               // G_BREAKPOINT ();
                                goto unverified;
                        }
 
@@ -4167,8 +4277,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (ip_in_bb (cfg, bblock, ip + 5) 
                                    && (!MONO_TYPE_ISSTRUCT (fsig->ret))
                                    && (!MONO_TYPE_IS_VOID (fsig->ret) || cmethod->string_ctor)
-                                   && (CODE_IS_STLOC (ip + 5) || ip [5] == CEE_POP || ip [5] == CEE_BRTRUE || ip [5] == CEE_BRFALSE ||
-                                       ip [5] == CEE_BRTRUE_S || ip [5] == CEE_BRFALSE_S || ip [5] == CEE_RET)) {
+                                   && (CODE_IS_STLOC (ip + 5) || ip [5] == CEE_POP || ip [5] == CEE_RET)) {
                                        /* no need to spill */
                                        ins = (MonoInst*)mono_emit_method_call (cfg, bblock, cmethod, fsig, sp, ip, virtual ? sp [0] : NULL);
                                        *sp++ = ins;
@@ -4415,9 +4524,37 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins_flag = 0;
                        inline_costs += 1;
                        break;
+               case CEE_MUL:
+                       CHECK_STACK (2);
+                       ADD_BINOP (*ip);
+
+#ifdef MONO_ARCH_NO_EMULATE_MUL_IMM
+                       /* FIXME: This breaks with ssapre (mono -O=ssapre loader.exe) */
+                       if ((ins->inst_right->opcode == OP_ICONST) && !(cfg->opt & MONO_OPT_SSAPRE)) {
+                               switch (ins->opcode) {
+                               case CEE_MUL:
+                                       ins->opcode = OP_IMUL_IMM;
+                                       ins->inst_imm = ins->inst_right->inst_c0;
+                                       break;
+                               case OP_LMUL:
+                                       ins->opcode = OP_LMUL_IMM;
+                                       ins->inst_imm = ins->inst_right->inst_c0;
+                                       break;
+                               default:
+                                       g_assert_not_reached ();
+                               }
+                       }
+#endif
+
+                       if (mono_find_jit_opcode_emulation (ins->opcode)) {
+                               --sp;
+                               *sp++ = emit_tree (cfg, bblock, ins, ip + 1);
+                               mono_get_got_var (cfg);
+                       }
+                       ip++;
+                       break;
                case CEE_ADD:
                case CEE_SUB:
-               case CEE_MUL:
                case CEE_DIV:
                case CEE_DIV_UN:
                case CEE_REM:
@@ -4518,12 +4655,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        CHECK_STACK (2);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
                        sp -= 2;
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                MonoInst *store, *load;
@@ -4571,12 +4705,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_STACK (1);
                        --sp;
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
                                ins->cil_code = ip;
@@ -4722,6 +4853,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        cmethod = mini_get_method (method, token, NULL, generic_context);
+                       if (!cmethod)
+                               goto load_error;
                        fsig = mono_method_get_signature (cmethod, image, token);
 
                        mono_class_init (cmethod->klass);
@@ -4824,11 +4957,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
 
                        /* Needed by the code generated in inssel.brg */
                        mono_get_got_var (cfg);
@@ -4882,11 +5013,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
-                       else 
-                               klass = mono_class_get_full (image, token, generic_context);
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
 
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                /* CASTCLASS */
@@ -4932,6 +5061,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                break;
                        }
 
+                       if (mono_class_is_nullable (klass)) {
+                               int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+                               NEW_TEMPLOAD (cfg, *sp, v);
+                               sp ++;
+                               ip += 5;
+                               break;
+                       }
+
                        MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
                        ins->type = STACK_OBJ;
                        ins->inst_left = *sp;
@@ -4978,11 +5115,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
-                       else 
-                               klass = mono_class_get_full (image, token, generic_context);
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
+
+                       if (mono_class_is_nullable (klass)) {
+                               int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+                               NEW_TEMPLOAD (cfg, *sp, v);
+                               sp ++;
+                               ip += 5;
+                               break;
+                       }
 
                        /* Needed by the code generated in inssel.brg */
                        mono_get_got_var (cfg);
@@ -5009,11 +5152,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
 
                        /* Needed by the code generated in inssel.brg */
                        mono_get_got_var (cfg);
@@ -5071,6 +5212,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->cil_code = ip - 1;
                        MONO_ADD_INS (bblock, ins);
                        sp = stack_start;
+                       
                        link_bblock (cfg, bblock, end_bblock);
                        start_new_bblock = 1;
                        mono_get_got_var (cfg);
@@ -5097,6 +5239,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        field = mono_field_from_token (image, token, &klass, generic_context);
+                       if (!field)
+                               goto load_error;
                        mono_class_init (klass);
 
                        foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
@@ -5158,7 +5302,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                }
                        } else {
                                if ((klass->marshalbyref && !MONO_CHECK_THIS (sp [0])) || klass->contextbound || klass == mono_defaults.marshalbyrefobject_class) {
-                                       MonoMethod *ldfld_wrapper = mono_marshal_get_ldfld_wrapper (field->type); 
+                                       MonoMethod *wrapper = (*ip == CEE_LDFLDA) ? mono_marshal_get_ldflda_wrapper (field->type) : mono_marshal_get_ldfld_wrapper (field->type); 
                                        MonoInst *iargs [4];
                                        int temp;
                                        
@@ -5166,8 +5310,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        NEW_CLASSCONST (cfg, iargs [1], klass);
                                        NEW_FIELDCONST (cfg, iargs [2], field);
                                        NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
-                                       if ((cfg->opt & MONO_OPT_INLINE) && !MONO_TYPE_ISSTRUCT (mono_method_signature (ldfld_wrapper)->ret)) {
-                                               costs = inline_method (cfg, ldfld_wrapper, mono_method_signature (ldfld_wrapper), bblock, 
+                                       if ((cfg->opt & MONO_OPT_INLINE) && !MONO_TYPE_ISSTRUCT (mono_method_signature (wrapper)->ret)) {
+                                               costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), bblock, 
                                                                       iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
                                                g_assert (costs > 0);
                                                      
@@ -5180,12 +5324,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                                temp = iargs [0]->inst_i0->inst_c0;
 
-                                               if (*ip == CEE_LDFLDA) {
-                                                       /* not sure howto handle this */
-                                                       NEW_TEMPLOADA (cfg, *sp, temp);
-                                               } else {
-                                                       NEW_TEMPLOAD (cfg, *sp, temp);
-                                               }
+                                               NEW_TEMPLOAD (cfg, *sp, temp);
                                                sp++;
 
                                                /* indicates start of a new block, and triggers a load of
@@ -5195,13 +5334,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                inline_costs += costs;
                                                break;
                                        } else {
-                                               temp = mono_emit_method_call_spilled (cfg, bblock, ldfld_wrapper, mono_method_signature (ldfld_wrapper), iargs, ip, NULL);
-                                               if (*ip == CEE_LDFLDA) {
-                                                       /* not sure howto handle this */
-                                                       NEW_TEMPLOADA (cfg, *sp, temp);
-                                               } else {
-                                                       NEW_TEMPLOAD (cfg, *sp, temp);
-                                               }
+                                               temp = mono_emit_method_call_spilled (cfg, bblock, wrapper, mono_method_signature (wrapper), iargs, ip, NULL);
+                                               NEW_TEMPLOAD (cfg, *sp, temp);
                                                sp++;
                                        }
                                } else {
@@ -5239,6 +5373,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        token = read32 (ip + 1);
 
                        field = mono_field_from_token (image, token, &klass, generic_context);
+                       if (!field)
+                               goto load_error;
                        mono_class_init (klass);
 
                        g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
@@ -5414,11 +5550,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        sp -= 2;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
                        n = mono_type_to_stind (&klass->byval_arg);
                        if (n == CEE_STOBJ) {
                                handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE);
@@ -5443,11 +5577,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        val = *sp;
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
 
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                *sp++ = val;
@@ -5478,12 +5610,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        /* Ditto */
                        mono_get_got_var (cfg);
 
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
-                       else
-                               klass = mono_class_get_full (image, token, generic_context);
-
-                       mono_class_init (klass);
+                       klass = mini_get_class (method, token, generic_context);
+                       if (!klass)
+                               goto load_error;
                        ins->inst_newa_class = klass;
                        ins->inst_newa_len = *sp;
                        ins->type = STACK_OBJ;
@@ -5520,11 +5649,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        sp -= 2;
                        CHECK_OPSIZE (5);
 
-                       if (method->wrapper_type != MONO_WRAPPER_NONE)
-                               klass = (MonoClass*)mono_method_get_wrapper_data (method, read32 (ip + 1));
-                       else
-                               klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
-                       
+                       klass = mini_get_class (method, read32 (ip + 1), generic_context);
+                       if (!klass)
+                               goto load_error;                        
                        /* we need to make sure that this array is exactly the type it needs
                         * to be for correctness. the wrappers are lax with their usage
                         * so we need to ignore them here
@@ -5552,6 +5679,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mono_class_get_full (image, token, generic_context);
+                       if (!klass)
+                               goto load_error;
                        mono_class_init (klass);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
@@ -5633,6 +5762,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (5);
                        token = read32 (ip + 1);
                        klass = mono_class_get_full (image, token, generic_context);
+                       if (!klass)
+                               goto load_error;
                        mono_class_init (klass);
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                MonoMethod* helper = mono_marshal_get_stelemref ();
@@ -5723,6 +5854,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+                       if (!klass)
+                               goto load_error;
                        mono_class_init (klass);
                        ins->type = STACK_MP;
                        ins->inst_left = *sp;
@@ -5740,6 +5873,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        --sp;
                        CHECK_OPSIZE (5);
                        klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+                       if (!klass)
+                               goto load_error;
                        mono_class_init (klass);
                        ins->cil_code = ip;
 
@@ -5772,6 +5907,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        else {
                                handle = mono_ldtoken (image, n, &handle_class, generic_context);
                        }
+                       if (!handle)
+                               goto load_error;
                        mono_class_init (handle_class);
 
                        if (cfg->opt & MONO_OPT_SHARED) {
@@ -6187,7 +6324,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                n = read32 (ip + 2);
                                cmethod = mini_get_method (method, n, NULL, generic_context);
-
+                               if (!cmethod)
+                                       goto load_error;
                                mono_class_init (cmethod->klass);
 
                                if (mono_use_security_manager) {
@@ -6216,7 +6354,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                n = read32 (ip + 2);
                                cmethod = mini_get_method (method, n, NULL, generic_context);
-
+                               if (!cmethod)
+                                       goto load_error;
                                mono_class_init (cmethod->klass);
 
                                if (mono_use_security_manager) {
@@ -6388,10 +6527,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                --sp;
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
-                               if (method->wrapper_type != MONO_WRAPPER_NONE)
-                                       klass = mono_method_get_wrapper_data (method, token);
-                               else
-                                       klass = mono_class_get_full (image, token, generic_context);
+                               klass = mini_get_class (method, token, generic_context);
+                               if (!klass)
+                                       goto load_error;
                                if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
                                        MonoInst *store, *load;
                                        NEW_PCONST (cfg, load, NULL);
@@ -6414,6 +6552,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
                                constrained_call = mono_class_get_full (image, token, generic_context);
+                               if (!constrained_call)
+                                       goto load_error;
                                ip += 6;
                                break;
                        case CEE_CPBLK:
@@ -6468,6 +6608,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                handler_offset = clause->handler_offset;
                                }
 
+                               bblock->flags |= BB_EXCEPTION_UNSAFE;
+
                                g_assert (handler_offset != -1);
 
                                NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, handler_offset)->inst_c0);
@@ -6492,9 +6634,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MonoType *type = mono_type_create_from_typespec (image, token);
                                        token = mono_type_size (type, &align);
                                } else {
-                                       MonoClass *szclass = mono_class_get_full (image, token, generic_context);
-                                       mono_class_init (szclass);
-                                       token = mono_class_value_size (szclass, &align);
+                                       MonoClass *klass = mono_class_get_full (image, token, generic_context);
+                                       if (!klass)
+                                               goto load_error;
+                                       mono_class_init (klass);
+                                       token = mono_class_value_size (klass, &align);
                                }
                                NEW_ICONST (cfg, ins, token);
                                ins->cil_code = ip;
@@ -6631,6 +6775,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        dont_inline = g_list_remove (dont_inline, method);
        return -1;
 
+ load_error:
+       if (cfg->method != method)
+               g_hash_table_destroy (bbhash);
+       g_slist_free (class_inits);
+       dont_inline = g_list_remove (dont_inline, method);
+       return -1;
+
  unverified:
        if (cfg->method != method) 
                g_hash_table_destroy (bbhash);
@@ -6824,6 +6975,17 @@ mono_init_trampolines (void)
 #endif
 }
 
+static void
+mono_init_exceptions (void)
+{
+#ifndef CUSTOM_EXCEPTION_HANDLING
+       mono_arch_get_restore_context ();
+       mono_arch_get_call_filter ();
+       mono_arch_get_throw_exception ();
+       mono_arch_get_rethrow_exception ();
+#endif
+}
+
 guint8 *
 mono_get_trampoline_code (MonoTrampolineType tramp_type)
 {
@@ -6858,11 +7020,11 @@ mono_create_class_init_trampoline (MonoVTable *vtable)
                                                          vtable, ptr);
        mono_domain_unlock (vtable->domain);
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (!class_init_hash_addr)
                class_init_hash_addr = g_hash_table_new (NULL, NULL);
        g_hash_table_insert (class_init_hash_addr, ptr, vtable);
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
 
        return ptr;
 }
@@ -7016,12 +7178,12 @@ mono_find_class_init_trampoline_by_addr (gconstpointer addr)
 {
        MonoVTable *res;
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (class_init_hash_addr)
                res = g_hash_table_lookup (class_init_hash_addr, addr);
        else
                res = NULL;
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
        return res;
 }
 
@@ -7052,7 +7214,7 @@ typedef struct {
 } StackSlotInfo;
 
 /*
- * mono_allocate_stack_slots:
+ * mono_allocate_stack_slots_full:
  *
  *  Allocate stack slots for all non register allocated variables using a
  * linear scan algorithm.
@@ -7061,7 +7223,7 @@ typedef struct {
  * STACK_ALIGN is set to the alignment needed by the locals area.
  */
 gint32*
-mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
+mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stack_size, guint32 *stack_align)
 {
        int i, slot, offset, size, align;
        MonoMethodVar *vmv;
@@ -7182,10 +7344,18 @@ mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_a
                        if (t->type == MONO_TYPE_VALUETYPE)
                                align = sizeof (gpointer);
 
-                       offset += size;
-                       offset += align - 1;
-                       offset &= ~(align - 1);
-                       slot = offset;
+                       if (backward) {
+                               offset += size;
+                               offset += align - 1;
+                               offset &= ~(align - 1);
+                               slot = offset;
+                       }
+                       else {
+                               offset += align - 1;
+                               offset &= ~(align - 1);
+                               slot = offset;
+                               offset += size;
+                       }
 
                        if (*stack_align == 0)
                                *stack_align = align;
@@ -7209,6 +7379,12 @@ mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_a
        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);
+}
+
 void
 mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, gboolean no_throw)
 {
@@ -7504,6 +7680,10 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
 
        mono_arch_setup_jit_tls_data (jit_tls);
 
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+       mono_setup_altstack (jit_tls);
+#endif
+
        return jit_tls;
 }
 
@@ -7547,6 +7727,10 @@ mini_thread_cleanup (MonoThread *thread)
 
        if (jit_tls) {
                mono_arch_free_jit_tls_data (jit_tls);
+
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+               mono_free_altstack (jit_tls);
+#endif
                g_free (jit_tls->first_lmf);
                g_free (jit_tls);
                thread->jit_data = NULL;
@@ -8757,7 +8941,7 @@ mono_cprop_invalidate_values (MonoInst *tree, MonoInst **acp, int acp_size)
        case CEE_STIND_R4:
        case CEE_STIND_R8:
        case CEE_STOBJ:
-               if (tree->ssa_op == MONO_SSA_NOP) {
+               if ((tree->ssa_op == MONO_SSA_NOP) || (tree->ssa_op & MONO_SSA_ADDRESS_TAKEN)) {
                        memset (acp, 0, sizeof (MonoInst *) * acp_size);
                        return;
                }
@@ -9019,10 +9203,16 @@ MonoCompile*
 mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, gboolean compile_aot, int parts)
 {
        MonoMethodHeader *header = mono_method_get_header (method);
-       guint8 *ip = (guint8 *)header->code;
+       guint8 *ip;
        MonoCompile *cfg;
        MonoJitInfo *jinfo;
        int dfn = 0, i, code_size_ratio;
+       gboolean deadce_has_run = FALSE;
+
+       if (!header)
+               return NULL;
+
+       ip = (guint8 *)header->code;
 
        mono_jit_stats.methods_compiled++;
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
@@ -9040,7 +9230,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        cfg->compile_aot = compile_aot;
        cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * 
                                            mono_method_get_header (method)->max_stack);
-
+       cfg->aliasing_info = NULL;
+       
        if (cfg->verbose_level > 2)
                g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
 
@@ -9125,7 +9316,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 #else 
 
        /* fixme: add all optimizations which requires SSA */
-       if (cfg->opt & (MONO_OPT_DEADCE | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
+       if (cfg->opt & (MONO_OPT_SSA | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
                if (!(cfg->comp_done & MONO_COMP_SSA) && !header->num_clauses && !cfg->disable_ssa) {
                        mono_local_cprop (cfg);
                        mono_ssa_compute (cfg);
@@ -9150,16 +9341,23 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        }
 
        if (cfg->comp_done & MONO_COMP_SSA) {                   
-               mono_ssa_deadce (cfg);
+               //mono_ssa_deadce (cfg);
 
                //mono_ssa_strength_reduction (cfg);
 
+               if (cfg->opt & MONO_OPT_SSAPRE) {
+                       mono_perform_ssapre (cfg);
+                       //mono_local_cprop (cfg);
+               }
+               
+               if (cfg->opt & MONO_OPT_DEADCE) {
+                       mono_ssa_deadce (cfg);
+                       deadce_has_run = TRUE;
+               }
+               
                if ((cfg->flags & MONO_CFG_HAS_LDELEMA) && (cfg->opt & MONO_OPT_ABCREM))
                        mono_perform_abc_removal (cfg);
                
-               if (cfg->opt & MONO_OPT_SSAPRE)
-                       mono_perform_ssapre (cfg);
-               
                mono_ssa_remove (cfg);
 
                if (cfg->opt & MONO_OPT_BRANCH)
@@ -9195,18 +9393,33 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 
        if (cfg->opt & MONO_OPT_LINEARS) {
                GList *vars, *regs;
+               
+               /* For now, compute aliasing info only if needed for deadce... */
+               if ((cfg->opt & MONO_OPT_DEADCE) && (! deadce_has_run) && (header->num_clauses == 0)) {
+                       cfg->aliasing_info = mono_build_aliasing_information (cfg);
+               }
 
                /* fixme: maybe we can avoid to compute livenesss here if already computed ? */
                cfg->comp_done &= ~MONO_COMP_LIVENESS;
                if (!(cfg->comp_done & MONO_COMP_LIVENESS))
                        mono_analyze_liveness (cfg);
 
+               if (cfg->aliasing_info != NULL) {
+                       mono_aliasing_deadce (cfg->aliasing_info);
+                       deadce_has_run = TRUE;
+               }
+               
                if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
                        regs = mono_arch_get_global_int_regs (cfg);
                        if (cfg->got_var)
                                regs = g_list_delete_link (regs, regs);
                        mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs);
                }
+               
+               if (cfg->aliasing_info != NULL) {
+                       mono_destroy_aliasing_information (cfg->aliasing_info);
+                       cfg->aliasing_info = NULL;
+               }
        }
 
        //mono_print_code (cfg);
@@ -9283,6 +9496,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
        }
 
        cfg->jit_info = jinfo;
+#if defined(__arm__)
+       mono_arch_fixup_jinfo (cfg);
+#endif
 
        mono_domain_lock (cfg->domain);
        mono_jit_info_table_add (cfg->domain, jinfo);
@@ -9347,7 +9563,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain)
        method = mono_get_inflated_method (method);
 
 #ifdef MONO_USE_AOT_COMPILER
-       if (!mono_compile_aot && (opt & MONO_OPT_AOT)) {
+       if (!mono_compile_aot && (opt & MONO_OPT_AOT) && !(mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)) {
                MonoJitInfo *info;
                MonoDomain *domain = mono_domain_get ();
 
@@ -9410,6 +9626,19 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain)
 
        cfg = mini_method_compile (method, opt, target_domain, TRUE, FALSE, 0);
 
+       if (!cfg) {
+               /* Throw a type load exception if needed */
+               MonoLoaderError *error = mono_loader_get_last_error ();
+
+               if (error) {
+                       MonoException *ex = mini_loader_error_to_exception (error);
+                       mono_loader_clear_error ();
+                       mono_raise_exception (ex);
+               }
+               else
+                       g_assert_not_reached ();
+       }
+
        mono_domain_lock (target_domain);
 
        /* Check if some other thread already did the job. In this case, we can
@@ -9473,13 +9702,13 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt)
                        mono_domain_unlock (target_domain);
                        mono_jit_stats.methods_lookups++;
                        mono_runtime_class_init (mono_class_vtable (domain, method->klass));
-                       return mono_create_ftnptr (domain, info->code_start);
+                       return mono_create_ftnptr (target_domain, info->code_start);
                }
        }
 
        mono_domain_unlock (target_domain);
        p = mono_jit_compile_method_inner (method, target_domain);
-       return mono_create_ftnptr (domain, p);
+       return mono_create_ftnptr (target_domain, p);
 }
 
 static gpointer
@@ -9618,7 +9847,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
 #define GET_CONTEXT \
     ucontext_t *uctx = context; \
     struct sigcontext *ctx = (struct sigcontext *)&(uctx->uc_mcontext);
-#elif defined(__ppc__) || defined (__powerpc__) || defined (__s390__) || defined (MONO_ARCH_USE_SIGACTION)
+#elif defined (MONO_ARCH_USE_SIGACTION)
 #define GET_CONTEXT \
     void *ctx = context;
 #else
@@ -9659,7 +9888,8 @@ static void
 SIG_HANDLER_SIGNATURE (sigill_signal_handler)
 {
        MonoException *exc;
-       GET_CONTEXT
+       GET_CONTEXT;
+
        exc = mono_get_exception_execution_engine ("SIGILL");
        
        mono_arch_handle_exception (ctx, exc, FALSE);
@@ -9677,10 +9907,25 @@ static void
 SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
 {
        MonoException *exc = NULL;
+       MonoJitInfo *ji;
+
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
 #endif
-       GET_CONTEXT
+       GET_CONTEXT;
+
+#ifdef MONO_ARCH_USE_SIGACTION
+       if (debug_options.collect_pagefault_stats) {
+               if (mono_raw_buffer_is_pagefault (info->si_addr)) {
+                       mono_raw_buffer_handle_pagefault (info->si_addr);
+                       return;
+               }
+               if (mono_aot_is_pagefault (info->si_addr)) {
+                       mono_aot_handle_pagefault (info->si_addr);
+                       return;
+               }
+       }
+#endif
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        /* Can't allocate memory using Boehm GC on altstack */
@@ -9692,13 +9937,9 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
                exc = mono_domain_get ()->null_reference_ex;
 #endif
 
-       if (debug_options.abort_on_sigsegv) {
-               MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
-               if (!ji) {
-                       fprintf (stderr, "Got SIGSEGV while in unmanaged code, and the 'abort-on-sigsegv' MONO_DEBUG option is set. Aborting...\n");
-                       /* Segfault in unmanaged code */
-                       abort ();
-               }
+       ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
+       if (!ji) {
+               mono_handle_native_sigsegv (ctx);
        }
                        
        mono_arch_handle_exception (ctx, exc, FALSE);
@@ -9739,19 +9980,19 @@ SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
 static void
 SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
 {
-       MonoException *exc;
-       GET_CONTEXT
+       MonoException *exc;
+       GET_CONTEXT;
 
-       exc = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
+       exc = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
        
-       mono_arch_handle_exception (ctx, exc, FALSE);
+       mono_arch_handle_exception (ctx, exc, FALSE);
 }
 
 static void
 SIG_HANDLER_SIGNATURE (sigint_signal_handler)
 {
        MonoException *exc;
-       GET_CONTEXT
+       GET_CONTEXT;
 
        exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
        
@@ -9818,6 +10059,7 @@ mono_runtime_install_handlers (void)
                add_signal_handler (SIGUSR2, sigusr2_signal_handler);
 
        add_signal_handler (mono_thread_get_abort_signal (), sigusr1_signal_handler);
+       signal (SIGPIPE, SIG_IGN);
 
        /* catch SIGSEGV */
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
@@ -9957,11 +10199,11 @@ mini_parse_debug_options (void)
                        debug_options.handle_sigint = TRUE;
                else if (!strcmp (arg, "keep-delegates"))
                        debug_options.keep_delegates = TRUE;
-               else if (!strcmp (arg, "abort-on-sigsegv"))
-                       debug_options.abort_on_sigsegv = TRUE;
+               else if (!strcmp (arg, "collect-pagefault-stats"))
+                       debug_options.collect_pagefault_stats = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'abort-on-sigsegv'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats'\n");
                        exit (1);
                }
        }
@@ -9985,6 +10227,8 @@ mini_init (const char *filename)
 
        mono_init_trampolines ();
 
+       mono_init_exceptions ();
+
        if (!g_thread_supported ())
                g_thread_init (NULL);
 
@@ -10028,6 +10272,11 @@ mini_init (const char *filename)
        mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
 
+       if (debug_options.collect_pagefault_stats) {
+               mono_raw_buffer_set_make_unreadable (TRUE);
+               mono_aot_set_make_unreadable (TRUE);
+       }
+
        domain = mono_init_from_assembly (filename, filename);
        mono_icall_init ();
 
@@ -10215,6 +10464,10 @@ print_jit_stats (void)
                        g_print ("LinkDemand (aptc)     : %ld\n", mono_jit_stats.cas_linkdemand_aptc);
                        g_print ("Demand (code gen)     : %ld\n", mono_jit_stats.cas_demand_generation);
                }
+               if (debug_options.collect_pagefault_stats) {
+                       g_print ("Metadata pagefaults   : %d\n", mono_raw_buffer_get_n_pagefaults ());
+                       g_print ("AOT pagefaults        : %d\n", mono_aot_get_n_pagefaults ());
+               }
        }
 }