diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.net8.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.net8.cs index 08f72de280193c..cd761c9a3f4e7d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.net8.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.net8.cs @@ -2,7 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; namespace System.Text.Json { @@ -19,7 +22,32 @@ internal static partial class JsonReaderHelper "\\"u8); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int IndexOfQuoteOrAnyControlOrBackSlash(this ReadOnlySpan span) => + public static int IndexOfQuoteOrAnyControlOrBackSlash(this ReadOnlySpan span) + { + // For most inputs, we have a large span and we typically find a match within the first 16 bytes + // Usually, it's a quote in a property name. + if (!Vector128.IsHardwareAccelerated || !BitConverter.IsLittleEndian || span.Length < Vector128.Count) + return IndexOfQuoteOrAnyControlOrBackSlash_Fallback(span); + + Vector128 vec = Vector128.Create(span); + + // Any control character (i.e. 0 to 31) or '"' or '\' + Vector128 cmp = Vector128.LessThan(vec, Vector128.Create(JsonConstants.Space)) | + Vector128.Equals(vec, Vector128.Create(JsonConstants.Quote)) | + Vector128.Equals(vec, Vector128.Create(JsonConstants.BackSlash)); + + int idx = Vector128.IndexOfWhereAllBitsSet(cmp); + if (idx >= 0) + { + return idx; + } + + int fallbackIndex = IndexOfQuoteOrAnyControlOrBackSlash_Fallback(span.Slice(Vector128.Count)); + return fallbackIndex >= 0 ? fallbackIndex + Vector128.Count : fallbackIndex; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int IndexOfQuoteOrAnyControlOrBackSlash_Fallback(ReadOnlySpan span) => span.IndexOfAny(s_controlQuoteBackslash); } }