Skip to content

Commit 0afa5b3

Browse files
jkotasstephentoub
authored andcommitted
Replace Unsafe.As with unmanaged pointers where possible
Reduces cost of the generic methods
1 parent 14b63c7 commit 0afa5b3

File tree

1 file changed

+61
-59
lines changed
  • src/libraries/System.Private.CoreLib/src/System

1 file changed

+61
-59
lines changed

src/libraries/System.Private.CoreLib/src/System/Enum.cs

+61-59
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
// to work well for them because the right behavior is often unclear, and it is hard to test and
1717
// very low value because such enums cannot be expressed in C# and are very rarely encountered.
1818

19+
#pragma warning disable 8500 // Allow taking address of managed types
20+
1921
namespace System
2022
{
2123
/// <summary>Provides the base class for enumerations.</summary>
@@ -34,25 +36,25 @@ public abstract partial class Enum : ValueType, IComparable, ISpanFormattable, I
3436
/// or <see langword="null"/> if no such constant is found.
3537
/// </returns>
3638
[MethodImpl(MethodImplOptions.AggressiveInlining)]
37-
public static string? GetName<TEnum>(TEnum value) where TEnum : struct, Enum
39+
public static unsafe string? GetName<TEnum>(TEnum value) where TEnum : struct, Enum
3840
{
3941
RuntimeType rt = (RuntimeType)typeof(TEnum);
4042
Type underlyingType = typeof(TEnum).GetEnumUnderlyingType();
4143

42-
if (underlyingType == typeof(int)) return GetNameInlined(GetEnumInfo<int>(rt), Unsafe.As<TEnum, int>(ref value));
43-
if (underlyingType == typeof(uint)) return GetNameInlined(GetEnumInfo<uint>(rt), Unsafe.As<TEnum, uint>(ref value));
44-
if (underlyingType == typeof(long)) return GetNameInlined(GetEnumInfo<long>(rt), Unsafe.As<TEnum, long>(ref value));
45-
if (underlyingType == typeof(ulong)) return GetNameInlined(GetEnumInfo<ulong>(rt), Unsafe.As<TEnum, ulong>(ref value));
46-
if (underlyingType == typeof(byte)) return GetNameInlined(GetEnumInfo<byte>(rt), Unsafe.As<TEnum, byte>(ref value));
47-
if (underlyingType == typeof(sbyte)) return GetNameInlined(GetEnumInfo<sbyte>(rt), Unsafe.As<TEnum, sbyte>(ref value));
48-
if (underlyingType == typeof(short)) return GetNameInlined(GetEnumInfo<short>(rt), Unsafe.As<TEnum, short>(ref value));
49-
if (underlyingType == typeof(ushort)) return GetNameInlined(GetEnumInfo<ushort>(rt), Unsafe.As<TEnum, ushort>(ref value));
50-
if (underlyingType == typeof(nint)) return GetNameInlined(GetEnumInfo<nint>(rt), Unsafe.As<TEnum, nint>(ref value));
51-
if (underlyingType == typeof(nuint)) return GetNameInlined(GetEnumInfo<nuint>(rt), Unsafe.As<TEnum, nuint>(ref value));
52-
if (underlyingType == typeof(char)) return GetNameInlined(GetEnumInfo<char>(rt), Unsafe.As<TEnum, char>(ref value));
53-
if (underlyingType == typeof(float)) return GetNameInlined(GetEnumInfo<float>(rt), Unsafe.As<TEnum, float>(ref value));
54-
if (underlyingType == typeof(double)) return GetNameInlined(GetEnumInfo<double>(rt), Unsafe.As<TEnum, double>(ref value));
55-
if (underlyingType == typeof(bool)) return GetNameInlined(GetEnumInfo<byte>(rt), Unsafe.As<TEnum, bool>(ref value) ? (byte)1 : (byte)0);
44+
if (underlyingType == typeof(int)) return GetNameInlined(GetEnumInfo<int>(rt), *(int*)&value);
45+
if (underlyingType == typeof(uint)) return GetNameInlined(GetEnumInfo<uint>(rt), *(uint*)&value);
46+
if (underlyingType == typeof(long)) return GetNameInlined(GetEnumInfo<long>(rt), *(long*)&value);
47+
if (underlyingType == typeof(ulong)) return GetNameInlined(GetEnumInfo<ulong>(rt), *(ulong*)&value);
48+
if (underlyingType == typeof(byte)) return GetNameInlined(GetEnumInfo<byte>(rt), *(byte*)&value);
49+
if (underlyingType == typeof(sbyte)) return GetNameInlined(GetEnumInfo<sbyte>(rt), *(sbyte*)&value);
50+
if (underlyingType == typeof(short)) return GetNameInlined(GetEnumInfo<short>(rt), *(short*)&value);
51+
if (underlyingType == typeof(ushort)) return GetNameInlined(GetEnumInfo<ushort>(rt), *(ushort*)&value);
52+
if (underlyingType == typeof(nint)) return GetNameInlined(GetEnumInfo<nint>(rt), *(nint*)&value);
53+
if (underlyingType == typeof(nuint)) return GetNameInlined(GetEnumInfo<nuint>(rt), *(nuint*)&value);
54+
if (underlyingType == typeof(char)) return GetNameInlined(GetEnumInfo<char>(rt), *(char*)&value);
55+
if (underlyingType == typeof(float)) return GetNameInlined(GetEnumInfo<float>(rt), *(float*)&value);
56+
if (underlyingType == typeof(double)) return GetNameInlined(GetEnumInfo<double>(rt), *(double*)&value);
57+
if (underlyingType == typeof(bool)) return GetNameInlined(GetEnumInfo<byte>(rt), *(bool*)&value ? (byte)1 : (byte)0);
5658

5759
throw CreateUnknownEnumTypeException();
5860
}
@@ -506,25 +508,25 @@ private static bool[] CopyByteArrayToNewBoolArray(byte[] bytes)
506508
/// <param name="value">The value or name of a constant in <typeparamref name="TEnum"/>.</param>
507509
/// <returns><see langword="true"/> if a given integral value exists in a specified enumeration; <see langword="false"/>, otherwise.</returns>
508510
[MethodImpl(MethodImplOptions.AggressiveInlining)]
509-
public static bool IsDefined<TEnum>(TEnum value) where TEnum : struct, Enum
511+
public static unsafe bool IsDefined<TEnum>(TEnum value) where TEnum : struct, Enum
510512
{
511513
RuntimeType rt = (RuntimeType)typeof(TEnum);
512514
Type underlyingType = typeof(TEnum).GetEnumUnderlyingType();
513515

514-
if (underlyingType == typeof(int)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, int>(ref value));
515-
if (underlyingType == typeof(uint)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, uint>(ref value));
516-
if (underlyingType == typeof(long)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, long>(ref value));
517-
if (underlyingType == typeof(ulong)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, ulong>(ref value));
518-
if (underlyingType == typeof(byte)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, byte>(ref value));
519-
if (underlyingType == typeof(sbyte)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, sbyte>(ref value));
520-
if (underlyingType == typeof(short)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, short>(ref value));
521-
if (underlyingType == typeof(ushort)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, ushort>(ref value));
522-
if (underlyingType == typeof(nint)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, nint>(ref value));
523-
if (underlyingType == typeof(nuint)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, nuint>(ref value));
524-
if (underlyingType == typeof(char)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, char>(ref value));
525-
if (underlyingType == typeof(float)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, float>(ref value));
526-
if (underlyingType == typeof(double)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, double>(ref value));
527-
if (underlyingType == typeof(bool)) return IsDefinedPrimitive(rt, Unsafe.As<TEnum, bool>(ref value) ? (byte)1 : (byte)0);
516+
if (underlyingType == typeof(int)) return IsDefinedPrimitive(rt, *(int*)&value);
517+
if (underlyingType == typeof(uint)) return IsDefinedPrimitive(rt, *(uint*)&value);
518+
if (underlyingType == typeof(long)) return IsDefinedPrimitive(rt, *(long*)&value);
519+
if (underlyingType == typeof(ulong)) return IsDefinedPrimitive(rt, *(ulong*)&value);
520+
if (underlyingType == typeof(byte)) return IsDefinedPrimitive(rt, *(byte*)&value);
521+
if (underlyingType == typeof(sbyte)) return IsDefinedPrimitive(rt, *(sbyte*)&value);
522+
if (underlyingType == typeof(short)) return IsDefinedPrimitive(rt, *(short*)&value);
523+
if (underlyingType == typeof(ushort)) return IsDefinedPrimitive(rt, *(ushort*)&value);
524+
if (underlyingType == typeof(nint)) return IsDefinedPrimitive(rt, *(nint*)&value);
525+
if (underlyingType == typeof(nuint)) return IsDefinedPrimitive(rt, *(nuint*)&value);
526+
if (underlyingType == typeof(char)) return IsDefinedPrimitive(rt, *(char*)&value);
527+
if (underlyingType == typeof(float)) return IsDefinedPrimitive(rt, *(float*)&value);
528+
if (underlyingType == typeof(double)) return IsDefinedPrimitive(rt, *(double*)&value);
529+
if (underlyingType == typeof(bool)) return IsDefinedPrimitive(rt, *(bool*)&value ? (byte)1 : (byte)0);
528530

529531
throw CreateUnknownEnumTypeException();
530532
}
@@ -1877,7 +1879,7 @@ public static unsafe bool TryFormat<TEnum>(TEnum value, Span<char> destination,
18771879
/// those constraints. It's a manual copy/paste right now to avoid pressure on the JIT's inlining mechanisms.
18781880
/// </remarks>
18791881
[MethodImpl(MethodImplOptions.AggressiveInlining)] // format is most frequently a constant, and we want it exposed to the implementation; this should be inlined automatically, anyway
1880-
internal static bool TryFormatUnconstrained<TEnum>(TEnum value, Span<char> destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.EnumFormat)] ReadOnlySpan<char> format = default)
1882+
internal static unsafe bool TryFormatUnconstrained<TEnum>(TEnum value, Span<char> destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.EnumFormat)] ReadOnlySpan<char> format = default)
18811883
{
18821884
Debug.Assert(typeof(TEnum).IsEnum);
18831885
Debug.Assert(value is not null);
@@ -1891,37 +1893,37 @@ internal static bool TryFormatUnconstrained<TEnum>(TEnum value, Span<char> desti
18911893
// be necessary for semantics inside of TryFormatPrimitiveNonDefault, so we can just do it here instead.
18921894
if (format.IsEmpty)
18931895
{
1894-
if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, int>(ref value), destination, out charsWritten);
1895-
if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, uint>(ref value), destination, out charsWritten);
1896-
if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, long>(ref value), destination, out charsWritten);
1897-
if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, ulong>(ref value), destination, out charsWritten);
1898-
if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, byte>(ref value), destination, out charsWritten);
1899-
if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, sbyte>(ref value), destination, out charsWritten);
1900-
if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, short>(ref value), destination, out charsWritten);
1901-
if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, ushort>(ref value), destination, out charsWritten);
1902-
if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, nint>(ref value), destination, out charsWritten);
1903-
if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, nuint>(ref value), destination, out charsWritten);
1904-
if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, char>(ref value), destination, out charsWritten);
1905-
if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, float>(ref value), destination, out charsWritten);
1906-
if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, Unsafe.As<TEnum, double>(ref value), destination, out charsWritten);
1907-
if (underlyingType == typeof(bool)) return TryFormatBool(rt, Unsafe.As<TEnum, bool>(ref value), destination, out charsWritten, format: default);
1896+
if (underlyingType == typeof(int)) return TryFormatPrimitiveDefault(rt, *(int*)&value, destination, out charsWritten);
1897+
if (underlyingType == typeof(uint)) return TryFormatPrimitiveDefault(rt, *(uint*)&value, destination, out charsWritten);
1898+
if (underlyingType == typeof(long)) return TryFormatPrimitiveDefault(rt, *(long*)&value, destination, out charsWritten);
1899+
if (underlyingType == typeof(ulong)) return TryFormatPrimitiveDefault(rt, *(ulong*)&value, destination, out charsWritten);
1900+
if (underlyingType == typeof(byte)) return TryFormatPrimitiveDefault(rt, *(byte*)&value, destination, out charsWritten);
1901+
if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveDefault(rt, *(sbyte*)&value, destination, out charsWritten);
1902+
if (underlyingType == typeof(short)) return TryFormatPrimitiveDefault(rt, *(short*)&value, destination, out charsWritten);
1903+
if (underlyingType == typeof(ushort)) return TryFormatPrimitiveDefault(rt, *(ushort*)&value, destination, out charsWritten);
1904+
if (underlyingType == typeof(nint)) return TryFormatPrimitiveDefault(rt, *(nint*)&value, destination, out charsWritten);
1905+
if (underlyingType == typeof(nuint)) return TryFormatPrimitiveDefault(rt, *(nuint*)&value, destination, out charsWritten);
1906+
if (underlyingType == typeof(char)) return TryFormatPrimitiveDefault(rt, *(char*)&value, destination, out charsWritten);
1907+
if (underlyingType == typeof(float)) return TryFormatPrimitiveDefault(rt, *(float*)&value, destination, out charsWritten);
1908+
if (underlyingType == typeof(double)) return TryFormatPrimitiveDefault(rt, *(double*)&value, destination, out charsWritten);
1909+
if (underlyingType == typeof(bool)) return TryFormatBool(rt, *(bool*)&value, destination, out charsWritten, format: default);
19081910
}
19091911
else
19101912
{
1911-
if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, int>(ref value), destination, out charsWritten, format);
1912-
if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, uint>(ref value), destination, out charsWritten, format);
1913-
if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, long>(ref value), destination, out charsWritten, format);
1914-
if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, ulong>(ref value), destination, out charsWritten, format);
1915-
if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, byte>(ref value), destination, out charsWritten, format);
1916-
if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, sbyte>(ref value), destination, out charsWritten, format);
1917-
if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, short>(ref value), destination, out charsWritten, format);
1918-
if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, ushort>(ref value), destination, out charsWritten, format);
1919-
if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, nint>(ref value), destination, out charsWritten, format);
1920-
if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, nuint>(ref value), destination, out charsWritten, format);
1921-
if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, char>(ref value), destination, out charsWritten, format);
1922-
if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, float>(ref value), destination, out charsWritten, format);
1923-
if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, Unsafe.As<TEnum, double>(ref value), destination, out charsWritten, format);
1924-
if (underlyingType == typeof(bool)) return TryFormatBool(rt, Unsafe.As<TEnum, bool>(ref value), destination, out charsWritten, format);
1913+
if (underlyingType == typeof(int)) return TryFormatPrimitiveNonDefault(rt, *(int*)&value, destination, out charsWritten, format);
1914+
if (underlyingType == typeof(uint)) return TryFormatPrimitiveNonDefault(rt, *(uint*)&value, destination, out charsWritten, format);
1915+
if (underlyingType == typeof(long)) return TryFormatPrimitiveNonDefault(rt, *(long*)&value, destination, out charsWritten, format);
1916+
if (underlyingType == typeof(ulong)) return TryFormatPrimitiveNonDefault(rt, *(ulong*)&value, destination, out charsWritten, format);
1917+
if (underlyingType == typeof(byte)) return TryFormatPrimitiveNonDefault(rt, *(byte*)&value, destination, out charsWritten, format);
1918+
if (underlyingType == typeof(sbyte)) return TryFormatPrimitiveNonDefault(rt, *(sbyte*)&value, destination, out charsWritten, format);
1919+
if (underlyingType == typeof(short)) return TryFormatPrimitiveNonDefault(rt, *(short*)&value, destination, out charsWritten, format);
1920+
if (underlyingType == typeof(ushort)) return TryFormatPrimitiveNonDefault(rt, *(ushort*)&value, destination, out charsWritten, format);
1921+
if (underlyingType == typeof(nint)) return TryFormatPrimitiveNonDefault(rt, *(nint*)&value, destination, out charsWritten, format);
1922+
if (underlyingType == typeof(nuint)) return TryFormatPrimitiveNonDefault(rt, *(nuint*)&value, destination, out charsWritten, format);
1923+
if (underlyingType == typeof(char)) return TryFormatPrimitiveNonDefault(rt, *(char*)&value, destination, out charsWritten, format);
1924+
if (underlyingType == typeof(float)) return TryFormatPrimitiveNonDefault(rt, *(float*)&value, destination, out charsWritten, format);
1925+
if (underlyingType == typeof(double)) return TryFormatPrimitiveNonDefault(rt, *(double*)&value, destination, out charsWritten, format);
1926+
if (underlyingType == typeof(bool)) return TryFormatBool(rt, *(bool*)&value, destination, out charsWritten, format);
19251927
}
19261928

19271929
throw CreateUnknownEnumTypeException();

0 commit comments

Comments
 (0)