Skip to content

Commit 322f20c

Browse files
stephentoubjkotas
andauthored
Use non-generic Array.Sort in EnumInfo on nativeaot (#79473)
* Use non-generic Array.Sort in EnumInfo on nativeaot * Non-generic sort * Update src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/NativeFormatEnumInfo.cs Co-authored-by: Jan Kotas <[email protected]>
1 parent ef903fd commit 322f20c

File tree

4 files changed

+40
-9
lines changed

4 files changed

+40
-9
lines changed

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/EnumInfo.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ public EnumInfo(Type underlyingType, TUnderlyingValue[] values, string[] names,
3333
base(underlyingType, names, isFlags)
3434
{
3535
Debug.Assert(values.Length == names.Length);
36-
37-
Array.Sort(keys: values, items: names);
36+
Debug.Assert(Enum.AreSorted(values));
3837

3938
Values = values;
4039
ValuesAreSequentialFromZero = Enum.AreSequentialFromZero(values);

src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/NativeFormatEnumInfo.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ namespace Internal.Reflection.Execution
1313
{
1414
static class NativeFormatEnumInfo
1515
{
16-
public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHandle typeHandle, MetadataReader reader, TypeDefinitionHandle typeDefHandle)
17-
where TUnderlyingValue : struct, INumber<TUnderlyingValue>
16+
private static void GetEnumValuesAndNames(MetadataReader reader, TypeDefinitionHandle typeDefHandle,
17+
out object[] sortedBoxedValues, out string[] sortedNames, out bool isFlags)
1818
{
1919
TypeDefinition typeDef = reader.GetTypeDefinition(typeDefHandle);
2020

@@ -30,8 +30,8 @@ public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHan
3030
}
3131
}
3232

33-
string[] names = new string[staticFieldCount];
34-
TUnderlyingValue[] values = new TUnderlyingValue[staticFieldCount];
33+
var names = new string[staticFieldCount];
34+
var boxedValues = new object[staticFieldCount]; // TODO: Avoid boxing the values
3535

3636
int i = 0;
3737
foreach (FieldHandle fieldHandle in typeDef.Fields)
@@ -40,17 +40,33 @@ public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHan
4040
if (0 != (field.Flags & FieldAttributes.Static))
4141
{
4242
names[i] = field.Name.GetString(reader);
43-
values[i] = (TUnderlyingValue)field.DefaultValue.ParseConstantNumericValue(reader);
43+
boxedValues[i] = field.DefaultValue.ParseConstantNumericValue(reader);
4444
i++;
4545
}
4646
}
4747

48-
bool isFlags = false;
48+
// Using object overload to avoid generic expansion for every underlying enum type
49+
Array.Sort<object, string>(boxedValues, names);
50+
51+
sortedBoxedValues = boxedValues;
52+
sortedNames = names;
53+
54+
isFlags = false;
4955
foreach (CustomAttributeHandle cah in typeDef.CustomAttributes)
5056
{
5157
if (cah.IsCustomAttributeOfType(reader, "System", "FlagsAttribute"))
5258
isFlags = true;
5359
}
60+
}
61+
62+
public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHandle typeHandle, MetadataReader reader, TypeDefinitionHandle typeDefHandle)
63+
where TUnderlyingValue : struct, INumber<TUnderlyingValue>
64+
{
65+
GetEnumValuesAndNames(reader, typeDefHandle, out object[] boxedValues, out string[] names, out bool isFlags);
66+
67+
var values = new TUnderlyingValue[boxedValues.Length];
68+
for (int i = 0; i < boxedValues.Length; i++)
69+
values[i] = (TUnderlyingValue)boxedValues[i];
5470

5571
return new EnumInfo<TUnderlyingValue>(RuntimeAugments.GetEnumUnderlyingType(typeHandle), values, names, isFlags);
5672
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ public EnumInfo(bool hasFlagsAttribute, TUnderlyingValue[] values, string[] name
2222
Values = values;
2323
Names = names;
2424

25-
Array.Sort(keys: values, items: names);
25+
if (!AreSorted(values))
26+
{
27+
Array.Sort(keys: values, items: names);
28+
}
2629

2730
ValuesAreSequentialFromZero = AreSequentialFromZero(values);
2831
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,5 +2293,18 @@ internal static bool AreSequentialFromZero<TUnderlyingValue>(TUnderlyingValue[]
22932293

22942294
return true;
22952295
}
2296+
2297+
internal static bool AreSorted<TUnderlyingValue>(TUnderlyingValue[] values) where TUnderlyingValue : struct, IComparable<TUnderlyingValue>
2298+
{
2299+
for (int i = 1; i < values.Length; i++)
2300+
{
2301+
if (values[i - 1].CompareTo(values[i]) > 0)
2302+
{
2303+
return false;
2304+
}
2305+
}
2306+
2307+
return true;
2308+
}
22962309
}
22972310
}

0 commit comments

Comments
 (0)