From 7dbf6a5f2fd636db350f9cc31b2dfd3af0eff1a8 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 17 Apr 2023 15:54:35 +0200 Subject: [PATCH] Improve SeqEquals shape (#84524) --- .../src/System/MemoryExtensions.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index bdeebbf560b7c..d12bf4f4fae0e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -1426,17 +1426,18 @@ private static void ThrowNullLowHighInclusive(T? lowInclusive, T? highInclusi public static unsafe bool SequenceEqual(this Span span, ReadOnlySpan other) where T : IEquatable? { int length = span.Length; + int otherLength = other.Length; if (RuntimeHelpers.IsBitwiseEquatable()) { - return length == other.Length && + return length == otherLength && SpanHelpers.SequenceEqual( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(other)), - ((uint)length) * (nuint)sizeof(T)); // 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. + ((uint)otherLength) * (nuint)sizeof(T)); // 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 == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); + return length == otherLength && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } /// @@ -2161,16 +2162,18 @@ public static int LastIndexOfAny(this ReadOnlySpan span, IndexOfAnyValues< public static unsafe bool SequenceEqual(this ReadOnlySpan span, ReadOnlySpan other) where T : IEquatable? { int length = span.Length; + int otherLength = other.Length; + if (RuntimeHelpers.IsBitwiseEquatable()) { - return length == other.Length && + return length == otherLength && SpanHelpers.SequenceEqual( ref Unsafe.As(ref MemoryMarshal.GetReference(span)), ref Unsafe.As(ref MemoryMarshal.GetReference(other)), - ((uint)length) * (nuint)sizeof(T)); // 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. + ((uint)otherLength) * (nuint)sizeof(T)); // 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 == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); + return length == otherLength && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length); } ///