diff options
author | Zoltan Varga <vargaz@gmail.com> | 2019-11-22 22:34:14 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-22 22:34:14 +0300 |
commit | 93e46c687b0f1b3bea7ecf362a667f3bd8b59fc5 (patch) | |
tree | f5f71be81bef02312239473d91864ac888bfb4ed | |
parent | cc137237d86b0553e844dc34c9a3cbc5b20782c0 (diff) |
[runtime] Treat calling a non-virtual method through an open delegate the same as the normal case instead of the OPEN_VIRTUAL case. (#17832)
* [runtime] Treat calling a non-virtual method through an open delegate the same as the normal case instead of the OPEN_VIRTUAL case.
* [amd64] Fix the return value mapping in gsharedvt calls, the return address might be in different registers in the caller and callee.
* [runtime] Always initialize del->method_ptr even if interp_method is set, JITted code makes calls through it in mixed mode.
* Add a test for open delegates and gsharedvt.
* Increase nrgctx trampoline count, its needed by dynamic-method-churn.exe in full-aot-interp mode.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | mono/metadata/marshal.c | 6 | ||||
-rw-r--r-- | mono/mini/gshared.cs | 24 | ||||
-rw-r--r-- | mono/mini/mini-amd64-gsharedvt.c | 2 | ||||
-rw-r--r-- | mono/mini/mini-runtime.c | 2 |
5 files changed, 32 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index 7ad189a7473..5eb2cf9beca 100644 --- a/configure.ac +++ b/configure.ac @@ -1347,7 +1347,7 @@ enable_cooperative_suspend_default=no enable_hybrid_suspend_default=no # For the sake of clearer error messages, these numbers should all be different from each other. -INVARIANT_AOT_OPTIONS=nimt-trampolines=2000,ntrampolines=10000,nrgctx-fetch-trampolines=256,ngsharedvt-trampolines=4400,nftnptr-arg-trampolines=4000 +INVARIANT_AOT_OPTIONS=nimt-trampolines=2000,ntrampolines=10000,nrgctx-fetch-trampolines=256,ngsharedvt-trampolines=4400,nftnptr-arg-trampolines=4000,nrgctx-trampolines=21000 AOT_BUILD_ATTRS=$INVARIANT_AOT_OPTIONS diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index df783091919..59a0c2eb9d2 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -2329,7 +2329,11 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del) sig = mono_signature_no_pinvoke (method); if (del && !del->target && del->method && mono_method_signature_internal (del->method)->hasthis) { - callvirt = TRUE; + if (!(del->method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !m_class_is_valuetype (del->method->klass) && sig->param_count == mono_method_signature_internal (del->method)->param_count + 1) { + /* The first argument of the delegate is passed as this, the normal invoke code can handle this */ + } else { + callvirt = TRUE; + } target_method = del->method; } diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs index 13cb8a55866..abcec7e2bd6 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -2217,6 +2217,30 @@ public class Tests var s = new AStruct () { a = 1, b = 2 }; return iface.foo<AStruct> (s); } + + interface IFaceOpenDel { + object AMethod<T> (); + } + + class ClassOpenDel : IFaceOpenDel { + public Nullable<int> field; + + public Nullable<int> getField () { + return field; + } + + public object AMethod<T> () { + var d = (Func<ClassOpenDel, T>)Delegate.CreateDelegate (typeof (Func<ClassOpenDel, T>), typeof (ClassOpenDel).GetMethod ("getField")); + return d (this); + } + } + + // Open instance delegate returning a gsharedvt value + public static int test_0_open_delegate () { + IFaceOpenDel iface = new ClassOpenDel () { field = 42 }; + var res = (Nullable<int>)iface.AMethod<Nullable<int>> (); + return res == 42 ? 0 : 1; + } } // #13191 diff --git a/mono/mini/mini-amd64-gsharedvt.c b/mono/mini/mini-amd64-gsharedvt.c index 3bd23b6d04e..03c79149dbe 100644 --- a/mono/mini/mini-amd64-gsharedvt.c +++ b/mono/mini/mini-amd64-gsharedvt.c @@ -411,7 +411,7 @@ mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_si if (cinfo->ret.storage == ArgValuetypeAddrInIReg) { /* Both the caller and the callee pass the vtype ret address in r8 (System V) and RCX or RDX (Windows) */ g_assert (gcinfo->ret.storage == ArgValuetypeAddrInIReg || gcinfo->ret.storage == ArgGsharedvtVariableInReg); - add_to_map (map, map_reg (cinfo->ret.reg), map_reg (cinfo->ret.reg)); + add_to_map (map, map_reg (caller_cinfo->ret.reg), map_reg (callee_cinfo->ret.reg)); } info = mono_domain_alloc0 (mono_domain_get (), sizeof (GSharedVtCallInfo) + (map->len * sizeof (int))); diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 3122bbe750e..a14a0a38702 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -3568,7 +3568,7 @@ mini_init_delegate (MonoDelegateHandle delegate, MonoError *error) g_assert (del->method); /* del->method_ptr might already be set to no_llvmonly_interp_method_pointer if the delegate was created from the interpreter */ del->method_ptr = mini_llvmonly_load_method_delegate (del->method, FALSE, FALSE, &del->extra_arg, error); - } else if (!del->method_ptr && !del->interp_method) { + } else if (!del->method_ptr) { del->method_ptr = create_delegate_method_ptr (del->method, error); return_if_nok (error); } |