[x86] Resurrect inlined fast tls
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 21 Nov 2016 21:52:50 +0000 (13:52 -0800)
committerVlad Brezae <brezaevlad@gmail.com>
Wed, 14 Dec 2016 15:52:50 +0000 (17:52 +0200)
mono/mini/cpu-x86.md
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/utils/mono-tls.c

index 3f92fcba2b68d5ca02f9e22af25c6a3b3743d4e0..df978e0ae9277944b8b5542ed56c481b53b0f82a 100644 (file)
@@ -304,9 +304,7 @@ bigmul_un: len:2 dest:l src1:a src2:i
 sext_i1: dest:i src1:y len:3
 sext_i2: dest:i src1:y len:3
 tls_get: dest:i len:32
-tls_get_reg: dest:i src1:i len:20
 tls_set: src1:i len:20
-tls_set_reg: src1:i src2:i len:20
 atomic_add_i4: src1:b src2:i dest:i len:16
 atomic_exchange_i4: src1:b src2:i dest:a len:24
 atomic_cas_i4: src1:b src2:i src3:a dest:a len:24
index d0c042ccee6f8acd8c3faf86f50e3281441cacbb..b616059dfb6d2f836b2d702ac380d3b54ddb1c6a 100644 (file)
@@ -2239,7 +2239,7 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
        return code;
 }
 
-#ifdef __APPLE__
+#ifdef TARGET_MACH
 static int tls_gs_offset;
 #endif
 
@@ -2247,14 +2247,14 @@ gboolean
 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_arch_have_fast_tls (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,41 +2318,20 @@ 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;
 }
+
 /*
  * emit_setup_lmf:
  *
@@ -4136,18 +4088,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);
@@ -5315,31 +5259,26 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                guint8 *patch;
 
                /* check if we need to restore protection of the stack after a stack overflow */
-               /* FIXME */
-#if 0
-               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);
                }
-#endif
+
+               /* 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)) {
index 7427f2759b9cab970e20f220498d470f65f6a702..b423c193b7e48175f3809fa814b7ee1fa9c8c0cd 100644 (file)
@@ -202,6 +202,7 @@ typedef struct {
 /* X86 uses jit_tls->lmf (See emit_push_lmf ()) */
 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
 #endif
+#define MONO_ARCH_HAVE_FAST_TLS (mono_x86_have_fast_tls ())
 #define MONO_ARCH_IMT_REG X86_EDX
 #define MONO_ARCH_VTABLE_REG X86_EDX
 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
@@ -334,17 +335,11 @@ typedef struct {
        ArgInfo args [1];
 } CallInfo;
 
-guint8*
-mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset);
-
-guint8*
-mono_x86_emit_tls_get_reg (guint8* code, int dreg, int offset_reg);
-
 guint32
 mono_x86_get_this_arg_offset (MonoMethodSignature *sig);
 
 gboolean
-mono_x86_have_tls_get (void);
+mono_x86_have_fast_tls (void);
 
 void
 mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc, 
index 5c41ba864531760756d28040584cb2f35d0fdd1f..abbbc1d9ae16d431f4f6b594ce9b0af4ef1761ec 100644 (file)
 #define MONO_THREAD_VAR_OFFSET(var,offset) do { guint64 foo;  __asm ("movq $" #var "@TPOFF, %0" : "=r" (foo)); offset = foo; } while (0)
 #endif
 
+#elif defined(TARGET_X86) && !defined(TARGET_MACH) && !defined(HOST_WIN32) && defined(__GNUC__)
+
+#if defined(PIC)
+#define MONO_THREAD_VAR_OFFSET(var,offset) do { int tmp; __asm ("call 1f; 1: popl %0; addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %0; movl " #var "@gotntpoff(%0), %1" : "=r" (tmp), "=r" (offset)); } while (0)
+#else
+#define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("movl $" #var "@ntpoff, %0" : "=r" (offset))
+#endif
+
 #else
 
 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
@@ -117,6 +125,8 @@ static __thread gpointer mono_tls_lmf_addr MONO_TLS_FAST;
 
 #if defined(TARGET_AMD64) && (defined(TARGET_MACH) || defined(HOST_WIN32))
 #define MONO_THREAD_VAR_OFFSET(key,offset) (offset) = (gint32)key
+#elif defined(TARGET_X86) && (defined(TARGET_MACH) || defined(HOST_WIN32))
+#define MONO_THREAD_VAR_OFFSET(key,offset) (offset) = (gint32)key
 #else
 #define MONO_THREAD_VAR_OFFSET(var,offset) (offset) = -1
 #endif