#! /bin/sh /usr/share/dpatch/dpatch-run ## fix-compile_generic_method.dpatch by Dmitry Potapov ## ## Back ported fix from SVN: ## r63339 | zoltan | 2006-08-04 13:42:21 +0400 (Fri, 04 Aug 2006) | 10 lines ## ## 2006-08-04 Zoltan Varga ## ## * jit-icalls.c (mono_helper_compile_generic_method): Unbox vtypes since this is a ## virtual call. Fixes #79010. ## ## * mini.c (mono_method_to_ir): Pass an additional out arg to compile_generic_method ## and use the result as the this argument in the real call. ## ## * generics.2.cs: Add a new test for #79010. @DPATCH@ diff -ur mono/mono/mini/generics.2.cs mono/mono/mini/generics.2.cs --- mono/mono/mini/generics.2.cs 2006-05-11 02:32:02.000000000 +0400 +++ mono/mono/mini/generics.2.cs 2006-08-05 15:09:11.355907128 +0400 @@ -88,6 +88,32 @@ return 1; } + public static int test_0_generic_virtual_call_on_vtype_unbox () { + object o = new Object (); + IMyHandler h = new Handler(o); + + if (h.Bar () != o) + return 1; + else + return 0; + } + + public interface IMyHandler { + object Bar(); + } + + struct Handler : IMyHandler { + object o; + + public Handler(object o) { + this.o = o; + } + + public object Bar() { + return o; + } + } + static object Box (T t) { return t; diff -ur mono/mono/mini/jit-icalls.c mono/mono/mini/jit-icalls.c --- mono/mono/mini/jit-icalls.c 2006-05-11 02:32:01.000000000 +0400 +++ mono/mono/mini/jit-icalls.c 2006-08-05 15:09:11.356906976 +0400 @@ -650,7 +650,7 @@ #endif static gpointer -helper_compile_generic_method (MonoObject *obj, MonoMethod *method, MonoGenericContext *context) +helper_compile_generic_method (MonoObject *obj, MonoMethod *method, MonoGenericContext *context, gpointer *this_arg) { MonoMethod *vmethod, *inflated; gpointer addr; @@ -662,6 +662,12 @@ inflated = mono_get_inflated_method (inflated); addr = mono_compile_method (inflated); + /* Since this is a virtual call, have to unbox vtypes */ + if (obj->vtable->klass->valuetype) + *this_arg = mono_object_unbox (obj); + else + *this_arg = obj; + return addr; } diff -ur mono/mono/mini/mini.c mono/mono/mini/mini.c --- mono/mono/mini/mini.c 2006-05-11 02:32:01.000000000 +0400 +++ mono/mono/mini/mini.c 2006-08-05 15:09:11.360906368 +0400 @@ -4064,8 +4064,8 @@ !((cmethod->flags & METHOD_ATTRIBUTE_FINAL) && cmethod->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK) && mono_method_signature (cmethod)->generic_param_count) { - MonoInst *this_temp, *store; - MonoInst *iargs [3]; + MonoInst *this_temp, *this_arg_temp, *store; + MonoInst *iargs [4]; g_assert (mono_method_signature (cmethod)->is_inflated); @@ -4076,13 +4076,18 @@ store->cil_code = ip; MONO_ADD_INS (bblock, store); + /* FIXME: This should be a managed pointer */ + this_arg_temp = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); + this_arg_temp->cil_code = ip; + NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0); NEW_PCONST (cfg, iargs [1], cmethod); NEW_PCONST (cfg, iargs [2], ((MonoMethodInflated *) cmethod)->context); + NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0); temp = mono_emit_jit_icall (cfg, bblock, helper_compile_generic_method, iargs, ip); NEW_TEMPLOAD (cfg, addr, temp); - NEW_TEMPLOAD (cfg, sp [0], this_temp->inst_c0); + NEW_TEMPLOAD (cfg, sp [0], this_arg_temp->inst_c0); if ((temp = mono_emit_calli (cfg, bblock, fsig, sp, addr, ip)) != -1) { NEW_TEMPLOAD (cfg, *sp, temp); @@ -10482,7 +10487,7 @@ register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE); register_icall (mono_ldftn_nosync, "mono_ldftn_nosync", "ptr ptr", FALSE); register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE); - register_icall (helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr", FALSE); + register_icall (helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr ptr", FALSE); register_icall (helper_ldstr, "helper_ldstr", "object ptr int", FALSE); #endif