未验证 提交 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
internal static unsafe void Memcpy(byte* dest, byte* src, int len)
{
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
......@@ -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(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)]
......
......@@ -31,7 +31,7 @@ public static Span<T> AsSpan<T>(this T[]? array, int start)
if ((uint)start > (uint)array.Length)
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>
......@@ -55,7 +55,7 @@ public static Span<T> AsSpan<T>(this T[]? array, Index startIndex)
if ((uint)actualIndex > (uint)array.Length)
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>
......@@ -79,7 +79,7 @@ public static Span<T> AsSpan<T>(this T[]? array, Range range)
ThrowHelper.ThrowArrayTypeMismatchException();
(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>
......@@ -118,7 +118,7 @@ public static ReadOnlySpan<char> AsSpan(this string? text, int start)
if ((uint)start > (uint)text.Length)
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>
......@@ -150,7 +150,7 @@ public static ReadOnlySpan<char> AsSpan(this string? text, int start, int length
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
#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>
......@@ -422,7 +422,7 @@ public static ReadOnlyMemory<char> AsMemory(this string? text, Range range)
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
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);
......@@ -912,7 +912,7 @@ public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other)
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
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);
......@@ -954,7 +954,7 @@ public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> o
return SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
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.
......@@ -1024,7 +1024,7 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
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);
......@@ -1044,7 +1044,7 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
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);
......@@ -1063,14 +1063,14 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= spanLength &&
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)),
((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 &&
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),
valueLength);
}
......@@ -1088,14 +1088,14 @@ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T
nuint size = (nuint)Unsafe.SizeOf<T>();
return valueLength <= spanLength &&
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)),
((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 &&
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),
valueLength);
}
......
......@@ -76,7 +76,7 @@ public ReadOnlySpan(T[]? array, int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#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;
}
......@@ -134,7 +134,7 @@ internal ReadOnlySpan(ref T ptr, int length)
{
if ((uint)index >= (uint)_length)
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)
if ((uint)start > (uint)_length)
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>
......@@ -358,7 +358,7 @@ public ReadOnlySpan<T> Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#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>
......@@ -372,7 +372,7 @@ public T[] ToArray()
return Array.Empty<T>();
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;
}
}
......
......@@ -81,7 +81,7 @@ public Span(T[]? array, int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#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;
}
......@@ -139,7 +139,7 @@ internal Span(ref T ptr, int length)
{
if ((uint)index >= (uint)_length)
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()
{
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
{
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)
if ((uint)start > (uint)_length)
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>
......@@ -417,7 +417,7 @@ public Span<T> Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#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>
......@@ -432,7 +432,7 @@ public T[] ToArray()
return Array.Empty<T>();
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;
}
}
......
......@@ -30,7 +30,7 @@ private static bool EqualsHelper(string strA, string strB)
return SpanHelpers.SequenceEqual(
ref Unsafe.As<char, byte>(ref strA.GetRawStringData()),
ref Unsafe.As<char, byte>(ref strB.GetRawStringData()),
((nuint)strA.Length) * 2);
((uint)strA.Length) * sizeof(char));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
......@@ -42,7 +42,9 @@ private static int CompareOrdinalHelper(string strA, int indexA, int countA, str
Debug.Assert(countA >= 0 && countB >= 0);
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)
......
......@@ -1747,7 +1747,7 @@ private string InternalSubString(int startIndex, int length)
Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
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;
}
......
......@@ -212,12 +212,12 @@ private static bool ArrayContains(char searchChar, char[] anyOf)
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)
{
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
}
#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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册