[mini] Fix delegate trampoline virtual call via delgate Invoke (#18073)
commit7704bd1b9260d0f6434ca02a2e7341f7c94113d8
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Tue, 10 Dec 2019 11:12:50 +0000 (10 06:12 -0500)
committerBernhard Urban-Forster <lewurm@gmail.com>
Tue, 10 Dec 2019 11:12:50 +0000 (10 12:12 +0100)
tree663bc40e252864ded1c63456ccad77bd62b822da
parentfd44435a84a1a963cbda97e1ff0fdb6e35e7d01a
[mini] Fix delegate trampoline virtual call via delgate Invoke (#18073)

* [mini] Fix delegate trampoline virtual call via delgate Invoke

If we need to jit the Invoke method of a delegate, we get tramp_info with a
NULL method.

Background: normally when we create a delegate around a virtual method,
handle_delegate_ctor will just create a virtual invoke trampoline with
mono_arch_get_delegate_virtual_invoke_impl which doesn't get here.  But if
we're asked to compile the delegate's Invoke method, then compile_special ()
will create a tramp_info with a null method, and return a delegate trampoline.

That's the case here - we had
  var del = SomeDelegate(obj.VirtualMethod);
  var invoke_method = del.GetType().GetMethod ("Invoke");
  invoke_method.Invoke (del, args);
or
  var del = SomeDelegate(obj.VirtualMethod);
  var another_del = OtherDelegate (del.Invoke);
  another_del (args);

in both cases, we end up in mono_delegate_trampoline with tramp_info->method ==
NULL.

in the second case the IL is like this:
   newobj instance void Derived::'.ctor'
   ldvirtftn instance void class Base::VirtualMethod()
   newobj instance void class SomeDelegate::'.ctor'(object, native int)

So delegate->target is a derived instance but delegate->method is some base
class method.

Addresses https://github.com/mono/mono/issues/17718

* [tests] Add tests for compiling delegate's Invoke method

Where the delegate calls a virtual method
mono/mini/mini-trampolines.c
mono/tests/Makefile.am
mono/tests/delegate17.cs [new file with mode: 0644]
mono/tests/delegate18.cs [new file with mode: 0644]