Simplify Comparer/EqualityComparers (#14737)
authorJan Kotas <jkotas@microsoft.com>
Mon, 30 Oct 2017 18:03:48 +0000 (11:03 -0700)
committerGitHub <noreply@github.com>
Mon, 30 Oct 2017 18:03:48 +0000 (11:03 -0700)
- Make EnumEqualityComparer sealed. This helps with JIT optimizations.
- Delete SByteEnumEqualityComparer and ShortEnumEqualityComparer because of they are not needed anymore. The optimization that they were introduced for is done by the JIT now.
- Deleted ForwardedFrom attributes on types that do not need them

src/mscorlib/src/System/Collections/Generic/Comparer.cs
src/mscorlib/src/System/Collections/Generic/ComparerHelpers.cs
src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
src/vm/compile.cpp
src/vm/jitinterface.cpp
src/vm/mscorlib.h

index bb9e07d..cb4ad85 100644 (file)
@@ -133,7 +133,6 @@ namespace System.Collections.Generic
     // since we want to serialize as ObjectComparer for
     // back-compat reasons (see below).
     [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
     internal sealed class Int32EnumComparer<T> : Comparer<T>, ISerializable where T : struct
     {
         public Int32EnumComparer()
@@ -169,7 +168,6 @@ namespace System.Collections.Generic
     }
 
     [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
     internal sealed class UInt32EnumComparer<T> : Comparer<T>, ISerializable where T : struct
     {
         public UInt32EnumComparer()
@@ -201,7 +199,6 @@ namespace System.Collections.Generic
     }
 
     [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
     internal sealed class Int64EnumComparer<T> : Comparer<T>, ISerializable where T : struct
     {
         public Int64EnumComparer()
@@ -230,7 +227,6 @@ namespace System.Collections.Generic
     }
 
     [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
     internal sealed class UInt64EnumComparer<T> : Comparer<T>, ISerializable where T : struct
     {
         public UInt64EnumComparer()
index 1c4b9bb..2575d4e 100644 (file)
@@ -187,17 +187,13 @@ namespace System.Collections.Generic
             TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(enumType));
 
             // Depending on the enum type, we need to special case the comparers so that we avoid boxing.
-            // Note: We have different comparers for short and sbyte, since for those types GetHashCode does not simply return the value.
-            // We need to preserve what they would return.
             switch (underlyingTypeCode)
             {
-                case TypeCode.Int16:
-                    return RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer<short>), enumType);
-                case TypeCode.SByte:
-                    return RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer<sbyte>), enumType);
                 case TypeCode.Int32:
                 case TypeCode.UInt32:
+                case TypeCode.SByte:
                 case TypeCode.Byte:
+                case TypeCode.Int16:
                 case TypeCode.UInt16:
                     return RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<int>), enumType);
                 case TypeCode.Int64:
index 3af0cf4..aad7c75 100644 (file)
@@ -363,7 +363,7 @@ namespace System.Collections.Generic
 
     [Serializable]
     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
-    internal class EnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
+    internal sealed class EnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override bool Equals(T x, T y)
@@ -376,8 +376,7 @@ namespace System.Collections.Generic
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override int GetHashCode(T obj)
         {
-            int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
-            return x_final.GetHashCode();
+            return obj.GetHashCode();
         }
 
         public EnumEqualityComparer() { }
@@ -426,41 +425,6 @@ namespace System.Collections.Generic
     }
 
     [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
-    internal sealed class SByteEnumEqualityComparer<T> : EnumEqualityComparer<T> where T : struct
-    {
-        public SByteEnumEqualityComparer() { }
-
-        // This is used by the serialization engine.
-        public SByteEnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public override int GetHashCode(T obj)
-        {
-            int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
-            return ((sbyte)x_final).GetHashCode();
-        }
-    }
-
-    [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
-    internal sealed class ShortEnumEqualityComparer<T> : EnumEqualityComparer<T>, ISerializable where T : struct
-    {
-        public ShortEnumEqualityComparer() { }
-
-        // This is used by the serialization engine.
-        public ShortEnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public override int GetHashCode(T obj)
-        {
-            int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
-            return ((short)x_final).GetHashCode();
-        }
-    }
-
-    [Serializable]
-    [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] 
     internal sealed class LongEnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
     {
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -474,8 +438,7 @@ namespace System.Collections.Generic
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public override int GetHashCode(T obj)
         {
-            long x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCastLong(obj);
-            return x_final.GetHashCode();
+            return obj.GetHashCode();
         }
 
         // Equals method for the comparer itself.
index fb93a89..327f0f1 100644 (file)
@@ -5205,21 +5205,13 @@ static void SpecializeEqualityComparer(SString& ss, Instantiation& inst)
         if (et == ELEMENT_TYPE_I4 ||
             et == ELEMENT_TYPE_U4 ||
             et == ELEMENT_TYPE_U2 ||
-            et == ELEMENT_TYPE_U1)
+            et == ELEMENT_TYPE_I2 ||
+            et == ELEMENT_TYPE_U1 ||
+            et == ELEMENT_TYPE_I1)
         {
             ss.Set(W("System.Collections.Generic.EnumEqualityComparer`1"));
             return;
         }
-        else if (et == ELEMENT_TYPE_I2)
-        {
-            ss.Set(W("System.Collections.Generic.ShortEnumEqualityComparer`1"));
-            return;
-        }
-        else if (et == ELEMENT_TYPE_I1)
-        {
-            ss.Set(W("System.Collections.Generic.SByteEnumEqualityComparer`1"));
-            return;
-        }
         else if (et == ELEMENT_TYPE_I8 ||
                  et == ELEMENT_TYPE_U8)
         {
index 7c9fa17..bce81c4 100644 (file)
@@ -8897,17 +8897,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getDefaultEqualityComparerClassHelper(CORINFO_CLAS
         switch(normType)
         {
             case ELEMENT_TYPE_I1:
-            {
-                targetClass = MscorlibBinder::GetClass(CLASS__SBYTE_ENUM_EQUALITYCOMPARER);
-                break;
-            }
-
             case ELEMENT_TYPE_I2:
-            {
-                targetClass = MscorlibBinder::GetClass(CLASS__SHORT_ENUM_EQUALITYCOMPARER);
-                break;
-            }
-
             case ELEMENT_TYPE_U1:
             case ELEMENT_TYPE_U2:
             case ELEMENT_TYPE_I4:
index e757624..f20e8d3 100644 (file)
@@ -1449,8 +1449,6 @@ DEFINE_METHOD(UTF8BUFFERMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, NoSig)
 // Classes referenced in EqualityComparer<T>.Default optimization
 
 DEFINE_CLASS(BYTE_EQUALITYCOMPARER, CollectionsGeneric, ByteEqualityComparer)
-DEFINE_CLASS(SHORT_ENUM_EQUALITYCOMPARER, CollectionsGeneric, ShortEnumEqualityComparer`1)
-DEFINE_CLASS(SBYTE_ENUM_EQUALITYCOMPARER, CollectionsGeneric, SByteEnumEqualityComparer`1)
 DEFINE_CLASS(ENUM_EQUALITYCOMPARER, CollectionsGeneric, EnumEqualityComparer`1)
 DEFINE_CLASS(LONG_ENUM_EQUALITYCOMPARER, CollectionsGeneric, LongEnumEqualityComparer`1)
 DEFINE_CLASS(NULLABLE_EQUALITYCOMPARER, CollectionsGeneric, NullableEqualityComparer`1)