[x86] Resurrect inlined fast tls
[mono.git] / mono / mini / mini-x86.c
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)) {