Revert "Better Tuple hashing, avoid boxing in Equals/GetHashCode (dotnet/coreclr...
authorJan Kotas <jkotas@microsoft.com>
Fri, 28 Oct 2016 11:20:21 +0000 (04:20 -0700)
committerJan Kotas <jkotas@microsoft.com>
Fri, 28 Oct 2016 11:45:58 +0000 (04:45 -0700)
This reverts commit dotnet/coreclr@361e6eb85c74b57691955d97dda801d725cd2a59.

Conflicts:
src/mscorlib/mscorlib.shared.sources.props

Commit migrated from https://github.com/dotnet/coreclr/commit/9ebb94e3fe54fab92bbf1b45d36b2b469e68be39

src/coreclr/src/mscorlib/src/System/Tuple.cs

index 92903ec..99164bc 100644 (file)
@@ -1,7 +1,6 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
-
 using System;
 using System.Text;
 using System.Collections;
@@ -53,46 +52,33 @@ namespace System {
             return new Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>>(item1, item2, item3, item4, item5, item6, item7, new Tuple<T8>(item8));
         }
 
-        internal static int CombineHashCodes(int h1, int h2)
-        {
-            // SRP: Keep the actual hashing logic in a separate class
-            // Note if that class is updated, the corresponding file in corefx
-            // should be as well
-            return System.Numerics.Hashing.HashHelpers.Combine(h1, h2);
-        }
-        
-        // These overloads mirror the ones in corefx/ValueTuple.
-        // We combine the hashes sequentially instead of in chunks,
-        // which results in simpler logic and a better spreading effect.
-        
-        internal static int CombineHashCodes(int h1, int h2, int h3)
-        {
+        // From System.Web.Util.HashCodeCombiner
+        internal static int CombineHashCodes(int h1, int h2) {
+            return (((h1 << 5) + h1) ^ h2);
+        }
+
+        internal static int CombineHashCodes(int h1, int h2, int h3) {
             return CombineHashCodes(CombineHashCodes(h1, h2), h3);
         }
-        
-        internal static int CombineHashCodes(int h1, int h2, int h3, int h4)
-        {
-            return CombineHashCodes(CombineHashCodes(h1, h2, h3), h4);
+
+        internal static int CombineHashCodes(int h1, int h2, int h3, int h4) {
+            return CombineHashCodes(CombineHashCodes(h1, h2), CombineHashCodes(h3, h4));
         }
-        
-        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)
-        {
+
+        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5) {
             return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);
         }
-        
-        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)
-        {
-            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4, h5), h6);
+
+        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6) {
+            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6));
         }
 
-        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)
-        {
-            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4, h5, h6), h7);
+        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7) {
+            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7));
         }
 
-        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)
-        {
-            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4, h5, h6, h7), h8);
+        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8) {
+            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7, h8));
         }
     }
 
@@ -107,16 +93,8 @@ namespace System {
             m_Item1 = item1;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1);
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -147,9 +125,8 @@ namespace System {
             return comparer.Compare(m_Item1, objTuple.m_Item1);
         }
 
-        public override int GetHashCode()
-        {
-            return EqualityComparer<T1>.Default.GetHashCode(Item1);
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -192,17 +169,8 @@ namespace System {
             m_Item2 = item2;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2);
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -239,10 +207,8 @@ namespace System {
             return comparer.Compare(m_Item2, objTuple.m_Item2);
         }
 
-        public override int GetHashCode()
-        {
-            return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                          EqualityComparer<T2>.Default.GetHashCode(Item2));
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -290,18 +256,8 @@ namespace System {
             m_Item3 = item3;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2, T3>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
-                && EqualityComparer<T3>.Default.Equals(Item3, other.Item3);
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -342,11 +298,8 @@ namespace System {
             return comparer.Compare(m_Item3, objTuple.m_Item3);
         }
 
-        public override int GetHashCode()
-        {
-            return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                          EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                          EqualityComparer<T3>.Default.GetHashCode(Item3));
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -399,19 +352,8 @@ namespace System {
             m_Item4 = item4;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2, T3, T4>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
-                && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
-                && EqualityComparer<T4>.Default.Equals(Item4, other.Item4);
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -456,12 +398,8 @@ namespace System {
             return comparer.Compare(m_Item4, objTuple.m_Item4);
         }
 
-        public override int GetHashCode()
-        {
-            return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                          EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                          EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                          EqualityComparer<T4>.Default.GetHashCode(Item4));
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -519,20 +457,8 @@ namespace System {
             m_Item5 = item5;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2, T3, T4, T5>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
-                && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
-                && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
-                && EqualityComparer<T5>.Default.Equals(Item5, other.Item5);
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -581,13 +507,8 @@ namespace System {
             return comparer.Compare(m_Item5, objTuple.m_Item5);
         }
 
-        public override int GetHashCode()
-        {
-            return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                          EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                          EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                          EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                          EqualityComparer<T5>.Default.GetHashCode(Item5));
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -650,21 +571,8 @@ namespace System {
             m_Item6 = item6;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2, T3, T4, T5, T6>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
-                && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
-                && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
-                && EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
-                && EqualityComparer<T6>.Default.Equals(Item6, other.Item6);
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -717,14 +625,8 @@ namespace System {
             return comparer.Compare(m_Item6, objTuple.m_Item6);
         }
 
-        public override int GetHashCode()
-        {
-            return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                          EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                          EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                          EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                          EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                          EqualityComparer<T6>.Default.GetHashCode(Item6));
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -791,23 +693,9 @@ namespace System {
             m_Item6 = item6;
             m_Item7 = item7;
         }
-        
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2, T3, T4, T5, T6, T7>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
-                && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
-                && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
-                && EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
-                && EqualityComparer<T6>.Default.Equals(Item6, other.Item6)
-                && EqualityComparer<T7>.Default.Equals(Item7, other.Item7);
+
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -864,15 +752,8 @@ namespace System {
             return comparer.Compare(m_Item7, objTuple.m_Item7);
         }
 
-        public override int GetHashCode()
-        {
-            return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                          EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                          EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                          EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                          EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                          EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                          EqualityComparer<T7>.Default.GetHashCode(Item7));
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
@@ -949,26 +830,8 @@ namespace System {
             m_Rest = rest;
         }
 
-        public override bool Equals(object obj)
-        {
-            var other = obj as Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>;
-            
-            if (other == null)
-            {
-                return false;
-            }
-            
-            return EqualityComparer<T1>.Default.Equals(Item1, other.Item1)
-                && EqualityComparer<T2>.Default.Equals(Item2, other.Item2)
-                && EqualityComparer<T3>.Default.Equals(Item3, other.Item3)
-                && EqualityComparer<T4>.Default.Equals(Item4, other.Item4)
-                && EqualityComparer<T5>.Default.Equals(Item5, other.Item5)
-                && EqualityComparer<T6>.Default.Equals(Item6, other.Item6)
-                && EqualityComparer<T7>.Default.Equals(Item7, other.Item7)
-                && EqualityComparer<TRest>.Default.Equals(Rest, other.Rest); // object.Equals(Rest, other.Rest) is not used here, since this
-                                                                             // may be faster if 1) Tuple eventually implements IEquatable or
-                                                                             // 2) calls to EqualityComparer.Default.Equals are intrinsified
-                                                                             // by the JIT.
+        public override Boolean Equals(Object obj) {
+            return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
         }
 
         Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
@@ -1029,78 +892,17 @@ namespace System {
             return comparer.Compare(m_Rest, objTuple.m_Rest);
         }
 
-        public override int GetHashCode()
-        {
-            // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple
-
-            var rest = (ITuple)Rest; // We checked that Rest was an ITuple in the constructor
-            int size = rest.Size;
-            
-            if (size >= 8)
-            {
-                return rest.GetHashCode();
-            }
-            
-            // In this case, the Rest member has less than 8 elements so we need to combine some of our elements with the ones in Rest
-            int before = 8 - size; // Number of elements we will hash in this tuple before Rest
-            switch (before)
-            {
-                case 1:
-                    return Tuple.CombineHashCodes(EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-                case 2:
-                    return Tuple.CombineHashCodes(EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                                  EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-                case 3:
-                    return Tuple.CombineHashCodes(EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                                  EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                                  EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-                case 4:
-                    return Tuple.CombineHashCodes(EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                                  EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                                  EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                                  EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-                case 5:
-                    return Tuple.CombineHashCodes(EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                                  EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                                  EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                                  EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                                  EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-                case 6:
-                    return Tuple.CombineHashCodes(EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                                  EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                                  EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                                  EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                                  EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                                  EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-                case 7:
-                    return Tuple.CombineHashCodes(EqualityComparer<T1>.Default.GetHashCode(Item1),
-                                                  EqualityComparer<T2>.Default.GetHashCode(Item2),
-                                                  EqualityComparer<T3>.Default.GetHashCode(Item3),
-                                                  EqualityComparer<T4>.Default.GetHashCode(Item4),
-                                                  EqualityComparer<T5>.Default.GetHashCode(Item5),
-                                                  EqualityComparer<T6>.Default.GetHashCode(Item6),
-                                                  EqualityComparer<T7>.Default.GetHashCode(Item7),
-                                                  rest.GetHashCode());
-            }
-            
-            Contract.Assert(false, "Missed all cases for computing Tuple hash code");
-            return -1;
+        public override int GetHashCode() {
+            return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
         }
 
         Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
             // We want to have a limited hash in this case.  We'll use the last 8 elements of the tuple
             ITuple t = (ITuple) m_Rest;
-            int size = t.Size; // cache the size to avoid an unncessary interface call
-            if (size >= 8) { return t.GetHashCode(comparer); }
+            if(t.Size >= 8) { return t.GetHashCode(comparer); }
             
             // In this case, the rest memeber has less than 8 elements so we need to combine some our elements with the elements in rest
-            int k = 8 - size;
+            int k = 8 - t.Size;
             switch(k) {
                 case 1:
                 return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));