Skip to content

Revert "Add IL Emit support for MethodInfo.Invoke() and friends" #69373

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

Merged
merged 2 commits into from
May 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<EnableDefaultItems>false</EnableDefaultItems>
Expand Down Expand Up @@ -155,12 +155,12 @@
<Compile Include="$(BclSourcesRoot)\System\Reflection\AssemblyName.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Associates.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\ConstructorInfo.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\ConstructorInvoker.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\AssemblyBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\ConstructorBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\CustomAttributeBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicILGenerator.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicMethod.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicMethodInvoker.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\EnumBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\EventBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\FieldBuilder.cs" />
Expand All @@ -187,7 +187,6 @@
<Compile Include="$(BclSourcesRoot)\System\Reflection\Metadata\AssemblyExtensions.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Metadata\MetadataUpdater.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodBase.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\MethodInvoker.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\RtFieldInfo.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\RuntimeAssembly.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\RuntimeConstructorInfo.CoreCLR.cs" />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public sealed class DynamicMethod : MethodInfo
private RuntimeModule m_module = null!;
internal bool m_skipVisibility;
internal RuntimeType? m_typeOwner; // can be null
private MethodInvoker? _invoker;
private DynamicMethodInvoker? _invoker;
private Signature? _signature;

// We want the creator of the DynamicMethod to control who has access to the
Expand Down Expand Up @@ -434,12 +434,13 @@ internal RuntimeMethodHandle GetMethodDescriptor()

public override bool IsSecurityTransparent => false;

private MethodInvoker Invoker
private DynamicMethodInvoker Invoker
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
_invoker ??= new MethodInvoker(this, Signature);
_invoker ??= new DynamicMethodInvoker(this);

return _invoker;
}
}
Expand Down Expand Up @@ -489,7 +490,7 @@ Signature LazyCreateSignature()
{
if (argCount == 0)
{
retValue = Invoker.InlinedInvoke(obj, args: default, invokeAttr);
retValue = Invoker.InvokeUnsafe(obj, args: default, invokeAttr);
}
else if (argCount > MaxStackAllocArgCount)
{
Expand All @@ -500,8 +501,8 @@ Signature LazyCreateSignature()
{
Debug.Assert(parameters != null);
StackAllocedArguments argStorage = default;
Span<object?> copyOfParameters = new(ref argStorage._arg0, argCount);
Span<ParameterCopyBackAction> shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount);
Span<object?> copyOfParameters = new Span<object?>(ref argStorage._arg0, argCount);
Span<bool> shouldCopyBackParameters = new Span<bool>(ref argStorage._copyBack0, argCount);

StackAllocatedByRefs byrefStorage = default;
IntPtr* pByRefStorage = (IntPtr*)&byrefStorage;
Expand All @@ -516,25 +517,14 @@ Signature LazyCreateSignature()
culture,
invokeAttr);

retValue = Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr);
retValue = Invoker.InvokeUnsafe(obj, pByRefStorage, invokeAttr);

// Copy modified values out. This should be done only with ByRef or Type.Missing parameters.
for (int i = 0; i < argCount; i++)
{
ParameterCopyBackAction action = shouldCopyBackParameters[i];
if (action != ParameterCopyBackAction.None)
if (shouldCopyBackParameters[i])
{
if (action == ParameterCopyBackAction.Copy)
{
parameters[i] = copyOfParameters[i];
}
else
{
Debug.Assert(action == ParameterCopyBackAction.CopyNullable);
Debug.Assert(copyOfParameters[i] != null);
Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT);
parameters[i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]);
}
parameters[i] = copyOfParameters[i];
}
}
}
Expand All @@ -556,15 +546,15 @@ Signature LazyCreateSignature()
CultureInfo? culture)
{
object[] objHolder = new object[argCount];
Span<object?> copyOfParameters = new(objHolder, 0, argCount);
Span<object?> copyOfParameters = new Span<object?>(objHolder, 0, argCount);

// We don't check a max stack size since we are invoking a method which
// naturally requires a stack size that is dependent on the arg count\size.
IntPtr* pByRefStorage = stackalloc IntPtr[argCount];
Buffer.ZeroMemory((byte*)pByRefStorage, (uint)(argCount * sizeof(IntPtr)));

ParameterCopyBackAction* copyBackActions = stackalloc ParameterCopyBackAction[argCount];
Span<ParameterCopyBackAction> shouldCopyBackParameters = new(copyBackActions, argCount);
bool* boolHolder = stackalloc bool[argCount];
Span<bool> shouldCopyBackParameters = new Span<bool>(boolHolder, argCount);

GCFrameRegistration reg = new(pByRefStorage, (uint)argCount, areByRefs: true);

Expand All @@ -582,7 +572,7 @@ Signature LazyCreateSignature()
culture,
invokeAttr);

retValue = mi.Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr);
retValue = mi.Invoker.InvokeUnsafe(obj, pByRefStorage, invokeAttr);
}
finally
{
Expand All @@ -592,26 +582,36 @@ Signature LazyCreateSignature()
// Copy modified values out. This should be done only with ByRef or Type.Missing parameters.
for (int i = 0; i < argCount; i++)
{
ParameterCopyBackAction action = shouldCopyBackParameters[i];
if (action != ParameterCopyBackAction.None)
if (shouldCopyBackParameters[i])
{
if (action == ParameterCopyBackAction.Copy)
{
parameters[i] = copyOfParameters[i];
}
else
{
Debug.Assert(action == ParameterCopyBackAction.CopyNullable);
Debug.Assert(copyOfParameters[i] != null);
Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT);
parameters[i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]);
}
parameters[i] = copyOfParameters[i];
}
}

return retValue;
}

[DebuggerHidden]
[DebuggerStepThrough]
internal unsafe object? InvokeNonEmitUnsafe(object? obj, IntPtr* arguments, 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);
}
}

public override object[] GetCustomAttributes(Type attributeType, bool inherit)
{
return m_dynMethod.GetCustomAttributes(attributeType, inherit);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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
{
private readonly DynamicMethod _dynamicMethod;

public DynamicMethodInvoker(DynamicMethod dynamicMethod)
{
_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);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public override void SetValue(object? obj, object? value, BindingFlags invokeAtt

CheckConsistency(obj);

ParameterCopyBackAction _ref = default;
bool _ref = false;
RuntimeType fieldType = (RuntimeType)FieldType;
if (value is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,27 @@ Signature LazyCreateSignature()

internal BindingFlags BindingFlags => m_bindingFlags;


[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)!;
}
}
#endregion

#region Object Overrides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private MethodInvoker Invoker
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
m_invoker ??= new MethodInvoker(this, Signature);
m_invoker ??= new MethodInvoker(this);
return m_invoker;
}
}
Expand Down Expand Up @@ -351,7 +351,7 @@ public override MethodImplAttributes GetMethodImplementationFlags()
StackAllocedArguments argStorage = default;
Span<object?> copyOfParameters = new(ref argStorage._arg0, 1);
ReadOnlySpan<object?> parameters = new(in parameter);
Span<ParameterCopyBackAction> shouldCopyBackParameters = new(ref argStorage._copyBack0, 1);
Span<bool> shouldCopyBackParameters = new(ref argStorage._copyBack0, 1);

StackAllocatedByRefs byrefStorage = default;
IntPtr* pByRefStorage = (IntPtr*)&byrefStorage;
Expand All @@ -366,16 +366,33 @@ public override MethodImplAttributes GetMethodImplementationFlags()
culture,
invokeAttr);

#if MONO // Temporary until Mono is updated.
retValue = Invoker.InlinedInvoke(obj, copyOfParameters, invokeAttr);
#else
retValue = Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr);
#endif
retValue = Invoker.InvokeUnsafe(obj, pByRefStorage, copyOfParameters, invokeAttr);
}

return retValue;
}

[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);
}
}

#endregion

#region MethodInfo Overrides
Expand Down
19 changes: 0 additions & 19 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,6 @@ internal static bool IsByRef(RuntimeType type)
return corElemType == CorElementType.ELEMENT_TYPE_BYREF;
}

internal static bool TryGetByRefElementType(RuntimeType type, [NotNullWhen(true)] out RuntimeType? elementType)
{
CorElementType corElemType = GetCorElementType(type);
if (corElemType == CorElementType.ELEMENT_TYPE_BYREF)
{
elementType = GetElementType(type);
return true;
}

elementType = null;
return false;
}

internal static bool IsPointer(RuntimeType type)
{
CorElementType corElemType = GetCorElementType(type);
Expand Down Expand Up @@ -994,12 +981,6 @@ 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