Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 7d96540

Browse files
benaadamsjkotas
authored andcommitted
Fix string.strlen (dotnet/coreclr#22397)
* Add explanation comment Fixes #22393 Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
1 parent 5ecbdb3 commit 7d96540

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/Common/src/CoreLib/System/SpanHelpers.Byte.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,36 @@ public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
266266
offset += 1;
267267
}
268268

269+
// We get past SequentialScan only if IsHardwareAccelerated or intrinsic .IsSupported is true; and remain length is greater than Vector length.
270+
// However, we still have the redundant check to allow the JIT to see that the code is unreachable and eliminate it when the platform does not
271+
// have hardware accelerated. After processing Vector lengths we return to SequentialScan to finish any remaining.
269272
if (Avx2.IsSupported)
270273
{
271274
if ((int)(byte*)offset < length)
272275
{
276+
if ((((nuint)Unsafe.AsPointer(ref searchSpace) + (nuint)offset) & (nuint)(Vector256<byte>.Count - 1)) != 0)
277+
{
278+
// Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches
279+
// with no upper bound e.g. String.strlen.
280+
// Start with a check on Vector128 to align to Vector256, before moving to processing Vector256.
281+
// This ensures we do not fault across memory pages while searching for an end of string.
282+
Vector128<byte> values = Vector128.Create(value);
283+
Vector128<byte> search = LoadVector128(ref searchSpace, offset);
284+
285+
// Same method as below
286+
int matches = Sse2.MoveMask(Sse2.CompareEqual(values, search));
287+
if (matches == 0)
288+
{
289+
// Zero flags set so no matches
290+
offset += Vector128<byte>.Count;
291+
}
292+
else
293+
{
294+
// Find bitflag offset of first match and add to current offset
295+
return ((int)(byte*)offset) + BitOps.TrailingZeroCount(matches);
296+
}
297+
}
298+
273299
nLength = GetByteVector256SpanLength(offset, length);
274300
if ((byte*)nLength > (byte*)offset)
275301
{

0 commit comments

Comments
 (0)