Skip to content

Commit a48e73a

Browse files
authored
For perf, use the new ConstructorInvoker APIs for ActivatorUtilities.CreateFactory (#90119)
1 parent a1c3f64 commit a48e73a

File tree

12 files changed

+759
-92
lines changed

12 files changed

+759
-92
lines changed

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

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using Internal.Reflection.Core.Execution;
55
using System.Diagnostics;
6+
using System.Diagnostics.CodeAnalysis;
67
using System.Reflection.Runtime.MethodInfos;
78
using static System.Reflection.DynamicInvokeInfo;
89

@@ -11,11 +12,13 @@ namespace System.Reflection
1112
public sealed class ConstructorInvoker
1213
{
1314
private readonly MethodBaseInvoker _methodBaseInvoker;
15+
private readonly int _parameterCount;
1416
private readonly RuntimeTypeHandle _declaringTypeHandle;
1517

1618
internal ConstructorInvoker(RuntimeConstructorInfo constructor)
1719
{
1820
_methodBaseInvoker = constructor.MethodInvoker;
21+
_parameterCount = constructor.GetParametersNoCopy().Length;
1922
_declaringTypeHandle = constructor.DeclaringType.TypeHandle;
2023
}
2124

@@ -32,6 +35,11 @@ public static ConstructorInvoker Create(ConstructorInfo constructor)
3235
[DebuggerGuidedStepThrough]
3336
public object Invoke()
3437
{
38+
if (_parameterCount != 0)
39+
{
40+
ThrowForArgCountMismatch();
41+
}
42+
3543
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(new Span<object?>());
3644
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
3745
return result;
@@ -40,43 +48,63 @@ public object Invoke()
4048
[DebuggerGuidedStepThrough]
4149
public object Invoke(object? arg1)
4250
{
43-
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(new Span<object?>(ref arg1));
51+
if (_parameterCount != 1)
52+
{
53+
ThrowForArgCountMismatch();
54+
}
55+
56+
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(new Span<object?>(ref arg1, _parameterCount));
4457
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
4558
return result;
4659
}
4760

4861
[DebuggerGuidedStepThrough]
4962
public object Invoke(object? arg1, object? arg2)
5063
{
64+
if (_parameterCount != 2)
65+
{
66+
ThrowForArgCountMismatch();
67+
}
68+
5169
StackAllocatedArguments argStorage = default;
5270
argStorage._args.Set(0, arg1);
5371
argStorage._args.Set(1, arg2);
54-
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(2));
72+
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(_parameterCount));
5573
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
5674
return result;
5775
}
5876

5977
[DebuggerGuidedStepThrough]
6078
public object Invoke(object? arg1, object? arg2, object? arg3)
6179
{
80+
if (_parameterCount != 3)
81+
{
82+
ThrowForArgCountMismatch();
83+
}
84+
6285
StackAllocatedArguments argStorage = default;
6386
argStorage._args.Set(0, arg1);
6487
argStorage._args.Set(1, arg2);
6588
argStorage._args.Set(2, arg3);
66-
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(3));
89+
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(_parameterCount));
6790
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
6891
return result;
6992
}
7093

7194
[DebuggerGuidedStepThrough]
7295
public object Invoke(object? arg1, object? arg2, object? arg3, object? arg4)
7396
{
97+
if (_parameterCount != 4)
98+
{
99+
ThrowForArgCountMismatch();
100+
}
101+
74102
StackAllocatedArguments argStorage = default;
75103
argStorage._args.Set(0, arg1);
76104
argStorage._args.Set(1, arg2);
77105
argStorage._args.Set(2, arg3);
78106
argStorage._args.Set(3, arg4);
79-
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(4));
107+
object result = _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(_parameterCount));
80108
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
81109
return result;
82110
}
@@ -88,5 +116,11 @@ public object Invoke(Span<object?> arguments)
88116
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
89117
return result;
90118
}
119+
120+
[DoesNotReturn]
121+
private static void ThrowForArgCountMismatch()
122+
{
123+
throw new TargetParameterCountException(SR.Arg_ParmCnt);
124+
}
91125
}
92126
}

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

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using Internal.Reflection.Core.Execution;
55
using System.Diagnostics;
6+
using System.Diagnostics.CodeAnalysis;
67
using System.Reflection.Runtime.MethodInfos;
78
using static System.Reflection.DynamicInvokeInfo;
89

@@ -11,10 +12,12 @@ namespace System.Reflection
1112
public sealed class MethodInvoker
1213
{
1314
private readonly MethodBaseInvoker _methodBaseInvoker;
15+
private readonly int _parameterCount;
1416

1517
internal MethodInvoker(RuntimeMethodInfo method)
1618
{
1719
_methodBaseInvoker = method.MethodInvoker;
20+
_parameterCount = method.GetParametersNoCopy().Length;
1821
}
1922

2023
internal MethodInvoker(RuntimeConstructorInfo constructor)
@@ -44,6 +47,11 @@ public static MethodInvoker Create(MethodBase method)
4447
[DebuggerGuidedStepThrough]
4548
public object? Invoke(object? obj)
4649
{
50+
if (_parameterCount != 0)
51+
{
52+
ThrowForArgCountMismatch();
53+
}
54+
4755
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, new Span<object?>());
4856
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
4957
return result;
@@ -52,46 +60,66 @@ public static MethodInvoker Create(MethodBase method)
5260
[DebuggerGuidedStepThrough]
5361
public object? Invoke(object? obj, object? arg1)
5462
{
55-
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, new Span<object?>(ref arg1));
63+
if (_parameterCount != 1)
64+
{
65+
ThrowForArgCountMismatch();
66+
}
67+
68+
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, new Span<object?>(ref arg1, _parameterCount));
5669
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
5770
return result;
5871
}
5972

6073
[DebuggerGuidedStepThrough]
6174
public object? Invoke(object? obj, object? arg1, object? arg2)
6275
{
76+
if (_parameterCount != 2)
77+
{
78+
ThrowForArgCountMismatch();
79+
}
80+
6381
StackAllocatedArguments argStorage = default;
6482
argStorage._args.Set(0, arg1);
6583
argStorage._args.Set(1, arg2);
6684

67-
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(2));
85+
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(_parameterCount));
6886
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
6987
return result;
7088
}
7189

7290
[DebuggerGuidedStepThrough]
7391
public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3)
7492
{
93+
if (_parameterCount != 3)
94+
{
95+
ThrowForArgCountMismatch();
96+
}
97+
7598
StackAllocatedArguments argStorage = default;
7699
argStorage._args.Set(0, arg1);
77100
argStorage._args.Set(1, arg2);
78101
argStorage._args.Set(2, arg3);
79102

80-
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(3));
103+
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(_parameterCount));
81104
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
82105
return result;
83106
}
84107

85108
[DebuggerGuidedStepThrough]
86109
public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3, object? arg4)
87110
{
111+
if (_parameterCount != 4)
112+
{
113+
ThrowForArgCountMismatch();
114+
}
115+
88116
StackAllocatedArguments argStorage = default;
89117
argStorage._args.Set(0, arg1);
90118
argStorage._args.Set(1, arg2);
91119
argStorage._args.Set(2, arg3);
92120
argStorage._args.Set(3, arg4);
93121

94-
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(4));
122+
object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(_parameterCount));
95123
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
96124
return result;
97125
}
@@ -103,5 +131,11 @@ public static MethodInvoker Create(MethodBase method)
103131
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
104132
return result;
105133
}
134+
135+
[DoesNotReturn]
136+
private static void ThrowForArgCountMismatch()
137+
{
138+
throw new TargetParameterCountException(SR.Arg_ParmCnt);
139+
}
106140
}
107141
}

src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.netstandard.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5-
using System.Diagnostics.CodeAnalysis;
65
using System.Reflection;
7-
using System.Runtime.Serialization;
86

97
namespace Microsoft.Extensions.Internal
108
{

0 commit comments

Comments
 (0)