From b02946a2f8d921b68f51bc7c28d42106c1b08358 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Tue, 9 Jul 2024 15:07:01 -0700 Subject: [PATCH 1/3] Add NET 8.0 target to Microsoft.Bcl.Memory package --- .../ref/Microsoft.Bcl.Memory.csproj | 6 +- .../src/Microsoft.Bcl.Memory.csproj | 8 +- .../tests/Microsoft.Bcl.Memory.Tests.csproj | 4 +- .../Text/Base64Helper/Base64DecoderHelper.cs | 26 +++- .../Text/Base64Helper/Base64EncoderHelper.cs | 16 ++- .../Buffers/Text/Base64Helper/Base64Helper.cs | 122 +++++++++++++++++- .../Text/Base64Url/Base64UrlDecoder.cs | 40 +++++- .../Text/Base64Url/Base64UrlEncoder.cs | 10 +- 8 files changed, 213 insertions(+), 19 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj index ae94b2d611097..a74221d64dff0 100644 --- a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj @@ -1,14 +1,14 @@ - netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppCurrent) + netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppMinimum);$(NetCoreAppCurrent) - + - + diff --git a/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj b/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj index 0b191a869540f..57f4610a279db 100644 --- a/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj @@ -1,7 +1,7 @@ - netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppCurrent) + netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppMinimum);$(NetCoreAppCurrent) true true MICROSOFT_BCL_MEMORY;$(DefineConstants) @@ -22,10 +22,10 @@ - true + true - + @@ -34,7 +34,7 @@ - + System\Buffers\Text\Base64Helper\Base64Helper.cs diff --git a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj index e805a830958db..8aab11978e0ea 100644 --- a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj @@ -1,7 +1,7 @@ - $(NetFrameworkMinimum);$(NetCoreAppCurrent); + $(NetFrameworkMinimum);$(NetCoreAppCurrent) true @@ -39,7 +39,7 @@ - + diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs index 628be863e38c6..c75252b90394a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs @@ -71,6 +71,7 @@ internal static unsafe OperationStatus DecodeFrom(TBase64Deco } } +#if NET9_0_OR_GREATER end = srcMax - 66; if (AdvSimd.Arm64.IsSupported && (end >= src)) { @@ -81,6 +82,7 @@ internal static unsafe OperationStatus DecodeFrom(TBase64Deco goto DoneExit; } } +#endif end = srcMax - 24; if ((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian && (end >= src)) @@ -641,8 +643,10 @@ private static OperationStatus DecodeWithWhiteSpaceFromUtf8InPlace(TBase64Decoder decoder, ref T* srcBytes, ref byte* destBytes, T* srcEnd, int sourceLength, int destLength, T* srcStart, byte* destStart) where TBase64Decoder : IBase64Decoder where T : unmanaged @@ -709,7 +713,9 @@ private static unsafe void Avx512Decode(TBase64Decoder decode } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif private static unsafe void Avx2Decode(TBase64Decoder decoder, ref T* srcBytes, ref byte* destBytes, T* srcEnd, int sourceLength, int destLength, T* srcStart, byte* destStart) where TBase64Decoder : IBase64Decoder where T : unmanaged @@ -813,8 +819,10 @@ private static unsafe void Avx2Decode(TBase64Decoder decoder, } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Ssse3))] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] +#endif internal static Vector128 SimdShuffle(Vector128 left, Vector128 right, Vector128 mask8F) { Debug.Assert((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian); @@ -824,9 +832,14 @@ internal static Vector128 SimdShuffle(Vector128 left, Vector128(TBase64Decoder decoder, ref T* srcBytes, ref byte* destBytes, T* srcEnd, int sourceLength, int destLength, T* srcStart, byte* destStart) @@ -966,10 +979,13 @@ private static unsafe void AdvSimdDecode(TBase64Decoder decod srcBytes = src; destBytes = dest; } +#endif [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(Ssse3))] +#endif private static unsafe void Vector128Decode(TBase64Decoder decoder, ref T* srcBytes, ref byte* destBytes, T* srcEnd, int sourceLength, int destLength, T* srcStart, byte* destStart) where TBase64Decoder : IBase64Decoder where T : unmanaged @@ -1249,8 +1265,10 @@ internal static bool IsWhiteSpace(int value) #if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(Ssse3))] +#endif public bool TryDecode128Core( Vector128 str, Vector128 hiNibbles, @@ -1284,7 +1302,9 @@ public bool TryDecode128Core( } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public bool TryDecode256Core( Vector256 str, Vector256 hiNibbles, @@ -1322,7 +1342,9 @@ public unsafe bool TryLoadVector512(byte* src, byte* srcStart, int sourceLength, } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public unsafe bool TryLoadAvxVector256(byte* src, byte* srcStart, int sourceLength, out Vector256 str) { AssertRead>(src, srcStart, sourceLength); @@ -1338,6 +1360,7 @@ public unsafe bool TryLoadVector128(byte* src, byte* srcStart, int sourceLength, return true; } +#if NET9_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] public unsafe bool TryLoadArmVector128x4(byte* src, byte* srcStart, int sourceLength, @@ -1348,7 +1371,8 @@ public unsafe bool TryLoadArmVector128x4(byte* src, byte* srcStart, int sourceLe return true; } -#endif +#endif // NET9_0_OR_GREATER +#endif // NET [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int DecodeFourElements(byte* source, ref sbyte decodingMap) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64EncoderHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64EncoderHelper.cs index 4788384515df4..23c42e547b6fa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64EncoderHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64EncoderHelper.cs @@ -58,6 +58,7 @@ internal static unsafe OperationStatus EncodeTo(TBase64Encode goto DoneExit; } +#if NET9_0_OR_GREATER end = srcMax - 48; if (AdvSimd.Arm64.IsSupported && (end >= src)) { @@ -66,6 +67,7 @@ internal static unsafe OperationStatus EncodeTo(TBase64Encode if (src == srcEnd) goto DoneExit; } +#endif end = srcMax - 16; if ((Ssse3.IsSupported || AdvSimd.Arm64.IsSupported) && BitConverter.IsLittleEndian && (end >= src)) @@ -130,8 +132,10 @@ internal static unsafe OperationStatus EncodeTo(TBase64Encode #if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx512BW))] [CompExactlyDependsOn(typeof(Avx512Vbmi))] +#endif private static unsafe void Avx512Encode(TBase64Encoder encoder, ref byte* srcBytes, ref T* destBytes, byte* srcEnd, int sourceLength, int destLength, byte* srcStart, T* destStart) where TBase64Encoder : IBase64Encoder where T : unmanaged @@ -205,7 +209,9 @@ private static unsafe void Avx512Encode(TBase64Encoder encode } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif private static unsafe void Avx2Encode(TBase64Encoder encoder, ref byte* srcBytes, ref T* destBytes, byte* srcEnd, int sourceLength, int destLength, byte* srcStart, T* destStart) where TBase64Encoder : IBase64Encoder where T : unmanaged @@ -376,6 +382,7 @@ private static unsafe void Avx2Encode(TBase64Encoder encoder, destBytes = dest; } +#if NET9_0_OR_GREATER // Part of the Arm APIs used here added in .NET 9 [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] private static unsafe void AdvSimdEncode(TBase64Encoder encoder, ref byte* srcBytes, ref T* destBytes, byte* srcEnd, int sourceLength, int destLength, byte* srcStart, T* destStart) @@ -434,10 +441,13 @@ private static unsafe void AdvSimdEncode(TBase64Encoder encod srcBytes = src; destBytes = dest; } +#endif [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Ssse3))] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] +#endif private static unsafe void Vector128Encode(TBase64Encoder encoder, ref byte* srcBytes, ref T* destBytes, byte* srcEnd, int sourceLength, int destLength, byte* srcStart, T* destStart) where TBase64Encoder : IBase64Encoder where T : unmanaged @@ -712,7 +722,9 @@ public unsafe void StoreVector512ToDestination(byte* dest, byte* destStart, int } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public unsafe void StoreVector256ToDestination(byte* dest, byte* destStart, int destLength, Vector256 str) { AssertWrite>(dest, destStart, destLength); @@ -726,6 +738,7 @@ public unsafe void StoreVector128ToDestination(byte* dest, byte* destStart, int str.Store(dest); } +#if NET9_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] public unsafe void StoreArmVector128x4ToDestination(byte* dest, byte* destStart, int destLength, @@ -734,7 +747,8 @@ public unsafe void StoreArmVector128x4ToDestination(byte* dest, byte* destStart, AssertWrite>(dest, destStart, destLength); AdvSimd.Arm64.StoreVectorAndZip(dest, (res1, res2, res3, res4)); } -#endif +#endif // NET9_0_OR_GREATER +#endif // NET [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void EncodeThreeAndWrite(byte* threeBytes, byte* destination, ref byte encodingMap) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64Helper.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64Helper.cs index b86600c74db27..4a4d9bd5def0f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64Helper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64Helper.cs @@ -5,6 +5,9 @@ using System.Runtime.CompilerServices; #if NET using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; +using System.Runtime.Intrinsics.X86; +using System.Runtime.Intrinsics.Wasm; #endif namespace System.Buffers.Text @@ -67,6 +70,117 @@ internal static unsafe void AssertWrite(ushort* dest, ushort* destStart } } +#if NET8_0 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool VectorContainsNonAsciiChar(Vector128 utf16Vector) + { + // prefer architecture specific intrinsic as they offer better perf + if (Sse2.IsSupported) + { + if (Sse41.IsSupported) + { + Vector128 asciiMaskForTestZ = Vector128.Create((ushort)0xFF80); + // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data. + return !Sse41.TestZ(utf16Vector.AsInt16(), asciiMaskForTestZ.AsInt16()); + } + else + { + Vector128 asciiMaskForAddSaturate = Vector128.Create((ushort)0x7F80); + // The operation below forces the 0x8000 bit of each WORD to be set iff the WORD element + // has value >= 0x0800 (non-ASCII). Then we'll treat the vector as a BYTE vector in order + // to extract the mask. Reminder: the 0x0080 bit of each WORD should be ignored. + return (Sse2.MoveMask(Sse2.AddSaturate(utf16Vector, asciiMaskForAddSaturate).AsByte()) & 0b_1010_1010_1010_1010) != 0; + } + } + else if (AdvSimd.Arm64.IsSupported) + { + // First we pick four chars, a larger one from all four pairs of adjecent chars in the vector. + // If any of those four chars has a non-ASCII bit set, we have seen non-ASCII data. + Vector128 maxChars = AdvSimd.Arm64.MaxPairwise(utf16Vector, utf16Vector); + return (maxChars.AsUInt64().ToScalar() & 0xFF80FF80FF80FF80) != 0; + } + else + { + const ushort asciiMask = ushort.MaxValue - 127; // 0xFF80 + Vector128 zeroIsAscii = utf16Vector & Vector128.Create(asciiMask); + // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data. + return zeroIsAscii != Vector128.Zero; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 ExtractAsciiVector(Vector128 vectorFirst, Vector128 vectorSecond) + { + // Narrows two vectors of words [ w7 w6 w5 w4 w3 w2 w1 w0 ] and [ w7' w6' w5' w4' w3' w2' w1' w0' ] + // to a vector of bytes [ b7 ... b0 b7' ... b0']. + + // prefer architecture specific intrinsic as they don't perform additional AND like Vector128.Narrow does + if (Sse2.IsSupported) + { + return Sse2.PackUnsignedSaturate(vectorFirst.AsInt16(), vectorSecond.AsInt16()); + } + else if (AdvSimd.Arm64.IsSupported) + { + return AdvSimd.Arm64.UnzipEven(vectorFirst.AsByte(), vectorSecond.AsByte()); + } + else if (PackedSimd.IsSupported) + { + return PackedSimd.ConvertNarrowingSaturateUnsigned(vectorFirst.AsInt16(), vectorSecond.AsInt16()); + } + else + { + return Vector128.Narrow(vectorFirst, vectorSecond); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool VectorContainsNonAsciiChar(Vector256 utf16Vector) + { + if (Avx.IsSupported) + { + Vector256 asciiMaskForTestZ = Vector256.Create((ushort)0xFF80); + return !Avx.TestZ(utf16Vector.AsInt16(), asciiMaskForTestZ.AsInt16()); + } + else + { + const ushort asciiMask = ushort.MaxValue - 127; // 0xFF80 + Vector256 zeroIsAscii = utf16Vector & Vector256.Create(asciiMask); + // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data. + return zeroIsAscii != Vector256.Zero; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool VectorContainsNonAsciiChar(Vector512 utf16Vector) + { + const ushort asciiMask = ushort.MaxValue - 127; // 0xFF80 + Vector512 zeroIsAscii = utf16Vector & Vector512.Create(asciiMask); + // If a non-ASCII bit is set in any WORD of the vector, we have seen non-ASCII data. + return zeroIsAscii != Vector512.Zero; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 ShuffleUnsafe(Vector128 vector, Vector128 indices) + { + if (Ssse3.IsSupported) + { + return Ssse3.Shuffle(vector, indices); + } + + if (AdvSimd.Arm64.IsSupported) + { + return AdvSimd.Arm64.VectorTableLookup(vector, indices); + } + + if (PackedSimd.IsSupported) + { + return PackedSimd.Swizzle(vector, indices); + } + + return Vector128.Shuffle(vector, indices); + } +#endif + internal interface IBase64Encoder where T : unmanaged { ReadOnlySpan EncodingMap { get; } @@ -86,9 +200,11 @@ internal interface IBase64Encoder where T : unmanaged unsafe void StoreVector512ToDestination(T* dest, T* destStart, int destLength, Vector512 str); unsafe void StoreVector256ToDestination(T* dest, T* destStart, int destLength, Vector256 str); unsafe void StoreVector128ToDestination(T* dest, T* destStart, int destLength, Vector128 str); +#if NET9_0_OR_GREATER unsafe void StoreArmVector128x4ToDestination(T* dest, T* destStart, int destLength, Vector128 res1, Vector128 res2, Vector128 res3, Vector128 res4); -#endif +#endif // NET9_0_OR_GREATER +#endif // NET } internal interface IBase64Decoder where T : unmanaged @@ -132,9 +248,11 @@ bool TryDecode256Core( unsafe bool TryLoadVector512(T* src, T* srcStart, int sourceLength, out Vector512 str); unsafe bool TryLoadAvxVector256(T* src, T* srcStart, int sourceLength, out Vector256 str); unsafe bool TryLoadVector128(T* src, T* srcStart, int sourceLength, out Vector128 str); +#if NET9_0_OR_GREATER unsafe bool TryLoadArmVector128x4(T* src, T* srcStart, int sourceLength, out Vector128 str1, out Vector128 str2, out Vector128 str3, out Vector128 str4); -#endif +#endif // NET9_0_OR_GREATER +#endif // NET unsafe int DecodeFourElements(T* source, ref sbyte decodingMap); unsafe int DecodeRemaining(T* srcEnd, ref sbyte decodingMap, long remaining, out uint t2, out uint t3); int IndexOfAnyExceptWhiteSpace(ReadOnlySpan span); diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlDecoder.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlDecoder.cs index ac03ef5847e39..7f11078b83053 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlDecoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlDecoder.cs @@ -490,8 +490,10 @@ public static byte[] DecodeFromChars(ReadOnlySpan source) #if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(Ssse3))] +#endif public bool TryDecode128Core( Vector128 str, Vector128 hiNibbles, @@ -527,7 +529,9 @@ public bool TryDecode128Core( } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public bool TryDecode256Core( Vector256 str, Vector256 hiNibbles, @@ -566,7 +570,9 @@ public unsafe bool TryLoadVector512(byte* src, byte* srcStart, int sourceLength, default(Base64DecoderByte).TryLoadVector512(src, srcStart, sourceLength, out str); [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public unsafe bool TryLoadAvxVector256(byte* src, byte* srcStart, int sourceLength, out Vector256 str) => default(Base64DecoderByte).TryLoadAvxVector256(src, srcStart, sourceLength, out str); @@ -574,12 +580,14 @@ public unsafe bool TryLoadAvxVector256(byte* src, byte* srcStart, int sourceLeng public unsafe bool TryLoadVector128(byte* src, byte* srcStart, int sourceLength, out Vector128 str) => default(Base64DecoderByte).TryLoadVector128(src, srcStart, sourceLength, out str); +#if NET9_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] public unsafe bool TryLoadArmVector128x4(byte* src, byte* srcStart, int sourceLength, out Vector128 str1, out Vector128 str2, out Vector128 str3, out Vector128 str4) => default(Base64DecoderByte).TryLoadArmVector128x4(src, srcStart, sourceLength, out str1, out str2, out str3, out str4); -#endif +#endif // NET9_0_OR_GREATER +#endif // NET [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int DecodeFourElements(byte* source, ref sbyte decodingMap) => @@ -634,14 +642,18 @@ public OperationStatus DecodeWithWhiteSpaceBlockwiseWrapper(TBas #if NET [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] [CompExactlyDependsOn(typeof(Ssse3))] +#endif public bool TryDecode128Core(Vector128 str, Vector128 hiNibbles, Vector128 maskSlashOrUnderscore, Vector128 mask8F, Vector128 lutLow, Vector128 lutHigh, Vector128 lutShift, Vector128 shiftForUnderscore, out Vector128 result) => default(Base64UrlDecoderByte).TryDecode128Core(str, hiNibbles, maskSlashOrUnderscore, mask8F, lutLow, lutHigh, lutShift, shiftForUnderscore, out result); [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public bool TryDecode256Core(Vector256 str, Vector256 hiNibbles, Vector256 maskSlashOrUnderscore, Vector256 lutLow, Vector256 lutHigh, Vector256 lutShift, Vector256 shiftForUnderscore, out Vector256 result) => default(Base64UrlDecoderByte).TryDecode256Core(str, hiNibbles, maskSlashOrUnderscore, lutLow, lutHigh, lutShift, shiftForUnderscore, out result); @@ -652,8 +664,11 @@ public unsafe bool TryLoadVector512(ushort* src, ushort* srcStart, int sourceLen AssertRead>(src, srcStart, sourceLength); Vector512 utf16VectorLower = Vector512.Load(src); Vector512 utf16VectorUpper = Vector512.Load(src + 32); - +#if NET9_0_OR_GREATER if (Ascii.VectorContainsNonAsciiChar(utf16VectorLower | utf16VectorUpper)) +#else + if (Base64Helper.VectorContainsNonAsciiChar(utf16VectorLower | utf16VectorUpper)) +#endif { str = default; return false; @@ -664,14 +679,20 @@ public unsafe bool TryLoadVector512(ushort* src, ushort* srcStart, int sourceLen } [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public unsafe bool TryLoadAvxVector256(ushort* src, ushort* srcStart, int sourceLength, out Vector256 str) { AssertRead>(src, srcStart, sourceLength); Vector256 utf16VectorLower = Avx.LoadVector256(src); Vector256 utf16VectorUpper = Avx.LoadVector256(src + 16); +#if NET9_0_OR_GREATER if (Ascii.VectorContainsNonAsciiChar(utf16VectorLower | utf16VectorUpper)) +#else + if (Base64Helper.VectorContainsNonAsciiChar(utf16VectorLower | utf16VectorUpper)) +#endif { str = default; return false; @@ -687,6 +708,7 @@ public unsafe bool TryLoadVector128(ushort* src, ushort* srcStart, int sourceLen AssertRead>(src, srcStart, sourceLength); Vector128 utf16VectorLower = Vector128.LoadUnsafe(ref *src); Vector128 utf16VectorUpper = Vector128.LoadUnsafe(ref *src, 8); +#if NET9_0_OR_GREATER if (Ascii.VectorContainsNonAsciiChar(utf16VectorLower | utf16VectorUpper)) { str = default; @@ -694,9 +716,18 @@ public unsafe bool TryLoadVector128(ushort* src, ushort* srcStart, int sourceLen } str = Ascii.ExtractAsciiVector(utf16VectorLower, utf16VectorUpper); +#else + if (Base64Helper.VectorContainsNonAsciiChar(utf16VectorLower | utf16VectorUpper)) + { + str = default; + return false; + } + + str = Base64Helper.ExtractAsciiVector(utf16VectorLower, utf16VectorUpper); +#endif return true; } - +#if NET9_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] public unsafe bool TryLoadArmVector128x4(ushort* src, ushort* srcStart, int sourceLength, @@ -719,7 +750,8 @@ public unsafe bool TryLoadArmVector128x4(ushort* src, ushort* srcStart, int sour return true; } -#endif +#endif // NET9_0_OR_GREATER +#endif // NET [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe int DecodeFourElements(ushort* source, ref sbyte decodingMap) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlEncoder.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlEncoder.cs index 675824b9b258b..ef95097f20635 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlEncoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlEncoder.cs @@ -291,7 +291,9 @@ public unsafe void StoreVector512ToDestination(byte* dest, byte* destStart, int default(Base64EncoderByte).StoreVector512ToDestination(dest, destStart, destLength, str); [MethodImpl(MethodImplOptions.AggressiveInlining)] +#if NET9_0_OR_GREATER [CompExactlyDependsOn(typeof(Avx2))] +#endif public unsafe void StoreVector256ToDestination(byte* dest, byte* destStart, int destLength, Vector256 str) => default(Base64EncoderByte).StoreVector256ToDestination(dest, destStart, destLength, str); @@ -299,12 +301,14 @@ public unsafe void StoreVector256ToDestination(byte* dest, byte* destStart, int public unsafe void StoreVector128ToDestination(byte* dest, byte* destStart, int destLength, Vector128 str) => default(Base64EncoderByte).StoreVector128ToDestination(dest, destStart, destLength, str); +#if NET9_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] public unsafe void StoreArmVector128x4ToDestination(byte* dest, byte* destStart, int destLength, Vector128 res1, Vector128 res2, Vector128 res3, Vector128 res4) => default(Base64EncoderByte).StoreArmVector128x4ToDestination(dest, destStart, destLength, res1, res2, res3, res4); -#endif +#endif // NET9_0_OR_GREATER +#endif // NET [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void EncodeThreeAndWrite(byte* threeBytes, byte* destination, ref byte encodingMap) => @@ -403,6 +407,7 @@ public unsafe void StoreVector128ToDestination(ushort* dest, ushort* destStart, utf16HighVector.Store(dest + Vector128.Count); } +#if NET9_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] [CompExactlyDependsOn(typeof(AdvSimd.Arm64))] public unsafe void StoreArmVector128x4ToDestination(ushort* dest, ushort* destStart, int destLength, @@ -416,7 +421,8 @@ public unsafe void StoreArmVector128x4ToDestination(ushort* dest, ushort* destSt AdvSimd.Arm64.StoreVectorAndZip(dest, (utf16LowVector1, utf16LowVector2, utf16LowVector3, utf16LowVector4)); AdvSimd.Arm64.StoreVectorAndZip(dest + 32, (utf16HighVector1, utf16HighVector2, utf16HighVector3, utf16HighVector4)); } -#endif +#endif // NET9_0_OR_GREATER +#endif // NET [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void EncodeThreeAndWrite(byte* threeBytes, ushort* destination, ref byte encodingMap) From a934fb863b7ad22afe1c2fd875876dfaa25f5380 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Wed, 10 Jul 2024 09:36:15 -0700 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Viktor Hofer --- .../Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj | 4 ++-- .../Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj | 6 +++--- .../tests/Microsoft.Bcl.Memory.Tests.csproj | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj index a74221d64dff0..98d9884ee14b2 100644 --- a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj @@ -4,11 +4,11 @@ netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppMinimum);$(NetCoreAppCurrent) - + - + diff --git a/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj b/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj index 57f4610a279db..da420d3e273b9 100644 --- a/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj @@ -22,10 +22,10 @@ - true + true - + @@ -34,7 +34,7 @@ - + System\Buffers\Text\Base64Helper\Base64Helper.cs diff --git a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj index 8aab11978e0ea..f4e7d308a5c74 100644 --- a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj @@ -39,7 +39,7 @@ - + From 195a80e15be47b55aa30218b52a59d34ca3f2e88 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Wed, 10 Jul 2024 11:11:28 -0700 Subject: [PATCH 3/3] Update src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj --- .../tests/Microsoft.Bcl.Memory.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj index f4e7d308a5c74..b7458269bedff 100644 --- a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj @@ -39,7 +39,7 @@ - +