From 716adcebdefde72ad2421dbef919d5b7737b6a48 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 9 Apr 2015 14:26:05 +0200 Subject: [PATCH] [corlib] Generic comparers from reference sources --- external/referencesource | 2 +- .../corlib/ReferenceSources/JitHelpers.cs | 12 +- .../corlib/ReferenceSources/RuntimeType.cs | 7 + .../System.Collections.Generic/Comparer.cs | 126 ---------- .../EqualityComparer.cs | 229 ------------------ mcs/class/corlib/System/Array.cs | 2 +- mcs/class/corlib/System/Buffer.cs | 72 ++++++ .../EqualityComparerTest.cs | 12 + mcs/class/corlib/corlib.dll.sources | 4 +- 9 files changed, 106 insertions(+), 360 deletions(-) delete mode 100644 mcs/class/corlib/System.Collections.Generic/Comparer.cs delete mode 100644 mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs diff --git a/external/referencesource b/external/referencesource index 7d6aea73bb4..e8b48b775c0 160000 --- a/external/referencesource +++ b/external/referencesource @@ -1 +1 @@ -Subproject commit 7d6aea73bb44fa0e3fa51221106571b51a3425e5 +Subproject commit e8b48b775c0b796f424d3d4e5375c6ff2dc21542 diff --git a/mcs/class/corlib/ReferenceSources/JitHelpers.cs b/mcs/class/corlib/ReferenceSources/JitHelpers.cs index 05c4d716cc1..d5d822fdb00 100644 --- a/mcs/class/corlib/ReferenceSources/JitHelpers.cs +++ b/mcs/class/corlib/ReferenceSources/JitHelpers.cs @@ -6,7 +6,17 @@ namespace System.Runtime.CompilerServices { { static internal T UnsafeCast(Object o) where T : class { - return (T)o; + return Array.UnsafeMov (o); + } + + static internal int UnsafeEnumCast(T val) where T : struct + { + return Array.UnsafeMov (val); + } + + static internal long UnsafeEnumCastLong(T val) where T : struct + { + throw new NotImplementedException (); } } } \ No newline at end of file diff --git a/mcs/class/corlib/ReferenceSources/RuntimeType.cs b/mcs/class/corlib/ReferenceSources/RuntimeType.cs index a2673c34886..9dd5e9c6ad0 100644 --- a/mcs/class/corlib/ReferenceSources/RuntimeType.cs +++ b/mcs/class/corlib/ReferenceSources/RuntimeType.cs @@ -394,6 +394,13 @@ namespace System return constraints; } + internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument) + { + var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument }); + var ctor = gt.GetDefaultConstructor (); + return ctor.InternalInvoke (null, null); + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern Type MakeGenericType (Type gt, Type [] types); diff --git a/mcs/class/corlib/System.Collections.Generic/Comparer.cs b/mcs/class/corlib/System.Collections.Generic/Comparer.cs deleted file mode 100644 index d19ce2cc8bb..00000000000 --- a/mcs/class/corlib/System.Collections.Generic/Comparer.cs +++ /dev/null @@ -1,126 +0,0 @@ -// -// Comparer.cs -// -// Authors: -// Ben Maurer (bmaurer@ximian.com) -// Marek Safar (marek.safar@gmail.com) -// -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) -// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Runtime.InteropServices; - -namespace System.Collections.Generic { - [Serializable] - public abstract class Comparer : IComparer, IComparer - { - static readonly Comparer _default = typeof (IComparable).IsAssignableFrom (typeof (T)) ? - (Comparer) Activator.CreateInstance (typeof (GenericComparer <>).MakeGenericType (typeof (T))) : - new DefaultComparer (); - - public abstract int Compare (T x, T y); - - public static Comparer Default { - get { - return _default; - } - } - - public static Comparer Create (Comparison comparison) - { - if (comparison == null) - throw new ArgumentNullException ("comparison"); - - return new ComparisonComparer (comparison); - } - - int IComparer.Compare (object x, object y) - { - if (x == y) - return 0; - if (x == null) - return y == null ? 0 : -1; - if (y == null) - return 1; - - if (x is T && y is T) - return Compare ((T) x, (T) y); - - throw new ArgumentException (); - } - - [Serializable] - sealed class DefaultComparer : Comparer - { - public override int Compare (T x, T y) - { - // `null' is less than any other ref type - if (x == null) - return y == null ? 0 : -1; - if (y == null) - return 1; - - var i = x as IComparable; - if (i != null) - return i.CompareTo (y); - - i = y as IComparable; - if (i != null) - return -i.CompareTo (x); - - throw new ArgumentException ("At least one argument has to implement IComparable interface"); - } - } - } - - [Serializable] - sealed class GenericComparer : Comparer where T : IComparable - { - public override int Compare (T x, T y) - { - // `null' is less than any other ref type - if (x == null) - return y == null ? 0 : -1; - if (y == null) - return 1; - - return x.CompareTo (y); - } - } - [Serializable] - sealed class ComparisonComparer : Comparer - { - readonly Comparison comparison; - - public ComparisonComparer (Comparison comparison) - { - this.comparison = comparison; - } - - public override int Compare (T x, T y) - { - return comparison (x, y); - } - } -} diff --git a/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs b/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs deleted file mode 100644 index 9338f966f50..00000000000 --- a/mcs/class/corlib/System.Collections.Generic/EqualityComparer.cs +++ /dev/null @@ -1,229 +0,0 @@ -// -// EqualityComparer.cs -// -// Authors: -// Ben Maurer (bmaurer@ximian.com) -// Marek Safar (marek.safar@gmail.com) -// -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) -// Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Runtime.InteropServices; - -namespace System.Collections.Generic { - [Serializable] - public abstract class EqualityComparer : IEqualityComparer, IEqualityComparer { - - static EqualityComparer () - { - var t = typeof (T); - if (t == typeof (string)) { - _default = (EqualityComparer) (object) new InternalStringComparer (); - return; - } - - if (t == typeof (int)) { - _default = (EqualityComparer) (object) new IntEqualityComparer (); - return; - } - - if (t.IsEnum && Enum.GetUnderlyingType (t) == typeof (int)) { - _default = new EnumIntEqualityComparer (); - return; - } - - if (typeof (IEquatable ).IsAssignableFrom (t)) - _default = (EqualityComparer ) Activator.CreateInstance (typeof (GenericEqualityComparer <>).MakeGenericType (t)); - else - _default = new DefaultComparer (); - } - - public abstract int GetHashCode (T obj); - public abstract bool Equals (T x, T y); - - static readonly EqualityComparer _default; - - public static EqualityComparer Default { - get { - return _default; - } - } - - int IEqualityComparer.GetHashCode (object obj) - { - if (obj == null) - return 0; - - if (!(obj is T)) - throw new ArgumentException ("Argument is not compatible", "obj"); - - return GetHashCode ((T)obj); - } - - bool IEqualityComparer.Equals (object x, object y) - { - if (x == y) - return true; - - if (x == null || y == null) - return false; - - if (!(x is T)) - throw new ArgumentException ("Argument is not compatible", "x"); - if (!(y is T)) - throw new ArgumentException ("Argument is not compatible", "y"); - return Equals ((T)x, (T)y); - } - - internal virtual int IndexOf (T[] array, T value, int startIndex, int endIndex) - { - for (int i = startIndex; i < endIndex; ++i) { - if (Equals (Array.UnsafeLoad (array, i), value)) - return i; - } - - return -1; - } - } - - [Serializable] - sealed class DefaultComparer : EqualityComparer { - - public override int GetHashCode (T obj) - { - if (obj == null) - return 0; - return obj.GetHashCode (); - } - - public override bool Equals (T x, T y) - { - if (x == null) - return y == null; - - return x.Equals (y); - } - } - - [Serializable] - sealed class InternalStringComparer : EqualityComparer { - - public override int GetHashCode (string obj) - { - if (obj == null) - return 0; - return obj.GetHashCode (); - } - - public override bool Equals (string x, string y) - { - if (x == null) - return y == null; - - if ((object) x == (object) y) - return true; - - return x.Equals (y); - } - - internal override int IndexOf (string[] array, string value, int startIndex, int endIndex) - { - for (int i = startIndex; i < endIndex; ++i) { - if (Array.UnsafeLoad (array, i) == value) - return i; - } - - return -1; - } - } - - [Serializable] - sealed class IntEqualityComparer : EqualityComparer - { - public override int GetHashCode (int obj) - { - return obj; - } - - public override bool Equals (int x, int y) - { - return x == y; - } - - internal override int IndexOf (int[] array, int value, int startIndex, int endIndex) - { - for (int i = startIndex; i < endIndex; ++i) { - if (Array.UnsafeLoad (array, i) == value) - return i; - } - - return -1; - } - } - - [Serializable] - sealed class EnumIntEqualityComparer : EqualityComparer - { - public override int GetHashCode (T obj) - { - return Array.UnsafeMov (obj); - } - - public override bool Equals (T x, T y) - { - return Array.UnsafeMov (x) == Array.UnsafeMov (y); - } - - internal override int IndexOf (T[] array, T value, int startIndex, int endIndex) - { - int v = Array.UnsafeMov (value); - var a = Array.UnsafeMov (array); - for (int i = startIndex; i < endIndex; ++i) { - if (Array.UnsafeLoad (a, i) == v) - return i; - } - - return -1; - } - } - - [Serializable] - sealed class GenericEqualityComparer : EqualityComparer where T : IEquatable { - - public override int GetHashCode (T obj) - { - if (obj == null) - return 0; - return obj.GetHashCode (); - } - - public override bool Equals (T x, T y) - { - if (x == null) - return y == null; - - return x.Equals (y); - } - } -} diff --git a/mcs/class/corlib/System/Array.cs b/mcs/class/corlib/System/Array.cs index b4afbe2eb84..9c263400572 100644 --- a/mcs/class/corlib/System/Array.cs +++ b/mcs/class/corlib/System/Array.cs @@ -3045,7 +3045,7 @@ namespace System if (count < 0 || startIndex < array.GetLowerBound (0) || startIndex - 1 > array.GetUpperBound (0) - count) throw new ArgumentOutOfRangeException (); - return EqualityComparer.Default.IndexOf (array, value, startIndex, startIndex + count); + return EqualityComparer.Default.IndexOf (array, value, startIndex, count); } public static int LastIndexOf (T [] array, T value) diff --git a/mcs/class/corlib/System/Buffer.cs b/mcs/class/corlib/System/Buffer.cs index 3f4960d7b79..3c20630fcf3 100644 --- a/mcs/class/corlib/System/Buffer.cs +++ b/mcs/class/corlib/System/Buffer.cs @@ -260,5 +260,77 @@ namespace System { } memcpy4 (dest, src, size); } + + internal unsafe static int IndexOfByte(byte* src, byte value, int index, int count) + { + Contract.Assert(src != null, "src should not be null"); + + byte* pByte = src + index; + + // Align up the pointer to sizeof(int). + while (((int)pByte & 3) != 0) + { + if (count == 0) + return -1; + else if (*pByte == value) + return (int) (pByte - src); + + count--; + pByte++; + } + + // Fill comparer with value byte for comparisons + // + // comparer = 0/0/value/value + uint comparer = (((uint)value << 8) + (uint)value); + // comparer = value/value/value/value + comparer = (comparer << 16) + comparer; + + // Run through buffer until we hit a 4-byte section which contains + // the byte we're looking for or until we exhaust the buffer. + while (count > 3) + { + // Test the buffer for presence of value. comparer contains the byte + // replicated 4 times. + uint t1 = *(uint*)pByte; + t1 = t1 ^ comparer; + uint t2 = 0x7efefeff + t1; + t1 = t1 ^ 0xffffffff; + t1 = t1 ^ t2; + t1 = t1 & 0x81010100; + + // if t1 is zero then these 4-bytes don't contain a match + if (t1 != 0) + { + // We've found a match for value, figure out which position it's in. + int foundIndex = (int) (pByte - src); + if (pByte[0] == value) + return foundIndex; + else if (pByte[1] == value) + return foundIndex + 1; + else if (pByte[2] == value) + return foundIndex + 2; + else if (pByte[3] == value) + return foundIndex + 3; + } + + count -= 4; + pByte += 4; + + } + + // Catch any bytes that might be left at the tail of the buffer + while (count > 0) + { + if (*pByte == value) + return (int) (pByte - src); + + count--; + pByte++; + } + + // If we don't have a match return -1; + return -1; + } } } diff --git a/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs b/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs index 5a0fd3b6a25..e238781bcb7 100644 --- a/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs +++ b/mcs/class/corlib/Test/System.Collections.Generic/EqualityComparerTest.cs @@ -37,6 +37,11 @@ namespace MonoTests.System.Collections.Generic { [TestFixture] public class EqualityComparerTest { + enum E + { + A, + B + } [Test] public void Default_GetHashCode_Null () @@ -59,6 +64,13 @@ namespace MonoTests.System.Collections.Generic { IEqualityComparer comparer = EqualityComparer.Default; Assert.IsTrue (comparer.Equals (null, null)); } + + [Test] + public void EnumComparison () + { + Assert.IsFalse (EqualityComparer.Default.Equals (E.A, E.B)); + Assert.IsFalse (EqualityComparer.Default.Equals (E.A, E.B)); + } } } diff --git a/mcs/class/corlib/corlib.dll.sources b/mcs/class/corlib/corlib.dll.sources index 4aef1fb9ff7..1a27579a157 100644 --- a/mcs/class/corlib/corlib.dll.sources +++ b/mcs/class/corlib/corlib.dll.sources @@ -1100,8 +1100,6 @@ System.Threading/Timer.cs System.Threading/TimerCallback.cs System.Threading/Volatile.cs System.Threading/WaitHandle.cs -System.Collections.Generic/Comparer.cs -System.Collections.Generic/EqualityComparer.cs System.Threading.Tasks/DecoupledTask.cs ../Mono.Parallel/Mono.Threading/AtomicBoolean.cs @@ -1307,8 +1305,10 @@ ReferenceSources/TypeBuilderInstantiation.cs ../../../external/referencesource/mscorlib/system/collections/stack.cs ../../../external/referencesource/mscorlib/system/collections/structuralcomparisons.cs +../../../external/referencesource/mscorlib/system/collections/generic/comparer.cs ../../../external/referencesource/mscorlib/system/collections/generic/debugview.cs ../../../external/referencesource/mscorlib/system/collections/generic/dictionary.cs +../../../external/referencesource/mscorlib/system/collections/generic/equalitycomparer.cs ../../../external/referencesource/mscorlib/system/collections/generic/icollection.cs ../../../external/referencesource/mscorlib/system/collections/generic/icomparer.cs ../../../external/referencesource/mscorlib/system/collections/generic/idictionary.cs -- 2.25.1