Skip to content

Commit

Permalink
[interp] handle box + brtrue/brfalse and box+isinst+unbox.any pattern…
Browse files Browse the repository at this point in the history
…s up front (#103052)

* [interp] handle box + brtrue/brfalse pattern for byreflike types

   In cases where we don't do cprop and deadce (for example if `mono_interp_opt` is 0 because we're debugging) don't emit a box_vt opcode before a branch.  Instead just emit a constant true

   Fixes #102988

* Revert "Revert uses of Unsafe.BitCast with spans to unblock mono (#102998)"

   This reverts commit c286a8e.

   Reverts #102998

* remove the box byreflike retry code

   we handle box byreflike code patterns directly now

* handle box;isinst;{brtrue|brfalse|unbox.any} IL patterns

* Add test locking down mismatched box;isinst;unbox.any pattern

* remove the mismatch case in the interp.  throw IPE at execution time

* Update src/tests/Loader/classloader/generics/ByRefLike/Validate.cs

Co-authored-by: Aaron Robinson <[email protected]>

---------

Co-authored-by: Aaron Robinson <[email protected]>
  • Loading branch information
lambdageek and AaronRobinsonMSFT authored Jun 9, 2024
1 parent b5948bf commit f47b491
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 76 deletions.
4 changes: 2 additions & 2 deletions src/libraries/System.Linq/src/System/Linq/Sum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ private static TResult Sum<T, TResult>(ReadOnlySpan<T> span)

if (typeof(T) == typeof(long))
{
return (TResult)(object)SumSignedIntegersVectorized(MemoryMarshal.Cast<T, long>(span));
return (TResult)(object)SumSignedIntegersVectorized(Unsafe.BitCast<ReadOnlySpan<T>, ReadOnlySpan<long>>(span));
}
if (typeof(T) == typeof(int))
{
return (TResult)(object)SumSignedIntegersVectorized(MemoryMarshal.Cast<T, int>(span));
return (TResult)(object)SumSignedIntegersVectorized(Unsafe.BitCast<ReadOnlySpan<T>, ReadOnlySpan<int>>(span));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ private static void ValidateInputOutputSpanNonOverlapping<T>(ReadOnlySpan<T> inp
private static unsafe Span<TTo> Rename<TFrom, TTo>(Span<TFrom> span)
{
Debug.Assert(sizeof(TFrom) == sizeof(TTo));
#if NET9_0_OR_GREATER
return Unsafe.BitCast<Span<TFrom>, Span<TTo>>(span);
#else
return *(Span<TTo>*)(&span);
#endif
}

/// <summary>Creates a span of <typeparamref name="TTo"/> from a <typeparamref name="TFrom"/> when they're the same type.</summary>
Expand All @@ -48,7 +52,11 @@ private static unsafe Span<TTo> Rename<TFrom, TTo>(Span<TFrom> span)
private static unsafe ReadOnlySpan<TTo> Rename<TFrom, TTo>(ReadOnlySpan<TFrom> span)
{
Debug.Assert(sizeof(TFrom) == sizeof(TTo));
#if NET9_0_OR_GREATER
return Unsafe.BitCast<ReadOnlySpan<TFrom>, ReadOnlySpan<TTo>>(span);
#else
return *(ReadOnlySpan<TTo>*)(&span);
#endif
}

/// <summary>Mask used to handle alignment elements before vectorized handling of the input.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -763,12 +763,12 @@ private static void AppendString<TChar>(ref ValueListBuilder<TChar> result, scop
{
if (typeof(TChar) == typeof(char))
{
result.Append(MemoryMarshal.Cast<char, TChar>(s));
result.Append(Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(s));
}
else
{
Debug.Assert(typeof(TChar) == typeof(byte));
Encoding.UTF8.GetBytes(s, MemoryMarshal.Cast<TChar, byte>(result.AppendSpan(Encoding.UTF8.GetByteCount(s))));
Encoding.UTF8.GetBytes(s, Unsafe.BitCast<Span<TChar>, Span<byte>>(result.AppendSpan(Encoding.UTF8.GetByteCount(s))));
}
}

Expand All @@ -777,8 +777,8 @@ internal static void FormatFraction<TChar>(ref ValueListBuilder<TChar> result, i
Span<TChar> chars = stackalloc TChar[11];
int charCount;
bool formatted = typeof(TChar) == typeof(char) ?
fraction.TryFormat(MemoryMarshal.Cast<TChar, char>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture) :
fraction.TryFormat(MemoryMarshal.Cast<TChar, byte>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture);
fraction.TryFormat(Unsafe.BitCast<Span<TChar>, Span<char>>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture) :
fraction.TryFormat(Unsafe.BitCast<Span<TChar>, Span<byte>>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture);
Debug.Assert(charCount != 0);
result.Append(chars.Slice(0, charCount));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ internal ReadOnlySpan<TChar> AMDesignatorTChar<TChar>() where TChar : unmanaged,
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(AMDesignator) :
MemoryMarshal.Cast<byte, TChar>(amDesignatorUtf8 ??= Encoding.UTF8.GetBytes(AMDesignator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(AMDesignator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(amDesignatorUtf8 ??= Encoding.UTF8.GetBytes(AMDesignator));
}

public Calendar Calendar
Expand Down Expand Up @@ -607,8 +607,8 @@ internal ReadOnlySpan<TChar> DateSeparatorTChar<TChar>() where TChar : unmanaged
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(DateSeparator) :
MemoryMarshal.Cast<byte, TChar>(dateSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DateSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(DateSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(dateSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DateSeparator));
}

public DayOfWeek FirstDayOfWeek
Expand Down Expand Up @@ -810,8 +810,8 @@ internal ReadOnlySpan<TChar> PMDesignatorTChar<TChar>() where TChar : unmanaged,
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(PMDesignator) :
MemoryMarshal.Cast<byte, TChar>(pmDesignatorUtf8 ??= Encoding.UTF8.GetBytes(PMDesignator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(PMDesignator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(pmDesignatorUtf8 ??= Encoding.UTF8.GetBytes(PMDesignator));
}

public string RFC1123Pattern => rfc1123Pattern;
Expand Down Expand Up @@ -992,8 +992,8 @@ internal ReadOnlySpan<TChar> TimeSeparatorTChar<TChar>() where TChar : unmanaged
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(TimeSeparator) :
MemoryMarshal.Cast<byte, TChar>(timeSeparatorUtf8 ??= Encoding.UTF8.GetBytes(TimeSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(TimeSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(timeSeparatorUtf8 ??= Encoding.UTF8.GetBytes(TimeSeparator));
}

public string UniversalSortableDateTimePattern => universalSortableDateTimePattern;
Expand Down Expand Up @@ -1731,8 +1731,8 @@ internal ReadOnlySpan<TChar> DecimalSeparatorTChar<TChar>() where TChar : unmana
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(DecimalSeparator) :
MemoryMarshal.Cast<byte, TChar>(_decimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DecimalSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(DecimalSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_decimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DecimalSeparator));
}

// Positive TimeSpan Pattern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ internal ReadOnlySpan<TChar> CurrencyDecimalSeparatorTChar<TChar>() where TChar
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_currencyDecimalSeparator) :
MemoryMarshal.Cast<byte, TChar>(_currencyDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyDecimalSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_currencyDecimalSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_currencyDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyDecimalSeparator));
}

public bool IsReadOnly => _isReadOnly;
Expand Down Expand Up @@ -361,8 +361,8 @@ internal ReadOnlySpan<TChar> CurrencyGroupSeparatorTChar<TChar>() where TChar :
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_currencyGroupSeparator) :
MemoryMarshal.Cast<byte, TChar>(_currencyGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyGroupSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_currencyGroupSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_currencyGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyGroupSeparator));
}

public string CurrencySymbol
Expand All @@ -383,8 +383,8 @@ internal ReadOnlySpan<TChar> CurrencySymbolTChar<TChar>() where TChar : unmanage
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_currencySymbol) :
MemoryMarshal.Cast<byte, TChar>(_currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_currencySymbol) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol));
}

internal byte[]? CurrencySymbolUtf8 => _currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol);
Expand Down Expand Up @@ -429,8 +429,8 @@ internal ReadOnlySpan<TChar> NaNSymbolTChar<TChar>() where TChar : unmanaged, IU
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_nanSymbol) :
MemoryMarshal.Cast<byte, TChar>(_nanSymbolUtf8 ??= Encoding.UTF8.GetBytes(_nanSymbol));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_nanSymbol) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_nanSymbolUtf8 ??= Encoding.UTF8.GetBytes(_nanSymbol));
}

public int CurrencyNegativePattern
Expand Down Expand Up @@ -514,8 +514,8 @@ internal ReadOnlySpan<TChar> NegativeInfinitySymbolTChar<TChar>() where TChar :
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_negativeInfinitySymbol) :
MemoryMarshal.Cast<byte, TChar>(_negativeInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_negativeInfinitySymbol));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_negativeInfinitySymbol) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_negativeInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_negativeInfinitySymbol));
}

public string NegativeSign
Expand All @@ -537,8 +537,8 @@ internal ReadOnlySpan<TChar> NegativeSignTChar<TChar>() where TChar : unmanaged,
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_negativeSign) :
MemoryMarshal.Cast<byte, TChar>(_negativeSignUtf8 ??= Encoding.UTF8.GetBytes(_negativeSign));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_negativeSign) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_negativeSignUtf8 ??= Encoding.UTF8.GetBytes(_negativeSign));
}

public int NumberDecimalDigits
Expand Down Expand Up @@ -573,8 +573,8 @@ internal ReadOnlySpan<TChar> NumberDecimalSeparatorTChar<TChar>() where TChar :
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_numberDecimalSeparator) :
MemoryMarshal.Cast<byte, TChar>(_numberDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberDecimalSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_numberDecimalSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_numberDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberDecimalSeparator));
}

public string NumberGroupSeparator
Expand All @@ -594,8 +594,8 @@ internal ReadOnlySpan<TChar> NumberGroupSeparatorTChar<TChar>() where TChar : un
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_numberGroupSeparator) :
MemoryMarshal.Cast<byte, TChar>(_numberGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberGroupSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_numberGroupSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_numberGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberGroupSeparator));
}

public int CurrencyPositivePattern
Expand Down Expand Up @@ -631,8 +631,8 @@ internal ReadOnlySpan<TChar> PositiveInfinitySymbolTChar<TChar>() where TChar :
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_positiveInfinitySymbol) :
MemoryMarshal.Cast<byte, TChar>(_positiveInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_positiveInfinitySymbol));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_positiveInfinitySymbol) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_positiveInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_positiveInfinitySymbol));
}

public string PositiveSign
Expand All @@ -654,8 +654,8 @@ internal ReadOnlySpan<TChar> PositiveSignTChar<TChar>() where TChar : unmanaged,
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_positiveSign) :
MemoryMarshal.Cast<byte, TChar>(_positiveSignUtf8 ??= Encoding.UTF8.GetBytes(_positiveSign));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_positiveSign) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_positiveSignUtf8 ??= Encoding.UTF8.GetBytes(_positiveSign));
}

public int PercentDecimalDigits
Expand Down Expand Up @@ -690,8 +690,8 @@ internal ReadOnlySpan<TChar> PercentDecimalSeparatorTChar<TChar>() where TChar :
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_percentDecimalSeparator) :
MemoryMarshal.Cast<byte, TChar>(_percentDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentDecimalSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_percentDecimalSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_percentDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentDecimalSeparator));
}

public string PercentGroupSeparator
Expand All @@ -711,8 +711,8 @@ internal ReadOnlySpan<TChar> PercentGroupSeparatorTChar<TChar>() where TChar : u
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_percentGroupSeparator) :
MemoryMarshal.Cast<byte, TChar>(_percentGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentGroupSeparator));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_percentGroupSeparator) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_percentGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentGroupSeparator));
}

public string PercentSymbol
Expand All @@ -732,8 +732,8 @@ internal ReadOnlySpan<TChar> PercentSymbolTChar<TChar>() where TChar : unmanaged
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_percentSymbol) :
MemoryMarshal.Cast<byte, TChar>(_percentSymbolUtf8 ??= Encoding.UTF8.GetBytes(_percentSymbol));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_percentSymbol) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_percentSymbolUtf8 ??= Encoding.UTF8.GetBytes(_percentSymbol));
}

public string PerMilleSymbol
Expand All @@ -754,8 +754,8 @@ internal ReadOnlySpan<TChar> PerMilleSymbolTChar<TChar>() where TChar : unmanage
{
Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte));
return typeof(TChar) == typeof(char) ?
MemoryMarshal.Cast<char, TChar>(_perMilleSymbol) :
MemoryMarshal.Cast<byte, TChar>(_perMilleSymbolUtf8 ??= Encoding.UTF8.GetBytes(_perMilleSymbol));
Unsafe.BitCast<ReadOnlySpan<char>, ReadOnlySpan<TChar>>(_perMilleSymbol) :
Unsafe.BitCast<ReadOnlySpan<byte>, ReadOnlySpan<TChar>>(_perMilleSymbolUtf8 ??= Encoding.UTF8.GetBytes(_perMilleSymbol));
}

public string[] NativeDigits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ private static bool TryCopyTo<TChar>(string source, Span<TChar> destination, out

if (typeof(TChar) == typeof(char))
{
if (source.TryCopyTo(MemoryMarshal.Cast<TChar, char>(destination)))
if (source.TryCopyTo(Unsafe.BitCast<Span<TChar>, Span<char>>(destination)))
{
charsWritten = source.Length;
return true;
Expand All @@ -632,7 +632,7 @@ private static bool TryCopyTo<TChar>(string source, Span<TChar> destination, out
}
else
{
return Encoding.UTF8.TryGetBytes(source, MemoryMarshal.Cast<TChar, byte>(destination), out charsWritten);
return Encoding.UTF8.TryGetBytes(source, Unsafe.BitCast<Span<TChar>, Span<byte>>(destination), out charsWritten);
}
}

Expand Down
Loading

0 comments on commit f47b491

Please sign in to comment.