Skip to content

Commit c853fc1

Browse files
authored
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<ParameterInfo>`, 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
1 parent 493a702 commit c853fc1

File tree

52 files changed

+112
-140
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+112
-140
lines changed

src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ private static void ClassRegistrationScenarioForType(ComActivationContext cxt, b
201201
}
202202

203203
// Finally validate signature
204-
ParameterInfo[] methParams = method.GetParameters();
204+
ReadOnlySpan<ParameterInfo> methParams = method.GetParametersAsSpan();
205205
if (method.ReturnType != typeof(void)
206206
|| methParams == null
207207
|| methParams.Length != 1

src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,7 @@ private static bool InternalIsDefined(EventInfo element, Type attributeType, boo
227227
}
228228
else
229229
{
230-
ParameterInfo[] parameters = rtMethod.GetParameters();
231-
return parameters[position]; // Point to the correct ParameterInfo of the method
230+
return rtMethod.GetParametersAsSpan()[position]; // Point to the correct ParameterInfo of the method
232231
}
233232
}
234233
}

src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ protected virtual MethodInfo GetMethodImpl()
200200
{
201201
// it's an open one, need to fetch the first arg of the instantiation
202202
MethodInfo invoke = this.GetType().GetMethod("Invoke")!;
203-
declaringType = (RuntimeType)invoke.GetParameters()[0].ParameterType;
203+
declaringType = (RuntimeType)invoke.GetParametersAsSpan()[0].ParameterType;
204204
}
205205
}
206206
}

src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public override void Emit(OpCode opcode, MethodInfo meth)
9494
}
9595
if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
9696
{
97-
stackchange -= meth.GetParametersNoCopy().Length;
97+
stackchange -= meth.GetParametersAsSpan().Length;
9898
}
9999
// Pop the "this" parameter if the method is non-static,
100100
// and the instruction is not newobj/ldtoken/ldftn.
@@ -416,7 +416,7 @@ private int GetMemberRefToken(MethodInfo methodInfo, Type[]? optionalParameterTy
416416
if (rtMeth == null && dm == null)
417417
throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo, nameof(methodInfo));
418418

419-
ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy();
419+
ReadOnlySpan<ParameterInfo> paramInfo = methodInfo.GetParametersAsSpan();
420420
if (paramInfo != null && paramInfo.Length != 0)
421421
{
422422
parameterTypes = new Type[paramInfo.Length];

src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeModuleBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ internal SignatureHelper GetMemberRefSignature(MethodBase? method, int cGenericP
458458
}
459459

460460
Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
461-
ParameterInfo[] parameters = method.GetParametersNoCopy();
461+
ReadOnlySpan<ParameterInfo> parameters = method.GetParametersAsSpan();
462462

463463
Type[] parameterTypes = new Type[parameters.Length];
464464
Type[][] requiredCustomModifiers = new Type[parameterTypes.Length][];

src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public abstract partial class MethodBase : MemberInfo
4747
// used by EE
4848
private IntPtr GetMethodDesc() { return MethodHandle.Value; }
4949

50-
internal virtual ParameterInfo[] GetParametersNoCopy() { return GetParameters(); }
50+
internal virtual ReadOnlySpan<ParameterInfo> GetParametersAsSpan() { return GetParameters(); }
5151
#endregion
5252
}
5353
}

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,20 +180,11 @@ public override IList<CustomAttributeData> GetCustomAttributesData()
180180
// This seems to always returns System.Void.
181181
internal override Type GetReturnType() { return Signature.ReturnType; }
182182

183-
internal override ParameterInfo[] GetParametersNoCopy() =>
183+
internal override ReadOnlySpan<ParameterInfo> GetParametersAsSpan() =>
184184
m_parameters ??= RuntimeParameterInfo.GetParameters(this, this, Signature);
185185

186-
public override ParameterInfo[] GetParameters()
187-
{
188-
ParameterInfo[] parameters = GetParametersNoCopy();
189-
190-
if (parameters.Length == 0)
191-
return parameters;
192-
193-
ParameterInfo[] ret = new ParameterInfo[parameters.Length];
194-
Array.Copy(parameters, ret, parameters.Length);
195-
return ret;
196-
}
186+
public override ParameterInfo[] GetParameters() =>
187+
GetParametersAsSpan().ToArray();
197188

198189
public override MethodImplAttributes GetMethodImplementationFlags()
199190
{

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToke
278278
m_ctor = (RuntimeConstructorInfo)scope.ResolveMethod(caCtorToken, attributeType.GenericTypeArguments, null)!.MethodHandle.GetMethodInfo();
279279
}
280280

281-
ParameterInfo[] parameters = m_ctor.GetParametersNoCopy();
281+
ReadOnlySpan<ParameterInfo> parameters = m_ctor.GetParametersAsSpan();
282282
if (parameters.Length != 0)
283283
{
284284
m_ctorParams = new CustomAttributeCtorParameter[parameters.Length];
@@ -412,7 +412,7 @@ private void Init(object pca)
412412
// Ensure there is only a single constructor for 'pca', so it is safe to suppress IL2075
413413
ConstructorInfo[] allCtors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
414414
Debug.Assert(allCtors.Length == 1);
415-
Debug.Assert(allCtors[0].GetParameters().Length == 0);
415+
Debug.Assert(allCtors[0].GetParametersAsSpan().Length == 0);
416416
#endif
417417

418418
m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ o is RuntimeEventInfo m &&
6363
#region Object Overrides
6464
public override string ToString()
6565
{
66-
if (m_addMethod == null || m_addMethod.GetParametersNoCopy().Length == 0)
66+
ReadOnlySpan<ParameterInfo> parameters;
67+
if (m_addMethod == null ||
68+
(parameters = m_addMethod.GetParametersAsSpan()).Length == 0)
69+
{
6770
throw new InvalidOperationException(SR.InvalidOperation_NoPublicAddMethod);
71+
}
6872

69-
return m_addMethod.GetParametersNoCopy()[0].ParameterType.FormatTypeName() + " " + Name;
73+
return parameters[0].ParameterType.FormatTypeName() + " " + Name;
7074
}
7175

7276
public override bool Equals(object? obj) =>

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public override Type? ReflectedType
240240
#endregion
241241

242242
#region MethodBase Overrides
243-
internal override ParameterInfo[] GetParametersNoCopy() =>
243+
internal override ReadOnlySpan<ParameterInfo> GetParametersAsSpan() =>
244244
FetchNonReturnParameters();
245245

246246
public override ParameterInfo[] GetParameters()

0 commit comments

Comments
 (0)