2008-05-22 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Thu, 22 May 2008 21:21:20 +0000 (21:21 -0000)
committerMark Probst <mark.probst@gmail.com>
Thu, 22 May 2008 21:21:20 +0000 (21:21 -0000)
* generic-sharing.c: Init generic class when a method of it is
requested via a runtime generic context.

2008-05-22  Mark Probst  <mark.probst@gmail.com>

* 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  <mark.probst@gmail.com>

* generic-method-patching.2.cs: Test callvirt to sealed generic
methods.

* Makefile.am: Test added.

svn path=/trunk/mono/; revision=103845

mono/metadata/ChangeLog
mono/metadata/generic-sharing.c
mono/mini/ChangeLog
mono/mini/mini.c
mono/tests/ChangeLog
mono/tests/Makefile.am
mono/tests/generic-method-patching.2.cs [new file with mode: 0644]

index d2f3cc5c98bf625991d28e3bf4f6406ca5146f08..b3b4592e79eaa121a689f90c2494ca1fff7acc81 100644 (file)
@@ -1,3 +1,8 @@
+2008-05-22  Mark Probst  <mark.probst@gmail.com>
+
+       * generic-sharing.c: Init generic class when a method of it is
+       requested via a runtime generic context.
+
 2008-05-22  Zoltan Varga  <vargaz@gmail.com>
 
        * class.c (mono_class_init): Add a comment about trying to avoid calling this.
index 6cd5a0b315989eb60348b2bbac086dee5a2c1c3f..145d4dfb9b0298dac6683bf00680594db8a9be30 100644 (file)
@@ -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: {
index 69c8ea42f2a6db3e9deb90ec308da3a7edb40f09..be2a79081b462b706c5e534afb6cd8dfd75b535c 100644 (file)
@@ -1,3 +1,9 @@
+2008-05-22  Mark Probst  <mark.probst@gmail.com>
+
+       * 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  <mark.probst@gmail.com>
 
        * inssel.brg, mini-ops.h: Added opcodes for mkrefany and refanyval
index 9cb6c4b66fd8a83a53e5f31493716d39be2c9119..4b2caf4a45b70a717f654356574cd9334632b294 100644 (file)
@@ -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);
index 4365a6ebf9f989df870698033c018949efc7d150..1788531bdd4df2601e30d86e3ecd6fe6af2e9e68 100644 (file)
@@ -1,3 +1,10 @@
+2008-05-22  Mark Probst  <mark.probst@gmail.com>
+
+       * generic-method-patching.2.cs: Test callvirt to sealed generic
+       methods.
+
+       * Makefile.am: Test added.
+
 2008-05-22  Mark Probst  <mark.probst@gmail.com>
 
        * generic-refanyval.2.il: Test case for generic refanyval.
index 6ba0c1ca93e133fd64a7c97230a1503ac1b7a65f..7f7d1a6d1c2b2156d6880fdf811d8992b592e716 100644 (file)
@@ -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 (file)
index 0000000..67d8650
--- /dev/null
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+
+public class MyDict<S,T> {
+    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<S,T> {
+    public abstract S Invoke (T bla);
+}
+
+public class StringFastFunc : FastFunc<string, int> {
+    public override string Invoke (int bla) {
+       return bla.ToString ();
+    }
+}
+
+public class ArrayFastFunc : FastFunc<byte [], int> {
+    public override byte [] Invoke (int bla) {
+       return new byte [bla];
+    }
+}
+
+public class IntCache<T> {
+    MyDict<int,T> cache;
+
+    public T Invoke (FastFunc<T,int> f, int bla) {
+       if (cache == null)
+           cache = new MyDict <int,T> ();
+
+       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<string> ics = new IntCache<string> ();
+       MyDict<string,string> dss = new MyDict<string,string> ();
+
+       dss.Add ("123", "456");
+
+       ics.Invoke (sff, 123);
+       ics.Invoke (sff, 456);
+
+       IntCache<byte []> ica = new IntCache<byte []> ();
+
+       ica.Invoke (aff, 1);
+       ica.Invoke (aff, 2);
+       ica.Invoke (aff, 3);
+
+       return 0;
+    }
+}