[arm] Call the tls get trampoline through a GOT slot instead of directly, since a...
authorZoltan Varga <vargaz@gmail.com>
Wed, 2 Nov 2016 02:05:54 +0000 (22:05 -0400)
committerGitHub <noreply@github.com>
Wed, 2 Nov 2016 02:05:54 +0000 (22:05 -0400)
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/mini-runtime.c
mono/mini/mini.h
mono/mini/patch-info.h

index c6ddc58cbc0a44b8f2d7f2f61527985c72ffdd43..9b606579522a8f000722179b1806288878ad7013 100644 (file)
@@ -5809,6 +5809,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_method_ref (acfg, patch_info->data.virt_method->method, p, &p);
                break;
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+       case MONO_PATCH_INFO_GET_TLS_TRAMP:
                break;
        default:
                g_warning ("unable to handle jump info %d", patch_info->type);
@@ -10382,6 +10383,11 @@ add_preinit_got_slots (MonoAotCompile *acfg)
        get_got_offset (acfg, FALSE, ji);
        get_got_offset (acfg, TRUE, ji);
 
+       ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_GET_TLS_TRAMP;
+       get_got_offset (acfg, FALSE, ji);
+       get_got_offset (acfg, TRUE, ji);
+
        for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) {
                ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
                ji->type = MONO_PATCH_INFO_INTERNAL_METHOD;
index dab7893604e40f24fd9a28e65c9cd439c2587df8..bcd2ddefb5c0ea23bf2b0d583986b590bf028765 100644 (file)
@@ -3702,6 +3702,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                break;
        }
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+       case MONO_PATCH_INFO_GET_TLS_TRAMP:
                break;
        case MONO_PATCH_INFO_AOT_JIT_INFO:
                ji->data.index = decode_value (p, &p);
index 82795e5b8e87e2e46c65bcc40e55190c19b4b338..13a3ffee37f8159a3b1346bf99c09b007ab5159b 100644 (file)
@@ -127,6 +127,7 @@ static int vfp_scratch2 = ARM_VFP_D1;
 static int i8_align;
 
 static gpointer single_step_tramp, breakpoint_tramp;
+static gpointer get_tls_tramp;
 
 /*
  * The code generated for sequence points reads from this location, which is
@@ -167,6 +168,9 @@ int mono_exc_esp_offset = 0;
 static void mono_arch_compute_omit_fp (MonoCompile *cfg);
 #endif
 
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, int patch_type, gpointer data);
+
 const char*
 mono_arch_regname (int reg)
 {
@@ -330,9 +334,21 @@ mono_arm_emit_tls_get (MonoCompile *cfg, guint8* code, int dreg, int tls_offset)
 {
 #ifdef HAVE_FAST_TLS
        code = mono_arm_emit_load_imm (code, ARMREG_R0, tls_offset);
-       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
-                       "mono_get_tls_key");
-       code = emit_call_seq (cfg, code);
+       if (cfg->compile_aot) {
+               /*
+                * This opcode is generated by CEE_MONO_JIT_ATTACH, so it can execute on
+                * threads which are not yet attached to the runtime. This means we can't
+                * call it directly, since the call would go through the trampoline code
+                * which assumes the thread is attached. So use a separate patch info type
+                * for it, and load it from a preinitialized GOT slot.
+                */
+               code = emit_aotconst (cfg, code, ARMREG_R1, MONO_PATCH_INFO_GET_TLS_TRAMP, NULL);
+               code = emit_call_reg (code, ARMREG_R1);
+       } else {
+               mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+                                                        "mono_get_tls_key");
+               code = emit_call_seq (cfg, code);
+       }
        if (dreg != ARMREG_R0)
                ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
 #else
@@ -347,9 +363,14 @@ mono_arm_emit_tls_get_reg (MonoCompile *cfg, guint8* code, int dreg, int tls_off
 #ifdef HAVE_FAST_TLS
        if (tls_offset_reg != ARMREG_R0)
                ARM_MOV_REG_REG (code, ARMREG_R0, tls_offset_reg);
-       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
-                       "mono_get_tls_key");
-       code = emit_call_seq (cfg, code);
+       if (cfg->compile_aot) {
+               code = emit_aotconst (cfg, code, ARMREG_R1, MONO_PATCH_INFO_GET_TLS_TRAMP, NULL);
+               code = emit_call_reg (code, ARMREG_R1);
+       } else {
+               mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+                                                        "mono_get_tls_key");
+               code = emit_call_seq (cfg, code);
+       }
        if (dreg != ARMREG_R0)
                ARM_MOV_REG_REG (code, dreg, ARMREG_R0);
 #else
@@ -5989,6 +6010,8 @@ mono_arch_register_lowlevel_calls (void)
                mono_register_jit_icall (tls_imp.get_tls_thunk, "mono_get_tls_key", mono_create_icall_signature ("ptr ptr"), TRUE);
                mono_register_jit_icall (tls_imp.set_tls_thunk, "mono_set_tls_key", mono_create_icall_signature ("void ptr ptr"), TRUE);
 
+               get_tls_tramp = tls_imp.get_tls_thunk;
+
                if (tls_imp.get_tls_thunk_end) {
                        mono_tramp_info_register (
                                mono_tramp_info_create (
@@ -7512,3 +7535,23 @@ mono_arch_get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
 {
        return get_call_info (mp, sig);
 }
+
+gpointer
+mono_arch_get_get_tls_tramp (void)
+{
+       return get_tls_tramp;
+}
+
+static guint8*
+emit_aotconst (MonoCompile *cfg, guint8 *code, int dreg, int patch_type, gpointer data)
+{
+       /* OP_AOTCONST */
+       mono_add_patch_info (cfg, code - cfg->native_code, patch_type, data);
+       ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
+       ARM_B (code, 0);
+       *(gpointer*)code = NULL;
+       code += 4;
+       /* Load the value from the GOT */
+       ARM_LDR_REG_REG (code, dreg, ARMREG_PC, dreg);
+       return code;
+}
index cb31a6e8b24f64f192e21cb32e1075805fbe0a8d..694f6b87e0e2d3f43ed800123f3925add53b1b2c 100644 (file)
@@ -350,6 +350,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES 1
 #define MONO_ARCH_HAVE_PATCH_CODE_NEW 1
 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT 1
+#define MONO_ARCH_HAVE_GET_TLS_TRAMP 1
 
 #define MONO_ARCH_HAVE_TLS_GET (mono_arm_have_tls_get ())
 #define MONO_ARCH_HAVE_TLS_GET_REG 1
index 987f8de2df90daab83d358542da79071dd6fc237..607ac73795bfcf25122492a51f75d3ea1405a5a8 100644 (file)
@@ -1222,6 +1222,7 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_GOT_OFFSET:
        case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
        case MONO_PATCH_INFO_AOT_MODULE:
+       case MONO_PATCH_INFO_GET_TLS_TRAMP:
                return (ji->type << 8);
        case MONO_PATCH_INFO_CASTCLASS_CACHE:
                return (ji->type << 8) | (ji->data.index);
@@ -1661,6 +1662,13 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
                target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
                break;
+       case MONO_PATCH_INFO_GET_TLS_TRAMP:
+#ifdef MONO_ARCH_HAVE_GET_TLS_TRAMP
+               target = mono_arch_get_get_tls_tramp ();
+#else
+               g_assert_not_reached ();
+#endif
+               break;
        default:
                g_assert_not_reached ();
        }
index 03ef9f89f199d3c3e606e3cf92af06d78fe8c600..492295493441cd6883abcabbba259b35b3eca6b3 100644 (file)
@@ -2679,6 +2679,7 @@ guint8*   mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo *
 gpointer  mono_arch_create_monitor_enter_trampoline (MonoTrampInfo **info, gboolean is_v4, gboolean aot);
 gpointer  mono_arch_create_monitor_exit_trampoline (MonoTrampInfo **info, gboolean aot);
 guint8   *mono_arch_create_llvm_native_thunk     (MonoDomain *domain, guint8* addr) MONO_LLVM_INTERNAL;
+gpointer  mono_arch_get_get_tls_tramp (void);
 GList    *mono_arch_get_allocatable_int_vars    (MonoCompile *cfg);
 GList    *mono_arch_get_global_int_regs         (MonoCompile *cfg);
 GList    *mono_arch_get_global_fp_regs          (MonoCompile *cfg);
index e6635a4b49c8cfe2bf945c3efeb683bf9ea44a18..a55700355721adf50355dbc89013664042f1d700 100644 (file)
@@ -57,3 +57,4 @@ PATCH_INFO(AOT_JIT_INFO, "aot_jit_info")
 PATCH_INFO(GC_NURSERY_BITS, "gc_nursery_bits")
 PATCH_INFO(GSHAREDVT_IN_WRAPPER, "gsharedvt_in_wrapper")
 PATCH_INFO(ICALL_ADDR_CALL, "icall_addr_call")
+PATCH_INFO(GET_TLS_TRAMP, "get_tls_tramp")