From: Zoltan Varga Date: Thu, 7 Jan 2016 18:08:26 +0000 (-0500) Subject: [llvmonly] Change the way delegate invokes are implemented, use a new CEE_MONO_CALLI_... X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=36bc196bde618a699e06d1be785661af5c0f84ef;p=mono.git [llvmonly] Change the way delegate invokes are implemented, use a new CEE_MONO_CALLI_EXTRA_ARG il instruction so most of the logic is in the JIT, not in marshal.c. --- diff --git a/mono/cil/cil-opcodes.xml b/mono/cil/cil-opcodes.xml index 5f747c7a9b2..a86b2be3741 100644 --- a/mono/cil/cil-opcodes.xml +++ b/mono/cil/cil-opcodes.xml @@ -315,4 +315,6 @@ + + diff --git a/mono/cil/opcode.def b/mono/cil/opcode.def index 96f53eb9eef..ad89c95e46c 100644 --- a/mono/cil/opcode.def +++ b/mono/cil/opcode.def @@ -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) diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index afee5aa710c..f8c91085a8e 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -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); diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 8d262fcd06d..0b6024e8255 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -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;