[jit] Treat the mono_threads_attach_coop () icall specially, since it can be called...
authorZoltan Varga <vargaz@gmail.com>
Mon, 19 Jun 2017 17:49:31 +0000 (13:49 -0400)
committerGitHub <noreply@github.com>
Mon, 19 Jun 2017 17:49:31 +0000 (13:49 -0400)
mono/metadata/marshal.c
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/method-to-ir.c
mono/mini/mini-runtime.c
mono/mini/patch-info.h

index 46c34f76a6fb560b63e584252e3572fdb79e0651..25fc058351e36735ff650c4dc7609040bcaaf118 100644 (file)
@@ -8595,6 +8595,10 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                mono_mb_emit_byte (mb, CEE_MONO_LDDOMAIN);
                mono_mb_emit_ldloc_addr (mb, attach_dummy_local);
+               /*
+                * This icall is special cased in the JIT so it works in native-to-managed wrappers in unattached threads.
+                * Keep this in sync with the CEE_JIT_ICALL code in the JIT.
+                */
                mono_mb_emit_icall (mb, mono_threads_attach_coop);
                mono_mb_emit_stloc (mb, attach_cookie_local);
        }
index 61991b5eb0f523cdd02d11c2b03f8f0764003024..a640300219ab69fbcdd10c51b992b820db10fca0 100644 (file)
@@ -5751,7 +5751,8 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
                encode_value (patch_info->data.index, p, &p);
                break;
        case MONO_PATCH_INFO_INTERNAL_METHOD:
-       case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: {
                guint32 len = strlen (patch_info->data.name);
 
                encode_value (len, p, &p);
@@ -11373,6 +11374,13 @@ add_preinit_got_slots (MonoAotCompile *acfg)
        get_got_offset (acfg, FALSE, ji);
        get_got_offset (acfg, TRUE, ji);
 
+       /* Called by native-to-managed wrappers on possibly unattached threads */
+       ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+       ji->type = MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL;
+       ji->data.name = "mono_threads_attach_coop";
+       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 a93776da15a6b4f6a3a024ab68856eb9cfdb8044..fbbc07a485adbaa0f29ad97ef6547397e9d31437 100644 (file)
@@ -3541,7 +3541,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                break;
        }
        case MONO_PATCH_INFO_INTERNAL_METHOD:
-       case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: {
                guint32 len = decode_value (p, &p);
 
                ji->data.name = (char*)p;
index 0c37dc1533c5b699e6444e144b806f9f8a7dfaed..ee2665821d15ae81e55789313e300cba0d25104a 100644 (file)
@@ -11457,7 +11457,20 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                CHECK_STACK (info->sig->param_count);
                                sp -= info->sig->param_count;
 
-                               ins = mono_emit_jit_icall (cfg, info->func, sp);
+                               if (cfg->compile_aot && !strcmp (info->name, "mono_threads_attach_coop")) {
+                                       MonoInst *addr;
+
+                                       /*
+                                        * This is called on unattached threads, so it cannot go through the trampoline
+                                        * infrastructure. Use an indirect call through a got slot initialized at load time
+                                        * instead.
+                                        */
+                                       EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL, (char*)info->name);
+                                       ins = mini_emit_calli (cfg, info->sig, sp, addr, NULL, NULL);
+                               } else {
+                                       ins = mono_emit_jit_icall (cfg, info->func, sp);
+                               }
+
                                if (!MONO_TYPE_IS_VOID (info->sig->ret))
                                        *sp++ = ins;
 
index f67497d6836e7989f6d9378287d704d08f1de5da..73c880ecf542a950ce8568c3ff2ffbd8a24482dd 100644 (file)
@@ -1237,6 +1237,7 @@ mono_patch_info_hash (gconstpointer data)
                return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
        }
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
                return (ji->type << 8) | g_str_hash (ji->data.target);
        case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
                return (ji->type << 8) | mono_signature_hash (ji->data.sig);
@@ -1301,6 +1302,7 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
        case MONO_PATCH_INFO_VIRT_METHOD:
                return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
        case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL:
                if (ji1->data.target == ji2->data.target)
                        return 1;
                return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
@@ -1353,7 +1355,8 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_icall_get_wrapper (mi);
                break;
        }
-       case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: {
                MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
                if (!mi) {
                        g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
index 5869eed77b113a0c2c0a5cedef2c68f2a5673e5c..8a4ba056ee089d3d40d0b694957111d81e171142 100644 (file)
@@ -58,3 +58,8 @@ PATCH_INFO(ICALL_ADDR_CALL, "icall_addr_call")
 PATCH_INFO(GET_TLS_TRAMP, "get_tls_tramp")
 PATCH_INFO(JIT_THREAD_ATTACH, "jit_thread_attach")
 PATCH_INFO(SET_TLS_TRAMP, "set_tls_tramp")
+/*
+ * The address of a C function implementing a JIT icall.
+ * Same as JIT_ICALL_ADDR, but not treated as a call.
+ */
+PATCH_INFO(JIT_ICALL_ADDR_NOCALL, "jit_icall_addr_nocall")