2008-03-20 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Thu, 20 Mar 2008 06:45:54 +0000 (06:45 -0000)
committerMark Probst <mark.probst@gmail.com>
Thu, 20 Mar 2008 06:45:54 +0000 (06:45 -0000)
* generic-sharing.c, class-internals.h: Code for putting
reflection types into the runtime generic context.

2008-03-20  Mark Probst  <mark.probst@gmail.com>

* generic-sharing.c: Put reflection types in the extensible part
of the runtime generic context.

* mini.c: Generic sharing of the GetTypeHandle special case of the
ldtoken instruction.

2008-03-20  Mark Probst  <mark.probst@gmail.com>

* generics-sharing.2.cs: Test cases for ldtoken.

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

mono/metadata/ChangeLog
mono/metadata/class-internals.h
mono/metadata/generic-sharing.c
mono/mini/ChangeLog
mono/mini/generic-sharing.c
mono/mini/mini.c
mono/tests/ChangeLog
mono/tests/generics-sharing.2.cs

index 668bbd66bdc5cea6ae2571230a8aff0b37933cbc..61e8f8325afa2e10c6447b3632a07d755e760207 100644 (file)
@@ -1,3 +1,8 @@
+2008-03-20  Mark Probst  <mark.probst@gmail.com>
+
+       * generic-sharing.c, class-internals.h: Code for putting
+       reflection types into the runtime generic context.
+
 2008-03-19 Rodrigo Kumpera  <rkumpera@novell.com>
 
        * icall.c (ves_icall_get_method_info): Return correct values for the call convention.
index d5f02fd0fd9eab2df39a0f962790e4819c1a3680..8ba1f1d5ff67a6a70c679f9a95635b450b6f321c 100644 (file)
@@ -195,6 +195,7 @@ enum {
        MONO_RGCTX_INFO_STATIC_DATA,
        MONO_RGCTX_INFO_KLASS,
        MONO_RGCTX_INFO_VTABLE,
+       MONO_RGCTX_INFO_REFLECTION_TYPE,
        MONO_RGCTX_INFO_METHOD,
        MONO_RGCTX_INFO_GENERIC_METHOD_CODE
 };
index 460624ad8adcac2df9ac7e591279d8a551e00ff6..a39bc78503568ce78c6d67fa4468a315de358d89 100644 (file)
@@ -450,6 +450,7 @@ inflate_other_data (gpointer data, int info_type, MonoGenericContext *context)
        case MONO_RGCTX_INFO_STATIC_DATA:
        case MONO_RGCTX_INFO_KLASS:
        case MONO_RGCTX_INFO_VTABLE:
+       case MONO_RGCTX_INFO_REFLECTION_TYPE:
                return mono_class_inflate_generic_type (data, context);
 
        case MONO_RGCTX_INFO_METHOD:
@@ -668,6 +669,8 @@ instantiate_other_info (MonoDomain *domain, MonoRuntimeGenericContextOtherInfoTe
 
                return class_type_info (domain, arg_class, oti->info_type);
        }
+       case MONO_RGCTX_INFO_REFLECTION_TYPE:
+               return mono_type_get_object (domain, data);
        case MONO_RGCTX_INFO_METHOD:
                return data;
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
@@ -865,6 +868,7 @@ other_info_equal (gpointer data1, gpointer data2, int info_type)
        case MONO_RGCTX_INFO_STATIC_DATA:
        case MONO_RGCTX_INFO_KLASS:
        case MONO_RGCTX_INFO_VTABLE:
+       case MONO_RGCTX_INFO_REFLECTION_TYPE:
                return mono_class_from_mono_type (data1) == mono_class_from_mono_type (data2);
        case MONO_RGCTX_INFO_METHOD:
        case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
index e0e1f2c0c2458b18dd062590d7e2743ce22c1749..00078aeae48ff901d2ed3217c683db23f766481c 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-20  Mark Probst  <mark.probst@gmail.com>
+
+       * generic-sharing.c: Put reflection types in the extensible part
+       of the runtime generic context.
+
+       * mini.c: Generic sharing of the GetTypeHandle special case of the
+       ldtoken instruction.
+
 2008-03-20  Zoltan Varga  <vargaz@gmail.com>
 
        * mini.h (MONO_BB_FOR_EACH_INS_SAFE): New helper macro.
index 203215d8dffa70a440159eb03932ca444f72d521..dc1f7423675da2e97b7909665b876f06cc738cbe 100644 (file)
@@ -310,28 +310,32 @@ mono_class_generic_class_relation (MonoClass *klass, int info_type, MonoClass *m
                mono_class_get_runtime_generic_context_template (method_klass);
        int i;
 
-       for (i = 0; i < rgctx_template->num_arg_infos; ++i) {
-               MonoType *arg_info = rgctx_template->arg_infos [i];
-               MonoType *inflated_arg;
-
-               if (arg_info == NULL)
-                       continue;
-
-               inflated_arg = mono_class_inflate_generic_type(arg_info, generic_context);
-
-               if (inflated_type_is_equal_to_class (inflated_arg, klass)) {
-                       if (arg_num)
-                               *arg_num = i;
-                       return MINI_GENERIC_CLASS_RELATION_ARGUMENT;
+       /* Reflection types can only be handled in the extensible
+          rgctx part. */
+       if (info_type != MONO_RGCTX_INFO_REFLECTION_TYPE) {
+               for (i = 0; i < rgctx_template->num_arg_infos; ++i) {
+                       MonoType *arg_info = rgctx_template->arg_infos [i];
+                       MonoType *inflated_arg;
+
+                       if (arg_info == NULL)
+                               continue;
+
+                       inflated_arg = mono_class_inflate_generic_type(arg_info, generic_context);
+
+                       if (inflated_type_is_equal_to_class (inflated_arg, klass)) {
+                               if (arg_num)
+                                       *arg_num = i;
+                               return MINI_GENERIC_CLASS_RELATION_ARGUMENT;
+                       }
                }
-       }
 
-       if (!klass->generic_class && !klass->generic_container)
-               g_assert_not_reached ();
+               if (!klass->generic_class && !klass->generic_container)
+                       g_assert_not_reached ();
 
-       if (mini_class_get_container_class (klass) == mini_class_get_container_class (method_klass) &&
-                       mono_generic_context_equal_deep (mini_class_get_context (klass), generic_context))
-               return MINI_GENERIC_CLASS_RELATION_SELF;
+               if (mini_class_get_container_class (klass) == mini_class_get_container_class (method_klass) &&
+                               mono_generic_context_equal_deep (mini_class_get_context (klass), generic_context))
+                       return MINI_GENERIC_CLASS_RELATION_SELF;
+       }
 
        i = mono_class_lookup_or_register_other_info (method_klass, &klass->byval_arg, info_type, generic_context);
        if (arg_num)
index 09bd5944f6618918d906a55b029d568dff52f394..85a4f72e786dff08f36be187bf69609fa65a36c7 100644 (file)
@@ -8242,6 +8242,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                case CEE_LDTOKEN: {
                        gpointer handle;
                        MonoClass *handle_class;
+                       int context_used = 0;
 
                        CHECK_STACK_OVF (1);
 
@@ -8256,14 +8257,32 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
                        else {
                                handle = mono_ldtoken (image, n, &handle_class, generic_context);
-                               if (cfg->generic_sharing_context &&
-                                               mono_class_check_context_used (handle_class))
-                                       GENERIC_SHARING_FAILURE (CEE_LDTOKEN);
                        }
                        if (!handle)
                                goto load_error;
                        mono_class_init (handle_class);
 
+                       if (cfg->generic_sharing_context) {
+                               if (handle_class == mono_defaults.typehandle_class) {
+                                       /* If we get a MONO_TYPE_CLASS
+                                          then we need to provide the
+                                          open type, not an
+                                          instantiation of it. */
+                                       if (mono_type_get_type (handle) == MONO_TYPE_CLASS)
+                                               context_used = 0;
+                                       else
+                                               context_used = mono_class_check_context_used (mono_class_from_mono_type (handle));
+                               } else if (handle_class == mono_defaults.fieldhandle_class)
+                                       context_used = mono_class_check_context_used (((MonoClassField*)handle)->parent);
+                               else if (handle_class == mono_defaults.methodhandle_class)
+                                       context_used = mono_method_check_context_used (handle);
+                               else
+                                       g_assert_not_reached ();
+
+                               if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD)
+                                       GENERIC_SHARING_FAILURE (CEE_LDTOKEN);
+                       }
+
                        if (cfg->opt & MONO_OPT_SHARED) {
                                int temp;
                                MonoInst *res, *store, *addr, *vtvar, *iargs [3];
@@ -8290,16 +8309,29 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
                                        MonoClass *tclass = mono_class_from_mono_type (handle);
                                        mono_class_init (tclass);
-                                       if (cfg->compile_aot)
+                                       if (context_used) {
+                                               MonoInst *this, *rgctx;
+
+                                               g_assert (!cfg->compile_aot);
+                                               if (!(method->flags & METHOD_ATTRIBUTE_STATIC))
+                                                       NEW_ARGLOAD (cfg, this, 0);
+                                               rgctx = get_runtime_generic_context (cfg, method, this, ip);
+                                               ins = get_runtime_generic_context_ptr (cfg, method, bblock, tclass,
+                                                       token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+                                                       rgctx, MONO_RGCTX_INFO_REFLECTION_TYPE, ip);
+                                       } else if (cfg->compile_aot) {
                                                NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, image, n);
-                                       else
+                                       } else {
                                                NEW_PCONST (cfg, ins, mono_type_get_object (cfg->domain, handle));
+                                       }
                                        ins->type = STACK_OBJ;
                                        ins->klass = cmethod->klass;
                                        ip += 5;
                                } else {
                                        MonoInst *store, *addr, *vtvar;
 
+                                       GENERIC_SHARING_FAILURE (CEE_LDTOKEN);
+
                                        if (cfg->compile_aot)
                                                NEW_LDTOKENCONST (cfg, ins, image, n);
                                        else
index baf98d4c3a115fc1399d19ef5f5656e8ab021871..ef6de9f7606cfa1dd5898f717ee8fa00b953c175 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-20  Mark Probst  <mark.probst@gmail.com>
+
+       * generics-sharing.2.cs: Test cases for ldtoken.
+
 2008-03-19  Rodrigo Kumpera  <rkumpera@novell.com>
 
        * bug-340662_bug.cs: Added. Regression test for the bug.
index aa2a5b85c9c04d40fe877c7c2a03080fd97731b9..5f0118e25ddb43bd1085b92017fc4e05ca68d2d0 100644 (file)
@@ -61,6 +61,14 @@ public struct GenStruct<T> {
        }
 }
 
+public interface IGen<T> {
+       T[] iMethod ();
+       void voidIMethod (int x);
+       long longIMethod (long x);
+       float floatIMethod ();
+       GenStruct<T> valueIMethod (int x);
+}
+
 public class GenA<T> {
        public static T[] arr;
 
@@ -119,6 +127,22 @@ public class GenA<T> {
                return (T)obj;
        }
 
+       public Type ldtokenT () {
+               return typeof (T);
+       }
+
+       public Type ldtokenIGenT () {
+               return typeof (IGen<T>);
+       }
+
+       public Type ldtokenGenAIGenT () {
+               return typeof (GenA<IGen<T>>);
+       }
+
+       public Type ldtokenGenB () {
+               return typeof (GenB<>);
+       }
+
        public void except () {
                try {
                        NonGen.doThrow ();
@@ -366,6 +390,15 @@ public class main {
                if (!comp.Equals (ga.cast (obj), obj))
                        error ("cast");
 
+               if (ga.ldtokenT () != typeof (T))
+                       error ("ldtokenT");
+               if (ga.ldtokenIGenT () != typeof (IGen<T>))
+                       error ("ldtokenIGenT");
+               if (ga.ldtokenGenAIGenT () != typeof (GenA<IGen<T>>))
+                       error ("ldtokenGenAIGenT");
+               if (ga.ldtokenGenB () != typeof (GenB<>))
+                       error ("ldtokenGenB");
+
                if (callStaticMethod<T> () != 54321)
                        error ("staticMethod");