Skip to content
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0e4b6eb
Replace OpCodes.NewObj with GetUninitializedObject()
steveharter Oct 7, 2024
062552f
Initial switch from Call to Calli
steveharter Oct 23, 2024
47ea274
Merge branch 'main' of https://github.com/steveharter/runtime into Re…
steveharter Oct 23, 2024
76bd6f9
Add back CallVirt; add caching and well-known signatures
steveharter Nov 10, 2024
fbf8049
Only cache dynamic methods, not invoker
steveharter Nov 12, 2024
a570df7
Merge branch 'main' of https://github.com/steveharter/runtime into Re…
steveharter Nov 12, 2024
febdd32
Share cache and more code across 3 invokers
steveharter Nov 14, 2024
34d9669
Add more well-known signatures
steveharter Nov 14, 2024
e57a58c
Initial mono; keep interpreted path
steveharter Nov 16, 2024
517e5d5
Initial mono; keep interpreted path #2
steveharter Nov 17, 2024
c7b5336
Address build and some test issues
steveharter Nov 18, 2024
eb37b87
Address a test issue with generics
steveharter Nov 18, 2024
b0f8a58
Misc cleanup; disable well-known method impl for now
steveharter Nov 22, 2024
c16d691
Add back well-known types
steveharter Nov 24, 2024
146c7d2
Fix compile issue due to auto-added incorrect using
steveharter Nov 25, 2024
77532ed
Fix a couple test cases
steveharter Nov 25, 2024
a0a4d46
Fix a mono build issue
steveharter Nov 25, 2024
2f00fff
Address a test issue
steveharter Nov 26, 2024
b04f1bd
Fix build issue due to change in main
steveharter Nov 27, 2024
1513336
Merge branch 'main' of https://github.com/steveharter/runtime into Re…
steveharter Nov 27, 2024
7e86911
Fix null ref exception; remove unnecessary fields
steveharter Nov 27, 2024
9f9d719
Merge branch 'main' of https://github.com/steveharter/runtime into Re…
steveharter Dec 27, 2024
9ef933d
Merge branch 'main' of https://github.com/steveharter/runtime into Re…
steveharter Jan 16, 2025
dfe0e4d
Fix merge; update unloadable assembly test
steveharter Jan 16, 2025
62d884a
Update some reflection tests
steveharter Jan 17, 2025
58a2c20
Fix some Mono test issues
steveharter Jan 21, 2025
baa3f2a
Check EventSource.IsSupported feature switch
steveharter Jan 22, 2025
287c67b
Misc cleanup
steveharter Jan 29, 2025
a585d31
Undo .sln changes; rename a variable
steveharter Feb 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodBase.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodBaseInvoker.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodInvoker.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodInvokerCommon.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\ModifiedType.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\RtFieldInfo.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\RuntimeAssembly.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using static System.Reflection.InvokerEmitUtil;
using static System.Reflection.MethodBase;
using static System.RuntimeType;

namespace System.Reflection
{
public partial class ConstructorInvoker
{
private readonly Signature? _signature;
private readonly CreateUninitializedCache? _allocator;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private object CreateUninitializedObject() => _allocator!.CreateUninitializedObject(_declaringType);

internal unsafe ConstructorInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
private bool ShouldAllocate => _allocator is not null;

private unsafe Delegate CreateInvokeDelegateForInterpreted()
{
_signature = constructor.Signature;
_invokeFunc_RefArgs = InterpretedInvoke;
Debug.Assert(MethodInvokerCommon.UseInterpretedPath);
Debug.Assert(_strategy == InvokerStrategy.Ref4 || _strategy == InvokerStrategy.RefMany);

return (InvokeFunc_RefArgs)InterpretedInvoke;
}

private unsafe object? InterpretedInvoke(object? obj, IntPtr* args)
private unsafe object? InterpretedInvoke(object? obj, IntPtr _, IntPtr* args)
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _method.Signature, isConstructor: obj is null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private MethodBaseInvoker Invoker
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return _invoker ??= new MethodBaseInvoker(this, Signature);
return _invoker ??= new MethodBaseInvoker(this, Signature.Arguments, ReturnType);
}
}

Expand Down Expand Up @@ -132,13 +132,17 @@ Signature LazyCreateSignature()
int argCount = (parameters != null) ? parameters.Length : 0;
if (Signature.Arguments.Length != argCount)
throw new TargetParameterCountException(SR.Arg_ParmCnt);
object? retValue = argCount switch

object? retValue = Invoker.Strategy switch
{
0 => Invoker.InvokeWithNoArgs(obj, invokeAttr),
1 => Invoker.InvokeWithOneArg(obj, invokeAttr, binder, parameters!, culture),
2 or 3 or 4 => Invoker.InvokeWithFewArgs(obj, invokeAttr, binder, parameters!, culture),
_ => Invoker.InvokeWithManyArgs(obj, invokeAttr, binder, parameters!, culture),
MethodBase.InvokerStrategy.Obj0 => Invoker.InvokeWithNoArgs(obj, invokeAttr),
MethodBase.InvokerStrategy.Obj1 => Invoker.InvokeWith1Arg(obj, invokeAttr, binder, parameters!, culture),
MethodBase.InvokerStrategy.Obj4 => Invoker.InvokeWith4Args(obj, invokeAttr, binder, parameters!, culture),
MethodBase.InvokerStrategy.ObjSpan => Invoker.InvokeWithSpanArgs(obj, invokeAttr, binder, parameters!, culture),
MethodBase.InvokerStrategy.Ref4 => Invoker.InvokeWith4RefArgs(obj, invokeAttr, binder, parameters, culture),
_ => Invoker.InvokeWithManyRefArgs(obj, invokeAttr, binder, parameters!, culture)
};

GC.KeepAlive(this);
return retValue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using static System.Reflection.InvokerEmitUtil;
using static System.Reflection.MethodBase;
using static System.RuntimeType;

namespace System.Reflection
{
internal partial class MethodBaseInvoker
{
private readonly Signature? _signature;
private readonly CreateUninitializedCache? _allocator;

internal unsafe MethodBaseInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
{
_signature = method.Signature;
_invocationFlags = method.ComputeAndUpdateInvocationFlags();
_invokeFunc_RefArgs = InterpretedInvoke_Method;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private object CreateUninitializedObject() => _allocator!.CreateUninitializedObject(_declaringType!);

internal unsafe MethodBaseInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
{
_signature = constructor.Signature;
_invocationFlags = constructor.ComputeAndUpdateInvocationFlags();
_invokeFunc_RefArgs = InterpretedInvoke_Constructor;
}
private bool ShouldAllocate => _allocator is not null;

internal unsafe MethodBaseInvoker(DynamicMethod method, Signature signature) : this(method, signature.Arguments)
private unsafe Delegate CreateInvokeDelegateForInterpreted()
{
_signature = signature;
_invokeFunc_RefArgs = InterpretedInvoke_Method;
Debug.Assert(MethodInvokerCommon.UseInterpretedPath);
Debug.Assert(_strategy == InvokerStrategy.Ref4 || _strategy == InvokerStrategy.RefMany);

if (_method is RuntimeMethodInfo)
{
return (InvokeFunc_RefArgs)InterpretedInvoke_Method;
}

if (_method is RuntimeConstructorInfo)
{
return (InvokeFunc_RefArgs)InterpretedInvoke_Constructor;
}

Debug.Assert(_method is DynamicMethod);
return (InvokeFunc_RefArgs)InterpretedInvoke_DynamicMethod;
}

private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr _, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, ((RuntimeMethodInfo)_method).Signature, isConstructor: false);

private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr _, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, ((RuntimeConstructorInfo)_method).Signature, isConstructor: obj is null);

private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: false);
private unsafe object? InterpretedInvoke_DynamicMethod(object? obj, IntPtr _, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, ((DynamicMethod)_method).Signature, isConstructor: false);
}
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Reflection.Emit;
using static System.Reflection.InvokerEmitUtil;
using static System.Reflection.MethodBase;

namespace System.Reflection
{
public partial class MethodInvoker
{
private readonly Signature? _signature;

private unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
private unsafe Delegate CreateInvokeDelegateForInterpreted()
{
_signature = method.Signature;
_invokeFunc_RefArgs = InterpretedInvoke_Method;
_invocationFlags = method.ComputeAndUpdateInvocationFlags();
}
Debug.Assert(MethodInvokerCommon.UseInterpretedPath);
Debug.Assert(_strategy == InvokerStrategy.Ref4 || _strategy == InvokerStrategy.RefMany);

private unsafe MethodInvoker(DynamicMethod method) : this(method, method.Signature.Arguments)
{
_signature = method.Signature;
_invokeFunc_RefArgs = InterpretedInvoke_Method;
// No _invocationFlags for DynamicMethod.
}
if (_method is RuntimeMethodInfo)
{
return (InvokeFunc_RefArgs)InterpretedInvoke_Method;
}

private unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
{
_signature = constructor.Signature;
_invokeFunc_RefArgs = InterpretedInvoke_Constructor;
_invocationFlags = constructor.ComputeAndUpdateInvocationFlags();
if (_method is RuntimeConstructorInfo)
{
return (InvokeFunc_RefArgs)InterpretedInvoke_Constructor;
}

Debug.Assert(_method is DynamicMethod);
return (InvokeFunc_RefArgs)InterpretedInvoke_DynamicMethod;
}

private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: false);
private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr _, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, ((RuntimeConstructorInfo)_method).Signature, isConstructor: obj is null);

private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr _, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, ((RuntimeMethodInfo)_method).Signature, isConstructor: false);

private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
private unsafe object? InterpretedInvoke_DynamicMethod(object? obj, IntPtr _, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, ((DynamicMethod)_method).Signature, isConstructor: false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;

namespace System.Reflection
{
internal static partial class MethodInvokerCommon
{
// For CoreClr, we may be able to remove the interpreted path; it is not used in the CoreCLR implementation
// unless the feature switch is enabled. Unlike Mono, there are no interpreted-only platforms.
internal static bool UseInterpretedPath => LocalAppContextSwitches.ForceInterpretedInvoke || !RuntimeFeature.IsDynamicCodeSupported;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,19 @@ internal sealed partial class RuntimeConstructorInfo : ConstructorInfo, IRuntime
private readonly BindingFlags m_bindingFlags;
private Signature? m_signature;
private MethodBaseInvoker? m_invoker;
private InvocationFlags m_invocationFlags;

internal InvocationFlags InvocationFlags
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
InvocationFlags flags = Invoker._invocationFlags;
InvocationFlags flags = m_invocationFlags;
if (flags == InvocationFlags.Unknown)
{
m_invocationFlags = flags = ComputeInvocationFlags();
}

Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized);
return flags;
}
Expand All @@ -46,8 +52,7 @@ private MethodBaseInvoker Invoker
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
m_invoker ??= new MethodBaseInvoker(this);
return m_invoker;
return m_invoker ??= new MethodBaseInvoker(this, ArgumentTypes, GetReturnType());
}
}
#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ internal sealed partial class RuntimeMethodInfo : MethodInfo, IRuntimeMethodInfo
private readonly RuntimeType m_declaringType;
private readonly object? m_keepalive;
private MethodBaseInvoker? m_invoker;
private InvocationFlags m_invocationFlags;

internal InvocationFlags InvocationFlags
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
InvocationFlags flags = Invoker._invocationFlags;
InvocationFlags flags = m_invocationFlags;
if (flags == InvocationFlags.Unknown)
{
m_invocationFlags = flags = ComputeInvocationFlags();
}

Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized);
return flags;
}
Expand All @@ -45,8 +51,7 @@ private MethodBaseInvoker Invoker
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
m_invoker ??= new MethodBaseInvoker(this);
return m_invoker;
return m_invoker ??= new MethodBaseInvoker(this, ArgumentTypes, ReturnType);
}
}
#endregion
Expand Down Expand Up @@ -306,7 +311,7 @@ internal void InvokePropertySetter(object? obj, BindingFlags invokeAttr, Binder?
throw new TargetParameterCountException(SR.Arg_ParmCnt);
}

Invoker.InvokePropertySetter(obj, invokeAttr, binder, parameter, culture);
Invoker.InvokeWith1Arg(obj, invokeAttr, binder, parameter, culture);
}

#endregion
Expand Down
Loading
Loading