From 9ebb94e3fe54fab92bbf1b45d36b2b469e68be39 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 28 Oct 2016 04:20:21 -0700 Subject: [PATCH] Revert "Better Tuple hashing, avoid boxing in Equals/GetHashCode (#6767)" This reverts commit 361e6eb85c74b57691955d97dda801d725cd2a59. Conflicts: src/mscorlib/mscorlib.shared.sources.props --- src/mscorlib/src/System/Tuple.cs | 304 +++++++-------------------------------- 1 file changed, 53 insertions(+), 251 deletions(-) diff --git a/src/mscorlib/src/System/Tuple.cs b/src/mscorlib/src/System/Tuple.cs index 92903ec..99164bc 100644 --- a/src/mscorlib/src/System/Tuple.cs +++ b/src/mscorlib/src/System/Tuple.cs @@ -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>(item1, item2, item3, item4, item5, item6, item7, new Tuple(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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1); + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2); + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2)); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3); + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3)); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4); + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4)); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5); + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5)); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5) - && EqualityComparer.Default.Equals(Item6, other.Item6); + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6)); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5) - && EqualityComparer.Default.Equals(Item6, other.Item6) - && EqualityComparer.Default.Equals(Item7, other.Item7); + + public override Boolean Equals(Object obj) { + return ((IStructuralEquatable) this).Equals(obj, EqualityComparer.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.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7)); + public override int GetHashCode() { + return ((IStructuralEquatable) this).GetHashCode(EqualityComparer.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; - - if (other == null) - { - return false; - } - - return EqualityComparer.Default.Equals(Item1, other.Item1) - && EqualityComparer.Default.Equals(Item2, other.Item2) - && EqualityComparer.Default.Equals(Item3, other.Item3) - && EqualityComparer.Default.Equals(Item4, other.Item4) - && EqualityComparer.Default.Equals(Item5, other.Item5) - && EqualityComparer.Default.Equals(Item6, other.Item6) - && EqualityComparer.Default.Equals(Item7, other.Item7) - && EqualityComparer.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.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.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 2: - return Tuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 3: - return Tuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 4: - return Tuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 5: - return Tuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 6: - return Tuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.Default.GetHashCode(Item7), - rest.GetHashCode()); - case 7: - return Tuple.CombineHashCodes(EqualityComparer.Default.GetHashCode(Item1), - EqualityComparer.Default.GetHashCode(Item2), - EqualityComparer.Default.GetHashCode(Item3), - EqualityComparer.Default.GetHashCode(Item4), - EqualityComparer.Default.GetHashCode(Item5), - EqualityComparer.Default.GetHashCode(Item6), - EqualityComparer.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.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)); -- 2.7.4