Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2019-11-22 22:34:14 +0300
committerGitHub <noreply@github.com>2019-11-22 22:34:14 +0300
commit93e46c687b0f1b3bea7ecf362a667f3bd8b59fc5 (patch)
treef5f71be81bef02312239473d91864ac888bfb4ed
parentcc137237d86b0553e844dc34c9a3cbc5b20782c0 (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.ac2
-rw-r--r--mono/metadata/marshal.c6
-rw-r--r--mono/mini/gshared.cs24
-rw-r--r--mono/mini/mini-amd64-gsharedvt.c2
-rw-r--r--mono/mini/mini-runtime.c2
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);
}