+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.
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);
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: {
+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
(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;
}
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;
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);
+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.
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 \
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
$(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
--- /dev/null
+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;
+ }
+}