X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-x86.c;h=75a6a7a24ad36c4a9a0a6749dc65e8949c692720;hb=7f23a0c1f3b357cea793f429b52a918f45157855;hp=675fd76045fd700169dbf4a01cccd0760323a6d3;hpb=9622039cfb0af1de5b65a159e717a60b888978e4;p=mono.git diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 675fd76045f..75a6a7a24ad 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -6,7 +6,9 @@ * Dietmar Maurer (dietmar@ximian.com) * Patrik Torstensson * - * (C) 2003 Ximian, Inc. + * Copyright 2003 Ximian, Inc. + * Copyright 2003-2011 Novell Inc. + * Copyright 2011 Xamarin Inc. */ #include "mini.h" #include @@ -24,11 +26,13 @@ #include #include #include +#include #include "trace.h" #include "mini-x86.h" #include "cpu-x86.h" #include "ir-emit.h" +#include "mini-gc.h" /* On windows, these hold the key returned by TlsAlloc () */ static gint lmf_tls_offset = -1; @@ -578,7 +582,7 @@ get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSign * FIXME: The metadata calls might not be signal safe. */ int -mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info) +mono_arch_get_argument_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info) { int len, k, args_size = 0; int size, pad; @@ -591,7 +595,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit cinfo = (CallInfo*)g_newa (guint8*, len); memset (cinfo, 0, len); - cinfo = get_call_info_internal (NULL, cinfo, csig); + cinfo = get_call_info_internal (gsctx, cinfo, csig); arg_info [0].offset = offset; @@ -797,6 +801,10 @@ 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 ()); DeleteCriticalSection (&mini_arch_mutex); } @@ -804,7 +812,7 @@ mono_arch_cleanup (void) * This function returns the optimizations supported on this cpu. */ guint32 -mono_arch_cpu_optimizazions (guint32 *exclude_mask) +mono_arch_cpu_optimizations (guint32 *exclude_mask) { #if !defined(__native_client__) int eax, ebx, ecx, edx; @@ -1129,7 +1137,7 @@ mono_arch_allocate_vars (MonoCompile *cfg) } /* Allocate locals */ - offsets = mono_allocate_stack_slots (cfg, &locals_stack_size, &locals_stack_align); + 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; @@ -1138,8 +1146,15 @@ mono_arch_allocate_vars (MonoCompile *cfg) return; } if (locals_stack_align) { + int prev_offset = offset; + offset += (locals_stack_align - 1); offset &= ~(locals_stack_align - 1); + + while (prev_offset < offset) { + prev_offset += 4; + mini_gc_set_slot_type_from_fp (cfg, - prev_offset, SLOT_NOREF); + } } cfg->locals_min_stack_offset = - (offset + locals_stack_size); cfg->locals_max_stack_offset = - offset; @@ -1234,6 +1249,8 @@ mono_arch_create_vars (MonoCompile *cfg) if ((cinfo->ret.storage != ArgValuetypeInReg) && MONO_TYPE_ISSTRUCT (sig->ret)) { cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG); } + + cfg->arch_eh_jit_info = 1; } /* @@ -1267,9 +1284,7 @@ static void emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) { MonoMethodSignature *tmp_sig; - - /* FIXME: Add support for signature tokens to AOT */ - cfg->disable_aot = TRUE; + int sig_reg; /* * mono_ArgIterator_Setup assumes the signature cookie is @@ -1282,7 +1297,13 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo) tmp_sig->sentinelpos = 0; memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_X86_PUSH_IMM, -1, -1, tmp_sig); + if (cfg->compile_aot) { + sig_reg = mono_alloc_ireg (cfg); + MONO_EMIT_NEW_SIGNATURECONST (cfg, sig_reg, tmp_sig); + MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, sig_reg); + } else { + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_X86_PUSH_IMM, -1, -1, tmp_sig); + } } #ifdef ENABLE_LLVM @@ -1396,14 +1417,27 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) } #endif +static void +emit_gc_param_slot_def (MonoCompile *cfg, int sp_offset, MonoType *t) +{ + if (cfg->compute_gc_maps) { + MonoInst *def; + + /* On x86, the offsets are from the sp value before the start of the call sequence */ + if (t == NULL) + t = &mono_defaults.int_class->byval_arg; + EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, sp_offset, t); + } +} + void mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) { MonoInst *arg, *in; MonoMethodSignature *sig; - int i, n; + int i, j, n; CallInfo *cinfo; - int sentinelpos = 0; + int sentinelpos = 0, sp_offset = 0; sig = call->signature; n = sig->param_count + sig->hasthis; @@ -1419,6 +1453,11 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) arg->sreg1 = X86_ESP; arg->inst_imm = cinfo->stack_align_amount; MONO_ADD_INS (cfg->cbb, arg); + for (i = 0; i < cinfo->stack_align_amount; i += sizeof (mgreg_t)) { + sp_offset += 4; + + emit_gc_param_slot_def (cfg, sp_offset, NULL); + } } if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) { @@ -1434,15 +1473,20 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } } + // FIXME: Emit EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF everywhere + /* Handle the case where there are no implicit arguments */ if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sentinelpos)) { emit_sig_cookie (cfg, call, cinfo); + sp_offset += 4; + emit_gc_param_slot_def (cfg, sp_offset, NULL); } /* Arguments are pushed in the reverse order */ for (i = n - 1; i >= 0; i --) { ArgInfo *ainfo = cinfo->args + i; - MonoType *t; + MonoType *orig_type, *t; + int argsize; if (cinfo->vtype_retaddr && cinfo->vret_arg_index == 1 && i == 0) { /* Push the vret arg before the first argument */ @@ -1451,12 +1495,15 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) vtarg->type = STACK_MP; vtarg->sreg1 = call->vret_var->dreg; MONO_ADD_INS (cfg->cbb, vtarg); + sp_offset += 4; + emit_gc_param_slot_def (cfg, sp_offset, NULL); } if (i >= sig->hasthis) t = sig->params [i - sig->hasthis]; else t = &mono_defaults.int_class->byval_arg; + orig_type = t; t = mini_type_get_underlying_type (cfg->generic_sharing_context, t); MONO_INST_NEW (cfg, arg, OP_X86_PUSH); @@ -1489,9 +1536,12 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) arg->backend.size = size; MONO_ADD_INS (cfg->cbb, arg); + sp_offset += size; + emit_gc_param_slot_def (cfg, sp_offset, orig_type); } - } - else { + } else { + argsize = 4; + switch (ainfo->storage) { case ArgOnStack: arg->opcode = OP_X86_PUSH; @@ -1501,14 +1551,17 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) arg->opcode = OP_STORER4_MEMBASE_REG; arg->inst_destbasereg = X86_ESP; arg->inst_offset = 0; + argsize = 4; } else if (t->type == MONO_TYPE_R8) { MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 8); arg->opcode = OP_STORER8_MEMBASE_REG; arg->inst_destbasereg = X86_ESP; arg->inst_offset = 0; + argsize = 8; } else if (t->type == MONO_TYPE_I8 || t->type == MONO_TYPE_U8) { arg->sreg1 ++; MONO_EMIT_NEW_UNALU (cfg, OP_X86_PUSH, -1, in->dreg + 2); + sp_offset += 4; } } break; @@ -1517,11 +1570,35 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } MONO_ADD_INS (cfg->cbb, arg); + + sp_offset += argsize; + + if (cfg->compute_gc_maps) { + if (argsize == 4) { + /* FIXME: The == STACK_OBJ check might be fragile ? */ + if (sig->hasthis && i == 0 && call->args [i]->type == STACK_OBJ) { + /* this */ + if (call->need_unbox_trampoline) + /* The unbox trampoline transforms this into a managed pointer */ + emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.int_class->this_arg); + else + emit_gc_param_slot_def (cfg, sp_offset, &mono_defaults.object_class->byval_arg); + } else { + emit_gc_param_slot_def (cfg, sp_offset, orig_type); + } + } else { + /* i8/r8 */ + for (j = 0; j < argsize; j += 4) + emit_gc_param_slot_def (cfg, sp_offset - j, NULL); + } + } } if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sentinelpos)) { /* Emit the signature cookie just before the implicit arguments */ emit_sig_cookie (cfg, call, cinfo); + sp_offset += 4; + emit_gc_param_slot_def (cfg, sp_offset, NULL); } } @@ -1546,6 +1623,8 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) vtarg->type = STACK_MP; vtarg->sreg1 = call->vret_var->dreg; MONO_ADD_INS (cfg->cbb, vtarg); + sp_offset += 4; + emit_gc_param_slot_def (cfg, sp_offset, NULL); } /* if the function returns a struct on stack, the called method already does a ret $0x4 */ @@ -1554,6 +1633,8 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } call->stack_usage = cinfo->stack_usage; + call->stack_align_amount = cinfo->stack_align_amount; + cfg->arch.param_area_size = MAX (cfg->arch.param_area_size, sp_offset); } void @@ -1821,8 +1902,10 @@ emit_call (MonoCompile *cfg, guint8 *code, guint32 patch_type, gconstpointer dat This is required for code patching to be safe on SMP machines. */ pad_size = (guint32)(code + 1 - cfg->native_code) & 0x3; +#ifndef __native_client_codegen__ if (needs_paddings && pad_size) - x86_padding (code, pad_size); + x86_padding (code, 4 - pad_size); +#endif mono_add_patch_info (cfg, code - cfg->native_code, patch_type, data); x86_call_code (code, 0); @@ -2199,33 +2282,56 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code) return code; } +#ifdef __APPLE__ +static int tls_gs_offset; +#endif + gboolean mono_x86_have_tls_get (void) { #ifdef __APPLE__ static gboolean have_tls_get = FALSE; static gboolean inited = FALSE; + guint32 *ins; if (inited) return have_tls_get; - guint32 *ins = (guint32*)pthread_getspecific; + ins = (guint32*)pthread_getspecific; /* * We're looking for these two instructions: * * mov 0x4(%esp),%eax - * mov %gs:0x48(,%eax,4),%eax + * mov %gs:[offset](,%eax,4),%eax */ - have_tls_get = ins [0] == 0x0424448b && ins [1] == 0x85048b65 && ins [2] == 0x00000048; + have_tls_get = ins [0] == 0x0424448b && ins [1] == 0x85048b65; + tls_gs_offset = ins [2]; inited = TRUE; return have_tls_get; +#elif defined(TARGET_ANDROID) + return FALSE; #else return TRUE; #endif } +static guint8* +mono_x86_emit_tls_set (guint8* code, int sreg, int tls_offset) +{ +#if defined(__APPLE__) + x86_prefix (code, X86_GS_PREFIX); + x86_mov_mem_reg (code, tls_gs_offset + (tls_offset * 4), sreg, 4); +#elif defined(TARGET_WIN32) + g_assert_not_reached (); +#else + x86_prefix (code, X86_GS_PREFIX); + x86_mov_mem_reg (code, tls_offset, sreg, 4); +#endif + return code; +} + /* * mono_x86_emit_tls_get: * @code: buffer to store code to @@ -2243,7 +2349,7 @@ mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset) { #if defined(__APPLE__) x86_prefix (code, X86_GS_PREFIX); - x86_mov_reg_mem (code, dreg, 0x48 + tls_offset * 4, 4); + x86_mov_reg_mem (code, dreg, tls_gs_offset + (tls_offset * 4), 4); #elif defined(TARGET_WIN32) /* * See the Under the Hood article in the May 1996 issue of Microsoft Systems @@ -2421,7 +2527,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) cfg->code_size *= 2; cfg->native_code = mono_realloc_native_code(cfg); code = cfg->native_code + offset; - mono_jit_stats.code_reallocs++; + cfg->stat_code_reallocs++; } if (cfg->debug_info) @@ -2632,6 +2738,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) */ for (i = 0; i < 6; ++i) x86_nop (code); + /* + * Add an additional nop so skipping the bp doesn't cause the ip to point + * to another IL offset. + */ + x86_nop (code); break; } case OP_ADDCC: @@ -3047,6 +3158,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) MonoCallInst *call = (MonoCallInst*)ins; int pos = 0, i; + ins->flags |= MONO_INST_GC_CALLSITE; + ins->backend.pc_offset = code - cfg->native_code; + /* FIXME: no tracing support... */ if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) code = mono_arch_instrument_epilog (cfg, mono_profiler_method_leave, code, FALSE); @@ -3075,7 +3189,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } /* Copy arguments on the stack to our argument area */ - for (i = 0; i < call->stack_usage; i += 4) { + for (i = 0; i < call->stack_usage - call->stack_align_amount; i += 4) { x86_mov_reg_membase (code, X86_EAX, X86_ESP, i, 4); x86_mov_membase_reg (code, X86_EBP, 8 + i, X86_EAX, 4); } @@ -3086,6 +3200,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0); x86_jump32 (code, 0); + ins->flags |= MONO_INST_GC_CALLSITE; cfg->disable_aot = TRUE; break; } @@ -3997,9 +4112,15 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; } case OP_MEMORY_BARRIER: { - /* http://blogs.sun.com/dave/resource/NHM-Pipeline-Blog-V2.txt */ - x86_prefix (code, X86_LOCK_PREFIX); - x86_alu_membase_imm (code, X86_ADD, X86_ESP, 0, 0); + /* x86 only needs barrier for StoreLoad and FullBarrier */ + switch (ins->backend.memory_barrier_kind) { + case StoreLoadBarrier: + case FullBarrier: + /* http://blogs.sun.com/dave/resource/NHM-Pipeline-Blog-V2.txt */ + x86_prefix (code, X86_LOCK_PREFIX); + x86_alu_membase_imm (code, X86_ADD, X86_ESP, 0, 0); + break; + } break; } case OP_ATOMIC_ADD_I4: { @@ -4618,10 +4739,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_INSERTX_R8_SLOW: x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE, TRUE); + if (cfg->verbose_level) + printf ("CONVERTING a OP_INSERTX_R8_SLOW %d offset %x\n", ins->inst_c0, offset); if (ins->inst_c0) x86_sse_alu_pd_reg_membase (code, X86_SSE_MOVHPD_REG_MEMBASE, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset); else - x86_sse_alu_pd_reg_membase (code, X86_SSE_MOVSD_REG_MEMBASE, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset); + x86_movsd_reg_membase (code, ins->dreg, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset); break; case OP_STOREX_MEMBASE_REG: @@ -4788,7 +4911,7 @@ mono_arch_register_lowlevel_calls (void) } void -mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors) +mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, MonoCodeManager *dyn_code_mp, gboolean run_cctors) { MonoJumpInfo *patch_info; gboolean compile_aot = !run_cctors; @@ -4921,6 +5044,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) // IP saved at CFA - 4 /* There is no IP reg on x86 */ mono_emit_unwind_op_offset (cfg, code, X86_NREG, -cfa_offset); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); need_stack_frame = needs_stack_frame (cfg); @@ -4931,6 +5055,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) mono_emit_unwind_op_offset (cfg, code, X86_EBP, - cfa_offset); x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4); mono_emit_unwind_op_def_cfa_reg (cfg, code, X86_EBP); + /* These are handled automatically by the stack marking code */ + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); } else { cfg->frame_reg = X86_ESP; } @@ -4938,49 +5064,6 @@ mono_arch_emit_prolog (MonoCompile *cfg) alloc_size = cfg->stack_offset; pos = 0; - if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { - /* Might need to attach the thread to the JIT or change the domain for the callback */ - if (appdomain_tls_offset != -1 && lmf_tls_offset != -1) { - guint8 *buf, *no_domain_branch; - - code = mono_x86_emit_tls_get (code, X86_EAX, appdomain_tls_offset); - x86_alu_reg_imm (code, X86_CMP, X86_EAX, GPOINTER_TO_UINT (cfg->domain)); - no_domain_branch = code; - x86_branch8 (code, X86_CC_NE, 0, 0); - code = mono_x86_emit_tls_get ( code, X86_EAX, lmf_tls_offset); - x86_test_reg_reg (code, X86_EAX, X86_EAX); - buf = code; - x86_branch8 (code, X86_CC_NE, 0, 0); - x86_patch (no_domain_branch, code); - x86_push_imm (code, cfg->domain); - code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach"); - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); - x86_patch (buf, code); -#ifdef TARGET_WIN32 - /* The TLS key actually contains a pointer to the MonoJitTlsData structure */ - /* FIXME: Add a separate key for LMF to avoid this */ - x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf)); -#endif - } - else { - if (cfg->compile_aot) { - /* - * This goes before the saving of callee saved regs, so save the got reg - * ourselves. - */ - x86_push_reg (code, MONO_ARCH_GOT_REG); - code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL); - x86_push_imm (code, 0); - } else { - x86_push_imm (code, cfg->domain); - } - code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_jit_thread_attach"); - x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4); - if (cfg->compile_aot) - x86_pop_reg (code, MONO_ARCH_GOT_REG); - } - } - if (method->save_lmf) { pos += sizeof (MonoLMF); @@ -4993,19 +5076,24 @@ mono_arch_emit_prolog (MonoCompile *cfg) x86_push_imm_template (code); } cfa_offset += sizeof (gpointer); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); /* save all caller saved regs */ x86_push_reg (code, X86_EBP); cfa_offset += sizeof (gpointer); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); x86_push_reg (code, X86_ESI); cfa_offset += sizeof (gpointer); mono_emit_unwind_op_offset (cfg, code, X86_ESI, - cfa_offset); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); x86_push_reg (code, X86_EDI); cfa_offset += sizeof (gpointer); mono_emit_unwind_op_offset (cfg, code, X86_EDI, - cfa_offset); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); x86_push_reg (code, X86_EBX); cfa_offset += sizeof (gpointer); mono_emit_unwind_op_offset (cfg, code, X86_EBX, - cfa_offset); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); if ((lmf_tls_offset != -1) && !is_win32 && !optimize_for_xen) { /* @@ -5013,15 +5101,19 @@ mono_arch_emit_prolog (MonoCompile *cfg) * through the mono_lmf_addr TLS variable. */ /* %eax = previous_lmf */ - x86_prefix (code, X86_GS_PREFIX); - x86_mov_reg_mem (code, X86_EAX, lmf_tls_offset, 4); + code = mono_x86_emit_tls_get (code, X86_EAX, lmf_tls_offset); /* skip esp + method_info + lmf */ x86_alu_reg_imm (code, X86_SUB, X86_ESP, 12); + cfa_offset += 12; + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + 4, SLOT_NOREF); + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + 8, SLOT_NOREF); /* push previous_lmf */ x86_push_reg (code, X86_EAX); + cfa_offset += 4; + mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF); /* new lmf = ESP */ - x86_prefix (code, X86_GS_PREFIX); - x86_mov_mem_reg (code, lmf_tls_offset, X86_ESP, 4); + code = mono_x86_emit_tls_set (code, X86_ESP, lmf_tls_offset); } else { /* get the address of lmf for the current thread */ /* @@ -5060,6 +5152,8 @@ mono_arch_emit_prolog (MonoCompile *cfg) pos += 4; cfa_offset += sizeof (gpointer); mono_emit_unwind_op_offset (cfg, code, X86_EBX, - cfa_offset); + /* These are handled automatically by the stack marking code */ + mini_gc_set_slot_type_from_cfa (cfg, - cfa_offset, SLOT_NOREF); } if (cfg->used_int_regs & (1 << X86_EDI)) { @@ -5067,6 +5161,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) pos += 4; cfa_offset += sizeof (gpointer); mono_emit_unwind_op_offset (cfg, code, X86_EDI, - cfa_offset); + mini_gc_set_slot_type_from_cfa (cfg, - cfa_offset, SLOT_NOREF); } if (cfg->used_int_regs & (1 << X86_ESI)) { @@ -5074,6 +5169,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) pos += 4; cfa_offset += sizeof (gpointer); mono_emit_unwind_op_offset (cfg, code, X86_ESI, - cfa_offset); + mini_gc_set_slot_type_from_cfa (cfg, - cfa_offset, SLOT_NOREF); } } @@ -5085,10 +5181,15 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (need_stack_frame) tot += 4; /* ebp */ tot &= MONO_ARCH_FRAME_ALIGNMENT - 1; - if (tot) + if (tot) { alloc_size += MONO_ARCH_FRAME_ALIGNMENT - tot; + for (i = 0; i < MONO_ARCH_FRAME_ALIGNMENT - tot; i += sizeof (mgreg_t)) + mini_gc_set_slot_type_from_fp (cfg, - (alloc_size + pos - i), SLOT_NOREF); + } } + cfg->arch.sp_fp_offset = alloc_size + pos; + if (alloc_size) { /* See mono_emit_stack_alloc */ #if defined(TARGET_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK) @@ -5101,7 +5202,7 @@ mono_arch_emit_prolog (MonoCompile *cfg) cfg->code_size *= 2; cfg->native_code = mono_realloc_native_code(cfg); code = cfg->native_code + offset; - mono_jit_stats.code_reallocs++; + cfg->stat_code_reallocs++; } while (remaining_size >= 0x1000) { x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x1000); @@ -5217,7 +5318,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) { cfg->code_size *= 2; cfg->native_code = mono_realloc_native_code(cfg); - mono_jit_stats.code_reallocs++; + cfg->stat_code_reallocs++; } code = cfg->native_code + cfg->code_len; @@ -5258,8 +5359,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) x86_mov_reg_membase (code, X86_ECX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4); /* lmf = previous_lmf */ - x86_prefix (code, X86_GS_PREFIX); - x86_mov_mem_reg (code, lmf_tls_offset, X86_ECX, 4); + code = mono_x86_emit_tls_set (code, X86_ECX, lmf_tls_offset); } else { /* Find a spare register */ switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) { @@ -5351,7 +5451,7 @@ mono_arch_emit_epilog (MonoCompile *cfg) if (CALLCONV_IS_STDCALL (sig)) { MonoJitArgumentInfo *arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1)); - stack_to_pop = mono_arch_get_argument_info (sig, sig->param_count, arg_info); + stack_to_pop = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info); } else if (MONO_TYPE_ISSTRUCT (mono_method_signature (cfg->method)->ret) && (cinfo->ret.storage == ArgOnStack)) stack_to_pop = 4; else @@ -5398,7 +5498,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg) while (cfg->code_len + code_size > (cfg->code_size - 16)) { cfg->code_size *= 2; cfg->native_code = mono_realloc_native_code(cfg); - mono_jit_stats.code_reallocs++; + cfg->stat_code_reallocs++; } code = cfg->native_code + cfg->code_len; @@ -5498,41 +5598,31 @@ mono_arch_is_inst_imm (gint64 imm) return TRUE; } -/* - * Support for fast access to the thread-local lmf structure using the GS - * segment register on NPTL + kernel 2.6.x. - */ - -static gboolean tls_offset_inited = FALSE; - void -mono_arch_setup_jit_tls_data (MonoJitTlsData *tls) +mono_arch_finish_init (void) { - if (!tls_offset_inited) { - if (!getenv ("MONO_NO_TLS")) { + if (!getenv ("MONO_NO_TLS")) { #ifdef TARGET_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 (); - - /* Only 64 tls entries can be accessed using inline code */ - if (appdomain_tls_offset >= 64) - appdomain_tls_offset = -1; - if (lmf_tls_offset >= 64) - lmf_tls_offset = -1; + /* + * 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 (); + + /* Only 64 tls entries can be accessed using inline code */ + if (appdomain_tls_offset >= 64) + appdomain_tls_offset = -1; + if (lmf_tls_offset >= 64) + lmf_tls_offset = -1; #else #if MONO_XEN_OPT - optimize_for_xen = access ("/proc/xen", F_OK) == 0; + optimize_for_xen = access ("/proc/xen", F_OK) == 0; #endif - tls_offset_inited = TRUE; - 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 (); + 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 (); #endif - } } } @@ -5819,9 +5909,9 @@ mono_arch_get_patch_offset (guint8 *code) { if ((code [0] == 0x8b) && (x86_modrm_mod (code [1]) == 0x2)) return 2; - else if ((code [0] == 0xba)) + else if (code [0] == 0xba) return 1; - else if ((code [0] == 0x68)) + else if (code [0] == 0x68) /* push IMM */ return 1; else if ((code [0] == 0xff) && (x86_modrm_reg (code [1]) == 0x6)) @@ -6089,19 +6179,54 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe return start; } -gpointer +mgreg_t mono_arch_context_get_int_reg (MonoContext *ctx, int reg) { switch (reg) { - case X86_EAX: return (gpointer)ctx->eax; - case X86_EBX: return (gpointer)ctx->ebx; - case X86_ECX: return (gpointer)ctx->ecx; - case X86_EDX: return (gpointer)ctx->edx; - case X86_ESP: return (gpointer)ctx->esp; - case X86_EBP: return (gpointer)ctx->ebp; - case X86_ESI: return (gpointer)ctx->esi; - case X86_EDI: return (gpointer)ctx->edi; - default: g_assert_not_reached (); + case X86_EAX: return ctx->eax; + case X86_EBX: return ctx->ebx; + case X86_ECX: return ctx->ecx; + case X86_EDX: return ctx->edx; + case X86_ESP: return ctx->esp; + case X86_EBP: return ctx->ebp; + case X86_ESI: return ctx->esi; + case X86_EDI: return ctx->edi; + default: + g_assert_not_reached (); + return 0; + } +} + +void +mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val) +{ + switch (reg) { + case X86_EAX: + ctx->eax = val; + break; + case X86_EBX: + ctx->ebx = val; + break; + case X86_ECX: + ctx->ecx = val; + break; + case X86_EDX: + ctx->edx = val; + break; + case X86_ESP: + ctx->esp = val; + break; + case X86_EBP: + ctx->ebp = val; + break; + case X86_ESI: + ctx->esi = val; + break; + case X86_EDI: + ctx->edi = val; + break; + default: + g_assert_not_reached (); } } @@ -6453,7 +6578,8 @@ gboolean mono_arch_is_single_step_event (void *info, void *sigctx) { #ifdef TARGET_WIN32 - EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info; /* Sometimes the address is off by 4 */ + EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */ + if ((einfo->ExceptionInformation[1] >= ss_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)ss_trigger_page + 128)) return TRUE; else @@ -6472,7 +6598,7 @@ gboolean mono_arch_is_breakpoint_event (void *info, void *sigctx) { #ifdef TARGET_WIN32 - EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info; /* Sometimes the address is off by 4 */ + EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */ if ((einfo->ExceptionInformation[1] >= bp_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)bp_trigger_page + 128)) return TRUE; else @@ -6487,44 +6613,15 @@ mono_arch_is_breakpoint_event (void *info, void *sigctx) #endif } -/* - * mono_arch_get_ip_for_breakpoint: - * - * See mini-amd64.c for docs. - */ -guint8* -mono_arch_get_ip_for_breakpoint (MonoJitInfo *ji, MonoContext *ctx) -{ - guint8 *ip = MONO_CONTEXT_GET_IP (ctx); - - return ip; -} - #define BREAKPOINT_SIZE 6 -/* - * mono_arch_get_ip_for_single_step: - * - * See mini-amd64.c for docs. - */ -guint8* -mono_arch_get_ip_for_single_step (MonoJitInfo *ji, MonoContext *ctx) -{ - guint8 *ip = MONO_CONTEXT_GET_IP (ctx); - - /* Size of x86_alu_reg_imm */ - ip += 6; - - return ip; -} - /* * mono_arch_skip_breakpoint: * * See mini-amd64.c for docs. */ void -mono_arch_skip_breakpoint (MonoContext *ctx) +mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji) { MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE); }