X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-x86.c;h=b85c2242c69e8fc7fb8e2b4ddfce4cb25bdcd6ab;hb=d46883ac2d6f8b4823c86bb0df149f9f1d3cf0c0;hp=aafc380d8f98af47218d0440dcaf78d9f6ca6161;hpb=c69ede50f2ab8deaee1b9970e025c0365a6496d6;p=mono.git diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index aafc380d8f9..b85c2242c69 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include "trace.h" @@ -63,9 +63,9 @@ static mono_mutex_t mini_arch_mutex; #ifdef TARGET_WIN32 /* Under windows, the default pinvoke calling convention is stdcall */ -#define CALLCONV_IS_STDCALL(sig) ((((sig)->call_convention) == MONO_CALL_STDCALL) || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_DEFAULT) || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_THISCALL)) +#define CALLCONV_IS_STDCALL(sig) ((sig)->pinvoke && ((sig)->call_convention == MONO_CALL_STDCALL || (sig)->call_convention == MONO_CALL_DEFAULT || (sig)->call_convention == MONO_CALL_THISCALL)) #else -#define CALLCONV_IS_STDCALL(sig) (((sig)->call_convention) == MONO_CALL_STDCALL || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_THISCALL)) +#define CALLCONV_IS_STDCALL(sig) ((sig)->pinvoke && ((sig)->call_convention == MONO_CALL_STDCALL || (sig)->call_convention == MONO_CALL_THISCALL)) #endif #define X86_IS_CALLEE_SAVED_REG(reg) (((reg) == X86_EBX) || ((reg) == X86_EDI) || ((reg) == X86_ESI)) @@ -543,7 +543,7 @@ get_call_info_internal (CallInfo *cinfo, MonoMethodSignature *sig) if (cinfo->vtype_retaddr) { /* if the function returns a struct on stack, the called method already does a ret $0x4 */ cinfo->callee_stack_pop = 4; - } else if (CALLCONV_IS_STDCALL (sig) && sig->pinvoke) { + } else if (CALLCONV_IS_STDCALL (sig)) { /* Have to compensate for the stack space popped by the native callee */ cinfo->callee_stack_pop = stack_size; } @@ -2239,22 +2239,22 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code) return code; } -#ifdef __APPLE__ +#ifdef TARGET_MACH static int tls_gs_offset; #endif gboolean -mono_x86_have_tls_get (void) +mono_arch_have_fast_tls (void) { #ifdef TARGET_MACH - static gboolean have_tls_get = FALSE; + static gboolean have_fast_tls = FALSE; static gboolean inited = FALSE; + guint32 *ins; + if (mini_get_debug_options ()->use_fallback_tls) + return FALSE; if (inited) - return have_tls_get; - -#ifdef MONO_HAVE_FAST_TLS - guint32 *ins; + return have_fast_tls; ins = (guint32*)pthread_getspecific; /* @@ -2263,56 +2263,29 @@ mono_x86_have_tls_get (void) * mov 0x4(%esp),%eax * mov %gs:[offset](,%eax,4),%eax */ - have_tls_get = ins [0] == 0x0424448b && ins [1] == 0x85048b65; + have_fast_tls = ins [0] == 0x0424448b && ins [1] == 0x85048b65; tls_gs_offset = ins [2]; -#endif - inited = TRUE; - return have_tls_get; + return have_fast_tls; #elif defined(TARGET_ANDROID) return FALSE; #else + if (mini_get_debug_options ()->use_fallback_tls) + return FALSE; 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 - * @dreg: hard register where to place the result - * @tls_offset: offset info - * - * mono_x86_emit_tls_get emits in @code the native code that puts in - * the dreg register the item in the thread local storage identified - * by tls_offset. - * - * Returns: a pointer to the end of the stored code - */ -guint8* mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset) { -#if defined(__APPLE__) +#if defined(TARGET_MACH) x86_prefix (code, X86_GS_PREFIX); 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 + /* + * See the Under the Hood article in the May 1996 issue of Microsoft Systems * Journal and/or a disassembly of the TlsGet () function. */ x86_prefix (code, X86_FS_PREFIX); @@ -2345,55 +2318,19 @@ mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset) } static guint8* -emit_tls_get_reg (guint8* code, int dreg, int offset_reg) +mono_x86_emit_tls_set (guint8* code, int sreg, int tls_offset) { - /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */ -#if defined(__APPLE__) || defined(__linux__) - if (dreg != offset_reg) - x86_mov_reg_reg (code, dreg, offset_reg, sizeof (mgreg_t)); +#if defined(TARGET_MACH) x86_prefix (code, X86_GS_PREFIX); - x86_mov_reg_membase (code, dreg, dreg, 0, sizeof (mgreg_t)); -#else - g_assert_not_reached (); -#endif - return code; -} - -guint8* -mono_x86_emit_tls_get_reg (guint8* code, int dreg, int offset_reg) -{ - return emit_tls_get_reg (code, dreg, offset_reg); -} - -static guint8* -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 + x86_mov_mem_reg (code, tls_gs_offset + (tls_offset * 4), sreg, 4); +#elif defined(TARGET_WIN32) g_assert_not_reached (); -#elif defined(__APPLE__) || defined(__linux__) - x86_prefix (code, X86_GS_PREFIX); - x86_mov_membase_reg (code, offset_reg, 0, sreg, sizeof (mgreg_t)); #else - g_assert_not_reached (); + x86_prefix (code, X86_GS_PREFIX); + x86_mov_mem_reg (code, tls_offset, sreg, 4); #endif return code; } - - /* - * mono_arch_translate_tls_offset: - * - * Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG. - */ -int -mono_arch_translate_tls_offset (int offset) -{ -#ifdef __APPLE__ - return tls_gs_offset + (offset * 4); -#else - return offset; -#endif -} /* * emit_setup_lmf: @@ -2709,9 +2646,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) /* Load ss_tramp_var */ /* This is equal to &ss_trampoline */ x86_mov_reg_membase (code, X86_ECX, var->inst_basereg, var->inst_offset, sizeof (mgreg_t)); - x86_alu_membase_imm (code, X86_CMP, X86_ECX, 0, 0); + x86_mov_reg_membase (code, X86_ECX, X86_ECX, 0, sizeof (mgreg_t)); + x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0); br[0] = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE); - x86_call_membase (code, X86_ECX, 0); + x86_call_reg (code, X86_ECX); x86_patch (br [0], code); } @@ -4151,18 +4089,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = mono_x86_emit_tls_get (code, ins->dreg, ins->inst_offset); break; } - case OP_TLS_GET_REG: { - code = emit_tls_get_reg (code, ins->dreg, ins->sreg1); - break; - } case OP_TLS_SET: { code = mono_x86_emit_tls_set (code, ins->sreg1, ins->inst_offset); break; } - case OP_TLS_SET_REG: { - code = emit_tls_set_reg (code, ins->sreg1, ins->sreg2); - break; - } case OP_MEMORY_BARRIER: { if (ins->backend.memory_barrier_kind == MONO_MEMORY_BARRIER_SEQ) { x86_prefix (code, X86_LOCK_PREFIX); @@ -4872,6 +4802,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_XZERO: x86_sse_alu_pd_reg_reg (code, X86_SSE_PXOR, ins->dreg, ins->dreg); break; + case OP_XONES: + x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPEQB, ins->dreg, ins->dreg); + break; case OP_FCONV_TO_R8_X: x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE, TRUE); @@ -5325,40 +5258,29 @@ mono_arch_emit_epilog (MonoCompile *cfg) if (method->save_lmf) { gint32 lmf_offset = cfg->lmf_var->inst_offset; guint8 *patch; - gboolean supported = FALSE; - - if (cfg->compile_aot) { -#if defined(MONO_HAVE_FAST_TLS) - supported = TRUE; -#endif - } else if (mono_get_jit_tls_offset () != -1) { - supported = TRUE; - } /* check if we need to restore protection of the stack after a stack overflow */ - if (supported) { - if (cfg->compile_aot) { - code = emit_load_aotconst (NULL, code, cfg, NULL, X86_ECX, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_JIT_TLS)); - - code = emit_tls_get_reg (code, X86_ECX, X86_ECX); - } else { - code = mono_x86_emit_tls_get (code, X86_ECX, mono_get_jit_tls_offset ()); - } - - /* we load the value in a separate instruction: this mechanism may be - * used later as a safer way to do thread interruption - */ - x86_mov_reg_membase (code, X86_ECX, X86_ECX, MONO_STRUCT_OFFSET (MonoJitTlsData, restore_stack_prot), 4); - x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0); - patch = code; - x86_branch8 (code, X86_CC_Z, 0, FALSE); - /* note that the call trampoline will preserve eax/edx */ - x86_call_reg (code, X86_ECX); - x86_patch (patch, code); + if (!cfg->compile_aot && mono_arch_have_fast_tls () && mono_tls_get_tls_offset (TLS_KEY_JIT_TLS) != -1) { + code = mono_x86_emit_tls_get (code, X86_ECX, mono_tls_get_tls_offset (TLS_KEY_JIT_TLS)); } else { - /* FIXME: maybe save the jit tls in the prolog */ + gpointer func = mono_tls_get_tls_getter (TLS_KEY_JIT_TLS, TRUE); + /* FIXME use tls only from IR level */ + x86_xchg_reg_reg (code, X86_EAX, X86_ECX, 4); + code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, func); + x86_xchg_reg_reg (code, X86_EAX, X86_ECX, 4); } + /* we load the value in a separate instruction: this mechanism may be + * used later as a safer way to do thread interruption + */ + x86_mov_reg_membase (code, X86_ECX, X86_ECX, MONO_STRUCT_OFFSET (MonoJitTlsData, restore_stack_prot), 4); + x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0); + patch = code; + x86_branch8 (code, X86_CC_Z, 0, FALSE); + /* note that the call trampoline will preserve eax/edx */ + x86_call_reg (code, X86_ECX); + x86_patch (patch, code); + /* restore caller saved regs */ if (cfg->used_int_regs & (1 << X86_EBX)) { x86_mov_reg_membase (code, X86_EBX, cfg->frame_reg, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, ebx), 4); @@ -5613,7 +5535,7 @@ imt_branch_distance (MonoIMTCheckItem **imt_entries, int start, int target) * LOCKING: called with the domain lock held */ gpointer -mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, +mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) { int i; @@ -5645,7 +5567,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI size += item->chunk_size; } if (fail_tramp) - code = mono_method_alloc_generic_virtual_thunk (domain, size); + code = mono_method_alloc_generic_virtual_trampoline (domain, size); else code = mono_domain_code_reserve (domain, size); start = code; @@ -5715,7 +5637,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI } if (!fail_tramp) - mono_stats.imt_thunks_size += code - start; + mono_stats.imt_trampolines_size += code - start; g_assert (code - start <= size); #if DEBUG_IMT @@ -5730,7 +5652,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI if (vtable) buff = g_strdup_printf ("imt_%s_%s_entries_%d", vtable->klass->name_space, vtable->klass->name, count); else - buff = g_strdup_printf ("imt_thunk_entries_%d", count); + buff = g_strdup_printf ("imt_trampoline_entries_%d", count); mono_emit_jit_tramp (start, code - start, buff); g_free (buff); }