From c7f5916ef6458c764b77810419f5788cfebcae4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Thu, 18 Jul 2019 16:46:55 -0400 Subject: [PATCH] [mini] Runtime check if boxing is needed for DIM constrained calls (mono/mono#15729) This is to handle the following example. The issue is that in Check() we have a constrained call where the called method is IAdder`1::PlusPlus() which is a default interface method, and we need to determine at runtime whether to box the this argument. ``` using System; public interface IAdder { int Add (int x); int PlusPlus () { return Add (1); } } interface IGen3 { } struct Adder : IAdder> { int _field; public int Add (int x) { _field = x + _field; return _field; } } public class P { public static int Check(T t) where T : IAdder { return t.PlusPlus () + t.PlusPlus (); } public static void Main () { var x = new Adder (); int y = Check, IGen3> (x); Console.WriteLine ("expect 2, got {0}", y); } } ``` Commit migrated from https://github.com/mono/mono/commit/3f55bfb5cc305c1c416edf84fff5440843784deb --- src/mono/mono/mini/method-to-ir.c | 4 +++- src/mono/mono/tests/Makefile.am | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index ff048d3991672d..0fc5164756bf38 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -5636,10 +5636,12 @@ handle_constrained_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignat * A simple solution would be to box always and make a normal virtual call, but that would * be bad performance wise. */ - if (mono_class_is_interface (cmethod->klass) && mono_class_is_ginst (cmethod->klass)) { + if (mono_class_is_interface (cmethod->klass) && mono_class_is_ginst (cmethod->klass) && + (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT)) { /* * The parent classes implement no generic interfaces, so the called method will be a vtype method, so no boxing neccessary. */ + /* If the method is not abstract, it's a default interface method, and we need to box */ need_box = FALSE; } diff --git a/src/mono/mono/tests/Makefile.am b/src/mono/mono/tests/Makefile.am index 567c2f7572fc89..c7929aa3983e51 100755 --- a/src/mono/mono/tests/Makefile.am +++ b/src/mono/mono/tests/Makefile.am @@ -1736,7 +1736,6 @@ KNOWN_FAILING_TESTS = \ appdomain-marshalbyref-assemblyload.exe \ abort-try-holes.exe \ threads-init.exe \ - dim-constrainedcall.exe \ gptail1.exe \ itaili1.exe \ sirtail1.exe \