Merge pull request #4048 from kumpera/iface_casting_cleanup
[mono.git] / mono / mini / method-to-ir.c
index cada92ac7bcf6004cf4acac6d2f9f1ec45ff8513..1b82009833f87b089f6dfc10c34c2c84a8579ed4 100644 (file)
@@ -156,6 +156,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
 static MonoMethodSignature *helper_sig_domain_get;
 static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
 static MonoMethodSignature *helper_sig_llvmonly_imt_trampoline;
+static MonoMethodSignature *helper_sig_jit_thread_attach;
 
 /* type loading helpers */
 static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
@@ -367,6 +368,7 @@ mono_create_helper_signatures (void)
        helper_sig_domain_get = mono_create_icall_signature ("ptr");
        helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
        helper_sig_llvmonly_imt_trampoline = mono_create_icall_signature ("ptr ptr ptr");
+       helper_sig_jit_thread_attach = mono_create_icall_signature ("ptr ptr");
 }
 
 static MONO_NEVER_INLINE void
@@ -3240,8 +3242,8 @@ emit_get_rgctx (MonoCompile *cfg, MonoMethod *method, int context_used)
 
        if (!(method->flags & METHOD_ATTRIBUTE_STATIC) &&
                        !(context_used & MONO_GENERIC_CONTEXT_USED_METHOD) &&
-                       !method->klass->valuetype)
-               EMIT_NEW_ARGLOAD (cfg, this_ins, 0);
+               !method->klass->valuetype)
+               EMIT_NEW_VARLOAD (cfg, this_ins, cfg->this_arg, &mono_defaults.object_class->byval_arg);
 
        if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD) {
                MonoInst *mrgctx_loc, *mrgctx_var;
@@ -3422,8 +3424,8 @@ MonoInst*
 mini_emit_get_rgctx_klass (MonoCompile *cfg, int context_used,
                                          MonoClass *klass, MonoRgctxInfoType rgctx_type)
 {
-       MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_CLASS, klass, rgctx_type);
-       MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+       MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_CLASS, klass, rgctx_type);
+       MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
        return emit_rgctx_fetch (cfg, rgctx, entry);
 }
@@ -3432,8 +3434,8 @@ static MonoInst*
 emit_get_rgctx_sig (MonoCompile *cfg, int context_used,
                                        MonoMethodSignature *sig, MonoRgctxInfoType rgctx_type)
 {
-       MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_SIGNATURE, sig, rgctx_type);
-       MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+       MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_SIGNATURE, sig, rgctx_type);
+       MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
        return emit_rgctx_fetch (cfg, rgctx, entry);
 }
@@ -3450,8 +3452,8 @@ emit_get_rgctx_gsharedvt_call (MonoCompile *cfg, int context_used,
        call_info->sig = sig;
        call_info->method = cmethod;
 
-       entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_CALL, call_info, rgctx_type);
-       rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+       entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_CALL, call_info, rgctx_type);
+       rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
        return emit_rgctx_fetch (cfg, rgctx, entry);
 }
@@ -3473,8 +3475,8 @@ emit_get_rgctx_virt_method (MonoCompile *cfg, int context_used,
        info->klass = klass;
        info->method = virt_method;
 
-       entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_VIRT_METHOD, info, rgctx_type);
-       rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+       entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_VIRT_METHOD, info, rgctx_type);
+       rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
        return emit_rgctx_fetch (cfg, rgctx, entry);
 }
@@ -3486,8 +3488,8 @@ emit_get_rgctx_gsharedvt_method (MonoCompile *cfg, int context_used,
        MonoJumpInfoRgctxEntry *entry;
        MonoInst *rgctx;
 
-       entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_METHOD, info, MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO);
-       rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+       entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_METHOD, info, MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO);
+       rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
        return emit_rgctx_fetch (cfg, rgctx, entry);
 }
@@ -3516,8 +3518,8 @@ emit_get_rgctx_method (MonoCompile *cfg, int context_used,
                        g_assert_not_reached ();
                }
        } else {
-               MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_METHODCONST, cmethod, rgctx_type);
-               MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+               MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_METHODCONST, cmethod, rgctx_type);
+               MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
                return emit_rgctx_fetch (cfg, rgctx, entry);
        }
@@ -3527,8 +3529,8 @@ static MonoInst*
 emit_get_rgctx_field (MonoCompile *cfg, int context_used,
                                          MonoClassField *field, MonoRgctxInfoType rgctx_type)
 {
-       MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_FIELD, field, rgctx_type);
-       MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+       MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_FIELD, field, rgctx_type);
+       MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
        return emit_rgctx_fetch (cfg, rgctx, entry);
 }
@@ -3798,7 +3800,7 @@ handle_unbox_nullable (MonoCompile* cfg, MonoInst* val, MonoClass* klass, int co
                        cfg->signatures = g_slist_prepend_mempool (cfg->mempool, cfg->signatures, mono_method_signature (method));
                        return emit_llvmonly_calli (cfg, mono_method_signature (method), &val, addr);
                } else {
-                       rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+                       rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
                        return mono_emit_calli (cfg, mono_method_signature (method), &val, addr, NULL, rgctx);
                }
@@ -4065,7 +4067,7 @@ handle_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used)
                                   have to get the method address from the RGCTX. */
                                MonoInst *addr = emit_get_rgctx_method (cfg, context_used, method,
                                                                                                                MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
-                               MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+                               MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
 
                                return mono_emit_calli (cfg, mono_method_signature (method), &val, addr, NULL, rgctx);
                        }
@@ -4541,7 +4543,7 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
 
        if (cfg->disable_inline)
                return FALSE;
-       if (cfg->gshared)
+       if (cfg->gsharedvt)
                return FALSE;
 
        if (cfg->inline_depth > 10)
@@ -4575,17 +4577,22 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
         * since it would mean inserting a call to mono_runtime_class_init()
         * inside the inlined code
         */
+       if (cfg->gshared && method->klass->has_cctor && mini_class_check_context_used (cfg, method->klass))
+               return FALSE;
+
        if (!(cfg->opt & MONO_OPT_SHARED)) {
                /* The AggressiveInlining hint is a good excuse to force that cctor to run. */
                if (method->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING) {
-                       vtable = mono_class_vtable (cfg->domain, method->klass);
-                       if (!vtable)
-                               return FALSE;
-                       if (!cfg->compile_aot) {
-                               MonoError error;
-                               if (!mono_runtime_class_init_full (vtable, &error)) {
-                                       mono_error_cleanup (&error);
+                       if (method->klass->has_cctor) {
+                               vtable = mono_class_vtable (cfg->domain, method->klass);
+                               if (!vtable)
                                        return FALSE;
+                               if (!cfg->compile_aot) {
+                                       MonoError error;
+                                       if (!mono_runtime_class_init_full (vtable, &error)) {
+                                               mono_error_cleanup (&error);
+                                               return FALSE;
+                                       }
                                }
                        }
                } else if (mono_class_is_before_field_init (method->klass)) {
@@ -6446,7 +6453,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        if ((costs >= 0 && costs < 60) || inline_always || (costs >= 0 && (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))) {
                if (cfg->verbose_level > 2)
                        printf ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
-               
+
                cfg->stat_inlined_methods++;
 
                /* always add some code to avoid block split failures */
@@ -12088,13 +12095,24 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                /* AOT code is only used in the root domain */
                                EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
-                               ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+                               if (cfg->compile_aot) {
+                                       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_THREAD_ATTACH, NULL);
+                                       ins = mono_emit_calli (cfg, helper_sig_jit_thread_attach, args, addr, NULL, NULL);
+                               } else {
+                                       ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+                               }
                                MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
 
                                if (next_bb)
                                        MONO_START_BB (cfg, next_bb);
 
-
                                ip += 2;
                                break;
                        }