From c853fc119fba66a5f49e45e0b34e596a470c57a7 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 20 Sep 2023 23:26:02 -0400 Subject: [PATCH] Change GetParametersNoCopy to GetParametersAsSpan and use it in a few more places (#92310) * Change GetParametersNoCopy to GetParametersAsSpan and use it in a few more places The internal GetParametersNoCopy avoids a defensive ParameterInfo[] copy, but it requires the callers to promise not to mutate the array. I'm changing the method to return a `ReadOnlySpan`, which means a caller can't mutate it without using unsafe code, and enabling the compiler to flag any misuse. I've then used it in a few more places. We might subsequently want to consider exposing it publicly. * Update src/libraries/Common/src/System/Runtime/InteropServices/ComEventsMethod.cs --- .../Runtime/InteropServices/ComActivator.cs | 2 +- .../src/System/Attribute.CoreCLR.cs | 3 +-- .../src/System/Delegate.CoreCLR.cs | 2 +- .../Reflection/Emit/DynamicILGenerator.cs | 4 +-- .../Reflection/Emit/RuntimeModuleBuilder.cs | 2 +- .../System/Reflection/MethodBase.CoreCLR.cs | 2 +- .../RuntimeConstructorInfo.CoreCLR.cs | 15 +++-------- .../Reflection/RuntimeCustomAttributeData.cs | 4 +-- .../src/System/Reflection/RuntimeEventInfo.cs | 8 ++++-- .../Reflection/RuntimeMethodInfo.CoreCLR.cs | 2 +- .../System/Reflection/RuntimePropertyInfo.cs | 25 +++++------------- .../src/System/RuntimeType.CoreCLR.cs | 7 +++-- .../src/CompatibilitySuppressions.xml | 2 +- .../CustomAttributeInheritanceRules.cs | 2 +- .../CustomAttributeInstantiator.cs | 6 ++--- .../src/System/ActivatorImplementation.cs | 2 +- .../System/Reflection/ConstructorInvoker.cs | 2 +- .../System/Reflection/DynamicInvokeInfo.cs | 4 +-- .../System/Reflection/MethodBase.NativeAot.cs | 2 +- .../src/System/Reflection/MethodInvoker.cs | 2 +- .../BindingFlagSupport/MemberPolicies.cs | 4 +-- .../Runtime/BindingFlagSupport/Shared.cs | 2 +- .../RuntimeCustomAttributeData.cs | 2 +- .../Runtime/EventInfos/RuntimeEventInfo.cs | 2 +- .../ReflectionCoreCallbacksImplementation.cs | 2 +- .../Runtime/MethodInfos/CustomMethodMapper.cs | 2 +- .../MethodInfos/RuntimeConstructorInfo.cs | 2 +- .../Runtime/MethodInfos/RuntimeMethodInfo.cs | 16 +++++------- .../TypeInfos/RuntimeTypeInfo.BindingFlags.cs | 3 +-- .../TypeInfos/RuntimeTypeInfo.InvokeMember.cs | 2 +- ...EnvironmentImplementation.MappingTables.cs | 10 +++---- .../MissingMetadataExceptionCreator.cs | 2 +- .../TypeLoader/ConstraintValidatorSupport.cs | 2 +- .../src/System/AppDomain.cs | 2 +- .../src/System/DefaultBinder.cs | 26 +++++++++---------- .../src/System/Diagnostics/StackTrace.cs | 8 +++--- .../System/Reflection/Emit/DynamicMethod.cs | 11 +++----- .../src/System/Reflection/EventInfo.cs | 2 +- .../src/System/Reflection/InvokerEmitUtil.cs | 6 ++--- .../src/System/Reflection/MethodBase.cs | 2 +- .../System/Reflection/MethodBaseInvoker.cs | 2 +- .../Reflection/NullabilityInfoContext.cs | 6 ++--- .../src/System/Reflection/ParameterInfo.cs | 8 +++--- .../src/System/RuntimeType.cs | 2 +- .../src/System/StartupHookProvider.cs | 2 +- .../src/System/Delegate.Mono.cs | 8 +++--- .../src/System/Reflection/CustomAttribute.cs | 2 +- .../Reflection/Emit/DynamicMethod.Mono.cs | 2 +- .../src/System/Reflection/MethodBase.Mono.cs | 2 +- .../Reflection/RuntimeMethodInfo.Mono.cs | 2 +- .../System/Reflection/RuntimeParameterInfo.cs | 2 +- .../src/System/RuntimeType.Mono.cs | 8 +++--- 52 files changed, 112 insertions(+), 140 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs index 6d2fff235fa7d..db8d4ead4659b 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs @@ -201,7 +201,7 @@ private static void ClassRegistrationScenarioForType(ComActivationContext cxt, b } // Finally validate signature - ParameterInfo[] methParams = method.GetParameters(); + ReadOnlySpan methParams = method.GetParametersAsSpan(); if (method.ReturnType != typeof(void) || methParams == null || methParams.Length != 1 diff --git a/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs index 9365f8ba0b869..7fbb594a1844d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs @@ -227,8 +227,7 @@ private static bool InternalIsDefined(EventInfo element, Type attributeType, boo } else { - ParameterInfo[] parameters = rtMethod.GetParameters(); - return parameters[position]; // Point to the correct ParameterInfo of the method + return rtMethod.GetParametersAsSpan()[position]; // Point to the correct ParameterInfo of the method } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs index 7fd8ed40d57b8..555b40216b735 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -200,7 +200,7 @@ protected virtual MethodInfo GetMethodImpl() { // it's an open one, need to fetch the first arg of the instantiation MethodInfo invoke = this.GetType().GetMethod("Invoke")!; - declaringType = (RuntimeType)invoke.GetParameters()[0].ParameterType; + declaringType = (RuntimeType)invoke.GetParametersAsSpan()[0].ParameterType; } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs index ad564aad7e3dd..81372c76ce2ec 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -94,7 +94,7 @@ public override void Emit(OpCode opcode, MethodInfo meth) } if (opcode.StackBehaviourPop == StackBehaviour.Varpop) { - stackchange -= meth.GetParametersNoCopy().Length; + stackchange -= meth.GetParametersAsSpan().Length; } // Pop the "this" parameter if the method is non-static, // and the instruction is not newobj/ldtoken/ldftn. @@ -416,7 +416,7 @@ private int GetMemberRefToken(MethodInfo methodInfo, Type[]? optionalParameterTy if (rtMeth == null && dm == null) throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, nameof(methodInfo)); - ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy(); + ReadOnlySpan paramInfo = methodInfo.GetParametersAsSpan(); if (paramInfo != null && paramInfo.Length != 0) { parameterTypes = new Type[paramInfo.Length]; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeModuleBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeModuleBuilder.cs index 496c24bb105ae..4fd4bd49c88a8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeModuleBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeModuleBuilder.cs @@ -458,7 +458,7 @@ internal SignatureHelper GetMemberRefSignature(MethodBase? method, int cGenericP } Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); - ParameterInfo[] parameters = method.GetParametersNoCopy(); + ReadOnlySpan parameters = method.GetParametersAsSpan(); Type[] parameterTypes = new Type[parameters.Length]; Type[][] requiredCustomModifiers = new Type[parameterTypes.Length][]; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs index e8bb0fa181493..26383704e3927 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs @@ -47,7 +47,7 @@ public abstract partial class MethodBase : MemberInfo // used by EE private IntPtr GetMethodDesc() { return MethodHandle.Value; } - internal virtual ParameterInfo[] GetParametersNoCopy() { return GetParameters(); } + internal virtual ReadOnlySpan GetParametersAsSpan() { return GetParameters(); } #endregion } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs index 500581553a3cb..c16d10e97b38d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs @@ -180,20 +180,11 @@ public override IList GetCustomAttributesData() // This seems to always returns System.Void. internal override Type GetReturnType() { return Signature.ReturnType; } - internal override ParameterInfo[] GetParametersNoCopy() => + internal override ReadOnlySpan GetParametersAsSpan() => m_parameters ??= RuntimeParameterInfo.GetParameters(this, this, Signature); - public override ParameterInfo[] GetParameters() - { - ParameterInfo[] parameters = GetParametersNoCopy(); - - if (parameters.Length == 0) - return parameters; - - ParameterInfo[] ret = new ParameterInfo[parameters.Length]; - Array.Copy(parameters, ret, parameters.Length); - return ret; - } + public override ParameterInfo[] GetParameters() => + GetParametersAsSpan().ToArray(); public override MethodImplAttributes GetMethodImplementationFlags() { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index ce9182cc4785b..434f50a7370a1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -278,7 +278,7 @@ private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToke m_ctor = (RuntimeConstructorInfo)scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo(); } - ParameterInfo[] parameters = m_ctor.GetParametersNoCopy(); + ReadOnlySpan parameters = m_ctor.GetParametersAsSpan(); if (parameters.Length != 0) { m_ctorParams = new CustomAttributeCtorParameter[parameters.Length]; @@ -412,7 +412,7 @@ private void Init(object pca) // Ensure there is only a single constructor for 'pca', so it is safe to suppress IL2075 ConstructorInfo[] allCtors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Debug.Assert(allCtors.Length == 1); - Debug.Assert(allCtors[0].GetParameters().Length == 0); + Debug.Assert(allCtors[0].GetParametersAsSpan().Length == 0); #endif m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0]; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs index 2f69ff6b0c009..34b5f378cbdbb 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs @@ -63,10 +63,14 @@ o is RuntimeEventInfo m && #region Object Overrides public override string ToString() { - if (m_addMethod == null || m_addMethod.GetParametersNoCopy().Length == 0) + ReadOnlySpan parameters; + if (m_addMethod == null || + (parameters = m_addMethod.GetParametersAsSpan()).Length == 0) + { throw new InvalidOperationException(SR.InvalidOperation_NoPublicAddMethod); + } - return m_addMethod.GetParametersNoCopy()[0].ParameterType.FormatTypeName() + " " + Name; + return parameters[0].ParameterType.FormatTypeName() + " " + Name; } public override bool Equals(object? obj) => diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index 1fd8da7fe5f66..de60e189ac918 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -240,7 +240,7 @@ public override Type? ReflectedType #endregion #region MethodBase Overrides - internal override ParameterInfo[] GetParametersNoCopy() => + internal override ReadOnlySpan GetParametersAsSpan() => FetchNonReturnParameters(); public override ParameterInfo[] GetParameters() diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index eb83e8f410d6c..933e05d0bf785 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -261,23 +261,10 @@ public override MethodInfo[] GetAccessors(bool nonPublic) return m_setterMethod; } - public override ParameterInfo[] GetIndexParameters() - { - ParameterInfo[] indexParams = GetIndexParametersNoCopy(); - - int numParams = indexParams.Length; - - if (numParams == 0) - return indexParams; - - ParameterInfo[] ret = new ParameterInfo[numParams]; - - Array.Copy(indexParams, ret, numParams); - - return ret; - } + public override ParameterInfo[] GetIndexParameters() => + GetIndexParametersSpan().ToArray(); - internal ParameterInfo[] GetIndexParametersNoCopy() + internal ReadOnlySpan GetIndexParametersSpan() { // @History - Logic ported from RTM @@ -285,14 +272,14 @@ internal ParameterInfo[] GetIndexParametersNoCopy() if (m_parameters == null) { int numParams = 0; - ParameterInfo[]? methParams = null; + ReadOnlySpan methParams = default; // First try to get the Get method. RuntimeMethodInfo? m = GetGetMethod(true); if (m != null) { // There is a Get method so use it. - methParams = m.GetParametersNoCopy(); + methParams = m.GetParametersAsSpan(); numParams = methParams.Length; } else @@ -302,7 +289,7 @@ internal ParameterInfo[] GetIndexParametersNoCopy() if (m != null) { - methParams = m.GetParametersNoCopy(); + methParams = m.GetParametersAsSpan(); numParams = methParams.Length - 1; } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 959489be1c7bb..e7e8b2508a851 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -2290,7 +2290,7 @@ private static bool FilterApplyMethodBase( // Check if argumentTypes supplied if (argumentTypes != null) { - ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); + ReadOnlySpan parameterInfos = methodBase.GetParametersAsSpan(); if (argumentTypes.Length != parameterInfos.Length) { @@ -2848,8 +2848,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn { ConstructorInfo firstCandidate = candidates[0]; - ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy(); - if (parameters == null || parameters.Length == 0) + if (firstCandidate.GetParametersAsSpan().IsEmpty) { return firstCandidate; } @@ -3817,7 +3816,7 @@ private void CreateInstanceCheckThis() throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, FullName)); } - if (invokeMethod.GetParametersNoCopy().Length == 0) + if (invokeMethod.GetParametersAsSpan().Length == 0) { if (args.Length != 0) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 9065c20bb8371..173a55afbadd5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -938,7 +938,7 @@ CP0002 - M:System.Reflection.MethodBase.GetParametersNoCopy + M:System.Reflection.MethodBase.GetParametersAsSpan CP0002 diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs index 56259b1b89521..bb7d373739edc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInheritanceRules.cs @@ -235,7 +235,7 @@ public sealed override ParameterInfo GetParent(ParameterInfo e) if (e.Position >= 0) { - return methodParent.GetParametersNoCopy()[e.Position]; + return methodParent.GetParametersAsSpan()[e.Position]; } else { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs index 1d29f98859935..8c1ee196f32ea 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs @@ -40,11 +40,11 @@ public static Attribute Instantiate(this CustomAttributeData cad) // Find the public constructor that matches the supplied arguments. // ConstructorInfo? matchingCtor = null; - ParameterInfo[]? matchingParameters = null; + ReadOnlySpan matchingParameters = default; IList constructorArguments = cad.ConstructorArguments; foreach (ConstructorInfo ctor in attributeType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { - ParameterInfo[] parameters = ctor.GetParametersNoCopy(); + ReadOnlySpan parameters = ctor.GetParametersAsSpan(); if (parameters.Length != constructorArguments.Count) continue; int i; @@ -68,7 +68,7 @@ public static Attribute Instantiate(this CustomAttributeData cad) // // Found the right constructor. Instantiate the Attribute. // - int arity = matchingParameters!.Length; + int arity = matchingParameters.Length; object?[] invokeArguments = new object[arity]; for (int i = 0; i < arity; i++) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs index c4c9c1ed397c2..b5ff4f3480157 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs @@ -99,7 +99,7 @@ public static object CreateInstance( binder ??= Type.DefaultBinder; MethodBase invokeMethod = binder.BindToMethod(bindingAttr, matches.ToArray(), ref args, null, culture, null, out object? state); - if (invokeMethod.GetParametersNoCopy().Length == 0) + if (invokeMethod.GetParametersAsSpan().Length == 0) { if (args.Length != 0) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs index 4ae10a2fe866e..0d98883bfaa9d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs @@ -18,7 +18,7 @@ public sealed class ConstructorInvoker internal ConstructorInvoker(RuntimeConstructorInfo constructor) { _methodBaseInvoker = constructor.MethodInvoker; - _parameterCount = constructor.GetParametersNoCopy().Length; + _parameterCount = constructor.GetParametersAsSpan().Length; _declaringTypeHandle = constructor.DeclaringType.TypeHandle; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs index 04caa2251bbdd..516df98423288 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs @@ -61,7 +61,7 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) // _isValueTypeInstanceMethod = method.DeclaringType?.IsValueType ?? false; - ParameterInfo[] parameters = method.GetParametersNoCopy(); + ReadOnlySpan parameters = method.GetParametersAsSpan(); _argumentCount = parameters.Length; @@ -579,7 +579,7 @@ private unsafe ref byte InvokeDirectWithFewArguments( private unsafe object? GetCoercedDefaultValue(int index, in ArgumentInfo argumentInfo) { - object? defaultValue = Method.GetParametersNoCopy()[index].DefaultValue; + object? defaultValue = Method.GetParametersAsSpan()[index].DefaultValue; if (defaultValue == DBNull.Value) throw new ArgumentException(SR.Arg_VarMissNull, "parameters"); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodBase.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodBase.NativeAot.cs index ecc6242f7e790..37db7595ab585 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodBase.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodBase.NativeAot.cs @@ -16,7 +16,7 @@ public abstract partial class MethodBase : MemberInfo public static MethodBase GetCurrentMethod() { throw NotImplemented.ByDesign; } //Implemented by toolchain. // This is not an api but needs to be declared public so that System.Private.Reflection.Core can access (and override it) - public virtual ParameterInfo[] GetParametersNoCopy() => GetParameters(); + public virtual ReadOnlySpan GetParametersAsSpan() => GetParameters(); // // MethodBase MetadataDefinitionMethod { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs index c200a702c7a43..4d617f522ab21 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs @@ -17,7 +17,7 @@ public sealed class MethodInvoker internal MethodInvoker(RuntimeMethodInfo method) { _methodBaseInvoker = method.MethodInvoker; - _parameterCount = method.GetParametersNoCopy().Length; + _parameterCount = method.GetParametersAsSpan().Length; } internal MethodInvoker(RuntimeConstructorInfo constructor) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs index db486a10486e6..b765a8394ad9f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs @@ -88,8 +88,8 @@ protected static bool AreNamesAndSignaturesEqual(MethodInfo method1, MethodInfo if (method1.Name != method2.Name) return false; - ParameterInfo[] p1 = method1.GetParametersNoCopy(); - ParameterInfo[] p2 = method2.GetParametersNoCopy(); + ReadOnlySpan p1 = method1.GetParametersAsSpan(); + ReadOnlySpan p2 = method2.GetParametersAsSpan(); if (p1.Length != p2.Length) return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs index ae8598c75e9f7..3c5486b89819c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs @@ -40,7 +40,7 @@ public static bool QualifiesBasedOnParameterCount(this MethodBase methodBase, Bi #endregion #region ArgumentTypes - ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); + ReadOnlySpan parameterInfos = methodBase.GetParametersAsSpan(); if (argumentTypes.Length != parameterInfos.Length) { 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 a181e5deec7e4..10072b006c00e 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 @@ -72,7 +72,7 @@ protected static ConstructorInfo ResolveAttributeConstructor( int parameterCount = parameterTypes.Length; foreach (ConstructorInfo candidate in attributeType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { - ParameterInfo[] candidateParameters = candidate.GetParametersNoCopy(); + ReadOnlySpan candidateParameters = candidate.GetParametersAsSpan(); if (parameterCount != candidateParameters.Length) continue; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs index 8b0ba5c6e55fb..2ad4e585957e2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs @@ -110,7 +110,7 @@ public sealed override MethodInfo RemoveMethod public sealed override string ToString() { MethodInfo addMethod = this.AddMethod; - ParameterInfo[] parameters = addMethod.GetParametersNoCopy(); + ReadOnlySpan parameters = addMethod.GetParametersAsSpan(); if (parameters.Length == 0) throw new InvalidOperationException(); // Legacy: Why is a ToString() intentionally throwing an exception? RuntimeParameterInfo runtimeParameterInfo = (RuntimeParameterInfo)(parameters[0]); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs index c156d8e938d18..80b877e6fc0e8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs @@ -304,7 +304,7 @@ private static RuntimeMethodInfo LookupMethodForCreateDelegate(RuntimeTypeInfo r bindingFlags |= BindingFlags.IgnoreCase; } RuntimeMethodInfo invokeMethod = runtimeDelegateType.GetInvokeMethod(); - ParameterInfo[] parameters = invokeMethod.GetParametersNoCopy(); + ReadOnlySpan parameters = invokeMethod.GetParametersAsSpan(); int numParameters = parameters.Length; Type[] parameterTypes = new Type[numParameters]; for (int i = 0; i < numParameters; i++) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs index 0de913d3bc885..0469a7bd2ed2b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs @@ -30,7 +30,7 @@ public static MethodBaseInvoker GetCustomMethodInvokerIfNeeded(this MethodBase m if (!map.TryGetValue(methodBase.MetadataDefinitionMethod, out CustomMethodInvokerAction? action)) return null; - ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); + ReadOnlySpan parameterInfos = methodBase.GetParametersAsSpan(); Type[] parameterTypes = new Type[parameterInfos.Length]; for (int i = 0; i < parameterInfos.Length; i++) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs index 1b56abb1e39b1..d41c672a5161a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs @@ -54,7 +54,7 @@ public sealed override ParameterInfo[] GetParameters() return result; } - public sealed override ParameterInfo[] GetParametersNoCopy() + public sealed override ReadOnlySpan GetParametersAsSpan() { return RuntimeParameters; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs index 397105b40863e..ba041558a334c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs @@ -151,7 +151,7 @@ public sealed override ParameterInfo[] GetParameters() return result; } - public sealed override ParameterInfo[] GetParametersNoCopy() + public sealed override ReadOnlySpan GetParametersAsSpan() { return RuntimeParameters; } @@ -325,18 +325,16 @@ internal Delegate CreateDelegateNoThrowOnBindFailure(RuntimeTypeInfo runtimeDele return null; } -#pragma warning disable CA1859 // Use concrete types when possible for improved performance https://github.com/dotnet/roslyn-analyzers/issues/6751 - IList delegateParameters = invokeMethod.GetParametersNoCopy(); - IList targetParameters = this.GetParametersNoCopy(); -#pragma warning restore CA1859 - IEnumerator delegateParameterEnumerator = delegateParameters.GetEnumerator(); - IEnumerator targetParameterEnumerator = targetParameters.GetEnumerator(); + ReadOnlySpan delegateParameters = invokeMethod.GetParametersAsSpan(); + ReadOnlySpan targetParameters = this.GetParametersAsSpan(); + ReadOnlySpan.Enumerator delegateParameterEnumerator = delegateParameters.GetEnumerator(); + ReadOnlySpan.Enumerator targetParameterEnumerator = targetParameters.GetEnumerator(); bool isStatic = this.IsStatic; bool isOpen; if (isStatic) { - if (delegateParameters.Count == targetParameters.Count) + if (delegateParameters.Length == targetParameters.Length) { // Open static: This is the "typical" case of calling a static method. isOpen = true; @@ -358,7 +356,7 @@ internal Delegate CreateDelegateNoThrowOnBindFailure(RuntimeTypeInfo runtimeDele } else { - if (delegateParameters.Count == targetParameters.Count) + if (delegateParameters.Length == targetParameters.Length) { // Closed instance: This is the "typical" case of invoking an instance method. isOpen = false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs index 35ae4a96ea7c2..bee3e2f9d1aad 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs @@ -33,8 +33,7 @@ protected sealed override ConstructorInfo GetConstructorImpl(BindingFlags bindin if (types.Length == 0 && candidates.Count == 1) { ConstructorInfo firstCandidate = candidates[0]; - ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy(); - if (parameters.Length == 0) + if (firstCandidate.GetParametersAsSpan().Length == 0) return firstCandidate; } 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 b0e4ddcd9f41d..bf63ff4ca8944 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 @@ -363,7 +363,7 @@ internal abstract partial class RuntimeTypeInfo #region Invoke if (finalists == null && argCnt == 0 && - finalist.GetParametersNoCopy().Length == 0 && + finalist.GetParametersAsSpan().Length == 0 && (bindingFlags & BindingFlags.OptionalParamBinding) == 0) { //if (useCache && argCnt == props[0].GetParameters().Length) 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 d96bfb65c52d5..8611b4b9f845a 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 @@ -1036,7 +1036,7 @@ public LowLevelList ParameterTypeHandles { get { - ParameterInfo[] parameters = _methodBase.GetParametersNoCopy(); + ReadOnlySpan parameters = _methodBase.GetParametersAsSpan(); LowLevelList result = new LowLevelList(parameters.Length); for (int i = 0; i < parameters.Length; i++) @@ -1081,7 +1081,7 @@ public bool[] ReturnTypeAndParametersByRefFlags { get { - ParameterInfo[] parameters = _methodBase.GetParametersNoCopy(); + ReadOnlySpan parameters = _methodBase.GetParametersAsSpan(); bool[] result = new bool[parameters.Length + 1]; MethodInfo reflectionMethodInfo = _methodBase as MethodInfo; @@ -1101,8 +1101,8 @@ private void GetReturnTypeAndParameterTypesAndMDHandles(ref Handle[] handles, re { Debug.Assert(_metadataReader != null && !_methodHandle.Equals(default(MethodHandle))); - _returnTypeAndParametersHandlesCache = new Handle[_methodBase.GetParametersNoCopy().Length + 1]; - _returnTypeAndParametersTypesCache = new Type[_methodBase.GetParametersNoCopy().Length + 1]; + _returnTypeAndParametersHandlesCache = new Handle[_methodBase.GetParametersAsSpan().Length + 1]; + _returnTypeAndParametersTypesCache = new Type[_methodBase.GetParametersAsSpan().Length + 1]; MethodSignature signature = _methodHandle.GetMethod(_metadataReader).Signature.GetMethodSignature(_metadataReader); @@ -1116,7 +1116,7 @@ private void GetReturnTypeAndParameterTypesAndMDHandles(ref Handle[] handles, re foreach (Handle paramSigHandle in signature.Parameters) { _returnTypeAndParametersHandlesCache[index] = paramSigHandle; - _returnTypeAndParametersTypesCache[index] = _methodBase.GetParametersNoCopy()[index - 1].ParameterType; + _returnTypeAndParametersTypesCache[index] = _methodBase.GetParametersAsSpan()[index - 1].ParameterType; index++; } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs index e77ca53198198..5dd4ab441f9de 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs @@ -43,7 +43,7 @@ public static string ComputeUsefulPertainantIfPossible(MemberInfo memberInfo) // write out actual parameters friendlyName.Append('('); first = true; - foreach (ParameterInfo parameter in method.GetParametersNoCopy()) + foreach (ParameterInfo parameter in method.GetParametersAsSpan()) { if (!first) friendlyName.Append(','); diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/TypeLoader/ConstraintValidatorSupport.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/TypeLoader/ConstraintValidatorSupport.cs index 76e62e41bb8aa..3fc11330cc508 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/TypeLoader/ConstraintValidatorSupport.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/TypeLoader/ConstraintValidatorSupport.cs @@ -289,7 +289,7 @@ private static bool HasExplicitOrImplicitPublicDefaultConstructor(this Type type foreach (var ctor in type.GetConstructors()) { - if (!ctor.IsStatic && ctor.IsPublic && ctor.GetParametersNoCopy().Length == 0) + if (!ctor.IsStatic && ctor.IsPublic && ctor.GetParametersAsSpan().Length == 0) return true; } return false; diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs index 4cac32a376dd0..4359cc41a7604 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs @@ -129,7 +129,7 @@ private static int ExecuteAssembly(Assembly assembly, string?[]? args) obj: null, invokeAttr: BindingFlags.DoNotWrapExceptions, binder: null, - parameters: entry.GetParameters().Length > 0 ? new object?[] { args } : null, + parameters: entry.GetParametersAsSpan().Length > 0 ? new object?[] { args } : null, culture: null); return result != null ? (int)result : 0; diff --git a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs index 293ecd8489380..3adad0979c6eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs @@ -52,7 +52,7 @@ public sealed override MethodBase BindToMethod( for (i = 0; i < candidates.Length; i++) { - ParameterInfo[] par = candidates[i]!.GetParametersNoCopy(); + ReadOnlySpan par = candidates[i]!.GetParametersAsSpan(); // args.Length + 1 takes into account the possibility of a last paramArray that can be omitted paramOrder[i] = new int[(par.Length > args.Length) ? par.Length : args.Length]; @@ -104,7 +104,7 @@ public sealed override MethodBase BindToMethod( if (candidates[i] == null) continue; - ParameterInfo[] par = candidates[i]!.GetParametersNoCopy(); + ReadOnlySpan par = candidates[i]!.GetParametersAsSpan(); #region Match method by parameter count if (par.Length == 0) @@ -306,7 +306,7 @@ public sealed override MethodBase BindToMethod( // If the parameters and the args are not the same length or there is a paramArray // then we need to create a argument array. - ParameterInfo[] parms = candidates[0]!.GetParametersNoCopy(); + ReadOnlySpan parms = candidates[0]!.GetParametersAsSpan(); if (parms.Length == args.Length) { @@ -397,7 +397,7 @@ public sealed override MethodBase BindToMethod( // If the parameters and the args are not the same length or there is a paramArray // then we need to create a argument array. - ParameterInfo[] parameters = bestMatch.GetParametersNoCopy(); + ReadOnlySpan parameters = bestMatch.GetParametersAsSpan(); if (parameters.Length == args.Length) { if (paramArrayTypes[currentMin] != null) @@ -562,7 +562,7 @@ public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo int CurIdx = 0; for (i = 0; i < candidates.Length; i++) { - ParameterInfo[] par = candidates[i].GetParametersNoCopy(); + ReadOnlySpan par = candidates[i].GetParametersAsSpan(); if (par.Length != types.Length) continue; for (j = 0; j < types.Length; j++) @@ -797,7 +797,7 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat for (int i = 0; i < match.Length; i++) { - ParameterInfo[] par = match[i].GetParametersNoCopy(); + ReadOnlySpan par = match[i].GetParametersAsSpan(); if (par.Length == 0) { continue; @@ -861,8 +861,8 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat return bestMatch; } - private static int FindMostSpecific(ParameterInfo[] p1, int[] paramOrder1, Type? paramArrayType1, - ParameterInfo[] p2, int[] paramOrder2, Type? paramArrayType2, + private static int FindMostSpecific(ReadOnlySpan p1, int[] paramOrder1, Type? paramArrayType1, + ReadOnlySpan p2, int[] paramOrder2, Type? paramArrayType2, Type[] types, object?[]? args) { // A method using params is always less specific than one not using params @@ -1016,8 +1016,8 @@ private static int FindMostSpecificMethod(MethodBase m1, int[] paramOrder1, Type Type[] types, object?[]? args) { // Find the most specific method based on the parameters. - int res = FindMostSpecific(m1.GetParametersNoCopy(), paramOrder1, paramArrayType1, - m2.GetParametersNoCopy(), paramOrder2, paramArrayType2, types, args); + int res = FindMostSpecific(m1.GetParametersAsSpan(), paramOrder1, paramArrayType1, + m2.GetParametersAsSpan(), paramOrder2, paramArrayType2, types, args); // If the match was not ambiguous then return the result. if (res != 0) @@ -1096,8 +1096,8 @@ private static int FindMostSpecificProperty(PropertyInfo cur1, PropertyInfo cur2 public static bool CompareMethodSig(MethodBase m1, MethodBase m2) { - ParameterInfo[] params1 = m1.GetParametersNoCopy(); - ParameterInfo[] params2 = m2.GetParametersNoCopy(); + ReadOnlySpan params1 = m1.GetParametersAsSpan(); + ReadOnlySpan params2 = m2.GetParametersAsSpan(); if (params1.Length != params2.Length) return false; @@ -1181,7 +1181,7 @@ private static void ReorderParams(int[] paramOrder, object?[] vars) // as the values and maps to the parameters of the method. We store the mapping // from the parameters to the names in the paramOrder array. All parameters that // don't have matching names are then stored in the array in order. - private static bool CreateParamOrder(int[] paramOrder, ParameterInfo[] pars, string[] names) + private static bool CreateParamOrder(int[] paramOrder, ReadOnlySpan pars, string[] names) { bool[] used = new bool[pars.Length]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs index 52a04a68b910a..06d6483088e34 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs @@ -279,17 +279,19 @@ internal void ToString(TraceFormat traceFormat, StringBuilder sb) sb.Append(']'); } - ParameterInfo[]? pi = null; + ReadOnlySpan pi = default; + bool appendParameters = true; try { - pi = mb.GetParameters(); + pi = mb.GetParametersAsSpan(); } catch { // The parameter info cannot be loaded, so we don't // append the parameter list. + appendParameters = false; } - if (pi != null) + if (appendParameters) { // arguments printing sb.Append('('); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 8a756b1ef1b0a..7a0c6461146c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -329,15 +329,10 @@ public override string ToString() public override MethodInfo GetBaseDefinition() => this; - public override ParameterInfo[] GetParameters() - { - ParameterInfo[] privateParameters = LoadParameters(); - ParameterInfo[] parameters = new ParameterInfo[privateParameters.Length]; - Array.Copy(privateParameters, parameters, privateParameters.Length); - return parameters; - } + public override ParameterInfo[] GetParameters() => + GetParametersAsSpan().ToArray(); - internal override ParameterInfo[] GetParametersNoCopy() => LoadParameters(); + internal override ReadOnlySpan GetParametersAsSpan() => LoadParameters(); public override MethodImplAttributes GetMethodImplementationFlags() => MethodImplAttributes.IL | MethodImplAttributes.NoInlining; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/EventInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/EventInfo.cs index 07e1f5bd15c07..a42feec69e5d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/EventInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/EventInfo.cs @@ -45,7 +45,7 @@ public virtual Type? EventHandlerType get { MethodInfo m = GetAddMethod(true)!; - ParameterInfo[] p = m.GetParametersNoCopy(); + ReadOnlySpan p = m.GetParametersAsSpan(); Type del = typeof(Delegate); for (int i = 0; i < p.Length; i++) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs index c890452df3ca2..30745bdcd708d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs @@ -46,7 +46,7 @@ public static unsafe InvokeFunc_Obj4Args CreateInvokeDelegate_Obj4Args(MethodBas } // Push the arguments. - ParameterInfo[] parameters = method.GetParametersNoCopy(); + ReadOnlySpan parameters = method.GetParametersAsSpan(); for (int i = 0; i < parameters.Length; i++) { RuntimeType parameterType = (RuntimeType)parameters[i].ParameterType; @@ -114,7 +114,7 @@ public static unsafe InvokeFunc_ObjSpanArgs CreateInvokeDelegate_ObjSpanArgs(Met } // Push the arguments. - ParameterInfo[] parameters = method.GetParametersNoCopy(); + ReadOnlySpan parameters = method.GetParametersAsSpan(); for (int i = 0; i < parameters.Length; i++) { RuntimeType parameterType = (RuntimeType)parameters[i].ParameterType; @@ -171,7 +171,7 @@ public static unsafe InvokeFunc_RefArgs CreateInvokeDelegate_RefArgs(MethodBase } // Push the arguments. - ParameterInfo[] parameters = method.GetParametersNoCopy(); + ReadOnlySpan parameters = method.GetParametersAsSpan(); for (int i = 0; i < parameters.Length; i++) { il.Emit(OpCodes.Ldarg_2); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs index d4dd02b06da47..087f9953a3af4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs @@ -125,7 +125,7 @@ internal static void AppendParameters(ref ValueStringBuilder sbParamList, Type[] internal virtual Type[] GetParameterTypes() { - ParameterInfo[] paramInfo = GetParametersNoCopy(); + ReadOnlySpan paramInfo = GetParametersAsSpan(); if (paramInfo.Length == 0) { return Type.EmptyTypes; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs index 6f1667713ca7e..02967f04b59de 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs @@ -365,7 +365,7 @@ BindingFlags invokeAttr // Convert a Type.Missing to the default value. if (ReferenceEquals(arg, Type.Missing)) { - arg = HandleTypeMissing(_method.GetParametersNoCopy()[i], sigType); + arg = HandleTypeMissing(_method.GetParametersAsSpan()[i], sigType); shouldCopyBack[i] = true; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs index a19e332dd16fc..e3e4da36d096b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs @@ -96,7 +96,7 @@ private void CheckParameterMetadataType(ParameterInfo parameter, NullabilityInfo } else { - ParameterInfo[] parameters = metaMethod.GetParameters(); + ReadOnlySpan parameters = metaMethod.GetParametersAsSpan(); for (int i = 0; i < parameters.Length; i++) { if (parameter.Position == i && @@ -200,7 +200,7 @@ public NullabilityInfo Create(PropertyInfo propertyInfo) if (setter != null) { - CheckNullabilityAttributes(nullability, setter.GetParameters()[^1].GetCustomAttributesData()); + CheckNullabilityAttributes(nullability, setter.GetParametersAsSpan()[^1].GetCustomAttributesData()); } else { @@ -444,7 +444,7 @@ private static Type GetPropertyMetaType(PropertyInfo property) return method.ReturnType; } - return property.GetSetMethod(true)!.GetParameters()[0].ParameterType; + return property.GetSetMethod(true)!.GetParametersAsSpan()[0].ParameterType; } private void CheckGenericParameters(NullabilityInfo nullability, MemberInfo metaMember, Type metaType, Type? reflectedType) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterInfo.cs index 6c93d8b7d01dc..5285f69b91976 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterInfo.cs @@ -65,7 +65,7 @@ public object GetRealObject(StreamingContext context) if (MemberImpl == null) throw new SerializationException(SR.Serialization_InsufficientState); - ParameterInfo[] args; + ReadOnlySpan args; switch (MemberImpl.MemberType) { case MemberTypes.Constructor: @@ -79,9 +79,9 @@ public object GetRealObject(StreamingContext context) } else { - args = ((MethodBase)MemberImpl).GetParametersNoCopy(); + args = ((MethodBase)MemberImpl).GetParametersAsSpan(); - if (args != null && PositionImpl < args.Length) + if (PositionImpl < args.Length) return args[PositionImpl]; else throw new SerializationException(SR.Serialization_BadParameterInfo); @@ -90,7 +90,7 @@ public object GetRealObject(StreamingContext context) case MemberTypes.Property: args = ((PropertyInfo)MemberImpl).GetIndexParameters(); - if (args != null && PositionImpl > -1 && PositionImpl < args.Length) + if (PositionImpl > -1 && PositionImpl < args.Length) return args[PositionImpl]; else throw new SerializationException(SR.Serialization_BadParameterInfo); diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index 9bb9541c571bf..213b2ceef9584 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -658,7 +658,7 @@ public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) // Invoke if (finalists == null && argCnt == 0 && - finalist.GetParametersNoCopy().Length == 0 && + finalist.GetParametersAsSpan().Length == 0 && (bindingFlags & BindingFlags.OptionalParamBinding) == 0) { return finalist.Invoke(target, bindingFlags, binder, providedArgs, culture); diff --git a/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs b/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs index 39a2d2e3a2eeb..8ac1864e1140e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs @@ -209,7 +209,7 @@ private static void CallStartupHook(StartupHookNameOrPath startupHook) Debug.Assert(initializeMethod != null && initializeMethod.IsStatic && initializeMethod.ReturnType == typeof(void) && - initializeMethod.GetParameters().Length == 0); + initializeMethod.GetParametersAsSpan().Length == 0); initializeMethod.Invoke(null, null); } diff --git a/src/mono/System.Private.CoreLib/src/System/Delegate.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Delegate.Mono.cs index d40e212a672fa..9f71ff470f3e4 100644 --- a/src/mono/System.Private.CoreLib/src/System/Delegate.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Delegate.Mono.cs @@ -210,7 +210,7 @@ public static Delegate CreateDelegate(Type type, object? firstArgument, MethodIn if (invoke is null) return null; - ParameterInfo[] delargs = invoke.GetParametersNoCopy(); + ReadOnlySpan delargs = invoke.GetParametersAsSpan(); Type[] delargtypes = new Type[delargs.Length]; for (int i = 0; i < delargs.Length; i++) @@ -250,8 +250,8 @@ private static bool IsMatchingCandidate(RuntimeType type, object? target, Method return false; } - ParameterInfo[] delargs = invoke.GetParametersNoCopy(); - ParameterInfo[] args = method.GetParametersNoCopy(); + ReadOnlySpan delargs = invoke.GetParametersAsSpan(); + ReadOnlySpan args = method.GetParametersAsSpan(); bool argLengthMatch; @@ -437,7 +437,7 @@ private static bool IsArgumentTypeMatchWithThis(Type delArgType, Type argType, b MethodInfo? invoke = GetType().GetMethod("Invoke"); if (invoke != null && args != null) { - ParameterInfo[] delegateParameters = invoke.GetParameters(); + ReadOnlySpan delegateParameters = invoke.GetParametersAsSpan(); for (int i = 0; i < args.Length; i++) { if (args[i] == Type.Missing) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs index add2c153f66f1..19c814cc5c72d 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs @@ -681,7 +681,7 @@ internal static bool IsDefined(ICustomAttributeProvider obj, Type attributeType, int position = parinfo.Position; if (position == -1) return bmethod.ReturnParameter; - return bmethod.GetParameters()[position]; + return bmethod.GetParametersAsSpan()[position]; } } /* diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs index 5a97e73dcd7d3..3ec41bb31fbda 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs @@ -146,7 +146,7 @@ private int AddRef(object reference) return _nrefs - 1; } - internal override int GetParametersCount() => GetParametersNoCopy().Length; + internal override int GetParametersCount() => GetParametersAsSpan().Length; private sealed class DynamicMethodTokenGenerator : ITokenGenerator { diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBase.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBase.Mono.cs index f498bebafc19f..53de103e2c4fb 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBase.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBase.Mono.cs @@ -39,7 +39,7 @@ public partial class MethodBase [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern MethodBase? GetCurrentMethod(); - internal virtual ParameterInfo[] GetParametersNoCopy() + internal virtual ReadOnlySpan GetParametersAsSpan() { return GetParametersInternal(); } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs index 914be3d3d7a12..7cbf84f2196f1 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs @@ -190,7 +190,7 @@ private string FormatNameAndSig() sbName.Append(RuntimeMethodHandle.ConstructInstantiation(this)); sbName.Append('('); - RuntimeParameterInfo.FormatParameters(sbName, GetParametersNoCopy(), CallingConvention); + RuntimeParameterInfo.FormatParameters(sbName, GetParametersAsSpan(), CallingConvention); sbName.Append(')'); return sbName.ToString(); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index 69f8537d6696b..b2a743b88b5b0 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -25,7 +25,7 @@ internal RuntimeParameterInfo(string name, Type type, int position, int attrs, o this.marshalAs = marshalAs; } - internal static void FormatParameters(StringBuilder sb, ParameterInfo[] p, CallingConventions callingConvention) + internal static void FormatParameters(StringBuilder sb, ReadOnlySpan p, CallingConventions callingConvention) { for (int i = 0; i < p.Length; ++i) { diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 5924d5c0640df..d44eb711e4747 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -419,7 +419,7 @@ private static bool FilterApplyMethodBase( #region If argumentTypes supplied if (argumentTypes != null) { - ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); + ReadOnlySpan parameterInfos = methodBase.GetParametersAsSpan(); if (argumentTypes.Length != parameterInfos.Length) { @@ -820,9 +820,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) if (types.Length == 0 && candidates.Count == 1) { ConstructorInfo firstCandidate = candidates[0]; - - ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy(); - if (parameters == null || parameters.Length == 0) + if (firstCandidate.GetParametersAsSpan().Length == 0) { return firstCandidate; } @@ -1557,7 +1555,7 @@ private void CreateInstanceCheckThis() throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, FullName)); } - if (invokeMethod.GetParametersNoCopy().Length == 0) + if (invokeMethod.GetParametersAsSpan().Length == 0) { if (args.Length != 0) {