Fix constrained gsharedvt calls on enums.
authorZoltan Varga <vargaz@gmail.com>
Sun, 2 Jun 2013 09:49:59 +0000 (11:49 +0200)
committerZoltan Varga <vargaz@gmail.com>
Sun, 2 Jun 2013 09:49:59 +0000 (11:49 +0200)
mono/mini/gshared.cs
mono/mini/jit-icalls.c

index 3e74643fd8f9b0de8fc48eda940caeeb5694c612..ec931443e23f6357e5dd5c5ab1ca1ad8293608bf 100644 (file)
@@ -897,11 +897,17 @@ public class Tests
                return t.ToString ();
        }
 
+       enum AnEnum {
+               One
+       };
+
        public static int test_0_constrained_tostring () {
                if (to_string<int, int> (1, 1) != "1")
                        return 1;
-               if (to_string<string, int> ("A", 1) != "A")
+               if (to_string<AnEnum, int> (AnEnum.One, 1) != "One")
                        return 2;
+               if (to_string<string, int> ("A", 1) != "A")
+                       return 3;
                return 0;
        }
 
@@ -915,8 +921,10 @@ public class Tests
                        return 1;
                if (get_hash<double, int> (1.0, 1) != 1.0.GetHashCode ())
                        return 2;
-               if (get_hash<string, int> ("A", 1) != "A".GetHashCode ())
+               if (get_hash<AnEnum, int> (AnEnum.One, 1) != AnEnum.One.GetHashCode ())
                        return 3;
+               if (get_hash<string, int> ("A", 1) != "A".GetHashCode ())
+                       return 4;
                return 0;
        }
 
@@ -930,8 +938,10 @@ public class Tests
                        return 1;
                if (equals<double, int> (1.0, 1) != true)
                        return 2;
-               if (equals<string, int> ("A", 1) != true)
+               if (equals<AnEnum, int> (AnEnum.One, 1) != true)
                        return 3;
+               if (equals<string, int> ("A", 1) != true)
+                       return 4;
                return 0;
        }
 
index 85f1dc7016ca8f49a39864854ecd9ab852d7e9f9..fd1843f119e8f5a439bdfcbb788f97be2e1da286 100644 (file)
@@ -1154,22 +1154,33 @@ mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpoin
        return mono_compile_method (m);
 }
 
-MonoObject*
-mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
+static MonoMethod*
+constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg)
 {
        MonoMethod *m;
        int vt_slot;
-       gpointer this_arg;
 
        /* Lookup the virtual method */
        mono_class_setup_vtable (klass);
        g_assert (klass->vtable);
        vt_slot = mono_method_get_vtable_slot (cmethod);
        m = klass->vtable [vt_slot];
-       if (klass->valuetype)
-               this_arg = mp;
+       if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
+               *this_arg = mono_value_box (mono_domain_get (), klass, mp);
+       else if (klass->valuetype)
+               *this_arg = mp;
        else
-               this_arg = *(gpointer*)mp;
+               *this_arg = *(gpointer*)mp;
+       return m;
+}
+
+MonoObject*
+mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
+{
+       MonoMethod *m;
+       gpointer this_arg;
+
+       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
        return mono_runtime_invoke (m, this_arg, NULL, NULL);
 }
 
@@ -1177,20 +1188,11 @@ int
 mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
 {
        MonoMethod *m;
-       int vt_slot;
        gpointer this_arg;
        MonoObject *res;
        gpointer p;
 
-       /* Lookup the virtual method */
-       mono_class_setup_vtable (klass);
-       g_assert (klass->vtable);
-       vt_slot = mono_method_get_vtable_slot (cmethod);
-       m = klass->vtable [vt_slot];
-       if (klass->valuetype)
-               this_arg = mp;
-       else
-               this_arg = *(gpointer*)mp;
+       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
        // FIXME: This boxes the result
        res = mono_runtime_invoke (m, this_arg, NULL, NULL);
        p = mono_object_unbox (res);
@@ -1201,21 +1203,12 @@ gboolean
 mono_object_equals_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass, MonoObject *arg)
 {
        MonoMethod *m;
-       int vt_slot;
        gpointer this_arg;
        MonoObject *res;
        gpointer p;
        void **args;
 
-       /* Lookup the virtual method */
-       mono_class_setup_vtable (klass);
-       g_assert (klass->vtable);
-       vt_slot = mono_method_get_vtable_slot (cmethod);
-       m = klass->vtable [vt_slot];
-       if (klass->valuetype)
-               this_arg = mp;
-       else
-               this_arg = *(gpointer*)mp;
+       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
        // FIXME: This boxes the result
        args = (void**)&arg;
        res = mono_runtime_invoke (m, this_arg, args, NULL);