From: Zoltan Varga Date: Fri, 22 Sep 2017 22:44:10 +0000 (+0200) Subject: [jit] Fix constrained calls from gsharedvt methods using an interface type to vtype... X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=878b260edc6eefc7ec36244f8a30af6aa475fcf8 [jit] Fix constrained calls from gsharedvt methods using an interface type to vtype methods, the receiver is boxed, needs to be unboxed. Fixes #58507. (#5628) --- diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs index 6b5bc95f134..75ea14aad6a 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -1823,6 +1823,19 @@ public class Tests } } + struct StructTest : IFaceTest { + + int i; + + public StructTest (int arg) { + i = arg; + } + + public int iface_method () { + return i; + } + } + // Test constrained calls on an interface made from gsharedvt methods public static int test_42_gsharedvt_constrained_iface () { IFaceConstrainedIFace obj = new ConstrainedIFace (); @@ -1830,6 +1843,12 @@ public class Tests return obj.foo (ref t); } + public static int test_42_gsharedvt_constrained_iface_vtype () { + IFaceConstrainedIFace obj = new ConstrainedIFace (); + IFaceTest t = new StructTest (42); + return obj.foo (ref t); + } + // Sign extension tests // 0x55 == 85 == 01010101 // 0xAA == 170 == 10101010 diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 56c7bc8169f..fa3d7a46819 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -1328,12 +1328,15 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k { MonoMethod *m; int vt_slot, iface_offset; + gboolean is_iface = FALSE; error_init (error); if (mono_class_is_interface (klass)) { MonoObject *this_obj; + is_iface = TRUE; + /* Have to use the receiver's type instead of klass, the receiver is a ref type */ this_obj = *(MonoObject**)mp; g_assert (this_obj); @@ -1359,21 +1362,33 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k m = mono_class_inflate_generic_method (m, mono_method_get_context (cmethod)); } - if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class)) + if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class)) { /* * Calling a non-vtype method with a vtype receiver, has to box. */ *this_arg = mono_value_box_checked (mono_domain_get (), klass, mp, error); - else if (klass->valuetype) - /* - * Calling a vtype method with a vtype receiver - */ - *this_arg = mp; - else + } else if (klass->valuetype) { + if (is_iface) { + /* + * The original type is an interface, so the receiver is a ref, + the called method is a vtype method, need to unbox. + */ + MonoObject *this_obj = *(MonoObject**)mp; + + *this_arg = mono_object_unbox (this_obj); + } else { + /* + * Calling a vtype method with a vtype receiver + */ + *this_arg = mp; + } + } else { /* * Calling a non-vtype method */ *this_arg = *(gpointer*)mp; + } + return m; }