Skip to content

Commit

Permalink
Use non-generic Array.Sort in EnumInfo on nativeaot (#79473)
Browse files Browse the repository at this point in the history
* 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 <jkotas@microsoft.com>
  • Loading branch information
stephentoub and jkotas committed Dec 14, 2022
1 parent ef903fd commit 322f20c
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ public EnumInfo(Type underlyingType, TUnderlyingValue[] values, string[] names,
base(underlyingType, names, isFlags)
{
Debug.Assert(values.Length == names.Length);

Array.Sort(keys: values, items: names);
Debug.Assert(Enum.AreSorted(values));

Values = values;
ValuesAreSequentialFromZero = Enum.AreSequentialFromZero(values);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ namespace Internal.Reflection.Execution
{
static class NativeFormatEnumInfo
{
public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHandle typeHandle, MetadataReader reader, TypeDefinitionHandle typeDefHandle)
where TUnderlyingValue : struct, INumber<TUnderlyingValue>
private static void GetEnumValuesAndNames(MetadataReader reader, TypeDefinitionHandle typeDefHandle,
out object[] sortedBoxedValues, out string[] sortedNames, out bool isFlags)
{
TypeDefinition typeDef = reader.GetTypeDefinition(typeDefHandle);

Expand All @@ -30,8 +30,8 @@ public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHan
}
}

string[] names = new string[staticFieldCount];
TUnderlyingValue[] values = new TUnderlyingValue[staticFieldCount];
var names = new string[staticFieldCount];
var boxedValues = new object[staticFieldCount]; // TODO: Avoid boxing the values

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

bool isFlags = false;
// Using object overload to avoid generic expansion for every underlying enum type
Array.Sort<object, string>(boxedValues, names);

sortedBoxedValues = boxedValues;
sortedNames = names;

isFlags = false;
foreach (CustomAttributeHandle cah in typeDef.CustomAttributes)
{
if (cah.IsCustomAttributeOfType(reader, "System", "FlagsAttribute"))
isFlags = true;
}
}

public static EnumInfo<TUnderlyingValue> Create<TUnderlyingValue>(RuntimeTypeHandle typeHandle, MetadataReader reader, TypeDefinitionHandle typeDefHandle)
where TUnderlyingValue : struct, INumber<TUnderlyingValue>
{
GetEnumValuesAndNames(reader, typeDefHandle, out object[] boxedValues, out string[] names, out bool isFlags);

var values = new TUnderlyingValue[boxedValues.Length];
for (int i = 0; i < boxedValues.Length; i++)
values[i] = (TUnderlyingValue)boxedValues[i];

return new EnumInfo<TUnderlyingValue>(RuntimeAugments.GetEnumUnderlyingType(typeHandle), values, names, isFlags);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ public EnumInfo(bool hasFlagsAttribute, TUnderlyingValue[] values, string[] name
Values = values;
Names = names;

Array.Sort(keys: values, items: names);
if (!AreSorted(values))
{
Array.Sort(keys: values, items: names);
}

ValuesAreSequentialFromZero = AreSequentialFromZero(values);
}
Expand Down
13 changes: 13 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Enum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2293,5 +2293,18 @@ internal static bool AreSequentialFromZero<TUnderlyingValue>(TUnderlyingValue[]

return true;
}

internal static bool AreSorted<TUnderlyingValue>(TUnderlyingValue[] values) where TUnderlyingValue : struct, IComparable<TUnderlyingValue>
{
for (int i = 1; i < values.Length; i++)
{
if (values[i - 1].CompareTo(values[i]) > 0)
{
return false;
}
}

return true;
}
}
}

0 comments on commit 322f20c

Please sign in to comment.