Merge pull request #2720 from mono/fix-39325
[mono.git] / mono / mini / mini-x86.c
index 179181f3d569f6e463f4a62f676f105eb0b795f1..5e9204611d7bf37760b7aae0a19dcb1057196085 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright 2003 Ximian, Inc.
  * Copyright 2003-2011 Novell Inc.
  * Copyright 2011 Xamarin Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include "mini.h"
 #include <string.h>
@@ -23,7 +24,7 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-mmap.h>
@@ -45,9 +46,15 @@ static gboolean optimize_for_xen = TRUE;
 #endif
 #endif
 
+/* The single step trampoline */
+static gpointer ss_trampoline;
+
+/* The breakpoint trampoline */
+static gpointer bp_trampoline;
+
 /* This mutex protects architecture specific caches */
-#define mono_mini_arch_lock() mono_mutex_lock (&mini_arch_mutex)
-#define mono_mini_arch_unlock() mono_mutex_unlock (&mini_arch_mutex)
+#define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
+#define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
 static mono_mutex_t mini_arch_mutex;
 
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
@@ -63,8 +70,7 @@ static mono_mutex_t mini_arch_mutex;
 
 #define X86_IS_CALLEE_SAVED_REG(reg) (((reg) == X86_EBX) || ((reg) == X86_EDI) || ((reg) == X86_ESI))
 
-MonoBreakpointInfo
-mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
+#define OP_SEQ_POINT_BP_OFFSET 7
 
 static guint8*
 emit_load_aotconst (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji, int dreg, int tramp_type, gconstpointer target);
@@ -102,15 +108,6 @@ mono_arch_nacl_skip_nops (guint8 *code)
 
 #endif /* __native_client_codegen__ */
 
-/*
- * The code generated for sequence points reads from this location, which is
- * made read-only when single stepping is enabled.
- */
-static gpointer ss_trigger_page;
-
-/* Enabled breakpoints read from this trigger page */
-static gpointer bp_trigger_page;
-
 const char*
 mono_arch_regname (int reg)
 {
@@ -183,49 +180,6 @@ mono_x86_patch (unsigned char* code, gpointer target)
        x86_patch (code, (unsigned char*)target);
 }
 
-typedef enum {
-       ArgInIReg,
-       ArgInFloatSSEReg,
-       ArgInDoubleSSEReg,
-       ArgOnStack,
-       ArgValuetypeInReg,
-       ArgOnFloatFpStack,
-       ArgOnDoubleFpStack,
-       /* gsharedvt argument passed by addr */
-       ArgGSharedVt,
-       ArgNone
-} ArgStorage;
-
-typedef struct {
-       gint16 offset;
-       gint8  reg;
-       ArgStorage storage;
-       int nslots;
-       gboolean is_pair;
-
-       /* Only if storage == ArgValuetypeInReg */
-       ArgStorage pair_storage [2];
-       gint8 pair_regs [2];
-} ArgInfo;
-
-typedef struct {
-       int nargs;
-       guint32 stack_usage;
-       guint32 reg_usage;
-       guint32 freg_usage;
-       gboolean need_stack_align;
-       guint32 stack_align_amount;
-       gboolean vtype_retaddr;
-       /* The index of the vret arg in the argument list */
-       int vret_arg_index;
-       int vret_arg_offset;
-       /* Argument space popped by the callee */
-       int callee_stack_pop;
-       ArgInfo ret;
-       ArgInfo sig_cookie;
-       ArgInfo args [1];
-} CallInfo;
-
 #define FLOAT_PARAM_REGS 0
 
 static const guint32 thiscall_param_regs [] = { X86_ECX, X86_NREG };
@@ -758,15 +712,14 @@ mono_arch_cpu_init (void)
 void
 mono_arch_init (void)
 {
-       mono_mutex_init_recursive (&mini_arch_mutex);
+       mono_os_mutex_init_recursive (&mini_arch_mutex);
 
-       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
-       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
-       mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
+       if (!mono_aot_only)
+               bp_trampoline = mini_get_breakpoint_trampoline ();
 
        mono_aot_register_jit_icall ("mono_x86_throw_exception", mono_x86_throw_exception);
        mono_aot_register_jit_icall ("mono_x86_throw_corlib_exception", mono_x86_throw_corlib_exception);
-#if defined(ENABLE_GSHAREDVT)
+#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
        mono_aot_register_jit_icall ("mono_x86_start_gsharedvt_call", mono_x86_start_gsharedvt_call);
 #endif
 }
@@ -777,11 +730,7 @@ mono_arch_init (void)
 void
 mono_arch_cleanup (void)
 {
-       if (ss_trigger_page)
-               mono_vfree (ss_trigger_page, mono_pagesize ());
-       if (bp_trigger_page)
-               mono_vfree (bp_trigger_page, mono_pagesize ());
-       mono_mutex_destroy (&mini_arch_mutex);
+       mono_os_mutex_destroy (&mini_arch_mutex);
 }
 
 /*
@@ -1105,8 +1054,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        offsets = mono_allocate_stack_slots (cfg, TRUE, &locals_stack_size, &locals_stack_align);
        if (locals_stack_size > MONO_ARCH_MAX_FRAME_SIZE) {
                char *mname = mono_method_full_name (cfg->method, TRUE);
-               cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
-               cfg->exception_message = g_strdup_printf ("Method %s stack is too big.", mname);
+               mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Method %s stack is too big.", mname));
                g_free (mname);
                return;
        }
@@ -1217,6 +1165,18 @@ mono_arch_create_vars (MonoCompile *cfg)
                cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
        }
 
+       if (cfg->gen_sdb_seq_points) {
+               MonoInst *ins;
+
+               ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               ins->flags |= MONO_INST_VOLATILE;
+               cfg->arch.ss_tramp_var = ins;
+
+               ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+               ins->flags |= MONO_INST_VOLATILE;
+               cfg->arch.bp_tramp_var = ins;
+       }
+
        if (cfg->method->save_lmf) {
                cfg->create_lmf_var = TRUE;
                cfg->lmf_ir = TRUE;
@@ -1344,11 +1304,11 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
 
                switch (ainfo->storage) {
                case ArgInIReg:
-                       linfo->args [i].storage = LLVMArgInIReg;
+                       linfo->args [i].storage = LLVMArgNormal;
                        break;
                case ArgInDoubleSSEReg:
                case ArgInFloatSSEReg:
-                       linfo->args [i].storage = LLVMArgInFPReg;
+                       linfo->args [i].storage = LLVMArgNormal;
                        break;
                case ArgOnStack:
                        if (mini_type_is_vtype (t)) {
@@ -1358,13 +1318,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
                                else
                                        linfo->args [i].storage = LLVMArgVtypeByVal;
                        } else {
-                               linfo->args [i].storage = LLVMArgInIReg;
-                               if (t->byref) {
-                                       if (t->type == MONO_TYPE_R4)
-                                               linfo->args [i].storage = LLVMArgInFPReg;
-                                       else if (t->type == MONO_TYPE_R8)
-                                               linfo->args [i].storage = LLVMArgInFPReg;
-                               }
+                               linfo->args [i].storage = LLVMArgNormal;
                        }
                        break;
                case ArgValuetypeInReg:
@@ -1540,8 +1494,8 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg);
                                                argsize = 8;
                                        } else if (t->type == MONO_TYPE_I8 || t->type == MONO_TYPE_U8) {
-                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset + 4, in->dreg + 2);
-                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg + 1);
+                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset + 4, MONO_LVREG_MS (in->dreg));
+                                               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, MONO_LVREG_LS (in->dreg));
                                                argsize = 4;
                                        } else {
                                                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg);
@@ -1677,8 +1631,8 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
                        if (COMPILE_LLVM (cfg))
                                MONO_EMIT_NEW_UNALU (cfg, OP_LMOVE, cfg->ret->dreg, val->dreg);
                        else {
-                               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, X86_EAX, val->dreg + 1);
-                               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, X86_EDX, val->dreg + 2);
+                               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, X86_EAX, MONO_LVREG_LS (val->dreg));
+                               MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, X86_EDX, MONO_LVREG_MS (val->dreg));
                        }
                        return;
                }
@@ -2479,26 +2433,6 @@ emit_setup_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, int cfa_offse
        return code;
 }
 
-#define REAL_PRINT_REG(text,reg) \
-mono_assert (reg >= 0); \
-x86_push_reg (code, X86_EAX); \
-x86_push_reg (code, X86_EDX); \
-x86_push_reg (code, X86_ECX); \
-x86_push_reg (code, reg); \
-x86_push_imm (code, reg); \
-x86_push_imm (code, text " %d %p\n"); \
-x86_mov_reg_imm (code, X86_EAX, printf); \
-x86_call_reg (code, X86_EAX); \
-x86_alu_reg_imm (code, X86_ADD, X86_ESP, 3*4); \
-x86_pop_reg (code, X86_ECX); \
-x86_pop_reg (code, X86_EDX); \
-x86_pop_reg (code, X86_EAX);
-
-/* REAL_PRINT_REG does not appear to be used, and was not adapted to work with Native Client. */
-#ifdef __native__client_codegen__
-#define REAL_PRINT_REG(text, reg) g_assert_not_reached()
-#endif
-
 /* benchmark and set based on cpu */
 #define LOOP_ALIGNMENT 8
 #define bb_is_loop_start(bb) ((bb)->loop_body_start && (bb)->nesting)
@@ -2773,22 +2707,51 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (cfg->compile_aot)
                                NOT_IMPLEMENTED;
 
+                       /* Have to use ecx as a temp reg since this can occur after OP_SETRET */
+
                        /* 
-                        * Read from the single stepping trigger page. This will cause a
-                        * SIGSEGV when single stepping is enabled.
                         * We do this _before_ the breakpoint, so single stepping after
                         * a breakpoint is hit will step to the next IL offset.
                         */
-                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC)
-                               x86_alu_reg_mem (code, X86_CMP, X86_EAX, (guint32)ss_trigger_page);
+                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
+                               MonoInst *var = cfg->arch.ss_tramp_var;
+                               guint8 *br [1];
+
+                               g_assert (var);
+                               g_assert (var->opcode == OP_REGOFFSET);
+                               /* Load ss_tramp_var */
+                               /* This is equal to &ss_trampoline */
+                               x86_mov_reg_membase (code, X86_ECX, var->inst_basereg, var->inst_offset, sizeof (mgreg_t));
+                               x86_alu_membase_imm (code, X86_CMP, X86_ECX, 0, 0);
+                               br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+                               x86_call_membase (code, X86_ECX, 0);
+                               x86_patch (br [0], code);
+                       }
+
+                       /*
+                        * Many parts of sdb depend on the ip after the single step trampoline call to be equal to the seq point offset.
+                        * This means we have to put the loading of bp_tramp_var after the offset.
+                        */
 
                        mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
 
+                       MonoInst *var = cfg->arch.bp_tramp_var;
+
+                       g_assert (var);
+                       g_assert (var->opcode == OP_REGOFFSET);
+                       /* Load the address of the bp trampoline */
+                       /* This needs to be constant size */
+                       guint8 *start = code;
+                       x86_mov_reg_membase (code, X86_ECX, var->inst_basereg, var->inst_offset, 4);
+                       if (code < start + OP_SEQ_POINT_BP_OFFSET) {
+                               int size = start + OP_SEQ_POINT_BP_OFFSET - code;
+                               x86_padding (code, size);
+                       }
                        /* 
                         * A placeholder for a possible breakpoint inserted by
                         * mono_arch_set_breakpoint ().
                         */
-                       for (i = 0; i < 6; ++i)
+                       for (i = 0; i < 2; ++i)
                                x86_nop (code);
                        /*
                         * Add an additional nop so skipping the bp doesn't cause the ip to point
@@ -3137,7 +3100,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                        saved_eax = TRUE;
                                        x86_push_reg (code, X86_EAX);
                                }
-                       } else if (ins->dreg != X86_EAX) {
+                       } else {
                                saved_edx = TRUE;
                                x86_push_reg (code, X86_EDX);
                        }
@@ -4207,7 +4170,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        x86_branch8 (code, X86_CC_NE, 0, FALSE);
 
                        x86_fstp (code, 0);                     
-                       EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "ArithmeticException");
+                       EMIT_COND_SYSTEM_EXCEPTION (X86_CC_EQ, FALSE, "OverflowException");
 
                        x86_patch (br1, code);
                        break;
@@ -5032,15 +4995,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        int compare_val = 0;
                        guint8 *br [1];
 
-#if defined (USE_COOP_GC)
-                       polling_func = "mono_threads_state_poll";
-                       compare_val = 1;
-#elif defined(__native_client_codegen__) && defined(__native_client_gc__)
+#if defined(__native_client_codegen__) && defined(__native_client_gc__)
                        polling_func = "mono_nacl_gc";
                        compare_val = 0xFFFFFFFF;
+#else
+                       g_assert (mono_threads_is_coop_enabled ());
+                       polling_func = "mono_threads_state_poll";
+                       compare_val = 1;
 #endif
-                       if (!polling_func)
-                               break;
 
                        x86_test_membase_imm (code, ins->sreg1, 0, compare_val);
                        br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
@@ -5106,9 +5068,6 @@ mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, guint8 *code, Mo
        case MONO_PATCH_INFO_BB:
        case MONO_PATCH_INFO_LABEL:
        case MONO_PATCH_INFO_RGCTX_FETCH:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
 #if defined(__native_client_codegen__) && defined(__native_client__)
                if (nacl_is_code_address (code)) {
@@ -5402,6 +5361,28 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
                code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
 
+       {
+               MonoInst *ins;
+
+               if (cfg->arch.ss_tramp_var) {
+                       /* Initialize ss_tramp_var */
+                       ins = cfg->arch.ss_tramp_var;
+                       g_assert (ins->opcode == OP_REGOFFSET);
+
+                       g_assert (!cfg->compile_aot);
+                       x86_mov_membase_imm (code, ins->inst_basereg, ins->inst_offset, (guint32)&ss_trampoline, 4);
+               }
+
+               if (cfg->arch.bp_tramp_var) {
+                       /* Initialize bp_tramp_var */
+                       ins = cfg->arch.bp_tramp_var;
+                       g_assert (ins->opcode == OP_REGOFFSET);
+
+                       g_assert (!cfg->compile_aot);
+                       x86_mov_membase_imm (code, ins->inst_basereg, ins->inst_offset, (guint32)&bp_trampoline, 4);
+               }
+       }
+
        /* load arguments allocated to register from the stack */
        sig = mono_method_signature (method);
        pos = 0;
@@ -5621,8 +5602,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
 
                        x86_patch (patch_info->ip.i + cfg->native_code, code);
 
-                       exc_class = mono_class_from_name (mono_defaults.corlib, "System", patch_info->data.name);
-                       g_assert (exc_class);
+                       exc_class = mono_class_load_from_name (mono_defaults.corlib, "System", patch_info->data.name);
                        throw_ip = patch_info->ip.i;
 
                        /* Find a throw sequence for the same exception class */
@@ -5762,6 +5742,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        int i;
        int size = 0;
        guint8 *code, *start;
+       GSList *unwind_ops;
 
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
@@ -5798,6 +5779,9 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                code = mono_domain_code_reserve (domain, size);
 #endif
        start = code;
+
+       unwind_ops = mono_arch_get_cie_program ();
+
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                item->code_target = code;
@@ -5884,7 +5868,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        nacl_domain_code_validate (domain, &start, size, &code);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
 
-       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL));
+       mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, unwind_ops), domain);
 
        return start;
 }
@@ -6081,6 +6065,9 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 par
 {
        guint8 *code, *start;
        int code_reserve = 64;
+       GSList *unwind_ops;
+
+       unwind_ops = mono_arch_get_cie_program ();
 
        /*
         * The stack contains:
@@ -6142,10 +6129,10 @@ get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 par
        nacl_global_codeman_validate (&start, code_reserve, &code);
 
        if (has_target) {
-               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
+               *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, unwind_ops);
        } else {
                char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
-               *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
+               *info = mono_tramp_info_create (name, start, code - start, NULL, unwind_ops);
                g_free (name);
        }
 
@@ -6172,6 +6159,7 @@ get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, i
        guint8 *code, *start;
        int size = 24;
        char *tramp_name;
+       GSList *unwind_ops;
 
        if (offset / (int)sizeof (gpointer) > MAX_VIRTUAL_DELEGATE_OFFSET)
                return NULL;
@@ -6183,6 +6171,8 @@ get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, i
         */
        start = code = mono_global_codeman_reserve (size);
 
+       unwind_ops = mono_arch_get_cie_program ();
+
        /* Replace the this argument with the target */
        x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
        x86_mov_reg_membase (code, X86_ECX, X86_EAX, MONO_STRUCT_OFFSET (MonoDelegate, target), 4);
@@ -6202,7 +6192,7 @@ get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, i
                tramp_name = g_strdup_printf ("delegate_virtual_invoke_imt_%d", - offset / sizeof (gpointer));
        else
                tramp_name = g_strdup_printf ("delegate_virtual_invoke_%d", offset / sizeof (gpointer));
-       *info = mono_tramp_info_create (tramp_name, start, code - start, NULL, NULL);
+       *info = mono_tramp_info_create (tramp_name, start, code - start, NULL, unwind_ops);
        g_free (tramp_name);
 
 
@@ -6263,7 +6253,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                } else {
                        MonoTrampInfo *info;
                        start = get_delegate_invoke_impl (&info, TRUE, 0);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -6288,7 +6278,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                } else {
                        MonoTrampInfo *info;
                        start = get_delegate_invoke_impl (&info, FALSE, sig->param_count);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
                }
 
                mono_memory_barrier ();
@@ -6307,7 +6297,7 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod
 
        code = get_delegate_virtual_invoke_impl (&info, load_imt_reg, offset);
        if (code)
-               mono_tramp_info_register (info);
+               mono_tramp_info_register (info, NULL);
        return code;
 }
 
@@ -6429,9 +6419,9 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
 
        if (long_ins->opcode == OP_LNEG) {
                ins = long_ins;
-               MONO_EMIT_NEW_UNALU (cfg, OP_INEG, ins->dreg + 1, ins->sreg1 + 1);
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, ins->dreg + 2, ins->sreg1 + 2, 0);
-               MONO_EMIT_NEW_UNALU (cfg, OP_INEG, ins->dreg + 2, ins->dreg + 2);
+               MONO_EMIT_NEW_UNALU (cfg, OP_INEG, MONO_LVREG_LS (ins->dreg), MONO_LVREG_LS (ins->sreg1));
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->sreg1), 0);
+               MONO_EMIT_NEW_UNALU (cfg, OP_INEG, MONO_LVREG_MS (ins->dreg), MONO_LVREG_MS (ins->dreg));
                NULLIFY_INS (ins);
                return;
        }
@@ -6460,7 +6450,7 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
                ins->klass = mono_defaults.int32_class;
                ins->sreg1 = vreg;
                ins->type = STACK_I4;
-               ins->dreg = long_ins->dreg + 1;
+               ins->dreg = MONO_LVREG_LS (long_ins->dreg);
                MONO_ADD_INS (cfg->cbb, ins);
        
                MONO_INST_NEW (cfg, ins, OP_PSHUFLED);
@@ -6475,7 +6465,7 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
                ins->klass = mono_defaults.int32_class;
                ins->sreg1 = vreg;
                ins->type = STACK_I4;
-               ins->dreg = long_ins->dreg + 2;
+               ins->dreg = MONO_LVREG_MS (long_ins->dreg);
                MONO_ADD_INS (cfg->cbb, ins);
        
                long_ins->opcode = OP_NOP;
@@ -6484,14 +6474,14 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
                MONO_INST_NEW (cfg, ins, OP_INSERTX_I4_SLOW);
                ins->dreg = long_ins->dreg;
                ins->sreg1 = long_ins->dreg;
-               ins->sreg2 = long_ins->sreg2 + 1;
+               ins->sreg2 = MONO_LVREG_LS (long_ins->sreg2);
                ins->inst_c0 = long_ins->inst_c0 * 2;
                MONO_ADD_INS (cfg->cbb, ins);
 
                MONO_INST_NEW (cfg, ins, OP_INSERTX_I4_SLOW);
                ins->dreg = long_ins->dreg;
                ins->sreg1 = long_ins->dreg;
-               ins->sreg2 = long_ins->sreg2 + 2;
+               ins->sreg2 = MONO_LVREG_MS (long_ins->sreg2);
                ins->inst_c0 = long_ins->inst_c0 * 2 + 1;
                MONO_ADD_INS (cfg->cbb, ins);
 
@@ -6500,7 +6490,7 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
        case OP_EXPAND_I8:
                MONO_INST_NEW (cfg, ins, OP_ICONV_TO_X);
                ins->dreg = long_ins->dreg;
-               ins->sreg1 = long_ins->sreg1 + 1;
+               ins->sreg1 = MONO_LVREG_LS (long_ins->sreg1);
                ins->klass = long_ins->klass;
                ins->type = STACK_VTYPE;
                MONO_ADD_INS (cfg->cbb, ins);
@@ -6508,7 +6498,7 @@ mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
                MONO_INST_NEW (cfg, ins, OP_INSERTX_I4_SLOW);
                ins->dreg = long_ins->dreg;
                ins->sreg1 = long_ins->dreg;
-               ins->sreg2 = long_ins->sreg1 + 2;
+               ins->sreg2 = MONO_LVREG_MS (long_ins->sreg1);
                ins->inst_c0 = 1;
                ins->klass = long_ins->klass;
                ins->type = STACK_VTYPE;
@@ -6595,7 +6585,7 @@ emit_load_aotconst (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo
  * EAX.
  */
 guint8*
-mono_arch_emit_load_aotconst (guint8 *start, guint8 *code, MonoJumpInfo **ji, int tramp_type, gconstpointer target)
+mono_arch_emit_load_aotconst (guint8 *start, guint8 *code, MonoJumpInfo **ji, MonoJumpInfoType tramp_type, gconstpointer target)
 {
        /* Load the mscorlib got address */
        x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_GOT_REG, sizeof (gpointer), 4);
@@ -6623,13 +6613,6 @@ mono_arch_get_trampolines (gboolean aot)
        return tramps;
 }
 
-
-#if __APPLE__
-#define DBG_SIGNAL SIGBUS
-#else
-#define DBG_SIGNAL SIGSEGV
-#endif
-
 /* Soft Debug support */
 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
 
@@ -6642,15 +6625,10 @@ mono_arch_get_trampolines (gboolean aot)
 void
 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
 {
-       guint8 *code = ip;
+       guint8 *code = ip + OP_SEQ_POINT_BP_OFFSET;
 
-       /* 
-        * In production, we will use int3 (has to fix the size in the md 
-        * file). But that could confuse gdb, so during development, we emit a SIGSEGV
-        * instead.
-        */
        g_assert (code [0] == 0x90);
-       x86_alu_reg_mem (code, X86_CMP, X86_EAX, (guint32)bp_trigger_page);
+       x86_call_membase (code, X86_ECX, 0);
 }
 
 /*
@@ -6661,10 +6639,10 @@ mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
 void
 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
 {
-       guint8 *code = ip;
+       guint8 *code = ip + OP_SEQ_POINT_BP_OFFSET;
        int i;
 
-       for (i = 0; i < 6; ++i)
+       for (i = 0; i < 2; ++i)
                x86_nop (code);
 }
        
@@ -6676,7 +6654,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
 void
 mono_arch_start_single_stepping (void)
 {
-       mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
+       ss_trampoline = mini_get_single_step_trampoline ();
 }
        
 /*
@@ -6687,7 +6665,7 @@ mono_arch_start_single_stepping (void)
 void
 mono_arch_stop_single_stepping (void)
 {
-       mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
+       ss_trampoline = NULL;
 }
 
 /*
@@ -6699,43 +6677,18 @@ mono_arch_stop_single_stepping (void)
 gboolean
 mono_arch_is_single_step_event (void *info, void *sigctx)
 {
-#ifdef TARGET_WIN32
-       EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */
-
-       if (((gpointer)einfo->ExceptionInformation[1] >= ss_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)ss_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#else
-       siginfo_t* sinfo = (siginfo_t*) info;
-       /* Sometimes the address is off by 4 */
-       if (sinfo->si_signo == DBG_SIGNAL && (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#endif
+       /* We use soft breakpoints */
+       return FALSE;
 }
 
 gboolean
 mono_arch_is_breakpoint_event (void *info, void *sigctx)
 {
-#ifdef TARGET_WIN32
-       EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */
-       if (((gpointer)einfo->ExceptionInformation[1] >= bp_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)bp_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#else
-       siginfo_t* sinfo = (siginfo_t*)info;
-       /* Sometimes the address is off by 4 */
-       if (sinfo->si_signo == DBG_SIGNAL && (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128))
-               return TRUE;
-       else
-               return FALSE;
-#endif
+       /* We use soft breakpoints */
+       return FALSE;
 }
 
-#define BREAKPOINT_SIZE 6
+#define BREAKPOINT_SIZE 2
 
 /*
  * mono_arch_skip_breakpoint:
@@ -6745,7 +6698,7 @@ mono_arch_is_breakpoint_event (void *info, void *sigctx)
 void
 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
 {
-       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
+       g_assert_not_reached ();
 }
 
 /*
@@ -6756,7 +6709,7 @@ mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
 void
 mono_arch_skip_single_step (MonoContext *ctx)
 {
-       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 6);
+       g_assert_not_reached ();
 }
 
 /*
@@ -6811,8 +6764,8 @@ mono_arch_opcode_supported (int opcode)
        }
 }
 
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/mini-x86-gsharedvt.c"
-
-#endif /* !MONOTOUCH */
+CallInfo*
+mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
+{
+       return get_call_info (mp, sig);
+}