Skip to content
Open
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,24 +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.CodeAnalysis;
using System.Reflection.Emit;
using static System.Reflection.InvokerEmitUtil;

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

internal unsafe ConstructorInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
{
_signature = constructor.Signature;
_invokeFunc_RefArgs = InterpretedInvoke;
}

[RequiresUnsafe]
private unsafe object? InterpretedInvoke(object? obj, IntPtr* args)
{
return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
InvokeFunc_RefArgs emitDelegate;
using (AssemblyBuilder.ForceAllowDynamicCode())
{
emitDelegate = CreateInvokeDelegate_RefArgs(_method);
}

// Don't cache for collectible assemblies: the DynamicMethod holds token
// references to types that would prevent the assembly from being unloaded.
Type? declaringType = _method.DeclaringType;
if (declaringType is null || !declaringType.Assembly.IsCollectible)
{
_invokeFunc_RefArgs = emitDelegate;
}

return emitDelegate(obj, args);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@
// 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.CodeAnalysis;
using System.Reflection.Emit;
using static System.Reflection.InvokerEmitUtil;
using static System.Reflection.MethodBase;

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

internal unsafe MethodBaseInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
{
_signature = method.Signature;
_invocationFlags = method.ComputeAndUpdateInvocationFlags();
_invokeFunc_RefArgs = InterpretedInvoke_Method;
}

internal unsafe MethodBaseInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
{
_signature = constructor.Signature;
_invocationFlags = constructor.ComputeAndUpdateInvocationFlags();
_invokeFunc_RefArgs = InterpretedInvoke_Constructor;
_invokeFunc_RefArgs = InterpretedInvoke_Method;
}

internal unsafe MethodBaseInvoker(DynamicMethod method, Signature signature) : this(method, signature.Arguments)
{
_signature = signature;
_invokeFunc_RefArgs = InterpretedInvoke_Method;
}

[RequiresUnsafe]
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* args)
{
InvokeFunc_RefArgs emitDelegate;
using (AssemblyBuilder.ForceAllowDynamicCode())
{
emitDelegate = CreateInvokeDelegate_RefArgs(_method);
}

// Don't cache for collectible assemblies: the DynamicMethod holds token
// references to types that would prevent the assembly from being unloaded.
Type? declaringType = _method.DeclaringType;
if (declaringType is null || !declaringType.Assembly.IsCollectible)
{
_invokeFunc_RefArgs = emitDelegate;
}

return emitDelegate(obj, args);
}

[RequiresUnsafe]
private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: false);
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,47 @@
// 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.CodeAnalysis;
using System.Reflection.Emit;
using static System.Reflection.InvokerEmitUtil;

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

private unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
{
_signature = method.Signature;
_invokeFunc_RefArgs = InterpretedInvoke_Method;
_invocationFlags = method.ComputeAndUpdateInvocationFlags();
_invokeFunc_RefArgs = InterpretedInvoke_Method;
}

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

private unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments)
{
_signature = constructor.Signature;
_invokeFunc_RefArgs = InterpretedInvoke_Constructor;
_invocationFlags = constructor.ComputeAndUpdateInvocationFlags();
_invokeFunc_RefArgs = InterpretedInvoke_Method;
}

[RequiresUnsafe]
private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: false);
private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr* args)
{
InvokeFunc_RefArgs emitDelegate;
using (AssemblyBuilder.ForceAllowDynamicCode())
{
emitDelegate = CreateInvokeDelegate_RefArgs(_method);
}

Type? declaringType = _method.DeclaringType;
if (declaringType is null || !declaringType.Assembly.IsCollectible)
{
_invokeFunc_RefArgs = emitDelegate;
}

return emitDelegate(obj, args);
}

[RequiresUnsafe]
private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) =>
RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ internal InvocationFlags InvocationFlags
}
}

private MethodBaseInvoker Invoker
internal MethodBaseInvoker Invoker
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,16 +302,16 @@ private RuntimeCustomAttributeData(RuntimeModule scope, MetadataToken caCtorToke
#region Pseudo Custom Attribute Constructor
internal RuntimeCustomAttributeData(Attribute attribute)
{
if (attribute is DllImportAttribute dllImportAttribute)
Init(dllImportAttribute);
else if (attribute is FieldOffsetAttribute fieldOffsetAttribute)
Init(fieldOffsetAttribute);
else if (attribute is MarshalAsAttribute marshalAsAttribute)
Init(marshalAsAttribute);
else if (attribute is TypeForwardedToAttribute typeForwardedToAttribute)
Init(typeForwardedToAttribute);
else
Init(attribute);
if (attribute is DllImportAttribute dllImportAttribute)
Init(dllImportAttribute);
else if (attribute is FieldOffsetAttribute fieldOffsetAttribute)
Init(fieldOffsetAttribute);
else if (attribute is MarshalAsAttribute marshalAsAttribute)
Init(marshalAsAttribute);
else if (attribute is TypeForwardedToAttribute typeForwardedToAttribute)
Init(typeForwardedToAttribute);
else
Init(attribute);
}
private void Init(DllImportAttribute dllImport)
{
Expand Down Expand Up @@ -849,24 +849,24 @@ private static CustomAttributeEncodedArgument ParseCustomAttributeValue(
arg.StringValue = parser.GetString();
break;
case CustomAttributeEncoding.Array:
{
arg.ArrayValue = null;
int len = parser.GetI4();
if (len != -1) // indicates array is null - ECMA-335 II.23.3.
{
attributeType = new CustomAttributeType(
attributeType.EncodedArrayType,
CustomAttributeEncoding.Undefined, // Array type
attributeType.EncodedEnumType,
attributeType.EnumType);
arg.ArrayValue = new CustomAttributeEncodedArgument[len];
for (int i = 0; i < len; ++i)
arg.ArrayValue = null;
int len = parser.GetI4();
if (len != -1) // indicates array is null - ECMA-335 II.23.3.
{
arg.ArrayValue[i] = ParseCustomAttributeValue(ref parser, attributeType, module);
attributeType = new CustomAttributeType(
attributeType.EncodedArrayType,
CustomAttributeEncoding.Undefined, // Array type
attributeType.EncodedEnumType,
attributeType.EnumType);
arg.ArrayValue = new CustomAttributeEncodedArgument[len];
for (int i = 0; i < len; ++i)
{
arg.ArrayValue[i] = ParseCustomAttributeValue(ref parser, attributeType, module);
}
}
break;
}
break;
}
default:
throw new BadImageFormatException();
}
Expand Down Expand Up @@ -1859,6 +1859,88 @@ private static bool ParseAttributeUsageAttribute(
return result != 0;
}

[UnmanagedCallersOnly]
[RequiresUnsafe]
private static unsafe void InvokeCustomAttributeCtor(NativeCtorInvokeContract* pContract, object* pResult, Exception* pException)
{
try
{
object?[]? parameters = *pContract->CtorArgs;
object? ctorObject = *pContract->CtorMethod;

int argCount = pContract->ArgCount;
if (argCount < 0 || parameters is null || parameters.Length != argCount)
{
throw new TargetParameterCountException(SR.Arg_ParmCnt);
}

RuntimeConstructorInfo? ctor = ctorObject as RuntimeConstructorInfo;
if (ctor is null)
{
if (ctorObject is not System.IRuntimeMethodInfo methodInfo ||
RuntimeType.GetMethodBase(methodInfo) is not RuntimeConstructorInfo resolvedCtor)
{
throw new InvalidOperationException("Invalid custom attribute constructor.");
}

ctor = resolvedCtor;
}

ReadOnlySpan<ParameterInfo> ctorParameters = default;
bool needCtorParameters = false;

for (int i = 0; i < argCount; i++)
{
object? arg = parameters[i];

if (ReferenceEquals(arg, DBNull.Value) || ReferenceEquals(arg, Missing.Value))
{
parameters[i] = null;
continue;
}

if (arg is not null && arg.GetType() == typeof(object))
{
if (!needCtorParameters)
{
ctorParameters = ctor.GetParametersAsSpan();
needCtorParameters = true;
}

if ((uint)i < (uint)ctorParameters.Length && ctorParameters[i].ParameterType == typeof(object))
{
// Native custom-attribute parsing can represent object-typed null as a plain object instance.
parameters[i] = null;
}
}
}

MethodBaseInvoker invoker = ctor.Invoker;
object? result = argCount switch
{
0 => invoker.InvokeWithNoArgs(obj: null, BindingFlags.DoNotWrapExceptions),
1 => invoker.InvokeWithOneArg(obj: null, BindingFlags.DoNotWrapExceptions, binder: null, parameters, culture: null),
2 or 3 or 4 => invoker.InvokeWithFewArgs(obj: null, BindingFlags.DoNotWrapExceptions, binder: null, parameters, culture: null),
_ => invoker.InvokeWithManyArgs(obj: null, BindingFlags.DoNotWrapExceptions, binder: null, parameters, culture: null),
};

*pResult = result!;
}
catch (Exception ex)
{
*pException = ex;
}
}

[StructLayout(LayoutKind.Sequential)]
private unsafe struct NativeCtorInvokeContract
{
public object[]* CtorArgs;
public int ArgCount;
public object* CtorMethod;
public object* CtorDeclaringType;
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_CreateCustomAttributeInstance")]
private static partial void CreateCustomAttributeInstance(
QCallModule pModule,
Expand Down
21 changes: 0 additions & 21 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,27 +1192,6 @@ internal static MdUtf8String GetUtf8Name(RuntimeMethodHandleInternal method)
return new MdUtf8String(name);
}

[DebuggerStepThrough]
[DebuggerHidden]
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_InvokeMethod")]
[RequiresUnsafe]
private static partial void InvokeMethod(ObjectHandleOnStack target, void** arguments, ObjectHandleOnStack sig, Interop.BOOL isConstructor, ObjectHandleOnStack result);

[DebuggerStepThrough]
[DebuggerHidden]
[RequiresUnsafe]
internal static object? InvokeMethod(object? target, void** arguments, Signature sig, bool isConstructor)
{
object? result = null;
InvokeMethod(
ObjectHandleOnStack.Create(ref target),
arguments,
ObjectHandleOnStack.Create(ref sig),
isConstructor ? Interop.BOOL.TRUE : Interop.BOOL.FALSE,
ObjectHandleOnStack.Create(ref result));
return result;
}

/// <summary>
/// For a true boxed Nullable{T}, re-box to a boxed {T} or null, otherwise just return the input.
/// </summary>
Expand Down
Loading
Loading