Skip to content

Commit a3428ed

Browse files
committed
Add public Invoker classes
1 parent 087651e commit a3428ed

File tree

81 files changed

+3504
-1329
lines changed

Some content is hidden

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

81 files changed

+3504
-1329
lines changed

build

Whitespace-only changes.

src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@
185185
<Compile Include="$(BclSourcesRoot)\System\Reflection\Metadata\AssemblyExtensions.cs" />
186186
<Compile Include="$(BclSourcesRoot)\System\Reflection\Metadata\MetadataUpdater.cs" />
187187
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodBase.CoreCLR.cs" />
188+
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodBaseInvoker.CoreCLR.cs" />
188189
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodInvoker.CoreCLR.cs" />
189190
<Compile Include="$(BclSourcesRoot)\System\Reflection\ModifiedType.CoreCLR.cs" />
190191
<Compile Include="$(BclSourcesRoot)\System\Reflection\RtFieldInfo.cs" />
@@ -219,6 +220,7 @@
219220
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeLibrary.CoreCLR.cs" />
220221
<Compile Include="$(BclSourcesRoot)\System\Runtime\Intrinsics\X86\X86Base.CoreCLR.cs" />
221222
<Compile Include="$(BclSourcesRoot)\System\Runtime\Loader\AssemblyLoadContext.CoreCLR.cs" />
223+
<Compile Include="$(BclSourcesRoot)\System\Runtime\RuntimeImports.CoreCLR.cs" />
222224
<Compile Include="$(BclSourcesRoot)\System\Runtime\Versioning\CompatibilitySwitch.cs" />
223225
<Compile Include="$(BclSourcesRoot)\System\RuntimeArgumentHandle.cs" />
224226
<Compile Include="$(BclSourcesRoot)\System\RuntimeHandles.cs" />
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Runtime.CompilerServices;
5-
64
namespace System.Reflection
75
{
8-
internal partial class ConstructorInvoker
6+
public partial class ConstructorInvoker
97
{
10-
public InvocationFlags _invocationFlags;
8+
private readonly Signature? _signature;
9+
10+
internal unsafe ConstructorInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
11+
{
12+
_signature = constructor.Signature;
13+
_invokeFunc_RefArgs = InterpretedInvoke;
14+
}
1115

12-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
13-
private unsafe object? InterpretedInvoke(object? obj, IntPtr* arguments)
16+
private unsafe object? InterpretedInvoke(object? obj, IntPtr* args)
1417
{
15-
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, _method.Signature, isConstructor: obj is null)!;
18+
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
1619
}
1720
}
1821
}

src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs

Lines changed: 18 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public sealed partial class DynamicMethod : MethodInfo
2424
private Module _module;
2525
internal bool _skipVisibility;
2626
internal RuntimeType? _typeOwner;
27-
private MethodInvoker? _invoker;
27+
private MethodBaseInvoker? _invoker;
2828
private Signature? _signature;
2929
private string _name;
3030
private MethodAttributes _attributes;
@@ -85,12 +85,12 @@ internal RuntimeMethodHandle GetMethodDescriptor()
8585
return new RuntimeMethodHandle(_methodHandle!);
8686
}
8787

88-
private MethodInvoker Invoker
88+
internal MethodBaseInvoker Invoker
8989
{
9090
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9191
get
9292
{
93-
return _invoker ??= new MethodInvoker(this, Signature);
93+
return _invoker ??= new MethodBaseInvoker(this, Signature);
9494
}
9595
}
9696

@@ -134,136 +134,28 @@ Signature LazyCreateSignature()
134134
throw new TargetParameterCountException(SR.Arg_ParmCnt);
135135

136136
object? retValue;
137-
138-
unsafe
137+
switch (argCount)
139138
{
140-
if (argCount == 0)
141-
{
142-
retValue = Invoker.InlinedInvoke(obj, args: default, invokeAttr);
143-
}
144-
else if (argCount > MaxStackAllocArgCount)
145-
{
146-
Debug.Assert(parameters != null);
147-
retValue = InvokeWithManyArguments(this, argCount, obj, invokeAttr, binder, parameters, culture);
148-
}
149-
else
150-
{
151-
Debug.Assert(parameters != null);
152-
StackAllocedArguments argStorage = default;
153-
Span<object?> copyOfParameters = argStorage._args.AsSpan(argCount);
154-
Span<ParameterCopyBackAction> shouldCopyBackParameters = argStorage._copyBacks.AsSpan(argCount);
155-
156-
StackAllocatedByRefs byrefStorage = default;
157-
#pragma warning disable CS8500
158-
IntPtr* pByRefStorage = (IntPtr*)&byrefStorage;
159-
#pragma warning restore CS8500
160-
161-
CheckArguments(
162-
copyOfParameters,
163-
pByRefStorage,
164-
shouldCopyBackParameters,
165-
parameters,
166-
Signature.Arguments,
167-
binder,
168-
culture,
169-
invokeAttr);
170-
171-
retValue = Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr);
172-
173-
// Copy modified values out. This should be done only with ByRef or Type.Missing parameters.
174-
for (int i = 0; i < argCount; i++)
175-
{
176-
ParameterCopyBackAction action = shouldCopyBackParameters[i];
177-
if (action != ParameterCopyBackAction.None)
178-
{
179-
if (action == ParameterCopyBackAction.Copy)
180-
{
181-
parameters[i] = copyOfParameters[i];
182-
}
183-
else
184-
{
185-
Debug.Assert(action == ParameterCopyBackAction.CopyNullable);
186-
Debug.Assert(copyOfParameters[i] != null);
187-
Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT);
188-
parameters[i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]);
189-
}
190-
}
191-
}
192-
}
139+
case 0:
140+
retValue = Invoker.InvokeWithNoArgs(obj, invokeAttr);
141+
break;
142+
case 1:
143+
retValue = Invoker.InvokeWithOneArg(obj, invokeAttr, binder, parameters!, culture);
144+
break;
145+
case 2:
146+
case 3:
147+
case 4:
148+
retValue = Invoker.InvokeWithFewArgs(obj, invokeAttr, binder, parameters!, culture);
149+
break;
150+
default:
151+
retValue = Invoker.InvokeWithManyArgs(obj, invokeAttr, binder, parameters!, culture);
152+
break;
193153
}
194154

195155
GC.KeepAlive(this);
196156
return retValue;
197157
}
198158

199-
// Slower path that does a heap alloc for copyOfParameters and registers byrefs to those objects.
200-
// This is a separate method to support better performance for the faster paths.
201-
private static unsafe object? InvokeWithManyArguments(
202-
DynamicMethod mi,
203-
int argCount,
204-
object? obj,
205-
BindingFlags invokeAttr,
206-
Binder? binder,
207-
object?[] parameters,
208-
CultureInfo? culture)
209-
{
210-
object[] objHolder = new object[argCount];
211-
Span<object?> copyOfParameters = new(objHolder, 0, argCount);
212-
213-
// We don't check a max stack size since we are invoking a method which
214-
// naturally requires a stack size that is dependent on the arg count\size.
215-
IntPtr* pByRefStorage = stackalloc IntPtr[argCount];
216-
NativeMemory.Clear(pByRefStorage, (uint)(argCount * sizeof(IntPtr)));
217-
218-
ParameterCopyBackAction* copyBackActions = stackalloc ParameterCopyBackAction[argCount];
219-
Span<ParameterCopyBackAction> shouldCopyBackParameters = new(copyBackActions, argCount);
220-
221-
GCFrameRegistration reg = new(pByRefStorage, (uint)argCount, areByRefs: true);
222-
223-
object? retValue;
224-
try
225-
{
226-
RegisterForGCReporting(&reg);
227-
mi.CheckArguments(
228-
copyOfParameters,
229-
pByRefStorage,
230-
shouldCopyBackParameters,
231-
parameters,
232-
mi.Signature.Arguments,
233-
binder,
234-
culture,
235-
invokeAttr);
236-
237-
retValue = mi.Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr);
238-
}
239-
finally
240-
{
241-
UnregisterForGCReporting(&reg);
242-
}
243-
244-
// Copy modified values out. This should be done only with ByRef or Type.Missing parameters.
245-
for (int i = 0; i < argCount; i++)
246-
{
247-
ParameterCopyBackAction action = shouldCopyBackParameters[i];
248-
if (action != ParameterCopyBackAction.None)
249-
{
250-
if (action == ParameterCopyBackAction.Copy)
251-
{
252-
parameters[i] = copyOfParameters[i];
253-
}
254-
else
255-
{
256-
Debug.Assert(action == ParameterCopyBackAction.CopyNullable);
257-
Debug.Assert(copyOfParameters[i] != null);
258-
Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT);
259-
parameters[i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]);
260-
}
261-
}
262-
}
263-
264-
return retValue;
265-
}
266-
267159
public DynamicILInfo GetDynamicILInfo()
268160
{
269161
if (_dynamicILInfo == null)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Reflection.Emit;
5+
6+
namespace System.Reflection
7+
{
8+
internal partial class MethodBaseInvoker
9+
{
10+
private readonly Signature? _signature;
11+
12+
internal unsafe MethodBaseInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
13+
{
14+
_signature = method.Signature;
15+
_invocationFlags = method.ComputeAndUpdateInvocationFlags();
16+
_invokeFunc_RefArgs = InterpretedInvoke_Method;
17+
}
18+
19+
internal unsafe MethodBaseInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
20+
{
21+
_signature = constructor.Signature;
22+
_invocationFlags = constructor.ComputeAndUpdateInvocationFlags();
23+
_invokeFunc_RefArgs = InterpretedInvoke_Constructor;
24+
}
25+
26+
internal unsafe MethodBaseInvoker(DynamicMethod method, Signature signature) : this(method, signature.Arguments)
27+
{
28+
_signature = signature;
29+
_invokeFunc_RefArgs = InterpretedInvoke_Method;
30+
}
31+
32+
private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) =>
33+
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
34+
35+
private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args) =>
36+
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor : false);
37+
}
38+
}
Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,39 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Runtime.CompilerServices;
4+
using System.Diagnostics;
5+
using System.Reflection.Emit;
56

67
namespace System.Reflection
78
{
8-
internal partial class MethodInvoker
9+
public partial class MethodInvoker
910
{
10-
private readonly Signature _signature;
11-
internal InvocationFlags _invocationFlags;
11+
private readonly Signature? _signature;
1212

13-
public MethodInvoker(MethodBase method, Signature signature)
13+
internal unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
1414
{
15-
_method = method;
16-
_signature = signature;
15+
_signature = method.Signature;
16+
_invokeFunc_RefArgs = InterpretedInvoke_Method;
17+
_invocationFlags = method.ComputeAndUpdateInvocationFlags();
18+
}
1719

18-
if (LocalAppContextSwitches.ForceInterpretedInvoke && !LocalAppContextSwitches.ForceEmitInvoke)
19-
{
20-
// Always use the native invoke; useful for testing.
21-
_strategyDetermined = true;
22-
}
23-
else if (LocalAppContextSwitches.ForceEmitInvoke && !LocalAppContextSwitches.ForceInterpretedInvoke)
24-
{
25-
// Always use emit invoke (if IsDynamicCodeSupported == true); useful for testing.
26-
_invoked = true;
27-
}
20+
internal unsafe MethodInvoker(DynamicMethod method) : this(method, method.Signature.Arguments)
21+
{
22+
_signature = method.Signature;
23+
_invokeFunc_RefArgs = InterpretedInvoke_Method;
2824
}
2925

30-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
31-
private unsafe object? InterpretedInvoke(object? obj, IntPtr* arguments)
26+
internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
3227
{
33-
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, _signature, isConstructor: false);
28+
_signature = constructor.Signature;
29+
_invokeFunc_RefArgs = InterpretedInvoke_Constructor;
30+
_invocationFlags = constructor.ComputeAndUpdateInvocationFlags();
3431
}
32+
33+
private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args) =>
34+
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: false);
35+
36+
private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) =>
37+
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
3538
}
3639
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,17 @@ public override void SetValue(object? obj, object? value, BindingFlags invokeAtt
194194

195195
CheckConsistency(obj);
196196

197-
ParameterCopyBackAction _ref = default;
198197
RuntimeType fieldType = (RuntimeType)FieldType;
199198
if (value is null)
200199
{
201200
if (RuntimeTypeHandle.IsValueType(fieldType))
202201
{
203-
fieldType.CheckValue(ref value, copyBack: ref _ref, binder, culture, invokeAttr);
202+
fieldType.CheckValue(ref value, binder, culture, invokeAttr);
204203
}
205204
}
206205
else if (!ReferenceEquals(value.GetType(), fieldType))
207206
{
208-
fieldType.CheckValue(ref value, copyBack: ref _ref, binder, culture, invokeAttr);
207+
fieldType.CheckValue(ref value, binder, culture, invokeAttr);
209208
}
210209

211210
bool domainInitialized = false;

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Collections.Generic;
55
using System.Diagnostics;
66
using System.Diagnostics.CodeAnalysis;
7-
using System.Globalization;
87
using System.Reflection.Metadata;
98
using System.Runtime.CompilerServices;
109
using System.Text;
@@ -29,28 +28,25 @@ internal sealed partial class RuntimeConstructorInfo : ConstructorInfo, IRuntime
2928
private readonly MethodAttributes m_methodAttributes;
3029
private readonly BindingFlags m_bindingFlags;
3130
private Signature? m_signature;
32-
private ConstructorInvoker? m_invoker;
31+
private MethodBaseInvoker? m_invoker;
3332

3433
internal InvocationFlags InvocationFlags
3534
{
3635
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3736
get
3837
{
3938
InvocationFlags flags = Invoker._invocationFlags;
40-
if ((flags & InvocationFlags.Initialized) == 0)
41-
{
42-
flags = ComputeAndUpdateInvocationFlags(this, ref Invoker._invocationFlags);
43-
}
39+
Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized);
4440
return flags;
4541
}
4642
}
4743

48-
private ConstructorInvoker Invoker
44+
internal MethodBaseInvoker Invoker
4945
{
5046
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5147
get
5248
{
53-
m_invoker ??= new ConstructorInvoker(this);
49+
m_invoker ??= new MethodBaseInvoker(this);
5450
return m_invoker;
5551
}
5652
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,7 @@ private static void AddCustomAttributes(
12591259
continue;
12601260
}
12611261

1262-
setMethod.InvokeOneParameter(attribute, BindingFlags.Default, null, value, null);
1262+
setMethod.InvokePropertySetter(attribute, BindingFlags.Default, null, value, null);
12631263
}
12641264
else
12651265
{

0 commit comments

Comments
 (0)