diff --git a/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs b/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs index a6e5e3a3fe975..bd3a854f39a64 100644 --- a/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs +++ b/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs @@ -31,7 +31,6 @@ namespace System.Collections.Generic // LowLevelList with no interface implementation minimizes both code and data size. // Data size is smaller because there will be minimal virtual function table. // Code size is smaller because only functions called will be in the binary. - // Use LowLevelListWithIList for IList support [DebuggerDisplay("Count = {Count}")] #if TYPE_LOADER_IMPLEMENTATION [System.Runtime.CompilerServices.ForceDictionaryLookups] @@ -196,356 +195,5 @@ private void EnsureCapacity(int min) Capacity = newCapacity; } } - -#if !TYPE_LOADER_IMPLEMENTATION - // Adds the elements of the given collection to the end of this list. If - // required, the capacity of the list is increased to twice the previous - // capacity or the new size, whichever is larger. - // - public void AddRange(IEnumerable collection) - { - - InsertRange(_size, collection); - } - - // Clears the contents of List. - public void Clear() - { - if (_size > 0) - { - Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references. - _size = 0; - } - _version++; - } - - // Contains returns true if the specified element is in the List. - // It does a linear, O(n) search. Equality is determined by calling - // item.Equals(). - // - public bool Contains(T item) - { - if ((object?)item == null) - { - for (int i = 0; i < _size; i++) - if ((object?)_items[i] == null) - return true; - return false; - } - else - { - int index = IndexOf(item); - if (index >= 0) - return true; - return false; - } - } - - - // Copies a section of this list to the given array at the given index. - // - // The method uses the Array.Copy method to copy the elements. - // - public void CopyTo(int index, T[] array, int arrayIndex, int count) - { - if (_size - index < count) - { - throw new ArgumentException(); - } - - // Delegate rest of error checking to Array.Copy. - Array.Copy(_items, index, array, arrayIndex, count); - } - - public void CopyTo(T[] array, int arrayIndex) - { - // Delegate rest of error checking to Array.Copy. - Array.Copy(_items, 0, array, arrayIndex, _size); - } - - // Returns the index of the first occurrence of a given value in a range of - // this list. The list is searched forwards from beginning to end. - // The elements of the list are compared to the given value using the - // Object.Equals method. - // - // This method uses the Array.IndexOf method to perform the - // search. - // - public int IndexOf(T item) - { - return Array.IndexOf(_items, item, 0, _size); - } - - - // Returns the index of the first occurrence of a given value in a range of - // this list. The list is searched forwards, starting at index - // index and ending at count number of elements. The - // elements of the list are compared to the given value using the - // Object.Equals method. - // - // This method uses the Array.IndexOf method to perform the - // search. - // - public int IndexOf(T item, int index) - { - ArgumentOutOfRangeException.ThrowIfGreaterThan(index, _size); - return Array.IndexOf(_items, item, index, _size - index); - } - - // Inserts an element into this list at a given index. The size of the list - // is increased by one. If required, the capacity of the list is doubled - // before inserting the new element. - // - public void Insert(int index, T item) - { - // Note that insertions at the end are legal. - ArgumentOutOfRangeException.ThrowIfGreaterThan((uint)index, (uint)_size, nameof(index)); - - if (_size == _items.Length) EnsureCapacity(_size + 1); - if (index < _size) - { - Array.Copy(_items, index, _items, index + 1, _size - index); - } - _items[index] = item; - _size++; - _version++; - } - - // Inserts the elements of the given collection at a given index. If - // required, the capacity of the list is increased to twice the previous - // capacity or the new size, whichever is larger. Ranges may be added - // to the end of the list by setting index to the List's size. - // - public void InsertRange(int index, IEnumerable collection) - { - ArgumentNullException.ThrowIfNull(collection); - ArgumentOutOfRangeException.ThrowIfGreaterThan((uint)index, (uint)_size, nameof(index)); - - ICollection? c = collection as ICollection; - if (c != null) - { // if collection is ICollection - int count = c.Count; - if (count > 0) - { - EnsureCapacity(_size + count); - if (index < _size) - { - Array.Copy(_items, index, _items, index + count, _size - index); - } - - // If we're inserting a List into itself, we want to be able to deal with that. - if (this == c) - { - // Copy first part of _items to insert location - Array.Copy(_items, 0, _items, index, index); - // Copy last part of _items back to inserted location - Array.Copy(_items, index + count, _items, index * 2, _size - index); - } - else - { - T[] itemsToInsert = new T[count]; - c.CopyTo(itemsToInsert, 0); - Array.Copy(itemsToInsert, 0, _items, index, count); - } - _size += count; - } - } - else - { - using (IEnumerator en = collection.GetEnumerator()) - { - while (en.MoveNext()) - { - Insert(index++, en.Current); - } - } - } - _version++; - } - - // Removes the element at the given index. The size of the list is - // decreased by one. - // - public bool Remove(T item) - { - int index = IndexOf(item); - if (index >= 0) - { - RemoveAt(index); - return true; - } - - return false; - } - - // This method removes all items which matches the predicate. - // The complexity is O(n). - public int RemoveAll(Predicate match) - { - ArgumentNullException.ThrowIfNull(match); - - int freeIndex = 0; // the first free slot in items array - - // Find the first item which needs to be removed. - while (freeIndex < _size && !match(_items[freeIndex]!)) freeIndex++; - if (freeIndex >= _size) return 0; - - int current = freeIndex + 1; - while (current < _size) - { - // Find the first item which needs to be kept. - while (current < _size && match(_items[current]!)) current++; - - if (current < _size) - { - // copy item to the free slot. - _items[freeIndex++] = _items[current++]; - } - } - - Array.Clear(_items, freeIndex, _size - freeIndex); - int result = _size - freeIndex; - _size = freeIndex; - _version++; - return result; - } - - // Removes the element at the given index. The size of the list is - // decreased by one. - // - public void RemoveAt(int index) - { - ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)_size, nameof(index)); - _size--; - if (index < _size) - { - Array.Copy(_items, index + 1, _items, index, _size - index); - } - _items[_size] = default!; - _version++; - } - - // ToArray returns a new Object array containing the contents of the List. - // This requires copying the List, which is an O(n) operation. - public T[] ToArray() - { - T[] array = new T[_size]; - Array.Copy(_items, 0, array, 0, _size); - return array; - } -#endif - } - -#if !TYPE_LOADER_IMPLEMENTATION - // LowLevelList with full IList implementation - internal sealed class LowLevelListWithIList : LowLevelList, IList - { - public LowLevelListWithIList() - { - } - - public LowLevelListWithIList(int capacity) - : base(capacity) - { - } - - public LowLevelListWithIList(IEnumerable collection) - : base(collection) - { - } - - // Is this List read-only? - bool ICollection.IsReadOnly - { - get { return false; } - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return new Enumerator(this); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return new Enumerator(this); - } - - private struct Enumerator : IEnumerator, System.Collections.IEnumerator - { - private LowLevelListWithIList _list; - private int _index; - private int _version; - private T? _current; - - internal Enumerator(LowLevelListWithIList list) - { - _list = list; - _index = 0; - _version = list._version; - _current = default(T); - } - - public void Dispose() - { - } - - public bool MoveNext() - { - LowLevelListWithIList localList = _list; - - if (_version == localList._version && ((uint)_index < (uint)localList._size)) - { - _current = localList._items[_index]; - _index++; - return true; - } - return MoveNextRare(); - } - - private bool MoveNextRare() - { - if (_version != _list._version) - { - throw new InvalidOperationException(); - } - - _index = _list._size + 1; - _current = default(T); - return false; - } - - public T Current - { - get - { - return _current!; - } - } - - object? System.Collections.IEnumerator.Current - { - get - { - if (_index == 0 || _index == _list._size + 1) - { - throw new InvalidOperationException(); - } - return Current; - } - } - - void System.Collections.IEnumerator.Reset() - { - if (_version != _list._version) - { - throw new InvalidOperationException(); - } - - _index = 0; - _current = default(T); - } - } } -#endif // !TYPE_LOADER_IMPLEMENTATION } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs index a619095037b5c..b68c2234d88fa 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs @@ -135,18 +135,23 @@ private static Attribute OneOrNull(IEnumerable results) Justification = "Arrays of reference types are safe to create.")] private static Attribute[] Instantiate(IEnumerable cads, Type actualElementType) { - LowLevelList attributes = new LowLevelList(); + ArrayBuilder attributes = default; foreach (CustomAttributeData cad in cads) { Attribute instantiatedAttribute = cad.Instantiate(); attributes.Add(instantiatedAttribute); } - int count = attributes.Count; - Attribute[] result = actualElementType.ContainsGenericParameters - ? new Attribute[count] - : (Attribute[])Array.CreateInstance(actualElementType, count); - attributes.CopyTo(result, 0); - return result; + + if (actualElementType.ContainsGenericParameters) + { + return attributes.ToArray(); + } + else + { + Attribute[] result = (Attribute[])Array.CreateInstance(actualElementType, attributes.Count); + attributes.CopyTo(result); + return result; + } } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs index 10c49ffe177bb..e7a7202b0400c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs @@ -116,7 +116,7 @@ internal sealed override IList GetConstructorArgum } Handle[] ctorTypeHandles = parameterTypeSignatureHandles.ToArray(); - LowLevelListWithIList customAttributeTypedArguments = new LowLevelListWithIList(); + ArrayBuilder customAttributeTypedArguments = new ArrayBuilder(_customAttribute.FixedArguments.Count); foreach (Handle fixedArgumentHandle in _customAttribute.FixedArguments) { Handle typeHandle = ctorTypeHandles[index]; @@ -147,7 +147,7 @@ internal sealed override IList GetConstructorArgum index++; } - return customAttributeTypedArguments; + return customAttributeTypedArguments.ToArray(); } // @@ -155,7 +155,7 @@ internal sealed override IList GetConstructorArgum // internal sealed override IList GetNamedArguments(bool throwIfMissingMetadata) { - LowLevelListWithIList customAttributeNamedArguments = new LowLevelListWithIList(); + ArrayBuilder customAttributeNamedArguments = new ArrayBuilder(_customAttribute.NamedArguments.Count); foreach (NamedArgumentHandle namedArgumentHandle in _customAttribute.NamedArguments) { NamedArgument namedArgument = namedArgumentHandle.GetNamedArgument(_reader); @@ -185,7 +185,7 @@ internal sealed override IList GetNamedArguments(b customAttributeNamedArguments.Add(CreateCustomAttributeNamedArgument(this.AttributeType, memberName, isField, typedValue)); } - return customAttributeNamedArguments; + return customAttributeNamedArguments.ToArray(); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs index 12b0cde3b166f..12b6000851694 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs @@ -171,13 +171,13 @@ protected static CustomAttributeTypedArgument WrapInCustomAttributeTypedArgument if (!argumentType.IsArray) throw new BadImageFormatException(); Type reportedElementType = argumentType.GetElementType()!; - LowLevelListWithIList elementTypedArguments = new LowLevelListWithIList(); + ArrayBuilder elementTypedArguments = default; foreach (object elementValue in enumerableValue) { CustomAttributeTypedArgument elementTypedArgument = WrapInCustomAttributeTypedArgument(elementValue, reportedElementType); elementTypedArguments.Add(elementTypedArgument); } - return new CustomAttributeTypedArgument(argumentType, new ReadOnlyCollection(elementTypedArguments)); + return new CustomAttributeTypedArgument(argumentType, new ReadOnlyCollection(elementTypedArguments.ToArray())); } else { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs index abe62427fb1dd..b6d019046c388 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs @@ -151,22 +151,26 @@ public static BinderBundle ToBinderBundle(this Binder binder, BindingFlags invok Justification = "Array.CreateInstance is only used with reference types here and is therefore safe.")] public static object[] InstantiateAsArray(this IEnumerable cads, Type actualElementType) { - LowLevelList attributes = new LowLevelList(); + ArrayBuilder attributes = default; foreach (CustomAttributeData cad in cads) { object instantiatedAttribute = cad.Instantiate(); attributes.Add(instantiatedAttribute); } - // This is here for desktop compatibility. ICustomAttribute.GetCustomAttributes() normally returns an array of the - // exact attribute type requested except in two cases: when the passed in type is an open type and when - // it is a value type. In these two cases, it returns an array of type Object[]. - bool useObjectArray = actualElementType.ContainsGenericParameters || actualElementType.IsValueType; - int count = attributes.Count; - object[] result = useObjectArray ? new object[count] : (object[])Array.CreateInstance(actualElementType, count); - - attributes.CopyTo(result, 0); - return result; + if (actualElementType.ContainsGenericParameters || actualElementType.IsValueType) + { + // This is here for desktop compatibility. ICustomAttribute.GetCustomAttributes() normally returns an array of the + // exact attribute type requested except in two cases: when the passed in type is an open type and when + // it is a value type. In these two cases, it returns an array of type Object[]. + return attributes.ToArray(); + } + else + { + object[] result = (object[])Array.CreateInstance(actualElementType, attributes.Count); + attributes.CopyTo(result); + return result; + } } private static object? GetRawDefaultValue(IEnumerable customAttributes) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs index f9f89d7343575..46ad09d02bf66 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs @@ -79,20 +79,21 @@ internal static Type[] GetCustomModifiers(this Handle handle, MetadataReader rea if (handleType != HandleType.ModifiedType) return Array.Empty(); - LowLevelList customModifiers = new LowLevelList(); + ArrayBuilder customModifiers = default; do { NativeFormatModifiedType modifiedType = handle.ToModifiedTypeHandle(reader).GetModifiedType(reader); if (optional == modifiedType.IsOptional) { Type customModifier = modifiedType.ModifierType.Resolve(reader, typeContext).ToType(); - customModifiers.Insert(0, customModifier); + customModifiers.Add(customModifier); } handle = modifiedType.Type; handleType = handle.HandleType; } while (handleType == HandleType.ModifiedType); + customModifiers.AsSpan().Reverse(); return customModifiers.ToArray(); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs index 44be913b0195c..3aed59328d502 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs @@ -138,7 +138,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle RuntimeTypeInfo? genericTypeDefinition = sig.GenericType.TryResolve(reader, typeContext, ref exception); if (genericTypeDefinition == null) return null; - LowLevelList genericTypeArguments = new LowLevelList(); + ArrayBuilder genericTypeArguments = new ArrayBuilder(sig.GenericTypeArguments.Count); foreach (Handle genericTypeArgumentHandle in sig.GenericTypeArguments) { RuntimeTypeInfo? genericTypeArgument = genericTypeArgumentHandle.TryResolve(reader, typeContext, ref exception); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs index a64e338004eae..c3090aa47eb10 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs @@ -73,7 +73,7 @@ protected sealed override QTypeDefRefOrSpec[] Constraints get { MetadataReader reader = Reader; - LowLevelList constraints = new LowLevelList(); + ArrayBuilder constraints = new ArrayBuilder(_genericParameter.Constraints.Count); foreach (Handle constraintHandle in _genericParameter.Constraints) { // We're skipping custom modifiers here because Roslyn generates diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs index 23c0aab5638c4..65f2c3597ecc2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs @@ -199,7 +199,7 @@ internal sealed override RuntimeTypeInfo[] RuntimeGenericTypeParameters { get { - LowLevelList genericTypeParameters = new LowLevelList(); + ArrayBuilder genericTypeParameters = new ArrayBuilder(_typeDefinition.GenericParameters.Count); foreach (GenericParameterHandle genericParameterHandle in _typeDefinition.GenericParameters) { @@ -233,7 +233,7 @@ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImpleme { get { - LowLevelList directlyImplementedInterfaces = new LowLevelList(); + ArrayBuilder directlyImplementedInterfaces = new ArrayBuilder(_typeDefinition.Interfaces.Count); foreach (Handle ifcHandle in _typeDefinition.Interfaces) directlyImplementedInterfaces.Add(new QTypeDefRefOrSpec(_reader, ifcHandle)); return directlyImplementedInterfaces.ToArray(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs index 3462bde38cf7a..478193a4400c9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs @@ -152,8 +152,8 @@ internal sealed override QTypeDefRefOrSpec[] TypeRefDefOrSpecsForDirectlyImpleme { get { - LowLevelList result = new LowLevelList(); QTypeDefRefOrSpec[] constraints = Constraints; + ArrayBuilder result = new ArrayBuilder(constraints.Length); RuntimeTypeInfo[] constraintInfos = ConstraintInfos; for (int i = 0; i < constraints.Length; i++) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs index 5383dc1f8ed68..7a8621c1bd1e5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs @@ -266,7 +266,7 @@ internal abstract partial class RuntimeTypeInfo { #region Lookup Methods MethodInfo[] semiFinalists = (MethodInfo[])GetMember(name, MemberTypes.Method, bindingFlags); - LowLevelListWithIList? results = null; + ArrayBuilder results = default; for (int i = 0; i < semiFinalists.Length; i++) { @@ -282,9 +282,8 @@ internal abstract partial class RuntimeTypeInfo } else { - if (results == null) + if (results.Count == 0) { - results = new LowLevelListWithIList(semiFinalists.Length); results.Add(finalist); } @@ -292,11 +291,9 @@ internal abstract partial class RuntimeTypeInfo } } - if (results != null) + if (results.Count > 0) { - Debug.Assert(results.Count > 1); - finalists = new MethodInfo[results.Count]; - results.CopyTo(finalists, 0); + finalists = results.ToArray(); } #endregion } @@ -309,7 +306,7 @@ internal abstract partial class RuntimeTypeInfo { #region Lookup Property PropertyInfo[] semiFinalists = (PropertyInfo[])GetMember(name, MemberTypes.Property, bindingFlags); - LowLevelListWithIList? results = null; + ArrayBuilder results = default; for (int i = 0; i < semiFinalists.Length; i++) { @@ -340,9 +337,8 @@ internal abstract partial class RuntimeTypeInfo } else { - if (results == null) + if (results.Count == 0) { - results = new LowLevelListWithIList(semiFinalists.Length); results.Add(finalist); } @@ -350,11 +346,9 @@ internal abstract partial class RuntimeTypeInfo } } - if (results != null) + if (results.Count > 0) { - Debug.Assert(results.Count > 1); - finalists = new MethodInfo[results.Count]; - results.CopyTo(finalists, 0); + finalists = results.ToArray(); } #endregion } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 34319199651d9..fd9fba5b7d12e 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -591,7 +591,7 @@ private static FunctionPointersToOffsets ComputeLdftnReverseLookup_InvokeMap(Nat NativeParser invokeMapParser = new NativeParser(invokeMapReader, 0); NativeHashtable invokeHashtable = new NativeHashtable(invokeMapParser); - LowLevelList functionPointers = new LowLevelList(); + ArrayBuilder functionPointers = default; var lookup = invokeHashtable.EnumerateAllEntries(); NativeParser entryParser; diff --git a/src/coreclr/tools/Common/Internal/LowLevelLinq/LowLevelEnumerable.ToArray.cs b/src/coreclr/tools/Common/Internal/LowLevelLinq/LowLevelEnumerable.ToArray.cs index 6d28c01316adc..e9bb5c90898f0 100644 --- a/src/coreclr/tools/Common/Internal/LowLevelLinq/LowLevelEnumerable.ToArray.cs +++ b/src/coreclr/tools/Common/Internal/LowLevelLinq/LowLevelEnumerable.ToArray.cs @@ -13,12 +13,12 @@ public static T[] ToArray(this IEnumerable values) { Debug.Assert(values != null); - LowLevelList list = new LowLevelList(); + ArrayBuilder arrayBuilder = default; foreach (T value in values) { - list.Add(value); + arrayBuilder.Add(value); } - return list.ToArray(); + return arrayBuilder.ToArray(); } } } diff --git a/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs b/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs index 0005f54747827..c947e2c762ff6 100644 --- a/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs +++ b/src/coreclr/tools/Common/System/Collections/Generic/ArrayBuilder.cs @@ -15,6 +15,11 @@ internal struct ArrayBuilder private T[] _items; private int _count; + public ArrayBuilder(int capacity) + { + _items = new T[capacity]; + } + public T[] ToArray() { if (_items == null) @@ -24,6 +29,15 @@ public T[] ToArray() return _items; } + public void CopyTo(T[] destination) + { + if (_items != null) + { + // Use Array.Copy instead of Span.CopyTo to handle covariant destination + Array.Copy(_items, destination, _count); + } + } + public void Add(T item) { if (_items == null || _count == _items.Length) @@ -32,7 +46,9 @@ public void Add(T item) } #if NET - public readonly Span AsSpan(int start) => _items.AsSpan(start); + public readonly Span AsSpan() => _items.AsSpan(0, _count); + + public readonly Span AsSpan(int start) => _items.AsSpan(start, _count - start); public Span AppendSpan(int length) {