[mini] Handle magic interfaces in common_trampoline as if they were variant.
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 31 Aug 2017 23:06:58 +0000 (16:06 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Fri, 1 Sep 2017 16:06:53 +0000 (09:06 -0700)
With the introduction of magic array interfaces, they must be handled as if they
were variant if they are being dispatched against an array.

This was not being done in common_trampoline and resulted in the IMT thunk never
getting rebuilt and getting decent perf.

With this patch, dispatch to simple methods such as Array::Count over a magic interface
in a covariant case (such as IList<object> dispatch onto string[]) will accrue gvi's.

On a trivial benchmark of executing Count 1M times, perf goes from 760ms to 50ms.

mono/mini/mini-trampolines.c

index a63b8ea322368427b297bc4a29397b1d97facadc..a11911e5c47985a582e0fe4eee35ec362d44fe04 100644 (file)
@@ -567,6 +567,10 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                        vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error);
                        return_val_if_nok (error, NULL);
 
+                       /* We must handle magic interfaces on rank 1 arrays of ref types as if they were variant */
+                       if (!variant_iface && vt->klass->rank == 1 && !vt->klass->element_class->valuetype && imt_method->klass->is_array_special_interface)
+                               variant_iface = imt_method;
+
                        /* This is the vcall slot which gets called through the IMT trampoline */
                        vtable_slot_to_patch = vtable_slot;