X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-amd64.c;h=c24fe349514d516044634b0139fa92ccab4fe0c5;hb=d2e184bbf7f82d83d767aae6af08359729769270;hp=69769b53be4fe4ab0939671900fcb45b837c21b1;hpb=518c3bcac5cac724eac73a3a9ae9e35c46c8de4e;p=mono.git diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index 69769b53be4..c24fe349514 100755 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "trace.h" #include "ir-emit.h" @@ -52,7 +53,7 @@ static gboolean optimize_for_xen = TRUE; #define IS_REX(inst) (((inst) >= 0x40) && ((inst) <= 0x4f)) -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 /* Under windows, the calling convention is never stdcall */ #define CALLCONV_IS_STDCALL(call_conv) (FALSE) #else @@ -85,6 +86,9 @@ static int breakpoint_fault_size; /* The size of the single step instruction causing the actual fault */ static int single_step_fault_size; +/* The single step trampoline */ +static gpointer ss_trampoline; + /* Offset between fp and the first argument in the callee */ #define ARGS_OFFSET 16 #define GP_SCRATCH_REG AMD64_R11 @@ -523,7 +527,7 @@ typedef struct { #define DEBUG(a) if (cfg->verbose_level > 1) a -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 static AMD64_Reg_No param_regs [] = { AMD64_RCX, AMD64_RDX, AMD64_R8, AMD64_R9 }; static AMD64_Reg_No return_regs [] = { AMD64_RAX, AMD64_RDX }; @@ -551,7 +555,7 @@ add_general (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo) } } -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 #define FLOAT_PARAM_REGS 4 #else #define FLOAT_PARAM_REGS 8 @@ -594,8 +598,6 @@ merge_argument_class_from_type (MonoGenericSharingContext *gsctx, MonoType *type ptype = mini_type_get_underlying_type (gsctx, type); switch (ptype->type) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_CHAR: case MONO_TYPE_I1: case MONO_TYPE_U1: case MONO_TYPE_I2: @@ -617,7 +619,7 @@ merge_argument_class_from_type (MonoGenericSharingContext *gsctx, MonoType *type break; case MONO_TYPE_R4: case MONO_TYPE_R8: -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 class2 = ARG_CLASS_INTEGER; #else class2 = ARG_CLASS_SSE; @@ -750,7 +752,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 HOST_WIN32 +#ifndef TARGET_WIN32 if (!sig->pinvoke && ((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)) { @@ -832,7 +834,7 @@ add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgIn g_assert (info); g_assert (fields); -#ifndef HOST_WIN32 +#ifndef TARGET_WIN32 if (info->native_size > 16) { ainfo->offset = *stack_size; *stack_size += ALIGN_TO (info->native_size, 8); @@ -1005,79 +1007,75 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign gr = 0; fr = 0; -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 /* Reserve space where the callee can save the argument registers */ stack_size = 4 * sizeof (mgreg_t); #endif /* return value */ - { - ret_type = mini_type_get_underlying_type (gsctx, sig->ret); - switch (ret_type->type) { - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U1: - case MONO_TYPE_I2: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_PTR: - case MONO_TYPE_FNPTR: - case MONO_TYPE_CLASS: - case MONO_TYPE_OBJECT: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: - case MONO_TYPE_STRING: - cinfo->ret.storage = ArgInIReg; - cinfo->ret.reg = AMD64_RAX; - break; - case MONO_TYPE_U8: - case MONO_TYPE_I8: + ret_type = mini_type_get_underlying_type (gsctx, sig->ret); + switch (ret_type->type) { + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_PTR: + case MONO_TYPE_FNPTR: + case MONO_TYPE_CLASS: + case MONO_TYPE_OBJECT: + case MONO_TYPE_SZARRAY: + case MONO_TYPE_ARRAY: + case MONO_TYPE_STRING: + cinfo->ret.storage = ArgInIReg; + cinfo->ret.reg = AMD64_RAX; + break; + case MONO_TYPE_U8: + case MONO_TYPE_I8: + cinfo->ret.storage = ArgInIReg; + cinfo->ret.reg = AMD64_RAX; + break; + case MONO_TYPE_R4: + cinfo->ret.storage = ArgInFloatSSEReg; + cinfo->ret.reg = AMD64_XMM0; + break; + case MONO_TYPE_R8: + cinfo->ret.storage = ArgInDoubleSSEReg; + cinfo->ret.reg = AMD64_XMM0; + break; + case MONO_TYPE_GENERICINST: + if (!mono_type_generic_inst_is_valuetype (ret_type)) { cinfo->ret.storage = ArgInIReg; cinfo->ret.reg = AMD64_RAX; break; - case MONO_TYPE_R4: - cinfo->ret.storage = ArgInFloatSSEReg; - cinfo->ret.reg = AMD64_XMM0; - break; - case MONO_TYPE_R8: - cinfo->ret.storage = ArgInDoubleSSEReg; - cinfo->ret.reg = AMD64_XMM0; - break; - case MONO_TYPE_GENERICINST: - if (!mono_type_generic_inst_is_valuetype (ret_type)) { - cinfo->ret.storage = ArgInIReg; - cinfo->ret.reg = AMD64_RAX; - break; - } - /* fall through */ + } + /* fall through */ #if defined( __native_client_codegen__ ) - case MONO_TYPE_TYPEDBYREF: + case MONO_TYPE_TYPEDBYREF: #endif - case MONO_TYPE_VALUETYPE: { - guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0; + case MONO_TYPE_VALUETYPE: { + guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0; - add_valuetype (gsctx, sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize); - if (cinfo->ret.storage == ArgOnStack) { - cinfo->vtype_retaddr = TRUE; - /* The caller passes the address where the value is stored */ - } - break; + add_valuetype (gsctx, sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize); + if (cinfo->ret.storage == ArgOnStack) { + cinfo->vtype_retaddr = TRUE; + /* The caller passes the address where the value is stored */ } + break; + } #if !defined( __native_client_codegen__ ) - case MONO_TYPE_TYPEDBYREF: - /* Same as a valuetype with size 24 */ - cinfo->vtype_retaddr = TRUE; - break; + case MONO_TYPE_TYPEDBYREF: + /* Same as a valuetype with size 24 */ + cinfo->vtype_retaddr = TRUE; + break; #endif - case MONO_TYPE_VOID: - break; - default: - g_error ("Can't handle as return value 0x%x", ret_type->type); - } + case MONO_TYPE_VOID: + break; + default: + g_error ("Can't handle as return value 0x%x", ret_type->type); } pstart = 0; @@ -1118,7 +1116,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign ArgInfo *ainfo = &cinfo->args [sig->hasthis + i]; MonoType *ptype; -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 /* The float param registers and other param registers must be the same index on Windows x64.*/ if (gr > fr) fr = gr; @@ -1141,14 +1139,12 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign ptype = mini_type_get_underlying_type (gsctx, sig->params [i]); switch (ptype->type) { - case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: add_general (&gr, &stack_size, ainfo); break; case MONO_TYPE_I2: case MONO_TYPE_U2: - case MONO_TYPE_CHAR: add_general (&gr, &stack_size, ainfo); break; case MONO_TYPE_I4: @@ -1545,7 +1541,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg) #ifndef __native_client_codegen__ regs = g_list_prepend (regs, (gpointer)AMD64_R15); #endif -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 regs = g_list_prepend (regs, (gpointer)AMD64_RDI); regs = g_list_prepend (regs, (gpointer)AMD64_RSI); #endif @@ -1649,13 +1645,10 @@ mono_arch_fill_argument_info (MonoCompile *cfg) { MonoType *sig_ret; MonoMethodSignature *sig; - MonoMethodHeader *header; MonoInst *ins; int i; CallInfo *cinfo; - header = cfg->header; - sig = mono_method_signature (cfg->method); cinfo = cfg->arch.cinfo; @@ -1693,15 +1686,9 @@ mono_arch_fill_argument_info (MonoCompile *cfg) for (i = 0; i < sig->param_count + sig->hasthis; ++i) { ArgInfo *ainfo = &cinfo->args [i]; - MonoType *arg_type; ins = cfg->args [i]; - if (sig->hasthis && (i == 0)) - arg_type = &mono_defaults.object_class->byval_arg; - else - arg_type = sig->params [i - sig->hasthis]; - switch (ainfo->storage) { case ArgInIReg: case ArgInFloatSSEReg: @@ -1729,15 +1716,12 @@ mono_arch_allocate_vars (MonoCompile *cfg) { MonoType *sig_ret; MonoMethodSignature *sig; - MonoMethodHeader *header; MonoInst *ins; int i, offset; guint32 locals_stack_size, locals_stack_align; gint32 *offsets; CallInfo *cinfo; - header = cfg->header; - sig = mono_method_signature (cfg->method); cinfo = cfg->arch.cinfo; @@ -1885,12 +1869,6 @@ mono_arch_allocate_vars (MonoCompile *cfg) if (ins->opcode != OP_REGVAR) { ArgInfo *ainfo = &cinfo->args [i]; gboolean inreg = TRUE; - MonoType *arg_type; - - if (sig->hasthis && (i == 0)) - arg_type = &mono_defaults.object_class->byval_arg; - else - arg_type = sig->params [i - sig->hasthis]; if (cfg->globalra) { /* The new allocator needs info about the original locations of the arguments */ @@ -2031,13 +2009,17 @@ mono_arch_create_vars (MonoCompile *cfg) } } - if (cfg->gen_seq_points_debug_data) { + if (cfg->gen_sdb_seq_points) { MonoInst *ins; if (cfg->compile_aot) { MonoInst *ins = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); ins->flags |= MONO_INST_VOLATILE; cfg->arch.seq_point_info_var = 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); @@ -2050,7 +2032,7 @@ mono_arch_create_vars (MonoCompile *cfg) if (cfg->method->save_lmf) { cfg->lmf_ir = TRUE; -#if !defined(HOST_WIN32) +#if !defined(TARGET_WIN32) if (mono_get_lmf_tls_offset () != -1 && !optimize_for_xen) cfg->lmf_ir_mono_lmf = TRUE; #endif @@ -2141,6 +2123,7 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, AMD64_RSP, cinfo->sig_cookie.offset, sig_reg); } +#ifdef ENABLE_LLVM static inline LLVMArgStorage arg_storage_to_llvm_arg_storage (MonoCompile *cfg, ArgStorage storage) { @@ -2155,7 +2138,6 @@ arg_storage_to_llvm_arg_storage (MonoCompile *cfg, ArgStorage storage) } } -#ifdef ENABLE_LLVM LLVMCallInfo* mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) { @@ -2256,12 +2238,10 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) MonoInst *arg, *in; MonoMethodSignature *sig; MonoType *sig_ret; - int i, n, stack_size; + int i, n; CallInfo *cinfo; ArgInfo *ainfo; - stack_size = 0; - sig = call->signature; n = sig->param_count + sig->hasthis; @@ -2290,6 +2270,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) else t = sig->params [i - sig->hasthis]; + t = mini_get_underlying_type (cfg, t); if (ainfo->storage == ArgOnStack && !MONO_TYPE_ISSTRUCT (t) && !call->tail_call) { if (!t->byref) { if (t->type == MONO_TYPE_R4) @@ -2706,7 +2687,7 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g p->regs [greg ++] = PTR_TO_GREG(ret); for (i = pindex; i < sig->param_count; i++) { - MonoType *t = mono_type_get_underlying_type (sig->params [i]); + MonoType *t = mini_type_get_underlying_type (NULL, sig->params [i]); gpointer *arg = args [arg_index ++]; if (t->byref) { @@ -2737,7 +2718,6 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g p->regs [greg ++] = *(guint64*)(arg); break; #endif - case MONO_TYPE_BOOLEAN: case MONO_TYPE_U1: p->regs [greg ++] = *(guint8*)(arg); break; @@ -2748,7 +2728,6 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g p->regs [greg ++] = *(gint16*)(arg); break; case MONO_TYPE_U2: - case MONO_TYPE_CHAR: p->regs [greg ++] = *(guint16*)(arg); break; case MONO_TYPE_I4: @@ -2802,7 +2781,7 @@ mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf) MonoMethodSignature *sig = dinfo->sig; guint8 *ret = ((DynCallArgs*)buf)->ret; mgreg_t res = ((DynCallArgs*)buf)->res; - MonoType *sig_ret = mono_type_get_underlying_type (sig->ret); + MonoType *sig_ret = mini_type_get_underlying_type (NULL, sig->ret); switch (sig_ret->type) { case MONO_TYPE_VOID: @@ -2822,14 +2801,12 @@ mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf) *(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: @@ -3026,12 +3003,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 HOST_WIN32 +#ifdef TARGET_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 HOST_WIN32 +#ifdef TARGET_WIN32 if (win64_adjust_stack) amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, 32); #endif @@ -3371,7 +3348,7 @@ mono_emit_stack_alloc (MonoCompile *cfg, guchar *code, MonoInst* tree) int sreg = tree->sreg1; int need_touch = FALSE; -#if defined(HOST_WIN32) +#if defined(TARGET_WIN32) need_touch = TRUE; #elif defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK) if (!tree->flags & MONO_INST_INIT) @@ -3487,8 +3464,9 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code) break; case OP_FCALL: case OP_FCALL_REG: - case OP_FCALL_MEMBASE: - if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) { + case OP_FCALL_MEMBASE: { + MonoType *rtype = mini_get_underlying_type (cfg, ((MonoCallInst*)ins)->signature->ret); + if (rtype->type == MONO_TYPE_R4) { amd64_sse_cvtss2sd_reg_reg (code, ins->dreg, AMD64_XMM0); } else { @@ -3496,6 +3474,7 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code) amd64_sse_movsd_reg_reg (code, ins->dreg, AMD64_XMM0); } break; + } case OP_RCALL: case OP_RCALL_REG: case OP_RCALL_MEMBASE: @@ -3613,7 +3592,7 @@ mono_amd64_get_tls_gs_offset (void) guint8* mono_amd64_emit_tls_get (guint8* code, int dreg, int tls_offset) { -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 if (tls_offset < 64) { x86_prefix (code, X86_GS_PREFIX); amd64_mov_reg_mem (code, dreg, (tls_offset * 8) + 0x1480, 8); @@ -3679,7 +3658,7 @@ emit_tls_get_reg (guint8* code, int dreg, int offset_reg) static guint8* amd64_emit_tls_set (guint8 *code, int sreg, int tls_offset) { -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 g_assert_not_reached (); #elif defined(__APPLE__) x86_prefix (code, X86_GS_PREFIX); @@ -3696,7 +3675,7 @@ static guint8* amd64_emit_tls_set_reg (guint8 *code, int sreg, int offset_reg) { /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */ -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 g_assert_not_reached (); #elif defined(__APPLE__) x86_prefix (code, X86_GS_PREFIX); @@ -3781,8 +3760,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MonoCallInst *call; guint offset; guint8 *code = cfg->native_code + cfg->code_len; - MonoInst *last_ins = NULL; - guint last_offset = 0; int max_len; /* Fix max_offset estimate for each successor bb */ @@ -4200,17 +4177,33 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_SEQ_POINT: { int i; - /* - * 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) { - MonoInst *var = cfg->arch.ss_trigger_page_var; + if (cfg->compile_aot) { + MonoInst *var = cfg->arch.ss_tramp_var; + guint8 *label; + + /* Load ss_tramp_var */ + amd64_mov_reg_membase (code, AMD64_R11, var->inst_basereg, var->inst_offset, 8); + /* Load the trampoline address */ + amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8); + /* Call it if it is non-null */ + amd64_test_reg_reg (code, AMD64_R11, AMD64_R11); + label = code; + amd64_branch8 (code, X86_CC_Z, 0, FALSE); + amd64_call_reg (code, AMD64_R11); + amd64_patch (label, code); + } else { + /* + * 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. + */ + 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); + 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); + } } /* @@ -4222,13 +4215,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) guint32 offset = code - cfg->native_code; guint32 val; MonoInst *info_var = cfg->arch.seq_point_info_var; + guint8 *label; /* Load info var */ amd64_mov_reg_membase (code, AMD64_R11, info_var->inst_basereg, info_var->inst_offset, 8); val = ((offset) * sizeof (guint8*)) + MONO_STRUCT_OFFSET (SeqPointInfo, bp_addrs); - /* Load the info->bp_addrs [offset], which is either a valid address or the address of a trigger page */ + /* Load the info->bp_addrs [offset], which is either NULL or the address of the breakpoint trampoline */ amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, val, 8); - amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8); + amd64_test_reg_reg (code, AMD64_R11, AMD64_R11); + label = code; + amd64_branch8 (code, X86_CC_Z, 0, FALSE); + /* Call the trampoline */ + amd64_call_reg (code, AMD64_R11); + amd64_patch (label, code); } else { /* * A placeholder for a possible breakpoint inserted by @@ -4442,9 +4441,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_shift_reg (code, X86_SAR, ins->dreg); break; case OP_SHR_IMM: - g_assert (amd64_is_imm32 (ins->inst_imm)); - amd64_shift_reg_imm_size (code, X86_SAR, ins->dreg, ins->inst_imm, 4); - break; case OP_LSHR_IMM: g_assert (amd64_is_imm32 (ins->inst_imm)); amd64_shift_reg_imm (code, X86_SAR, ins->dreg, ins->inst_imm); @@ -4462,9 +4458,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_shift_reg (code, X86_SHR, ins->dreg); break; case OP_SHL_IMM: - g_assert (amd64_is_imm32 (ins->inst_imm)); - amd64_shift_reg_imm_size (code, X86_SHL, ins->dreg, ins->inst_imm, 4); - break; case OP_LSHL_IMM: g_assert (amd64_is_imm32 (ins->inst_imm)); amd64_shift_reg_imm (code, X86_SHL, ins->dreg, ins->inst_imm); @@ -5002,7 +4995,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) amd64_ret (code); break; } - + case OP_GET_EX_OBJ: + if (ins->dreg != AMD64_RAX) + amd64_mov_reg_reg (code, ins->dreg, AMD64_RAX, sizeof (gpointer)); + break; case OP_LABEL: ins->inst_c0 = code - cfg->native_code; break; @@ -6560,22 +6556,28 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code; break; } - case OP_NACL_GC_SAFE_POINT: { -#if defined(__native_client_codegen__) && defined(__native_client_gc__) - if (cfg->compile_aot) - code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc, TRUE); - else { - guint8 *br [1]; + case OP_GC_SAFE_POINT: { + gpointer polling_func = NULL; + int compare_val = 0; + guint8 *br [1]; - amd64_mov_reg_imm_size (code, AMD64_R11, (gpointer)&__nacl_thread_suspension_needed, 4); - amd64_test_membase_imm_size (code, AMD64_R11, 0, 0xFFFFFFFF, 4); - br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE); - code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, (gpointer)mono_nacl_gc, TRUE); - amd64_patch (br[0], code); - } +#if defined (USE_COOP_GC) + polling_func = (gpointer)mono_threads_state_poll; + compare_val = 1; +#elif defined(__native_client_codegen__) && defined(__native_client_gc__) + polling_func = (gpointer)mono_nacl_gc; + compare_val = 0xFFFFFFFF; #endif + if (!polling_func) + break; + + amd64_test_membase_imm_size (code, ins->sreg1, 0, compare_val, 4); + br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE); + code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, polling_func, TRUE); + amd64_patch (br[0], code); break; } + case OP_GC_LIVENESS_DEF: case OP_GC_LIVENESS_USE: case OP_GC_PARAM_SLOT_LIVENESS_DEF: @@ -6597,9 +6599,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert_not_reached (); #endif } - - last_ins = ins; - last_offset = offset; } cfg->code_len = code - cfg->native_code; @@ -6785,7 +6784,7 @@ 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 HOST_WIN32 +#ifdef TARGET_WIN32 mono_arch_unwindinfo_add_push_nonvol (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP); #endif /* These are handled automatically by the stack marking code */ @@ -6794,7 +6793,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, sizeof(mgreg_t)); mono_emit_unwind_op_def_cfa_reg (cfg, code, AMD64_RBP); async_exc_point (code); -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 mono_arch_unwindinfo_add_set_fpreg (&cfg->arch.unwindinfo, cfg->native_code, code, AMD64_RBP); #endif } @@ -6835,7 +6834,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* Allocate stack frame */ if (alloc_size) { /* See mono_emit_stack_alloc */ -#if defined(HOST_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK) +#if defined(TARGET_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*/ @@ -6855,7 +6854,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset); } async_exc_point (code); -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 if (cfg->arch.omit_fp) mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, 0x1000); #endif @@ -6870,7 +6869,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset); async_exc_point (code); } -#ifdef HOST_WIN32 +#ifdef TARGET_WIN32 if (cfg->arch.omit_fp) mono_arch_unwindinfo_add_alloc_stack (&cfg->arch.unwindinfo, cfg->native_code, code, remaining_size); #endif @@ -7024,8 +7023,6 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* Keep this in sync with emit_load_volatile_arguments */ for (i = 0; i < sig->param_count + sig->hasthis; ++i) { ArgInfo *ainfo = cinfo->args + i; - gint32 stack_offset; - MonoType *arg_type; ins = cfg->args [i]; @@ -7033,13 +7030,6 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* Unused arguments */ continue; - if (sig->hasthis && (i == 0)) - arg_type = &mono_defaults.object_class->byval_arg; - else - arg_type = sig->params [i - sig->hasthis]; - - stack_offset = ainfo->offset + ARGS_OFFSET; - if (cfg->globalra) { /* All the other moves are done by the register allocator */ switch (ainfo->storage) { @@ -7233,7 +7223,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) } } - if (cfg->gen_seq_points_debug_data) { + if (cfg->gen_sdb_seq_points) { MonoInst *info_var = cfg->arch.seq_point_info_var; /* Initialize seq_point_info_var */ @@ -7246,18 +7236,23 @@ mono_arch_emit_prolog (MonoCompile *cfg) amd64_mov_membase_reg (code, info_var->inst_basereg, info_var->inst_offset, AMD64_R11, 8); } - /* Initialize ss_trigger_page_var */ - ins = cfg->arch.ss_trigger_page_var; - - g_assert (ins->opcode == OP_REGOFFSET); - if (cfg->compile_aot) { + /* Initialize ss_tramp_var */ + ins = cfg->arch.ss_tramp_var; + g_assert (ins->opcode == OP_REGOFFSET); + amd64_mov_reg_membase (code, AMD64_R11, info_var->inst_basereg, info_var->inst_offset, 8); - amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, MONO_STRUCT_OFFSET (SeqPointInfo, ss_trigger_page), 8); + amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, MONO_STRUCT_OFFSET (SeqPointInfo, ss_tramp_addr), 8); + amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8); } else { + /* Initialize ss_trigger_page_var */ + ins = cfg->arch.ss_trigger_page_var; + + g_assert (ins->opcode == OP_REGOFFSET); + amd64_mov_reg_imm (code, AMD64_R11, (guint64)ss_trigger_page); + amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8); } - amd64_mov_membase_reg (code, ins->inst_basereg, ins->inst_offset, AMD64_R11, 8); } cfg->code_len = code - cfg->native_code; @@ -7271,7 +7266,7 @@ void mono_arch_emit_epilog (MonoCompile *cfg) { MonoMethod *method = cfg->method; - int quad, pos, i; + int quad, i; guint8 *code; int max_epilog_size; CallInfo *cinfo; @@ -7299,7 +7294,6 @@ mono_arch_emit_epilog (MonoCompile *cfg) code = mono_arch_instrument_epilog (cfg, mono_trace_leave_method, code, TRUE); /* the code restoring the registers must be kept in sync with OP_TAILCALL */ - pos = 0; if (method->save_lmf) { /* check if we need to restore protection of the stack after a stack overflow */ @@ -7606,7 +7600,6 @@ void* mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) { guchar *code = p; - CallInfo *cinfo = NULL; MonoMethodSignature *sig; MonoInst *inst; int i, n, stack_area = 0; @@ -7617,8 +7610,6 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean ena /* Allocate a new area on the stack and save arguments there */ sig = mono_method_signature (cfg->method); - cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig); - n = sig->param_count + sig->hasthis; stack_area = ALIGN_TO (n * 8, 16); @@ -7972,7 +7963,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 HOST_WIN32 +#ifdef TARGET_WIN32 if (i < 3) amd64_mov_reg_reg (code, param_regs [i], param_regs [i + 1], 8); else @@ -7988,6 +7979,7 @@ get_delegate_invoke_impl (gboolean has_target, guint32 param_count, guint32 *cod } nacl_global_codeman_validate (&start, 64, &code); + mono_arch_flush_icache (start, code - start); if (code_len) *code_len = code - start; @@ -8535,7 +8527,7 @@ mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip) SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start); g_assert (info->bp_addrs [native_offset] == 0); - info->bp_addrs [native_offset] = bp_trigger_page; + info->bp_addrs [native_offset] = mini_get_breakpoint_trampoline (); } else { /* * In production, we will use int3 (has to fix the size in the md @@ -8569,8 +8561,7 @@ mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip) guint32 native_offset = ip - (guint8*)ji->code_start; SeqPointInfo *info = mono_arch_get_seq_point_info (mono_domain_get (), ji->code_start); - g_assert (info->bp_addrs [native_offset] == 0); - info->bp_addrs [native_offset] = info; + info->bp_addrs [native_offset] = NULL; } else { for (i = 0; i < breakpoint_size; ++i) x86_nop (code); @@ -8606,8 +8597,7 @@ void mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji) { if (ji->from_aot) { - /* amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, 8) */ - MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 3); + /* The breakpoint instruction is a call */ } else { MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + breakpoint_fault_size); } @@ -8622,6 +8612,7 @@ void mono_arch_start_single_stepping (void) { mono_mprotect (ss_trigger_page, mono_pagesize (), 0); + ss_trampoline = mini_get_single_step_trampoline (); } /* @@ -8633,6 +8624,7 @@ void mono_arch_stop_single_stepping (void) { mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ); + ss_trampoline = NULL; } /* @@ -8683,7 +8675,6 @@ mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code) { SeqPointInfo *info; MonoJitInfo *ji; - int i; // FIXME: Add a free function @@ -8699,11 +8690,7 @@ mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code) // FIXME: Optimize the size info = g_malloc0 (sizeof (SeqPointInfo) + (ji->code_size * sizeof (gpointer))); - info->ss_trigger_page = ss_trigger_page; - info->bp_trigger_page = bp_trigger_page; - /* Initialize to a valid address */ - for (i = 0; i < ji->code_size; ++i) - info->bp_addrs [i] = info; + info->ss_tramp_addr = &ss_trampoline; mono_domain_lock (domain); g_hash_table_insert (domain_jit_info (domain)->arch_seq_points,