[llvmonly] Change the way delegate invokes are implemented, use a new CEE_MONO_CALLI_...
authorZoltan Varga <vargaz@gmail.com>
Thu, 7 Jan 2016 18:08:26 +0000 (13:08 -0500)
committerZoltan Varga <vargaz@gmail.com>
Thu, 7 Jan 2016 18:08:26 +0000 (13:08 -0500)
mono/cil/cil-opcodes.xml
mono/cil/opcode.def
mono/metadata/marshal.c
mono/mini/method-to-ir.c

index 5f747c7a9b2458d76a8b1a276ebdd5413ec49f8f..a86b2be374115316ab024a42aec3dcc8d91de75a 100644 (file)
 <opcode name="mono_ldptr_int_req_flag" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x14" flow="next" />
 <opcode name="mono_ldptr_card_table" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x15" flow="next" />
 <opcode name="mono_ldptr_nursery_start" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x16" flow="next" />
+<opcode name="mono_ldptr_nursery_bits" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x17" flow="next" />
+<opcode name="mono_calli_extra_arg" input="VarPop" output="VarPush" args="InlineSig" o1="0xF0" o2="0x18" flow="call" />
 </opdesc>
index 96f53eb9eef0f626ddd7f0f7f10c99026961f063..ad89c95e46c2245750c5c2d275fcce1c671f12ab 100644 (file)
@@ -316,6 +316,7 @@ OPDEF(CEE_MONO_LDPTR_INT_REQ_FLAG, "mono_ldptr_int_req_flag", Pop0, PushI, Inlin
 OPDEF(CEE_MONO_LDPTR_CARD_TABLE, "mono_ldptr_card_table", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x15, NEXT)
 OPDEF(CEE_MONO_LDPTR_NURSERY_START, "mono_ldptr_nursery_start", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x16, NEXT)
 OPDEF(CEE_MONO_LDPTR_NURSERY_BITS, "mono_ldptr_nursery_bits", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x17, NEXT)
+OPDEF(CEE_MONO_CALLI_EXTRA_ARG, "mono_calli_extra_arg", VarPop, VarPush, InlineSig, X, 2, 0xF0, 0x18, CALL)
 #ifndef OPALIAS
 #define _MONO_CIL_OPALIAS_DEFINED_
 #define OPALIAS(a,s,r)
index afee5aa710c4adc14eb04f3910390358f8a6598f..f8c91085a8e69e8d114b939d65ceceb7bd58e403 100644 (file)
@@ -3010,22 +3010,6 @@ free_signature_pointer_pair (SignaturePointerPair *pair)
        g_free (pair);
 }
 
-static MonoMethodSignature*
-sig_to_rgctx_sig (MonoMethodSignature *sig)
-{
-       // FIXME: memory allocation
-       MonoMethodSignature *res;
-       int i;
-
-       res = (MonoMethodSignature *)g_malloc (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count + 1) * sizeof (MonoType*));
-       memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
-       res->param_count = sig->param_count + 1;
-       for (i = 0; i < sig->param_count; ++i)
-               res->params [i] = sig->params [i];
-       res->params [sig->param_count] = &mono_defaults.int_class->byval_arg;
-       return res;
-}
-
 MonoMethod *
 mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt, gboolean static_method_with_first_arg_bound, MonoMethod *target_method)
 {
@@ -3038,7 +3022,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        SignaturePointerPair key;
        SignaturePointerPair *new_key;
        int local_i, local_len, local_delegates, local_d, local_target, local_res;
-       int pos0, pos1, pos2, pos3, pos4;
+       int pos0, pos1, pos2;
        char *name;
        MonoClass *target_class = NULL;
        gboolean closed_over_null = FALSE;
@@ -3226,17 +3210,6 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                        // FIXME:
                        mono_mb_emit_exception_full (mb, "System", "NotImplementedException", "");
                } else {
-                       MonoMethodSignature *rgctx_sig;
-
-                       // FIXME: Support this for the other cases as well
-                       mono_mb_emit_ldarg (mb, 0);
-                       mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
-                       mono_mb_emit_byte (mb, CEE_LDIND_I);
-                       pos3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
-                       /* Rgctx case */
-                       rgctx_sig = sig_to_rgctx_sig (sig);
-
                        mono_mb_emit_ldloc (mb, local_target);
                        for (i = 0; i < sig->param_count; ++i)
                                mono_mb_emit_ldarg (mb, i + 1);
@@ -3246,21 +3219,8 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                        mono_mb_emit_ldarg (mb, 0);
                        mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
                        mono_mb_emit_byte (mb, CEE_LDIND_I);
-                       mono_mb_emit_op (mb, CEE_CALLI, rgctx_sig);
-                       pos4 = mono_mb_emit_branch (mb, CEE_BR);
-
-                       /* Non-rgctx case */
-                       mono_mb_patch_branch (mb, pos3);
-                       mono_mb_emit_ldloc (mb, local_target);
-                       for (i = 0; i < sig->param_count; ++i)
-                               mono_mb_emit_ldarg (mb, i + 1);
-                       mono_mb_emit_ldarg (mb, 0);
-                       mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
-                       mono_mb_emit_byte (mb, CEE_LDIND_I );
-                       mono_mb_emit_op (mb, CEE_CALLI, sig);
-
-                       mono_mb_patch_branch (mb, pos4);
-
+                       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+                       mono_mb_emit_op (mb, CEE_MONO_CALLI_EXTRA_ARG, sig);
                        mono_mb_emit_byte (mb, CEE_RET);
                }
        
@@ -3289,16 +3249,6 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                        mono_mb_emit_op (mb, CEE_CALL, target_method);
                }
        } else {
-               MonoMethodSignature *rgctx_sig;
-
-               mono_mb_emit_ldarg (mb, 0);
-               mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
-               mono_mb_emit_byte (mb, CEE_LDIND_I);
-               pos3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
-               /* Rgctx case */
-               rgctx_sig = sig_to_rgctx_sig (invoke_sig);
-
                if (static_method_with_first_arg_bound) {
                        mono_mb_emit_ldloc (mb, local_target);
                        if (!MONO_TYPE_IS_REFERENCE (invoke_sig->params[0]))
@@ -3312,24 +3262,8 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
                mono_mb_emit_ldarg (mb, 0);
                mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
                mono_mb_emit_byte (mb, CEE_LDIND_I);
-               mono_mb_emit_op (mb, CEE_CALLI, rgctx_sig);
-               pos4 = mono_mb_emit_branch (mb, CEE_BR);
-
-               /* Non-rgctx case */
-               mono_mb_patch_branch (mb, pos3);
-               if (static_method_with_first_arg_bound) {
-                       mono_mb_emit_ldloc (mb, local_target);
-                       if (!MONO_TYPE_IS_REFERENCE (invoke_sig->params[0]))
-                               mono_mb_emit_op (mb, CEE_UNBOX_ANY, mono_class_from_mono_type (invoke_sig->params[0]));
-               }
-               for (i = 0; i < sig->param_count; ++i)
-                       mono_mb_emit_ldarg (mb, i + 1);
-               mono_mb_emit_ldarg (mb, 0);
-               mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
-               mono_mb_emit_byte (mb, CEE_LDIND_I);
-               mono_mb_emit_op (mb, CEE_CALLI, invoke_sig);
-
-               mono_mb_patch_branch (mb, pos4);
+               mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+               mono_mb_emit_op (mb, CEE_MONO_CALLI_EXTRA_ARG, invoke_sig);
        }
 
        mono_mb_emit_byte (mb, CEE_RET);
index 8d262fcd06d33c33675dabb256f843beb9c9060f..0b6024e8255214083a77f0eb788dfef51bcfae70 100644 (file)
@@ -12729,6 +12729,75 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ip += 2;
                                break;
                        }
+                       case CEE_MONO_CALLI_EXTRA_ARG: {
+                               MonoInst *addr;
+                               MonoMethodSignature *fsig;
+                               MonoInst *arg;
+
+                               /*
+                                * This is the same as CEE_CALLI, but passes an additional argument
+                                * to the called method in llvmonly mode.
+                                * This is only used by delegate invoke wrappers to call the
+                                * actual delegate method.
+                                */
+                               g_assert (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE);
+
+                               CHECK_OPSIZE (6);
+                               token = read32 (ip + 2);
+
+                               ins = NULL;
+
+                               cmethod = NULL;
+                               CHECK_STACK (1);
+                               --sp;
+                               addr = *sp;
+                               fsig = mini_get_signature (method, token, generic_context);
+
+                               n = fsig->param_count + fsig->hasthis + 1;
+
+                               CHECK_STACK (n);
+
+                               sp -= n;
+                               arg = sp [n - 1];
+
+                               if (cfg->llvm_only) {
+                                       if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig)) {
+                                               MonoInst *callee = addr;
+
+                                               GSHAREDVT_FAILURE (*ip);
+
+                                               addr = emit_get_rgctx_sig (cfg, context_used,
+                                                                                                  fsig, MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI);
+                                               ins = emit_extra_arg_calli (cfg, fsig, sp, arg->dreg, callee);
+                                       } else {
+                                               ins = emit_extra_arg_calli (cfg, fsig, sp, arg->dreg, addr);
+                                       }
+                               } else {
+                                       /* Same as CEE_CALLI */
+                                       if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig)) {
+                                               /*
+                                                * We pass the address to the gsharedvt trampoline in the rgctx reg
+                                                */
+                                               MonoInst *callee = addr;
+
+                                               addr = emit_get_rgctx_sig (cfg, context_used,
+                                                                                                  fsig, MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI);
+                                               ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, callee);
+                                       } else {
+                                               ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
+                                       }
+                               }
+
+                               if (!MONO_TYPE_IS_VOID (fsig->ret))
+                                       *sp++ = mono_emit_widen_call_res (cfg, ins, fsig);
+
+                               CHECK_CFG_EXCEPTION;
+
+                               ip += 6;
+                               ins_flag = 0;
+                               constrained_class = NULL;
+                               break;
+                       }
                        default:
                                g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
                                break;