未验证 提交 de591a85 编写于 作者: L Levi Broderick 提交者: GitHub

Avoid conv.i opcodes in hot paths in CoreLib (#51190)

上级 1983573f
...@@ -84,7 +84,7 @@ private static void _BulkMoveWithWriteBarrier(ref byte destination, ref byte sou ...@@ -84,7 +84,7 @@ private static void _BulkMoveWithWriteBarrier(ref byte destination, ref byte sou
internal static unsafe void Memcpy(byte* dest, byte* src, int len) internal static unsafe void Memcpy(byte* dest, byte* src, int len)
{ {
Debug.Assert(len >= 0, "Negative length in memcpy!"); Debug.Assert(len >= 0, "Negative length in memcpy!");
Memmove(ref *dest, ref *src, (nuint)len); Memmove(ref *dest, ref *src, (nuint)(uint)len /* force zero-extension */);
} }
// Used by ilmarshalers.cpp // Used by ilmarshalers.cpp
...@@ -93,7 +93,7 @@ internal static unsafe void Memcpy(byte* pDest, int destIndex, byte[] src, int s ...@@ -93,7 +93,7 @@ internal static unsafe void Memcpy(byte* pDest, int destIndex, byte[] src, int s
Debug.Assert((srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); Debug.Assert((srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
Debug.Assert(src.Length - srcIndex >= len, "not enough bytes in src"); Debug.Assert(src.Length - srcIndex >= len, "not enough bytes in src");
Memmove(ref *(pDest + destIndex), ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(src), srcIndex), (nuint)len); Memmove(ref *(pDest + (uint)destIndex), ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(src), (nint)(uint)srcIndex /* force zero-extension */), (uint)len);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
......
...@@ -31,7 +31,7 @@ public static Span<T> AsSpan<T>(this T[]? array, int start) ...@@ -31,7 +31,7 @@ public static Span<T> AsSpan<T>(this T[]? array, int start)
if ((uint)start > (uint)array.Length) if ((uint)start > (uint)array.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
return new Span<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), start), array.Length - start); return new Span<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */), array.Length - start);
} }
/// <summary> /// <summary>
...@@ -55,7 +55,7 @@ public static Span<T> AsSpan<T>(this T[]? array, Index startIndex) ...@@ -55,7 +55,7 @@ public static Span<T> AsSpan<T>(this T[]? array, Index startIndex)
if ((uint)actualIndex > (uint)array.Length) if ((uint)actualIndex > (uint)array.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
return new Span<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), actualIndex), array.Length - actualIndex); return new Span<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)actualIndex /* force zero-extension */), array.Length - actualIndex);
} }
/// <summary> /// <summary>
...@@ -79,7 +79,7 @@ public static Span<T> AsSpan<T>(this T[]? array, Range range) ...@@ -79,7 +79,7 @@ public static Span<T> AsSpan<T>(this T[]? array, Range range)
ThrowHelper.ThrowArrayTypeMismatchException(); ThrowHelper.ThrowArrayTypeMismatchException();
(int start, int length) = range.GetOffsetAndLength(array.Length); (int start, int length) = range.GetOffsetAndLength(array.Length);
return new Span<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), start), length); return new Span<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */), length);
} }
/// <summary> /// <summary>
...@@ -118,7 +118,7 @@ public static ReadOnlySpan<char> AsSpan(this string? text, int start) ...@@ -118,7 +118,7 @@ public static ReadOnlySpan<char> AsSpan(this string? text, int start)
if ((uint)start > (uint)text.Length) if ((uint)start > (uint)text.Length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
return new ReadOnlySpan<char>(ref Unsafe.Add(ref text.GetRawStringData(), start), text.Length - start); return new ReadOnlySpan<char>(ref Unsafe.Add(ref text.GetRawStringData(), (nint)(uint)start /* force zero-extension */), text.Length - start);
} }
/// <summary> /// <summary>
...@@ -150,7 +150,7 @@ public static ReadOnlySpan<char> AsSpan(this string? text, int start, int length ...@@ -150,7 +150,7 @@ public static ReadOnlySpan<char> AsSpan(this string? text, int start, int length
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
#endif #endif
return new ReadOnlySpan<char>(ref Unsafe.Add(ref text.GetRawStringData(), start), length); return new ReadOnlySpan<char>(ref Unsafe.Add(ref text.GetRawStringData(), (nint)(uint)start /* force zero-extension */), length);
} }
/// <summary>Creates a new <see cref="ReadOnlyMemory{T}"/> over the portion of the target string.</summary> /// <summary>Creates a new <see cref="ReadOnlyMemory{T}"/> over the portion of the target string.</summary>
...@@ -422,7 +422,7 @@ public static ReadOnlyMemory<char> AsMemory(this string? text, Range range) ...@@ -422,7 +422,7 @@ public static ReadOnlyMemory<char> AsMemory(this string? text, Range range)
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
((nuint)length) * size); // 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)length) * size); // 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 == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
...@@ -912,7 +912,7 @@ public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other) ...@@ -912,7 +912,7 @@ public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other)
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
((nuint)length) * size); // 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)length) * size); // 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 == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
...@@ -954,7 +954,7 @@ public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> o ...@@ -954,7 +954,7 @@ public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> o
return SpanHelpers.SequenceEqual( return SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
((nuint)span.Length) * size); // 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)span.Length) * size); // 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.
} }
// Otherwise, compare each element using EqualityComparer<T>.Default.Equals in a way that will enable it to devirtualize. // Otherwise, compare each element using EqualityComparer<T>.Default.Equals in a way that will enable it to devirtualize.
...@@ -1024,7 +1024,7 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T ...@@ -1024,7 +1024,7 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // 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)valueLength) * size); // 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 valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength); return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
...@@ -1044,7 +1044,7 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T ...@@ -1044,7 +1044,7 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // 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)valueLength) * size); // 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 valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength); return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
...@@ -1063,14 +1063,14 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T ...@@ -1063,14 +1063,14 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
nuint size = (nuint)Unsafe.SizeOf<T>(); nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= spanLength && return valueLength <= spanLength &&
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)), ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)(spanLength - valueLength) /* force zero-extension */)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // 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)valueLength) * size); // 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 valueLength <= spanLength && return valueLength <= spanLength &&
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength), ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)(spanLength - valueLength) /* force zero-extension */),
ref MemoryMarshal.GetReference(value), ref MemoryMarshal.GetReference(value),
valueLength); valueLength);
} }
...@@ -1088,14 +1088,14 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T ...@@ -1088,14 +1088,14 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
nuint size = (nuint)Unsafe.SizeOf<T>(); nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= spanLength && return valueLength <= spanLength &&
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)), ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)(spanLength - valueLength) /* force zero-extension */)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)), ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
((nuint)valueLength) * size); // 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)valueLength) * size); // 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 valueLength <= spanLength && return valueLength <= spanLength &&
SpanHelpers.SequenceEqual( SpanHelpers.SequenceEqual(
ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength), ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)(spanLength - valueLength) /* force zero-extension */),
ref MemoryMarshal.GetReference(value), ref MemoryMarshal.GetReference(value),
valueLength); valueLength);
} }
......
...@@ -76,7 +76,7 @@ public ReadOnlySpan(T[]? array, int start, int length) ...@@ -76,7 +76,7 @@ public ReadOnlySpan(T[]? array, int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
#endif #endif
_pointer = new ByReference<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), start)); _pointer = new ByReference<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */));
_length = length; _length = length;
} }
...@@ -134,7 +134,7 @@ internal ReadOnlySpan(ref T ptr, int length) ...@@ -134,7 +134,7 @@ internal ReadOnlySpan(ref T ptr, int length)
{ {
if ((uint)index >= (uint)_length) if ((uint)index >= (uint)_length)
ThrowHelper.ThrowIndexOutOfRangeException(); ThrowHelper.ThrowIndexOutOfRangeException();
return ref Unsafe.Add(ref _pointer.Value, index); return ref Unsafe.Add(ref _pointer.Value, (nint)(uint)index /* force zero-extension */);
} }
} }
...@@ -335,7 +335,7 @@ public ReadOnlySpan<T> Slice(int start) ...@@ -335,7 +335,7 @@ public ReadOnlySpan<T> Slice(int start)
if ((uint)start > (uint)_length) if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, start), _length - start); return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start);
} }
/// <summary> /// <summary>
...@@ -358,7 +358,7 @@ public ReadOnlySpan<T> Slice(int start, int length) ...@@ -358,7 +358,7 @@ public ReadOnlySpan<T> Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
#endif #endif
return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, start), length); return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), length);
} }
/// <summary> /// <summary>
...@@ -372,7 +372,7 @@ public T[] ToArray() ...@@ -372,7 +372,7 @@ public T[] ToArray()
return Array.Empty<T>(); return Array.Empty<T>();
var destination = new T[_length]; var destination = new T[_length];
Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _pointer.Value, (nuint)_length); Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _pointer.Value, (uint)_length);
return destination; return destination;
} }
} }
......
...@@ -81,7 +81,7 @@ public Span(T[]? array, int start, int length) ...@@ -81,7 +81,7 @@ public Span(T[]? array, int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
#endif #endif
_pointer = new ByReference<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), start)); _pointer = new ByReference<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */));
_length = length; _length = length;
} }
...@@ -139,7 +139,7 @@ internal Span(ref T ptr, int length) ...@@ -139,7 +139,7 @@ internal Span(ref T ptr, int length)
{ {
if ((uint)index >= (uint)_length) if ((uint)index >= (uint)_length)
ThrowHelper.ThrowIndexOutOfRangeException(); ThrowHelper.ThrowIndexOutOfRangeException();
return ref Unsafe.Add(ref _pointer.Value, index); return ref Unsafe.Add(ref _pointer.Value, (nint)(uint)index /* force zero-extension */);
} }
} }
...@@ -268,11 +268,11 @@ public unsafe void Clear() ...@@ -268,11 +268,11 @@ public unsafe void Clear()
{ {
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{ {
SpanHelpers.ClearWithReferences(ref Unsafe.As<T, IntPtr>(ref _pointer.Value), (nuint)_length * (nuint)(Unsafe.SizeOf<T>() / sizeof(nuint))); SpanHelpers.ClearWithReferences(ref Unsafe.As<T, IntPtr>(ref _pointer.Value), (uint)_length * (nuint)(Unsafe.SizeOf<T>() / sizeof(nuint)));
} }
else else
{ {
SpanHelpers.ClearWithoutReferences(ref Unsafe.As<T, byte>(ref _pointer.Value), (nuint)_length * (nuint)Unsafe.SizeOf<T>()); SpanHelpers.ClearWithoutReferences(ref Unsafe.As<T, byte>(ref _pointer.Value), (uint)_length * (nuint)Unsafe.SizeOf<T>());
} }
} }
...@@ -389,7 +389,7 @@ public Span<T> Slice(int start) ...@@ -389,7 +389,7 @@ public Span<T> Slice(int start)
if ((uint)start > (uint)_length) if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
return new Span<T>(ref Unsafe.Add(ref _pointer.Value, start), _length - start); return new Span<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start);
} }
/// <summary> /// <summary>
...@@ -417,7 +417,7 @@ public Span<T> Slice(int start, int length) ...@@ -417,7 +417,7 @@ public Span<T> Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException(); ThrowHelper.ThrowArgumentOutOfRangeException();
#endif #endif
return new Span<T>(ref Unsafe.Add(ref _pointer.Value, start), length); return new Span<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), length);
} }
/// <summary> /// <summary>
...@@ -432,7 +432,7 @@ public T[] ToArray() ...@@ -432,7 +432,7 @@ public T[] ToArray()
return Array.Empty<T>(); return Array.Empty<T>();
var destination = new T[_length]; var destination = new T[_length];
Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _pointer.Value, (nuint)_length); Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _pointer.Value, (uint)_length);
return destination; return destination;
} }
} }
......
...@@ -30,7 +30,7 @@ private static bool EqualsHelper(string strA, string strB) ...@@ -30,7 +30,7 @@ private static bool EqualsHelper(string strA, string strB)
return SpanHelpers.SequenceEqual( return SpanHelpers.SequenceEqual(
ref Unsafe.As<char, byte>(ref strA.GetRawStringData()), ref Unsafe.As<char, byte>(ref strA.GetRawStringData()),
ref Unsafe.As<char, byte>(ref strB.GetRawStringData()), ref Unsafe.As<char, byte>(ref strB.GetRawStringData()),
((nuint)strA.Length) * 2); ((uint)strA.Length) * sizeof(char));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
...@@ -42,7 +42,9 @@ private static int CompareOrdinalHelper(string strA, int indexA, int countA, str ...@@ -42,7 +42,9 @@ private static int CompareOrdinalHelper(string strA, int indexA, int countA, str
Debug.Assert(countA >= 0 && countB >= 0); Debug.Assert(countA >= 0 && countB >= 0);
Debug.Assert(indexA + countA <= strA.Length && indexB + countB <= strB.Length); Debug.Assert(indexA + countA <= strA.Length && indexB + countB <= strB.Length);
return SpanHelpers.SequenceCompareTo(ref Unsafe.Add(ref strA.GetRawStringData(), indexA), countA, ref Unsafe.Add(ref strB.GetRawStringData(), indexB), countB); return SpanHelpers.SequenceCompareTo(
ref Unsafe.Add(ref strA.GetRawStringData(), (nint)(uint)indexA /* force zero-extension */), countA,
ref Unsafe.Add(ref strB.GetRawStringData(), (nint)(uint)indexB /* force zero-extension */), countB);
} }
internal static bool EqualsOrdinalIgnoreCase(string? strA, string? strB) internal static bool EqualsOrdinalIgnoreCase(string? strA, string? strB)
......
...@@ -1747,7 +1747,7 @@ private string InternalSubString(int startIndex, int length) ...@@ -1747,7 +1747,7 @@ private string InternalSubString(int startIndex, int length)
Buffer.Memmove( Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar, destination: ref result._firstChar,
source: ref Unsafe.Add(ref _firstChar, startIndex)); source: ref Unsafe.Add(ref _firstChar, (nint)(uint)startIndex /* force zero-extension */));
return result; return result;
} }
......
...@@ -212,12 +212,12 @@ private static bool ArrayContains(char searchChar, char[] anyOf) ...@@ -212,12 +212,12 @@ private static bool ArrayContains(char searchChar, char[] anyOf)
private static unsafe bool IsCharBitSet(uint* charMap, byte value) private static unsafe bool IsCharBitSet(uint* charMap, byte value)
{ {
return (charMap[value & PROBABILISTICMAP_BLOCK_INDEX_MASK] & (1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT))) != 0; return (charMap[(uint)value & PROBABILISTICMAP_BLOCK_INDEX_MASK] & (1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT))) != 0;
} }
private static unsafe void SetCharBit(uint* charMap, byte value) private static unsafe void SetCharBit(uint* charMap, byte value)
{ {
charMap[value & PROBABILISTICMAP_BLOCK_INDEX_MASK] |= 1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT); charMap[(uint)value & PROBABILISTICMAP_BLOCK_INDEX_MASK] |= 1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT);
} }
/* /*
......
...@@ -403,7 +403,7 @@ internal bool TryGetSpan(int startIndex, int count, out ReadOnlySpan<char> slice ...@@ -403,7 +403,7 @@ internal bool TryGetSpan(int startIndex, int count, out ReadOnlySpan<char> slice
} }
#endif #endif
slice = new ReadOnlySpan<char>(ref Unsafe.Add(ref _firstChar, startIndex), count); slice = new ReadOnlySpan<char>(ref Unsafe.Add(ref _firstChar, (nint)(uint)startIndex /* force zero-extension */), count);
return true; return true;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册