Port SequentialEqual() optimizations to ReadOnlySpan overloads (#28073)
authorAtsushi Kanamori <AtsushiKan@users.noreply.github.com>
Thu, 15 Mar 2018 13:54:58 +0000 (06:54 -0700)
committerJan Kotas <jkotas@microsoft.com>
Fri, 16 Mar 2018 01:16:34 +0000 (18:16 -0700)
Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
src/mscorlib/shared/System/MemoryExtensions.cs

index 4f278b6..e4bc825 100644 (file)
@@ -635,12 +635,34 @@ namespace System
             where T : IEquatable<T>
         {
             int length = first.Length;
-            if (typeof(T) == typeof(byte))
+            if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
                 return length == second.Length &&
                 SpanHelpers.SequenceEqual(
                     ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
                     ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
                     length);
+
+            if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort))
+                return length == second.Length &&
+                SpanHelpers.SequenceEqualBytes(
+                    ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
+                    ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
+                    ((nuint)length) * 2); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking. 
+
+            if (typeof(T) == typeof(int) || typeof(T) == typeof(uint))
+                return length == second.Length &&
+                SpanHelpers.SequenceEqualBytes(
+                    ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
+                    ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
+                    ((nuint)length) * 4); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking. 
+
+            if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong))
+                return length == second.Length &&
+                SpanHelpers.SequenceEqualBytes(
+                    ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
+                    ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
+                    ((nuint)length) * 8); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking. 
+
             return length == second.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(first), ref MemoryMarshal.GetReference(second), length);
         }