Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IL Emit support for MethodInfo.Invoke() and friends #67917

Merged
merged 23 commits into from
May 9, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d4f6b51
Add IL Emit support for MethodInfo.Invoke()
steveharter Apr 11, 2022
023299c
Test updates
steveharter Apr 13, 2022
19959c0
Create true Nullable<T>s to simplify native and IL
steveharter Apr 19, 2022
40eb391
Update Emit code for new Nullability; still running non-emit for tests
steveharter Apr 19, 2022
a1f7a5c
Enable IL for testing; improve perf for ByRef param validation
steveharter Apr 20, 2022
50cd45b
Merge branch 'main' of https://github.com/steveharter/runtime into Em…
steveharter Apr 21, 2022
ba141ce
Fixup merge
steveharter Apr 21, 2022
79571d9
Ensure a copy is made for byref value types
steveharter Apr 22, 2022
c2ae6e4
Remove temps in IL
steveharter Apr 24, 2022
97dc203
Remove hard check for Type.GetType()
steveharter Apr 24, 2022
69d467d
Active issue some tests; misc other
steveharter Apr 25, 2022
259c4e0
Remove IL-only test hack; ready for review
steveharter Apr 27, 2022
9dab8f7
Add emit to DynamicMethod; other misc feedback
steveharter Apr 28, 2022
e7878ff
Fix Mono compile issue
steveharter Apr 28, 2022
13f913a
Fix shuffle thunk; other misc non-functional
steveharter Apr 29, 2022
1516fbf
Fix possible null method.DeclaringType; binding test failures with Ch…
steveharter May 2, 2022
54e0a77
Fix DynamicMethod.Invoke when using Emit-based invoke
steveharter May 3, 2022
89a0483
Disable some JIT Stress tests on arm32 linux
steveharter May 3, 2022
9e50960
renaming; native perf; other feedback
steveharter May 5, 2022
53a4167
Nit feedback
steveharter May 5, 2022
8efba3d
For perf, avoid calling ReboxFromNullable when not necessary
steveharter May 6, 2022
55a4f95
Merge branch 'main' into EmitInvoke
steveharter May 6, 2022
c7bee67
For perf, avoid calling ReboxFromNullable when not necessary part 2
steveharter May 6, 2022
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 @@ -524,7 +524,7 @@ Signature LazyCreateSignature()
{
if (shouldCopyBackParameters[i])
{
parameters[i] = copyOfParameters[i];
parameters[i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]);
}
}
}
Expand Down Expand Up @@ -584,7 +584,7 @@ Signature LazyCreateSignature()
{
if (shouldCopyBackParameters[i])
{
parameters[i] = copyOfParameters[i];
parameters[i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]);
}
}

Expand All @@ -593,23 +593,9 @@ Signature LazyCreateSignature()

[DebuggerHidden]
[DebuggerStepThrough]
internal unsafe object? InvokeNonEmitUnsafe(object? obj, IntPtr* arguments, BindingFlags invokeAttr)
internal unsafe object? InvokeNonEmitUnsafe(object? obj, IntPtr* arguments)
{
if ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0)
{
try
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, Signature, isConstructor: false);
}
catch (Exception e)
{
throw new TargetInvocationException(e);
}
}
else
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, Signature, isConstructor: false);
}
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, Signature, isConstructor: false);
}

public override object[] GetCustomAttributes(Type attributeType, bool inherit)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// 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.Runtime.CompilerServices;

namespace System.Reflection.Emit
{
internal sealed partial class DynamicMethodInvoker
Expand All @@ -17,8 +14,23 @@ public DynamicMethodInvoker(DynamicMethod dynamicMethod)

public unsafe object? InvokeUnsafe(object? obj, IntPtr* args, BindingFlags invokeAttr)
{
// Todo: add strategy for calling IL Emit-based version
return _dynamicMethod.InvokeNonEmitUnsafe(obj, args, invokeAttr);
// Always use the slow path; the Emit-based fast path can be added but in general dynamic
steveharter marked this conversation as resolved.
Show resolved Hide resolved
// methods are invoked through a direct delegate, not through Invoke().
if ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0)
{
try
{
return _dynamicMethod.InvokeNonEmitUnsafe(obj, args);
}
catch (Exception e)
{
throw new TargetInvocationException(e);
}
}
else
{
return _dynamicMethod.InvokeNonEmitUnsafe(obj, args);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,26 +95,15 @@ Signature LazyCreateSignature()

internal BindingFlags BindingFlags => m_bindingFlags;

#pragma warning disable CA1822 // Mark members as static
internal bool SupportsNewInvoke => true;
#pragma warning restore CA1822 // Mark members as static

[DebuggerStepThrough]
[DebuggerHidden]
internal unsafe object InvokeNonEmitUnsafe(object? obj, IntPtr* args, Span<object?> argsForTemporaryMonoSupport, BindingFlags invokeAttr)
{
if ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0)
{
try
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, Signature, isConstructor: obj is null)!;
}
catch (Exception ex)
{
throw new TargetInvocationException(ex);
}
}
else
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, Signature, isConstructor: obj is null)!;
}
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, Signature, isConstructor: obj is null)!;
}
#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,25 +372,15 @@ public override MethodImplAttributes GetMethodImplementationFlags()
return retValue;
}

#pragma warning disable CA1822 // Mark members as static
internal bool SupportsNewInvoke => true;
#pragma warning restore CA1822 // Mark members as static

[DebuggerHidden]
[DebuggerStepThrough]
internal unsafe object? InvokeNonEmitUnsafe(object? obj, IntPtr* arguments, Span<object?> argsForTemporaryMonoSupport, BindingFlags invokeAttr)
{
if ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0)
{
try
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, Signature, isConstructor: false);
}
catch (Exception e)
{
throw new TargetInvocationException(e);
}
}
else
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, Signature, isConstructor: false);
}
return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, Signature, isConstructor: false);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,12 @@ internal static MdUtf8String GetUtf8Name(RuntimeMethodHandleInternal method)
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object? InvokeMethod(object? target, void** arguments, Signature sig, bool isConstructor);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object? ReboxFromNullable(object? src);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object ReboxToNullable(object? src, RuntimeType destNullableType);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_GetMethodInstantiation")]
private static partial void GetMethodInstantiation(RuntimeMethodHandleInternal method, ObjectHandleOnStack types, Interop.BOOL fAsRuntimeTypeArray);

Expand Down
Loading