2010-05-05 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-amd64.c
index c09f7722a22f29ce032298fc148b7adfa12b021a..fd6cc4b07163a8227ff086ff75af89442c2f3fef 100644 (file)
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/utils/mono-math.h>
+#include <mono/utils/mono-mmap.h>
 
 #include "trace.h"
 #include "ir-emit.h"
 #include "mini-amd64.h"
 #include "cpu-amd64.h"
+#include "debugger-agent.h"
 
 /* 
  * Can't define this in mini-amd64.h cause that would turn on the generic code in
@@ -39,7 +41,6 @@
 static gint lmf_tls_offset = -1;
 static gint lmf_addr_tls_offset = -1;
 static gint appdomain_tls_offset = -1;
-static gint thread_tls_offset = -1;
 
 #ifdef MONO_XEN_OPT
 static gboolean optimize_for_xen = TRUE;
@@ -53,7 +54,7 @@ static gboolean optimize_for_xen = TRUE;
 
 #define IS_REX(inst) (((inst) >= 0x40) && ((inst) <= 0x4f))
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 /* Under windows, the calling convention is never stdcall */
 #define CALLCONV_IS_STDCALL(call_conv) (FALSE)
 #else
@@ -68,7 +69,25 @@ static CRITICAL_SECTION mini_arch_mutex;
 MonoBreakpointInfo
 mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
 
-#ifdef PLATFORM_WIN32
+/*
+ * 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;
+
+/* The size of the breakpoint sequence */
+static int breakpoint_size;
+
+/* The size of the breakpoint instruction causing the actual fault */
+static int breakpoint_fault_size;
+
+/* The size of the single step instruction causing the actual fault */
+static int single_step_fault_size;
+
+#ifdef HOST_WIN32
 /* On Win64 always reserve first 32 bytes for first four arguments */
 #define ARGS_OFFSET 48
 #else
@@ -255,6 +274,7 @@ typedef struct {
        guint32 reg_usage;
        guint32 freg_usage;
        gboolean need_stack_align;
+       gboolean vtype_retaddr;
        ArgInfo ret;
        ArgInfo sig_cookie;
        ArgInfo args [1];
@@ -262,7 +282,7 @@ typedef struct {
 
 #define DEBUG(a) if (cfg->verbose_level > 1) a
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 #define PARAM_REGS 4
 
 static AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 };
@@ -292,7 +312,7 @@ add_general (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo)
     }
 }
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 #define FLOAT_PARAM_REGS 4
 #else
 #define FLOAT_PARAM_REGS 8
@@ -356,7 +376,7 @@ merge_argument_class_from_type (MonoType *type, ArgumentClass class1)
                break;
        case MONO_TYPE_R4:
        case MONO_TYPE_R8:
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                class2 = ARG_CLASS_INTEGER;
 #else
                class2 = ARG_CLASS_SSE;
@@ -423,7 +443,7 @@ add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgIn
 
        klass = mono_class_from_mono_type (type);
        size = mini_type_stack_size_full (gsctx, &klass->byval_arg, NULL, sig->pinvoke);
-#ifndef PLATFORM_WIN32
+#ifndef HOST_WIN32
        if (!sig->pinvoke && !disable_vtypes_in_regs && ((is_return && (size == 8)) || (!is_return && (size <= 16)))) {
                /* We pass and return vtypes of size 8 in a register */
        } else if (!sig->pinvoke || (size == 0) || (size > 16)) {
@@ -471,7 +491,7 @@ add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgIn
                info = mono_marshal_load_type_info (klass);
                g_assert (info);
 
-#ifndef PLATFORM_WIN32
+#ifndef HOST_WIN32
                if (info->native_size > 16) {
                        ainfo->offset = *stack_size;
                        *stack_size += ALIGN_TO (info->native_size, 8);
@@ -618,6 +638,8 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
        else
                cinfo = g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
 
+       cinfo->nargs = n;
+
        gr = 0;
        fr = 0;
 
@@ -659,7 +681,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                        cinfo->ret.reg = AMD64_XMM0;
                        break;
                case MONO_TYPE_GENERICINST:
-                       if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
+                       if (!mono_type_generic_inst_is_valuetype (ret_type)) {
                                cinfo->ret.storage = ArgInIReg;
                                cinfo->ret.reg = AMD64_RAX;
                                break;
@@ -669,9 +691,11 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                        guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
 
                        add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
-                       if (cinfo->ret.storage == ArgOnStack)
+                       if (cinfo->ret.storage == ArgOnStack) {
+                               cinfo->vtype_retaddr = TRUE;
                                /* The caller passes the address where the value is stored */
                                add_general (&gr, &stack_size, &cinfo->ret);
+                       }
                        break;
                }
                case MONO_TYPE_TYPEDBYREF:
@@ -702,7 +726,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                ArgInfo *ainfo = &cinfo->args [sig->hasthis + i];
                MonoType *ptype;
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                /* The float param registers and other param registers must be the same index on Windows x64.*/
                if (gr > fr)
                        fr = gr;
@@ -723,10 +747,6 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                        add_general (&gr, &stack_size, &cinfo->sig_cookie);
                }
 
-               if (sig->params [i]->byref) {
-                       add_general (&gr, &stack_size, ainfo);
-                       continue;
-               }
                ptype = mini_type_get_underlying_type (gsctx, sig->params [i]);
                switch (ptype->type) {
                case MONO_TYPE_BOOLEAN:
@@ -764,7 +784,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                        add_valuetype (gsctx, sig, ainfo, sig->params [i], FALSE, &gr, &fr, &stack_size);
                        break;
                case MONO_TYPE_TYPEDBYREF:
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                        add_valuetype (gsctx, sig, ainfo, sig->params [i], FALSE, &gr, &fr, &stack_size);
 #else
                        stack_size += sizeof (MonoTypedRef);
@@ -794,7 +814,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign
                add_general (&gr, &stack_size, &cinfo->sig_cookie);
        }
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        // There always is 32 bytes reserved on the stack when calling on Winx64
        stack_size += 0x20;
 #endif
@@ -891,7 +911,32 @@ mono_arch_cpu_init (void)
 void
 mono_arch_init (void)
 {
+       int flags;
+
        InitializeCriticalSection (&mini_arch_mutex);
+
+#ifdef MONO_ARCH_NOMAP32BIT
+       flags = MONO_MMAP_READ;
+       /* amd64_mov_reg_imm () + amd64_mov_reg_membase () */
+       breakpoint_size = 13;
+       breakpoint_fault_size = 3;
+       /* amd64_alu_membase_imm_size (code, X86_CMP, AMD64_R11, 0, 0, 4); */
+       single_step_fault_size = 5;
+#else
+       flags = MONO_MMAP_READ|MONO_MMAP_32BIT;
+       /* amd64_mov_reg_mem () */
+       breakpoint_size = 8;
+       breakpoint_fault_size = 8;
+       single_step_fault_size = 8;
+#endif
+
+       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), flags);
+       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), flags);
+       mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
+
+       mono_aot_register_jit_icall ("mono_amd64_throw_exception", mono_amd64_throw_exception);
+       mono_aot_register_jit_icall ("mono_amd64_throw_corlib_exception", mono_amd64_throw_corlib_exception);
+       mono_aot_register_jit_icall ("mono_amd64_get_original_ip", mono_amd64_get_original_ip);
 }
 
 /*
@@ -935,7 +980,6 @@ mono_arch_cpu_optimizazions (guint32 *exclude_mask)
  *
  * Returns a bitmask corresponding to all supported versions.
  * 
- * TODO detect other versions like SSE4a.
  */
 guint32
 mono_arch_cpu_enumerate_simd_versions (void)
@@ -945,21 +989,36 @@ mono_arch_cpu_enumerate_simd_versions (void)
 
        if (cpuid (1, &eax, &ebx, &ecx, &edx)) {
                if (edx & (1 << 25))
-                       sse_opts |= 1 << SIMD_VERSION_SSE1;
+                       sse_opts |= SIMD_VERSION_SSE1;
                if (edx & (1 << 26))
-                       sse_opts |= 1 << SIMD_VERSION_SSE2;
+                       sse_opts |= SIMD_VERSION_SSE2;
                if (ecx & (1 << 0))
-                       sse_opts |= 1 << SIMD_VERSION_SSE3;
+                       sse_opts |= SIMD_VERSION_SSE3;
                if (ecx & (1 << 9))
-                       sse_opts |= 1 << SIMD_VERSION_SSSE3;
+                       sse_opts |= SIMD_VERSION_SSSE3;
                if (ecx & (1 << 19))
-                       sse_opts |= 1 << SIMD_VERSION_SSE41;
+                       sse_opts |= SIMD_VERSION_SSE41;
                if (ecx & (1 << 20))
-                       sse_opts |= 1 << SIMD_VERSION_SSE42;
+                       sse_opts |= SIMD_VERSION_SSE42;
        }
+
+       /* Yes, all this needs to be done to check for sse4a.
+          See: "Amd: CPUID Specification"
+        */
+       if (cpuid (0x80000000, &eax, &ebx, &ecx, &edx)) {
+               /* eax greater or equal than 0x80000001, ebx = 'htuA', ecx = DMAc', edx = 'itne'*/
+               if ((((unsigned int) eax) >= 0x80000001) && (ebx == 0x68747541) && (ecx == 0x444D4163) && (edx == 0x69746E65)) {
+                       cpuid (0x80000001, &eax, &ebx, &ecx, &edx);
+                       if (ecx & (1 << 6))
+                               sse_opts |= SIMD_VERSION_SSE4a;
+               }
+       }
+
        return sse_opts;        
 }
 
+#ifndef DISABLE_JIT
+
 GList *
 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
 {
@@ -1006,7 +1065,7 @@ mono_arch_compute_omit_fp (MonoCompile *cfg)
        if (cfg->arch.omit_fp_computed)
                return;
 
-       header = mono_method_get_header (cfg->method);
+       header = cfg->header;
 
        sig = mono_method_signature (cfg->method);
 
@@ -1096,7 +1155,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg)
                regs = g_list_prepend (regs, (gpointer)AMD64_R13);
                regs = g_list_prepend (regs, (gpointer)AMD64_R14);
                regs = g_list_prepend (regs, (gpointer)AMD64_R15);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                regs = g_list_prepend (regs, (gpointer)AMD64_RDI);
                regs = g_list_prepend (regs, (gpointer)AMD64_RSI);
 #endif
@@ -1202,7 +1261,7 @@ mono_arch_fill_argument_info (MonoCompile *cfg)
        int i;
        CallInfo *cinfo;
 
-       header = mono_method_get_header (cfg->method);
+       header = cfg->header;
 
        sig = mono_method_signature (cfg->method);
 
@@ -1282,7 +1341,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        gint32 *offsets;
        CallInfo *cinfo;
 
-       header = mono_method_get_header (cfg->method);
+       header = cfg->header;
 
        sig = mono_method_signature (cfg->method);
 
@@ -1389,6 +1448,14 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        /* Allocate locals */
        if (!cfg->globalra) {
                offsets = mono_allocate_stack_slots_full (cfg, cfg->arch.omit_fp ? FALSE: 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);
+                       g_free (mname);
+                       return;
+               }
+               
                if (locals_stack_align) {
                        offset += (locals_stack_align - 1);
                        offset &= ~(locals_stack_align - 1);
@@ -1534,9 +1601,12 @@ mono_arch_allocate_vars (MonoCompile *cfg)
                                if (cfg->arch.omit_fp) {
                                        ins->inst_offset = offset;
                                        offset += (ainfo->storage == ArgValuetypeInReg) ? 2 * sizeof (gpointer) : sizeof (gpointer);
+                                       // Arguments are yet supported by the stack map creation code
+                                       //cfg->locals_max_stack_offset = MAX (cfg->locals_max_stack_offset, offset);
                                } else {
                                        offset += (ainfo->storage == ArgValuetypeInReg) ? 2 * sizeof (gpointer) : sizeof (gpointer);
                                        ins->inst_offset = - offset;
+                                       //cfg->locals_min_stack_offset = MIN (cfg->locals_min_stack_offset, offset);
                                }
                        }
                }
@@ -1568,6 +1638,14 @@ mono_arch_create_vars (MonoCompile *cfg)
                }
        }
 
+       if (cfg->gen_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_trigger_page_var = ins;
+       }
+
 #ifdef MONO_AMD64_NO_PUSHES
        /*
         * When this is set, we pass arguments on the stack by moves, and by allocating 
@@ -1697,6 +1775,7 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
        ArgInfo *ainfo;
        int j;
        LLVMCallInfo *linfo;
+       MonoType *t;
 
        n = sig->param_count + sig->hasthis;
 
@@ -1730,6 +1809,11 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
        for (i = 0; i < n; ++i) {
                ainfo = cinfo->args + i;
 
+               if (i >= sig->hasthis)
+                       t = sig->params [i - sig->hasthis];
+               else
+                       t = &mono_defaults.int_class->byval_arg;
+
                linfo->args [i].storage = LLVMArgNone;
 
                switch (ainfo->storage) {
@@ -1741,16 +1825,15 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
                        linfo->args [i].storage = LLVMArgInFPReg;
                        break;
                case ArgOnStack:
-                       if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(sig->params [i - sig->hasthis]))) {
+                       if (MONO_TYPE_ISSTRUCT (t)) {
                                linfo->args [i].storage = LLVMArgVtypeByVal;
                        } else {
                                linfo->args [i].storage = LLVMArgInIReg;
-                               if (!sig->params [i - sig->hasthis]->byref) {
-                                       if (sig->params [i - sig->hasthis]->type == MONO_TYPE_R4) {
+                               if (!t->byref) {
+                                       if (t->type == MONO_TYPE_R4)
                                                linfo->args [i].storage = LLVMArgInFPReg;
-                                       } else if (sig->params [i - sig->hasthis]->type == MONO_TYPE_R8) {
+                                       else if (t->type == MONO_TYPE_R8)
                                                linfo->args [i].storage = LLVMArgInFPReg;
-                                       }
                                }
                        }
                        break;
@@ -1890,6 +1973,13 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                                }
                                g_assert (in->klass);
 
+                               if (ainfo->storage == ArgOnStack && size >= 10000) {
+                                       /* Avoid asserts in emit_memcpy () */
+                                       cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
+                                       cfg->exception_message = g_strdup_printf ("Passing an argument of size '%d'.", size);
+                                       /* Continue normally */
+                               }
+
                                if (size > 0) {
                                        MONO_INST_NEW (cfg, arg, OP_OUTARG_VT);
                                        arg->sreg1 = in->dreg;
@@ -1981,7 +2071,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
                }
        }
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        if (call->inst.opcode != OP_JMP && OP_TAILCALL != call->inst.opcode) {
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 0x20);
        }
@@ -2098,22 +2188,22 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
 {
        MonoType *ret = mini_type_get_underlying_type (NULL, mono_method_signature (method)->ret);
 
-       if (!ret->byref) {
-               if (ret->type == MONO_TYPE_R4) {
-                       if (COMPILE_LLVM (cfg))
-                               MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
-                       else
-                               MONO_EMIT_NEW_UNALU (cfg, OP_AMD64_SET_XMMREG_R4, cfg->ret->dreg, val->dreg);
-                       return;
-               } else if (ret->type == MONO_TYPE_R8) {
+       if (ret->type == MONO_TYPE_R4) {
+               if (COMPILE_LLVM (cfg))
                        MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
-                       return;
-               }
+               else
+                       MONO_EMIT_NEW_UNALU (cfg, OP_AMD64_SET_XMMREG_R4, cfg->ret->dreg, val->dreg);
+               return;
+       } else if (ret->type == MONO_TYPE_R8) {
+               MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
+               return;
        }
                        
        MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
 }
 
+#endif /* DISABLE_JIT */
+
 #define EMIT_COND_BRANCH(ins,cond,sign) \
         if (ins->inst_true_bb->native_offset) { \
                x86_branch (code, cond, cfg->native_code + ins->inst_true_bb->native_offset, sign); \
@@ -2126,6 +2216,299 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
                        x86_branch32 (code, cond, 0, sign); \
 }
 
+typedef struct {
+       MonoMethodSignature *sig;
+       CallInfo *cinfo;
+} ArchDynCallInfo;
+
+typedef struct {
+       mgreg_t regs [PARAM_REGS];
+       mgreg_t res;
+       guint8 *ret;
+} DynCallArgs;
+
+static gboolean
+dyn_call_supported (MonoMethodSignature *sig, CallInfo *cinfo)
+{
+       int i;
+
+#ifdef HOST_WIN32
+       return FALSE;
+#endif
+
+       switch (cinfo->ret.storage) {
+       case ArgNone:
+       case ArgInIReg:
+               break;
+       case ArgValuetypeInReg: {
+               ArgInfo *ainfo = &cinfo->ret;
+
+               if (ainfo->pair_storage [0] != ArgNone && ainfo->pair_storage [0] != ArgInIReg)
+                       return FALSE;
+               if (ainfo->pair_storage [1] != ArgNone && ainfo->pair_storage [1] != ArgInIReg)
+                       return FALSE;
+               break;
+       }
+       default:
+               return FALSE;
+       }
+
+       for (i = 0; i < cinfo->nargs; ++i) {
+               ArgInfo *ainfo = &cinfo->args [i];
+               switch (ainfo->storage) {
+               case ArgInIReg:
+                       break;
+               case ArgValuetypeInReg:
+                       if (ainfo->pair_storage [0] != ArgNone && ainfo->pair_storage [0] != ArgInIReg)
+                               return FALSE;
+                       if (ainfo->pair_storage [1] != ArgNone && ainfo->pair_storage [1] != ArgInIReg)
+                               return FALSE;
+                       break;
+               default:
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+/*
+ * mono_arch_dyn_call_prepare:
+ *
+ *   Return a pointer to an arch-specific structure which contains information 
+ * needed by mono_arch_get_dyn_call_args (). Return NULL if OP_DYN_CALL is not
+ * supported for SIG.
+ * This function is equivalent to ffi_prep_cif in libffi.
+ */
+MonoDynCallInfo*
+mono_arch_dyn_call_prepare (MonoMethodSignature *sig)
+{
+       ArchDynCallInfo *info;
+       CallInfo *cinfo;
+
+       cinfo = get_call_info (NULL, NULL, sig, FALSE);
+
+       if (!dyn_call_supported (sig, cinfo)) {
+               g_free (cinfo);
+               return NULL;
+       }
+
+       info = g_new0 (ArchDynCallInfo, 1);
+       // FIXME: Preprocess the info to speed up get_dyn_call_args ().
+       info->sig = sig;
+       info->cinfo = cinfo;
+       
+       return (MonoDynCallInfo*)info;
+}
+
+/*
+ * mono_arch_dyn_call_free:
+ *
+ *   Free a MonoDynCallInfo structure.
+ */
+void
+mono_arch_dyn_call_free (MonoDynCallInfo *info)
+{
+       ArchDynCallInfo *ainfo = (ArchDynCallInfo*)info;
+
+       g_free (ainfo->cinfo);
+       g_free (ainfo);
+}
+
+/*
+ * mono_arch_get_start_dyn_call:
+ *
+ *   Convert the arguments ARGS to a format which can be passed to OP_DYN_CALL, and
+ * store the result into BUF.
+ * ARGS should be an array of pointers pointing to the arguments.
+ * RET should point to a memory buffer large enought to hold the result of the
+ * call.
+ * This function should be as fast as possible, any work which does not depend
+ * on the actual values of the arguments should be done in 
+ * mono_arch_dyn_call_prepare ().
+ * start_dyn_call + OP_DYN_CALL + finish_dyn_call is equivalent to ffi_call in
+ * libffi.
+ */
+void
+mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, guint8 *buf, int buf_len)
+{
+       ArchDynCallInfo *dinfo = (ArchDynCallInfo*)info;
+       DynCallArgs *p = (DynCallArgs*)buf;
+       int arg_index, greg, i;
+       MonoMethodSignature *sig = dinfo->sig;
+
+       g_assert (buf_len >= sizeof (DynCallArgs));
+
+       p->res = 0;
+       p->ret = ret;
+
+       arg_index = 0;
+       greg = 0;
+
+       if (dinfo->cinfo->vtype_retaddr)
+               p->regs [greg ++] = (mgreg_t)ret;
+
+       if (sig->hasthis) {
+               p->regs [greg ++] = (mgreg_t)*(args [arg_index ++]);
+       }
+
+       for (i = 0; i < sig->param_count; i++) {
+               MonoType *t = mono_type_get_underlying_type (sig->params [i]);
+               gpointer *arg = args [arg_index ++];
+
+               if (t->byref) {
+                       p->regs [greg ++] = (mgreg_t)*(arg);
+                       continue;
+               }
+
+               switch (t->type) {
+               case MONO_TYPE_STRING:
+               case MONO_TYPE_CLASS:  
+               case MONO_TYPE_ARRAY:
+               case MONO_TYPE_SZARRAY:
+               case MONO_TYPE_OBJECT:
+               case MONO_TYPE_PTR:
+               case MONO_TYPE_I:
+               case MONO_TYPE_U:
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+                       g_assert (dinfo->cinfo->args [i + sig->hasthis].reg == param_regs [greg]);
+                       p->regs [greg ++] = (mgreg_t)*(arg);
+                       break;
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_U1:
+                       p->regs [greg ++] = *(guint8*)(arg);
+                       break;
+               case MONO_TYPE_I1:
+                       p->regs [greg ++] = *(gint8*)(arg);
+                       break;
+               case MONO_TYPE_I2:
+                       p->regs [greg ++] = *(gint16*)(arg);
+                       break;
+               case MONO_TYPE_U2:
+               case MONO_TYPE_CHAR:
+                       p->regs [greg ++] = *(guint16*)(arg);
+                       break;
+               case MONO_TYPE_I4:
+                       p->regs [greg ++] = *(gint32*)(arg);
+                       break;
+               case MONO_TYPE_U4:
+                       p->regs [greg ++] = *(guint32*)(arg);
+                       break;
+               case MONO_TYPE_GENERICINST:
+                   if (MONO_TYPE_IS_REFERENCE (t)) {
+                               p->regs [greg ++] = (mgreg_t)*(arg);
+                               break;
+                       } else {
+                               /* Fall through */
+                       }
+               case MONO_TYPE_VALUETYPE: {
+                       ArgInfo *ainfo = &dinfo->cinfo->args [i + sig->hasthis];
+
+                       g_assert (ainfo->storage == ArgValuetypeInReg);
+                       if (ainfo->pair_storage [0] != ArgNone) {
+                               g_assert (ainfo->pair_storage [0] == ArgInIReg);
+                               p->regs [greg ++] = ((mgreg_t*)(arg))[0];
+                       }
+                       if (ainfo->pair_storage [1] != ArgNone) {
+                               g_assert (ainfo->pair_storage [1] == ArgInIReg);
+                               p->regs [greg ++] = ((mgreg_t*)(arg))[1];
+                       }
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+               }
+       }
+
+       g_assert (greg <= PARAM_REGS);
+}
+
+/*
+ * mono_arch_finish_dyn_call:
+ *
+ *   Store the result of a dyn call into the return value buffer passed to
+ * start_dyn_call ().
+ * This function should be as fast as possible, any work which does not depend
+ * on the actual values of the arguments should be done in 
+ * mono_arch_dyn_call_prepare ().
+ */
+void
+mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf)
+{
+       ArchDynCallInfo *dinfo = (ArchDynCallInfo*)info;
+       MonoMethodSignature *sig = dinfo->sig;
+       guint8 *ret = ((DynCallArgs*)buf)->ret;
+       mgreg_t res = ((DynCallArgs*)buf)->res;
+
+       switch (mono_type_get_underlying_type (sig->ret)->type) {
+       case MONO_TYPE_VOID:
+               *(gpointer*)ret = NULL;
+               break;
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_CLASS:  
+       case MONO_TYPE_ARRAY:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_PTR:
+               *(gpointer*)ret = (gpointer)res;
+               break;
+       case MONO_TYPE_I1:
+               *(gint8*)ret = res;
+               break;
+       case MONO_TYPE_U1:
+       case MONO_TYPE_BOOLEAN:
+               *(guint8*)ret = res;
+               break;
+       case MONO_TYPE_I2:
+               *(gint16*)ret = res;
+               break;
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+               *(guint16*)ret = res;
+               break;
+       case MONO_TYPE_I4:
+               *(gint32*)ret = res;
+               break;
+       case MONO_TYPE_U4:
+               *(guint32*)ret = res;
+               break;
+       case MONO_TYPE_I8:
+               *(gint64*)ret = res;
+               break;
+       case MONO_TYPE_U8:
+               *(guint64*)ret = res;
+               break;
+       case MONO_TYPE_GENERICINST:
+               if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
+                       *(gpointer*)ret = (gpointer)res;
+                       break;
+               } else {
+                       /* Fall through */
+               }
+       case MONO_TYPE_VALUETYPE:
+               if (dinfo->cinfo->vtype_retaddr) {
+                       /* Nothing to do */
+               } else {
+                       ArgInfo *ainfo = &dinfo->cinfo->ret;
+
+                       g_assert (ainfo->storage == ArgValuetypeInReg);
+
+                       if (ainfo->pair_storage [0] != ArgNone) {
+                               g_assert (ainfo->pair_storage [0] == ArgInIReg);
+                               ((mgreg_t*)ret)[0] = res;
+                       }
+
+                       g_assert (ainfo->pair_storage [1] == ArgNone);
+               }
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
 /* emit an exception if condition is fail */
 #define EMIT_COND_SYSTEM_EXCEPTION(cond,signed,exc_name)            \
         do {                                                        \
@@ -2234,15 +2617,19 @@ emit_call_body (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointe
                        /* These methods are allocated using malloc */
                        near_call = FALSE;
 
+#ifdef MONO_ARCH_NOMAP32BIT
+               near_call = FALSE;
+#endif
+
+               /* The 64bit XEN kernel does not honour the MAP_32BIT flag. (#522894) */
+               if (optimize_for_xen)
+                       near_call = FALSE;
+
                if (cfg->compile_aot) {
                        near_call = TRUE;
                        no_patch = TRUE;
                }
 
-#ifdef MONO_ARCH_NOMAP32BIT
-               near_call = FALSE;
-#endif
-
                if (near_call) {
                        /* 
                         * Align the call displacement to an address divisible by 4 so it does
@@ -2267,12 +2654,12 @@ emit_call_body (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointe
 static inline guint8*
 emit_call (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointer data, gboolean win64_adjust_stack)
 {
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        if (win64_adjust_stack)
                amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 32);
 #endif
        code = emit_call_body (cfg, code, patch_type, data);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        if (win64_adjust_stack)
                amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 32);
 #endif 
@@ -2295,6 +2682,8 @@ store_membase_imm_to_store_membase_reg (int opcode)
        return -1;
 }
 
+#ifndef DISABLE_JIT
+
 #define INST_IGNORES_CFLAGS(opcode) (!(((opcode) == OP_ADC) || ((opcode) == OP_ADC_IMM) || ((opcode) == OP_IADC) || ((opcode) == OP_IADC_IMM) || ((opcode) == OP_SBB) || ((opcode) == OP_SBB_IMM) || ((opcode) == OP_ISBB) || ((opcode) == OP_ISBB_IMM)))
 
 /*
@@ -2434,7 +2823,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
                                        if (((ins2->opcode == OP_STORE_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_IMM) || (ins2->opcode == OP_STOREI8_MEMBASE_IMM) || (ins2->opcode == OP_STORE_MEMBASE_IMM)) && (ins2->inst_imm == 0)) {
                                                ins2->opcode = store_membase_imm_to_store_membase_reg (ins2->opcode);
                                                ins2->sreg1 = ins->dreg;
-                                       } else if ((ins2->opcode == OP_STOREI1_MEMBASE_IMM) || (ins2->opcode == OP_STOREI2_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_REG) || (ins2->opcode == OP_STOREI8_MEMBASE_REG) || (ins2->opcode == OP_STORE_MEMBASE_REG)) {
+                                       } else if ((ins2->opcode == OP_STOREI1_MEMBASE_IMM) || (ins2->opcode == OP_STOREI2_MEMBASE_IMM) || (ins2->opcode == OP_STOREI4_MEMBASE_REG) || (ins2->opcode == OP_STOREI8_MEMBASE_REG) || (ins2->opcode == OP_STORE_MEMBASE_REG) || (ins2->opcode == OP_LIVERANGE_START)) {
                                                /* Continue */
                                        } else if (((ins2->opcode == OP_ICONST) || (ins2->opcode == OP_I8CONST)) && (ins2->dreg == ins->dreg) && (ins2->inst_c0 == 0)) {
                                                NULLIFY_INS (ins2);
@@ -2597,7 +2986,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree)
        int sreg = tree->sreg1;
        int need_touch = FALSE;
 
-#if defined(PLATFORM_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
+#if defined(HOST_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
        if (!tree->flags & MONO_INST_INIT)
                need_touch = TRUE;
 #endif
@@ -2746,6 +3135,8 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
        return code;
 }
 
+#endif /* DISABLE_JIT */
+
 /*
  * mono_amd64_emit_tls_get:
  * @code: buffer to store code to
@@ -2761,7 +3152,7 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
 guint8*
 mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset)
 {
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        g_assert (tls_offset < 64);
        x86_prefix (code, X86_GS_PREFIX);
        amd64_mov_reg_mem (code, dreg, (tls_offset * 8) + 0x1480, 8);
@@ -3166,6 +3557,44 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_NOT_REACHED:
                case OP_NOT_NULL:
                        break;
+               case OP_SEQ_POINT: {
+                       int i;
+
+                       if (cfg->compile_aot)
+                               NOT_IMPLEMENTED;
+
+                       /* 
+                        * 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) {
+                               if (((guint64)ss_trigger_page >> 32) == 0)
+                                       amd64_mov_reg_mem (code, AMD64_R11, (guint64)ss_trigger_page, 4);
+                               else {
+                                       MonoInst *var = cfg->arch.ss_trigger_page_var;
+
+                                       amd64_mov_reg_membase (code, AMD64_R11, var->inst_basereg, var->inst_offset, 8);
+                                       amd64_alu_membase_imm_size (code, X86_CMP, AMD64_R11, 0, 0, 4);
+                               }
+                       }
+
+                       /* 
+                        * This is the address which is saved in seq points, 
+                        * get_ip_for_single_step () / get_ip_for_breakpoint () needs to compute this
+                        * from the address of the instruction causing the fault.
+                        */
+                       mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
+
+                       /* 
+                        * A placeholder for a possible breakpoint inserted by
+                        * mono_arch_set_breakpoint ().
+                        */
+                       for (i = 0; i < breakpoint_size; ++i)
+                               x86_nop (code);
+                       break;
+               }
                case OP_ADDCC:
                case OP_LADD:
                        amd64_alu_reg_reg (code, X86_ADD, ins->sreg1, ins->sreg2);
@@ -3778,6 +4207,32 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, call->stack_usage);
                        code = emit_move_return_value (cfg, ins, code);
                        break;
+               case OP_DYN_CALL: {
+                       int i;
+                       MonoInst *var = cfg->dyn_call_var;
+
+                       g_assert (var->opcode == OP_REGOFFSET);
+
+                       /* r11 = args buffer filled by mono_arch_get_dyn_call_args () */
+                       amd64_mov_reg_reg (code, AMD64_R11, ins->sreg1, 8);
+                       /* r10 = ftn */
+                       amd64_mov_reg_reg (code, AMD64_R10, ins->sreg2, 8);
+
+                       /* Save args buffer */
+                       amd64_mov_membase_reg (code, var->inst_basereg, var->inst_offset, AMD64_R11, 8);
+
+                       /* Set argument registers */
+                       for (i = 0; i < PARAM_REGS; ++i)
+                               amd64_mov_reg_membase (code, param_regs [i], AMD64_R11, i * sizeof (gpointer), 8);
+                       
+                       /* Make the call */
+                       amd64_call_reg (code, AMD64_R10);
+
+                       /* Save result */
+                       amd64_mov_reg_membase (code, AMD64_R11, var->inst_basereg, var->inst_offset, 8);
+                       amd64_mov_membase_reg (code, AMD64_R11, G_STRUCT_OFFSET (DynCallArgs, res), AMD64_RAX, 8);
+                       break;
+               }
                case OP_AMD64_SAVE_SP_TO_LMF:
                        amd64_mov_membase_reg (code, cfg->frame_reg, cfg->arch.lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_RSP, 8);
                        break;
@@ -3881,6 +4336,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 8);
                        mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_BB, ins->inst_target_bb);
                        amd64_call_imm (code, 0);
+                       mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
                        /* Restore stack alignment */
                        amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 8);
                        break;
@@ -4014,9 +4470,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_STORER8_MEMBASE_REG:
                        amd64_sse_movsd_membase_reg (code, ins->inst_destbasereg, ins->inst_offset, ins->sreg1);
                        break;
-               case OP_LOADR8_SPILL_MEMBASE:
-                       g_assert_not_reached ();
-                       break;
                case OP_LOADR8_MEMBASE:
                        amd64_sse_movsd_reg_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
                        break;
@@ -5195,6 +5648,8 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
        }
 }
 
+#ifndef DISABLE_JIT
+
 static int
 get_max_epilog_size (MonoCompile *cfg)
 {
@@ -5241,7 +5696,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        gboolean args_clobbered = FALSE;
        gboolean trace = FALSE;
 
-       cfg->code_size =  MAX (((MonoMethodNormal *)method)->header->code_size * 4, 10240);
+       cfg->code_size =  MAX (cfg->header->code_size * 4, 10240);
 
        code = cfg->native_code = g_malloc (cfg->code_size);
 
@@ -5282,14 +5737,14 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
                mono_emit_unwind_op_offset (cfg, code, AMD64_RBP, - cfa_offset);
                async_exc_point (code);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                mono_arch_unwindinfo_add_push_nonvol (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP);
 #endif
                
                amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof (gpointer));
                mono_emit_unwind_op_def_cfa_reg (cfg, code, AMD64_RBP);
                async_exc_point (code);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                mono_arch_unwindinfo_add_set_fpreg (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP);
 #endif
        }
@@ -5337,8 +5792,19 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        /* Allocate stack frame */
        if (alloc_size) {
                /* See mono_emit_stack_alloc */
-#if defined(PLATFORM_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
+#if defined(HOST_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK)
                guint32 remaining_size = alloc_size;
+               /*FIXME handle unbounded code expansion, we should use a loop in case of more than X interactions*/
+               guint32 required_code_size = ((remaining_size / 0x1000) + 1) * 10; /*10 is the max size of amd64_alu_reg_imm + amd64_test_membase_reg*/
+               guint32 offset = code - cfg->native_code;
+               if (G_UNLIKELY (required_code_size >= (cfg->code_size - offset))) {
+                       while (required_code_size >= (cfg->code_size - offset))
+                               cfg->code_size *= 2;
+                       cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+                       code = cfg->native_code + offset;
+                       mono_jit_stats.code_reallocs++;
+               }
+
                while (remaining_size >= 0x1000) {
                        amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 0x1000);
                        if (cfg->arch.omit_fp) {
@@ -5346,7 +5812,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
                        }
                        async_exc_point (code);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                        if (cfg->arch.omit_fp) 
                                mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, 0x1000);
 #endif
@@ -5361,7 +5827,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
                                async_exc_point (code);
                        }
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                        if (cfg->arch.omit_fp) 
                                mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, remaining_size);
 #endif
@@ -5387,12 +5853,37 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        }
 #endif
 
+#ifndef TARGET_WIN32
+       if (mini_get_debug_options ()->init_stacks) {
+               /* Fill the stack frame with a dummy value to force deterministic behavior */
+       
+               /* Save registers to the red zone */
+               amd64_mov_membase_reg (code, AMD64_RSP, -8, AMD64_RDI, 8);
+               amd64_mov_membase_reg (code, AMD64_RSP, -16, AMD64_RCX, 8);
+
+               amd64_mov_reg_imm (code, AMD64_RAX, 0x2a2a2a2a2a2a2a2a);
+               amd64_mov_reg_imm (code, AMD64_RCX, alloc_size / 8);
+               amd64_mov_reg_reg (code, AMD64_RDI, AMD64_RSP, 8);
+
+               amd64_cld (code);
+               amd64_prefix (code, X86_REP_PREFIX);
+               amd64_stosl (code);
+
+               amd64_mov_reg_membase (code, AMD64_RDI, AMD64_RSP, -8, 8);
+               amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RSP, -16, 8);
+       }
+#endif 
+
        /* Save LMF */
        if (method->save_lmf) {
                /* 
                 * The ip field is not set, the exception handling code will obtain it from the stack location pointed to by the sp field.
                 */
-               /* sp is saved right before calls */
+               /* 
+                * sp is saved right before calls but we need to save it here too so
+                * async stack walks would work.
+                */
+               amd64_mov_membase_reg (code, cfg->frame_reg, cfg->arch.lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_RSP, 8);
                /* Skip method (only needed for trampoline LMF frames) */
                /* Save callee saved regs */
                for (i = 0; i < MONO_MAX_IREGS; ++i) {
@@ -5405,7 +5896,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        case AMD64_R13: offset = G_STRUCT_OFFSET (MonoLMF, r13); break;
                        case AMD64_R14: offset = G_STRUCT_OFFSET (MonoLMF, r14); break;
                        case AMD64_R15: offset = G_STRUCT_OFFSET (MonoLMF, r15); break;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                        case AMD64_RDI: offset = G_STRUCT_OFFSET (MonoLMF, rdi); break;
                        case AMD64_RSI: offset = G_STRUCT_OFFSET (MonoLMF, rsi); break;
 #endif
@@ -5634,7 +6125,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, 
                                          (gpointer)"mono_jit_thread_attach", TRUE);
                        amd64_patch (buf, code);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                        /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
                        /* FIXME: Add a separate key for LMF to avoid this */
                        amd64_alu_reg_imm (code, X86_ADD, AMD64_RAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
@@ -5680,7 +6171,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        if (lmf_addr_tls_offset != -1) {
                                /* Load lmf quicky using the FS register */
                                code = mono_amd64_emit_tls_get (code, AMD64_RAX, lmf_addr_tls_offset);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                                /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
                                /* FIXME: Add a separate key for LMF to avoid this */
                                amd64_alu_reg_imm (code, X86_ADD, AMD64_RAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
@@ -5782,6 +6273,17 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                }
        }
 
+       /* Initialize ss_trigger_page_var */
+       if (cfg->arch.ss_trigger_page_var) {
+               MonoInst *var = cfg->arch.ss_trigger_page_var;
+
+               g_assert (!cfg->compile_aot);
+               g_assert (var->opcode == OP_REGOFFSET);
+
+               amd64_mov_reg_imm (code, AMD64_R11, (guint64)ss_trigger_page);
+               amd64_mov_membase_reg (code, var->inst_basereg, var->inst_offset, AMD64_R11, 8);
+       }
+
        cfg->code_len = code - cfg->native_code;
 
        g_assert (cfg->code_len < cfg->code_size);
@@ -5868,7 +6370,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                if (cfg->used_int_regs & (1 << AMD64_R15)) {
                        amd64_mov_reg_membase (code, AMD64_R15, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r15), 8);
                }
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                if (cfg->used_int_regs & (1 << AMD64_RDI)) {
                        amd64_mov_reg_membase (code, AMD64_RDI, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rdi), 8);
                }
@@ -6090,6 +6592,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
 
 }
 
+#endif /* DISABLE_JIT */
+
 void*
 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
 {
@@ -6150,9 +6654,9 @@ mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolea
        guchar *code = p;
        int save_mode = SAVE_NONE;
        MonoMethod *method = cfg->method;
-       int rtype = mini_type_get_underlying_type (NULL, mono_method_signature (method)->ret)->type;
+       MonoType *ret_type = mini_type_get_underlying_type (NULL, mono_method_signature (method)->ret);
        
-       switch (rtype) {
+       switch (ret_type->type) {
        case MONO_TYPE_VOID:
                /* special case string .ctor icall */
                if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
@@ -6169,7 +6673,7 @@ mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolea
                save_mode = SAVE_XMM;
                break;
        case MONO_TYPE_GENERICINST:
-               if (!mono_type_generic_inst_is_valuetype (mono_method_signature (method)->ret)) {
+               if (!mono_type_generic_inst_is_valuetype (ret_type)) {
                        save_mode = SAVE_EAX;
                        break;
                }
@@ -6404,8 +6908,15 @@ mono_arch_get_vcall_slot (guint8 *code, mgreg_t *regs, int *displacement)
        guint32 reg;
        gint32 disp;
        guint8 rex = 0;
+       MonoJitInfo *ji = NULL;
+
+#ifdef ENABLE_LLVM
+       /* code - 9 might be before the start of the method */
+       /* FIXME: Avoid this expensive call somehow */
+       ji = mono_jit_info_table_find (mono_domain_get (), (char*)code);
+#endif
 
-       mono_breakpoint_clean_code (NULL, code, 9, buf, sizeof (buf));
+       mono_breakpoint_clean_code (ji ? ji->code_start : NULL, code, 9, buf, sizeof (buf));
        code = buf + 9;
 
        *displacement = 0;
@@ -6535,7 +7046,7 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
                        /* We have to shift the arguments left */
                        amd64_mov_reg_reg (code, AMD64_RAX, AMD64_ARG_REG1, 8);
                        for (i = 0; i < param_count; ++i) {
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                                if (i < 3)
                                        amd64_mov_reg_reg (code, param_regs [i], param_regs [i + 1], 8);
                                else
@@ -6561,7 +7072,7 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod
 /*
  * mono_arch_get_delegate_invoke_impls:
  *
- *   Return a list of MonoAotTrampInfo structures for the delegate invoke impl
+ *   Return a list of MonoTrampInfo structures for the delegate invoke impl
  * trampolines.
  */
 GSList*
@@ -6573,11 +7084,11 @@ mono_arch_get_delegate_invoke_impls (void)
        int i;
 
        code = get_delegate_invoke_impl (TRUE, 0, &code_len);
-       res = g_slist_prepend (res, mono_aot_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len));
+       res = g_slist_prepend (res, mono_tramp_info_create (g_strdup ("delegate_invoke_impl_has_target"), code, code_len, NULL, NULL));
 
        for (i = 0; i < MAX_ARCH_DELEGATE_PARAMS; ++i) {
                code = get_delegate_invoke_impl (FALSE, i, &code_len);
-               res = g_slist_prepend (res, mono_aot_tramp_info_create (g_strdup_printf ("delegate_invoke_impl_target_%d", i), code, code_len));
+               res = g_slist_prepend (res, mono_tramp_info_create (g_strdup_printf ("delegate_invoke_impl_target_%d", i), code, code_len, NULL, NULL));
        }
 
        return res;
@@ -6603,7 +7114,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
                        return cached;
 
                if (mono_aot_only)
-                       start = mono_aot_get_named_code ("delegate_invoke_impl_has_target");
+                       start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
                else
                        start = get_delegate_invoke_impl (TRUE, 0, NULL);
 
@@ -6624,7 +7135,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe
 
                if (mono_aot_only) {
                        char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
-                       start = mono_aot_get_named_code (name);
+                       start = mono_aot_get_trampoline (name);
                        g_free (name);
                } else {
                        start = get_delegate_invoke_impl (FALSE, sig->param_count, NULL);
@@ -6649,14 +7160,13 @@ void
 mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
 {
        if (!tls_offset_inited) {
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                /* 
                 * We need to init this multiple times, since when we are first called, the key might not
                 * be initialized yet.
                 */
                appdomain_tls_offset = mono_domain_get_tls_key ();
                lmf_tls_offset = mono_get_jit_tls_key ();
-               thread_tls_offset = mono_thread_get_tls_key ();
                lmf_addr_tls_offset = mono_get_jit_tls_key ();
 
                /* Only 64 tls entries can be accessed using inline code */
@@ -6664,8 +7174,6 @@ mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
                        appdomain_tls_offset = -1;
                if (lmf_tls_offset >= 64)
                        lmf_tls_offset = -1;
-               if (thread_tls_offset >= 64)
-                       thread_tls_offset = -1;
 #else
                tls_offset_inited = TRUE;
 #ifdef MONO_XEN_OPT
@@ -6674,7 +7182,6 @@ mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
                appdomain_tls_offset = mono_domain_get_tls_offset ();
                lmf_tls_offset = mono_get_lmf_tls_offset ();
                lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
-               thread_tls_offset = mono_thread_get_tls_offset ();
 #endif
        }               
 }
@@ -6860,12 +7367,6 @@ mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
 {
        return (MonoMethod*)regs [MONO_ARCH_IMT_REG];
 }
-
-MonoObject*
-mono_arch_find_this_argument (mgreg_t *regs, MonoMethod *method, MonoGenericSharingContext *gsctx)
-{
-       return mono_arch_get_this_arg_from_call (gsctx, mono_method_signature (method), regs, NULL);
-}
 #endif
 
 MonoVTable*
@@ -6874,6 +7375,17 @@ mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
        return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
 }
 
+GSList*
+mono_arch_get_cie_program (void)
+{
+       GSList *l = NULL;
+
+       mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, AMD64_RSP, 8);
+       mono_add_unwind_op_offset (l, (guint8*)NULL, (guint8*)NULL, AMD64_RIP, -8);
+
+       return l;
+}
+
 MonoInst*
 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
@@ -6967,18 +7479,6 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
        return ins;
 }
 
-MonoInst* mono_arch_get_thread_intrinsic (MonoCompile* cfg)
-{
-       MonoInst* ins;
-       
-       if (thread_tls_offset == -1)
-               return NULL;
-       
-       MONO_INST_NEW (cfg, ins, OP_TLS_GET);
-       ins->inst_offset = thread_tls_offset;
-       return ins;
-}
-
 #define _CTX_REG(ctx,fld,i) ((gpointer)((&ctx->fld)[i]))
 
 gpointer
@@ -6999,3 +7499,214 @@ mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
                        g_assert_not_reached ();
        }
 }
+
+/*
+ * mono_arch_emit_load_aotconst:
+ *
+ *   Emit code to load the contents of the GOT slot identified by TRAMP_TYPE and
+ * TARGET from the mscorlib GOT in full-aot code.
+ * On AMD64, the result is placed into R11.
+ */
+guint8*
+mono_arch_emit_load_aotconst (guint8 *start, guint8 *code, MonoJumpInfo **ji, int tramp_type, gconstpointer target)
+{
+       *ji = mono_patch_info_list_prepend (*ji, code - start, tramp_type, target);
+       amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+
+       return code;
+}
+
+/*
+ * mono_arch_get_trampolines:
+ *
+ *   Return a list of MonoTrampInfo structures describing arch specific trampolines
+ * for AOT.
+ */
+GSList *
+mono_arch_get_trampolines (gboolean aot)
+{
+       MonoTrampInfo *info;
+       GSList *tramps = NULL;
+
+       mono_arch_get_throw_pending_exception (&info, aot);
+
+       tramps = g_slist_append (tramps, info);
+
+       return tramps;
+}
+
+/* Soft Debug support */
+#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
+
+/*
+ * mono_arch_set_breakpoint:
+ *
+ *   Set a breakpoint at the native code corresponding to JI at NATIVE_OFFSET.
+ * The location should contain code emitted by OP_SEQ_POINT.
+ */
+void
+mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+       guint8 *orig_code = code;
+
+       /* 
+        * 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);
+       if (breakpoint_size == 8) {
+               amd64_mov_reg_mem (code, AMD64_R11, (guint64)bp_trigger_page, 4);
+       } else {
+               amd64_mov_reg_imm_size (code, AMD64_R11, (guint64)bp_trigger_page, 8);
+               amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 4);
+       }
+
+       g_assert (code - orig_code == breakpoint_size);
+}
+
+/*
+ * mono_arch_clear_breakpoint:
+ *
+ *   Clear the breakpoint at IP.
+ */
+void
+mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+       int i;
+
+       for (i = 0; i < breakpoint_size; ++i)
+               x86_nop (code);
+}
+
+gboolean
+mono_arch_is_breakpoint_event (void *info, void *sigctx)
+{
+#ifdef HOST_WIN32
+       EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info;
+       return FALSE;
+#else
+       siginfo_t* sinfo = (siginfo_t*) info;
+       /* Sometimes the address is off by 4 */
+       if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
+               return TRUE;
+       else
+               return FALSE;
+#endif
+}
+
+/*
+ * mono_arch_get_ip_for_breakpoint:
+ *
+ *   Convert the ip in CTX to the address where a breakpoint was placed.
+ */
+guint8*
+mono_arch_get_ip_for_breakpoint (MonoJitInfo *ji, MonoContext *ctx)
+{
+       guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
+
+       /* ip points to the instruction causing the fault */
+       ip -= (breakpoint_size - breakpoint_fault_size);
+
+       return ip;
+}
+
+/*
+ * mono_arch_skip_breakpoint:
+ *
+ *   Modify CTX so the ip is placed after the breakpoint instruction, so when
+ * we resume, the instruction is not executed again.
+ */
+void
+mono_arch_skip_breakpoint (MonoContext *ctx)
+{
+       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + breakpoint_fault_size);
+}
+       
+/*
+ * mono_arch_start_single_stepping:
+ *
+ *   Start single stepping.
+ */
+void
+mono_arch_start_single_stepping (void)
+{
+       mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
+}
+       
+/*
+ * mono_arch_stop_single_stepping:
+ *
+ *   Stop single stepping.
+ */
+void
+mono_arch_stop_single_stepping (void)
+{
+       mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
+}
+
+/*
+ * mono_arch_is_single_step_event:
+ *
+ *   Return whenever the machine state in SIGCTX corresponds to a single
+ * step event.
+ */
+gboolean
+mono_arch_is_single_step_event (void *info, void *sigctx)
+{
+#ifdef HOST_WIN32
+       EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info;
+       return FALSE;
+#else
+       siginfo_t* sinfo = (siginfo_t*) info;
+       /* Sometimes the address is off by 4 */
+       if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
+               return TRUE;
+       else
+               return FALSE;
+#endif
+}
+
+/*
+ * mono_arch_get_ip_for_single_step:
+ *
+ *   Convert the ip in CTX to the address stored in seq_points.
+ */
+guint8*
+mono_arch_get_ip_for_single_step (MonoJitInfo *ji, MonoContext *ctx)
+{
+       guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
+
+       ip += single_step_fault_size;
+
+       return ip;
+}
+
+/*
+ * mono_arch_skip_single_step:
+ *
+ *   Modify CTX so the ip is placed after the single step trigger instruction,
+ * we resume, the instruction is not executed again.
+ */
+void
+mono_arch_skip_single_step (MonoContext *ctx)
+{
+       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + single_step_fault_size);
+}
+
+/*
+ * mono_arch_create_seq_point_info:
+ *
+ *   Return a pointer to a data structure which is used by the sequence
+ * point implementation in AOTed code.
+ */
+gpointer
+mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
+{
+       NOT_IMPLEMENTED;
+       return NULL;
+}
+
+#endif