2009-02-27 Rodrigo Kumpera <rkumpera@novell.com>
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 27 Feb 2009 23:19:58 +0000 (23:19 -0000)
committerRodrigo Kumpera <kumpera@gmail.com>
Fri, 27 Feb 2009 23:19:58 +0000 (23:19 -0000)
* icall.c: New icall ves_icall_System_Enum_compare_value_to that
helps Enum::CompareTo to be implemented without reboxing all enums
to their underlying type.

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

mono/metadata/ChangeLog
mono/metadata/icall-def.h
mono/metadata/icall.c

index b76193cb309811acc8b352f59005e6fab1df9a67..42a99f12804d361bab0d26002986d73d954dadd9 100644 (file)
@@ -1,3 +1,8 @@
+2009-02-27 Rodrigo Kumpera  <rkumpera@novell.com>
+
+       * icall.c: New icall ves_icall_System_Enum_compare_value_to that
+       helps Enum::CompareTo to be implemented without reboxing all enums
+       to their underlying type.
 2009-02-27  Zoltan Varga  <vargaz@gmail.com>
 
        * domain.c (SET_APPDOMAIN): Avoid calling TlsSetValue () on some platforms,
index 9edd24a8a906a5b47f787ef42ea266b3e662afa7..da9198b07c99e1c725913c1b53dfd5e859960654 100644 (file)
@@ -228,6 +228,7 @@ ICALL(DOUBLE_1, "ParseImpl",    mono_double_ParseImpl)
 
 ICALL_TYPE(ENUM, "System.Enum", ENUM_1)
 ICALL(ENUM_1, "ToObject", ves_icall_System_Enum_ToObject)
+ICALL(ENUM_5, "compare_value_to", ves_icall_System_Enum_compare_value_to)
 ICALL(ENUM_4, "get_hashcode", ves_icall_System_Enum_get_hashcode)
 ICALL(ENUM_3, "get_underlying_type", ves_icall_System_Enum_get_underlying_type)
 ICALL(ENUM_2, "get_value", ves_icall_System_Enum_get_value)
index 153b74fff752fc614c5a95a82f32f9b22786b652..525bc039736d5f4a3d78230240dc7c2a0fd9304d 100644 (file)
@@ -3382,6 +3382,55 @@ ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
 }
 
 static int
+ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
+{
+       gpointer tdata = (char *)this + sizeof (MonoObject);
+       gpointer odata = (char *)other + sizeof (MonoObject);
+       MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
+       g_assert (basetype);
+
+#define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
+               ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
+               ENUM_TYPE other = *((ENUM_TYPE*)odata); \
+               if (me == other) \
+                       return 0; \
+               return me > other ? 1 : -1; \
+       } while (0)
+
+#define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
+               ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
+               ENUM_TYPE other = *((ENUM_TYPE*)odata); \
+               if (me == other) \
+                       return 0; \
+               return me - other; \
+       } while (0)
+
+       switch (basetype->type) {
+               case MONO_TYPE_U1:
+                       COMPARE_ENUM_VALUES (guint8);
+               case MONO_TYPE_I1:
+                       COMPARE_ENUM_VALUES (gint8);
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_U2:
+                       COMPARE_ENUM_VALUES_RANGE (guint16);
+               case MONO_TYPE_I2:
+                       COMPARE_ENUM_VALUES (gint16);
+               case MONO_TYPE_U4:
+                       COMPARE_ENUM_VALUES (guint32);
+               case MONO_TYPE_I4:
+                       COMPARE_ENUM_VALUES (gint32);
+               case MONO_TYPE_U8:
+                       COMPARE_ENUM_VALUES (guint64);
+               case MONO_TYPE_I8:
+                       COMPARE_ENUM_VALUES (gint64);
+               default:
+                       g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
+       }
+#undef COMPARE_ENUM_VALUES_RANGE
+#undef COMPARE_ENUM_VALUES
+       return 0;
+}
+
 ves_icall_System_Enum_get_hashcode (MonoObject *this)
 {
        gpointer data = (char *)this + sizeof (MonoObject);