From: Mark Probst Date: Thu, 22 May 2008 21:21:20 +0000 (-0000) Subject: 2008-05-22 Mark Probst X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=fec6b1a75f9099a6c9dcf36e253e8c770fb58481;p=mono.git 2008-05-22 Mark Probst * generic-sharing.c: Init generic class when a method of it is requested via a runtime generic context. 2008-05-22 Mark Probst * mini.c: Treat callvirts to final methods like non-virtual calls when doing generic sharing, i.e. look them up in the runtime generic context. 2008-05-22 Mark Probst * generic-method-patching.2.cs: Test callvirt to sealed generic methods. * Makefile.am: Test added. svn path=/trunk/mono/; revision=103845 --- diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index d2f3cc5c98b..b3b4592e79e 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,8 @@ +2008-05-22 Mark Probst + + * generic-sharing.c: Init generic class when a method of it is + requested via a runtime generic context. + 2008-05-22 Zoltan Varga * class.c (mono_class_init): Add a comment about trying to avoid calling this. diff --git a/mono/metadata/generic-sharing.c b/mono/metadata/generic-sharing.c index 6cd5a0b3159..145d4dfb9b0 100644 --- a/mono/metadata/generic-sharing.c +++ b/mono/metadata/generic-sharing.c @@ -400,6 +400,7 @@ inflate_other_data (gpointer data, int info_type, MonoGenericContext *context) case MONO_RGCTX_INFO_METHOD: case MONO_RGCTX_INFO_GENERIC_METHOD_CODE: { MonoMethod *method = data; + MonoMethod *inflated_method; if (method->wrapper_type != MONO_WRAPPER_NONE) { g_assert (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE); @@ -409,7 +410,9 @@ inflate_other_data (gpointer data, int info_type, MonoGenericContext *context) method = mono_marshal_get_static_rgctx_invoke (method); } - return mono_class_inflate_generic_method (method, context); + inflated_method = mono_class_inflate_generic_method (method, context); + mono_class_init (inflated_method->klass); + return inflated_method; } case MONO_RGCTX_INFO_CLASS_FIELD: { diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 69c8ea42f2a..be2a79081b4 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,9 @@ +2008-05-22 Mark Probst + + * mini.c: Treat callvirts to final methods like non-virtual calls + when doing generic sharing, i.e. look them up in the runtime + generic context. + 2008-05-22 Mark Probst * inssel.brg, mini-ops.h: Added opcodes for mkrefany and refanyval diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 9cb6c4b66fd..4b2caf4a45b 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -5776,7 +5776,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b (cmethod->klass->valuetype || (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) || ((cmethod->flags & METHOD_ATTRIBUTE_STATIC) && - mono_class_generic_sharing_enabled (cmethod->klass)))) { + mono_class_generic_sharing_enabled (cmethod->klass)) || + (!mono_method_is_generic_sharable_impl (cmethod) && + (!virtual || cmethod->flags & METHOD_ATTRIBUTE_FINAL || + !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))))) { MonoInst *this = NULL, *rgctx; INLINE_FAILURE; @@ -5802,12 +5805,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } if (addr) { - if (*ip == CEE_CALL) + if (*ip == CEE_CALL) { g_assert (context_used); - else if (*ip == CEE_CALLI) + } else if (*ip == CEE_CALLI) { g_assert (!vtable_arg); - else - g_assert_not_reached (); + } else { + g_assert (cmethod->flags & METHOD_ATTRIBUTE_FINAL || + !(cmethod->flags & METHOD_ATTRIBUTE_FINAL)); + } /* Prevent inlining of methods with indirect calls */ INLINE_FAILURE; @@ -6742,7 +6747,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b INLINE_FAILURE; mono_emit_method_call_spilled (cfg, bblock, cmethod, fsig, sp, ip, callvirt_this_arg); } - } else if (generic_shared && cmethod->klass->valuetype) { + } else if (generic_shared && + (cmethod->klass->valuetype || + !mono_method_is_generic_sharable_impl (cmethod))) { MonoInst *this = NULL, *rgctx, *cmethod_addr; g_assert (!callvirt_this_arg); diff --git a/mono/tests/ChangeLog b/mono/tests/ChangeLog index 4365a6ebf9f..1788531bdd4 100644 --- a/mono/tests/ChangeLog +++ b/mono/tests/ChangeLog @@ -1,3 +1,10 @@ +2008-05-22 Mark Probst + + * generic-method-patching.2.cs: Test callvirt to sealed generic + methods. + + * Makefile.am: Test added. + 2008-05-22 Mark Probst * generic-refanyval.2.il: Test case for generic refanyval. diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 6ba0c1ca93e..7f7d1a6d1c2 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -270,6 +270,7 @@ BASE_TEST_CS_SRC= \ generic-virtual.2.cs \ generic-interface-methods.2.cs \ generic-array-type.2.cs \ + generic-method-patching.2.cs \ generic-null-call.2.cs \ recursive-generics.2.cs \ bug-80392.2.cs \ @@ -697,6 +698,7 @@ test-generic-sharing : generics-sharing.2.exe shared-generic-methods.2.exe \ generic-ldtoken-method.2.exe generic-ldtoken-field.2.exe \ generic-virtual.2.exe generic-tailcall.2.exe \ generic-interface-methods.2.exe generic-array-type.2.exe \ + generic-method-patching.2.exe \ generic-null-call.2.exe $(RUNTIME) -O=gshared,-inline generics-sharing.2.exe $(RUNTIME) -O=gshared,-inline shared-generic-methods.2.exe @@ -717,6 +719,7 @@ test-generic-sharing : generics-sharing.2.exe shared-generic-methods.2.exe \ $(RUNTIME) -O=gshared,-inline generic-tailcall.2.exe $(RUNTIME) -O=gshared,-inline generic-interface-methods.2.exe $(RUNTIME) -O=gshared,-inline generic-array-type.2.exe + $(RUNTIME) -O=gshared,-inline generic-method-patching.2.exe $(RUNTIME) -O=gshared,-inline generic-null-call.2.exe EXTRA_DIST += async-exceptions.cs diff --git a/mono/tests/generic-method-patching.2.cs b/mono/tests/generic-method-patching.2.cs new file mode 100644 index 00000000000..67d86504647 --- /dev/null +++ b/mono/tests/generic-method-patching.2.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; + +public class MyDict { + public void Add (S key, T value) { + S[] sa = new S[1]; + T[] ta = new T[1]; + + sa[0] = key; + ta[0] = value; + } +} + +public abstract class FastFunc { + public abstract S Invoke (T bla); +} + +public class StringFastFunc : FastFunc { + public override string Invoke (int bla) { + return bla.ToString (); + } +} + +public class ArrayFastFunc : FastFunc { + public override byte [] Invoke (int bla) { + return new byte [bla]; + } +} + +public class IntCache { + MyDict cache; + + public T Invoke (FastFunc f, int bla) { + if (cache == null) + cache = new MyDict (); + + T value = f.Invoke (bla); + + cache.Add (bla, value); + + return value; + } +} + +public class main { + public static int Main () { + StringFastFunc sff = new StringFastFunc (); + ArrayFastFunc aff = new ArrayFastFunc (); + IntCache ics = new IntCache (); + MyDict dss = new MyDict (); + + dss.Add ("123", "456"); + + ics.Invoke (sff, 123); + ics.Invoke (sff, 456); + + IntCache ica = new IntCache (); + + ica.Invoke (aff, 1); + ica.Invoke (aff, 2); + ica.Invoke (aff, 3); + + return 0; + } +}