Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs509
1 files changed, 271 insertions, 238 deletions
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
index 860b2efa0..373065363 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
@@ -4,18 +4,19 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Numerics;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
-#if !netstandard11
-using System.Numerics;
-#endif
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif // BIT64
namespace System
{
- internal static partial class SpanHelpers
+ internal static partial class SpanHelpers // .Byte
{
public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
{
@@ -70,7 +71,8 @@ namespace System
// Reduce space for search, cause we don't care if we find the search value after the index of a previously found value
searchSpaceLength = tempIndex;
- if (index == 0) break;
+ if (index == 0)
+ break;
}
}
return index;
@@ -88,48 +90,137 @@ namespace System
for (int i = 0; i < valueLength; i++)
{
var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
- if (tempIndex > index) index = tempIndex;
+ if (tempIndex > index)
+ index = tempIndex;
}
return index;
}
- public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
+ // Adapted from IndexOf(...)
+ public static unsafe bool Contains(ref byte searchSpace, byte value, int length)
{
Debug.Assert(length >= 0);
-
+
uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ }
+
+ SequentialScan:
+ while ((byte*)nLength >= (byte*)8)
+ {
+ nLength -= 8;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 0) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
+ {
+ goto Found;
+ }
+
+ index += 8;
+ }
+
+ if ((byte*)nLength >= (byte*)4)
+ {
+ nLength -= 4;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 0) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
+ {
+ goto Found;
+ }
+
+ index += 4;
+ }
+
+ while ((byte*)nLength > (byte*)0)
+ {
+ nLength -= 1;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
+ goto Found;
+
+ index += 1;
+ }
+
+ if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
+ {
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
+ // Get comparison Vector
+ Vector<byte> vComparison = new Vector<byte>(value);
+
+ while ((byte*)nLength > (byte*)index)
{
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index)));
+ if (Vector<byte>.Zero.Equals(vMatches))
+ {
+ index += Vector<byte>.Count;
+ continue;
+ }
+
+ goto Found;
+ }
+
+ if ((int)(byte*)index < length)
+ {
+ nLength = (IntPtr)(length - (int)(byte*)index);
+ goto SequentialScan;
}
}
+
+ return false;
+
+ Found:
+ return true;
+ }
+
+ public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
+ {
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ }
SequentialScan:
-#endif
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 4))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4))
goto Found4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 5))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5))
goto Found5;
- if (uValue == Unsafe.Add(ref searchSpace, index + 6))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6))
goto Found6;
- if (uValue == Unsafe.Add(ref searchSpace, index + 7))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
goto Found7;
index += 8;
@@ -139,13 +230,13 @@ namespace System
{
nLength -= 4;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
index += 4;
@@ -155,17 +246,19 @@ namespace System
{
nLength -= 1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> vComparison = GetVector(value);
+ Vector<byte> vComparison = new Vector<byte>(value);
+
while ((byte*)nLength > (byte*)index)
{
var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index)));
@@ -180,14 +273,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -246,39 +335,35 @@ namespace System
Debug.Assert(length >= 0);
uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- if (uValue == Unsafe.Add(ref searchSpace, index + 7))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
goto Found7;
- if (uValue == Unsafe.Add(ref searchSpace, index + 6))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6))
goto Found6;
- if (uValue == Unsafe.Add(ref searchSpace, index + 5))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5))
goto Found5;
- if (uValue == Unsafe.Add(ref searchSpace, index + 4))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4))
goto Found4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
@@ -287,13 +372,13 @@ namespace System
nLength -= 4;
index -= 4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
@@ -302,16 +387,17 @@ namespace System
nLength -= 1;
index -= 1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
// Get comparison Vector
- Vector<byte> vComparison = GetVector(value);
+ Vector<byte> vComparison = new Vector<byte>(value);
+
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index - Vector<byte>.Count)));
@@ -322,15 +408,14 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -356,46 +441,42 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found7;
@@ -406,16 +487,16 @@ namespace System
{
nLength -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
@@ -426,19 +507,20 @@ namespace System
{
nLength -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
while ((byte*)nLength > (byte*)index)
{
@@ -457,14 +539,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -491,46 +569,42 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found7;
@@ -541,16 +615,16 @@ namespace System
{
nLength -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
@@ -561,20 +635,22 @@ namespace System
{
nLength -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
- Vector<byte> values2 = GetVector(value2);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
+ Vector<byte> values2 = new Vector<byte>(value2);
+
while ((byte*)nLength > (byte*)index)
{
Vector<byte> vData = Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index));
@@ -596,14 +672,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -629,47 +701,43 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found7;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
@@ -679,16 +747,16 @@ namespace System
nLength -= 4;
index -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
@@ -698,17 +766,18 @@ namespace System
nLength -= 1;
index -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
@@ -723,16 +792,15 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -759,47 +827,43 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found7;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
@@ -809,16 +873,16 @@ namespace System
nLength -= 4;
index -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
@@ -828,18 +892,20 @@ namespace System
nLength -= 1;
index -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
- Vector<byte> values2 = GetVector(value2);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
+ Vector<byte> values2 = new Vector<byte>(value2);
+
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
Vector<byte> vData = Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index - Vector<byte>.Count));
@@ -857,16 +923,15 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -886,17 +951,16 @@ namespace System
return (int)(byte*)(index + 7);
}
- public static unsafe bool SequenceEqual(ref byte first, ref byte second, int length)
+ // Optimized byte-based SequenceEquals. The "length" parameter for this one is declared a nuint rather than int as we also use it for types other than byte
+ // where the length can exceed 2Gb once scaled by sizeof(T).
+ public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint length)
{
- Debug.Assert(length >= 0);
-
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
- IntPtr i = (IntPtr)0; // Use IntPtr and byte* for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr n = (IntPtr)length;
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr n = (IntPtr)(void*)length;
-#if !netstandard11
if (Vector.IsHardwareAccelerated && (byte*)n >= (byte*)Vector<byte>.Count)
{
n -= Vector<byte>.Count;
@@ -912,7 +976,6 @@ namespace System
return Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref first, n)) ==
Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref second, n));
}
-#endif
if ((byte*)n >= (byte*)sizeof(UIntPtr))
{
@@ -944,7 +1007,6 @@ namespace System
return false;
}
-#if !netstandard11
// Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateFirstFoundByte(Vector<byte> match)
@@ -965,7 +1027,6 @@ namespace System
// Single LEA instruction with jitted const (using function result)
return i * 8 + LocateFirstFoundByte(candidate);
}
-#endif
public static unsafe int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength)
{
@@ -975,13 +1036,11 @@ namespace System
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
- var minLength = firstLength;
- if (minLength > secondLength) minLength = secondLength;
+ IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
- IntPtr i = (IntPtr)0; // Use IntPtr and byte* for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr n = (IntPtr)minLength;
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr n = (IntPtr)(void*)minLength;
-#if !netstandard11
if (Vector.IsHardwareAccelerated && (byte*)n > (byte*)Vector<byte>.Count)
{
n -= Vector<byte>.Count;
@@ -996,7 +1055,6 @@ namespace System
}
goto NotEqual;
}
-#endif
if ((byte*)n > (byte*)sizeof(UIntPtr))
{
@@ -1013,10 +1071,11 @@ namespace System
}
NotEqual: // Workaround for https://github.com/dotnet/coreclr/issues/13549
- while((byte*)minLength > (byte*)i)
+ while ((byte*)minLength > (byte*)i)
{
int result = Unsafe.AddByteOffset(ref first, i).CompareTo(Unsafe.AddByteOffset(ref second, i));
- if (result != 0) return result;
+ if (result != 0)
+ return result;
i += 1;
}
@@ -1024,7 +1083,6 @@ namespace System
return firstLength - secondLength;
}
-#if !netstandard11
// Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(Vector<byte> match)
@@ -1045,23 +1103,16 @@ namespace System
// Single LEA instruction with jitted const (using function result)
return i * 8 + LocateLastFoundByte(candidate);
}
-#endif
-#if !netstandard11
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateFirstFoundByte(ulong match)
{
- unchecked
- {
- // Flag least significant power of two bit
- var powerOfTwoFlag = match ^ (match - 1);
- // Shift all powers of two into the high byte and extract
- return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57);
- }
+ // Flag least significant power of two bit
+ var powerOfTwoFlag = match ^ (match - 1);
+ // Shift all powers of two into the high byte and extract
+ return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57);
}
-#endif
-#if !netstandard11
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(ulong match)
{
@@ -1074,24 +1125,7 @@ namespace System
}
return index;
}
-#endif
-
-#if !netstandard11
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Vector<byte> GetVector(byte vectorByte)
- {
-#if !netcoreapp
- // Vector<byte> .ctor doesn't become an intrinsic due to detection issue
- // However this does cause it to become an intrinsic (with additional multiply and reg->reg copy)
- // https://github.com/dotnet/coreclr/issues/7459#issuecomment-253965670
- return Vector.AsVectorByte(new Vector<uint>(vectorByte * 0x01010101u));
-#else
- return new Vector<byte>(vectorByte);
-#endif
- }
-#endif
-#if !netstandard11
private const ulong XorPowerOfTwoToHighByte = (0x07ul |
0x06ul << 8 |
0x05ul << 16 |
@@ -1099,6 +1133,5 @@ namespace System
0x03ul << 32 |
0x02ul << 40 |
0x01ul << 48) + 1;
-#endif
}
}