From a3428edd3119c375b2bca994da9c8e56937f90ff Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Thu, 27 Apr 2023 14:30:41 -0500 Subject: [PATCH 1/6] Add public Invoker classes --- build | 0 .../System.Private.CoreLib.csproj | 2 + .../Reflection/ConstructorInvoker.CoreCLR.cs | 17 +- .../Reflection/Emit/DynamicMethod.CoreCLR.cs | 144 +----- .../Reflection/MethodBaseInvoker.CoreCLR.cs | 38 ++ .../Reflection/MethodInvoker.CoreCLR.cs | 43 +- .../src/System/Reflection/RtFieldInfo.cs | 5 +- .../RuntimeConstructorInfo.CoreCLR.cs | 12 +- .../Reflection/RuntimeCustomAttributeData.cs | 2 +- .../Reflection/RuntimeMethodInfo.CoreCLR.cs | 51 +- .../System/Reflection/RuntimePropertyInfo.cs | 2 +- .../RuntimeHelpers.CoreCLR.cs | 28 -- .../System/Runtime/RuntimeImports.CoreCLR.cs | 39 ++ .../src/System/RuntimeType.CoreCLR.cs | 44 +- .../src/CompatibilitySuppressions.xml | 2 +- .../Core/Execution/ExecutionEnvironment.cs | 10 +- ...{MethodInvoker.cs => MethodBaseInvoker.cs} | 12 +- .../Runtime/Augments/RuntimeAugments.cs | 2 +- .../src/System.Private.CoreLib.csproj | 4 +- .../System/Reflection/ConstructorInvoker.cs | 74 +++ .../System/Reflection/DynamicInvokeInfo.cs | 447 ++++++++++++++++-- .../src/System/Reflection/MethodInvoker.cs | 102 ++++ .../ReflectionCoreCallbacksImplementation.cs | 2 +- .../MethodInfos/CustomMethodInvoker.cs | 27 +- .../Runtime/MethodInfos/CustomMethodMapper.cs | 2 +- .../MethodInfos/IRuntimeMethodCommon.cs | 2 +- .../NativeFormat/NativeFormatMethodCommon.cs | 2 +- .../Runtime/MethodInfos/OpenMethodInvoker.cs | 22 +- .../RuntimeConstructedGenericMethodInfo.cs | 2 +- .../MethodInfos/RuntimeConstructorInfo.cs | 17 +- .../MethodInfos/RuntimeDummyMethodInfo.cs | 4 +- .../Runtime/MethodInfos/RuntimeMethodInfo.cs | 12 +- .../MethodInfos/RuntimeNamedMethodInfo.cs | 12 +- .../RuntimePlainConstructorInfo.cs | 4 +- .../RuntimeSyntheticConstructorInfo.cs | 4 +- .../MethodInfos/RuntimeSyntheticMethodInfo.cs | 2 +- .../PropertyInfos/RuntimePropertyInfo.cs | 4 +- .../src/System/RuntimeType.cs | 4 + ...EnvironmentImplementation.MappingTables.cs | 3 +- ...cutionEnvironmentImplementation.Runtime.cs | 2 +- .../MethodInvokers/InstanceMethodInvoker.cs | 54 ++- .../MethodInvokerWithMethodInvokeInfo.cs | 4 +- .../MethodInvokers/StaticMethodInvoker.cs | 43 +- .../MethodInvokers/VirtualMethodInvoker.cs | 56 ++- src/coreclr/vm/appdomain.cpp | 3 +- src/coreclr/vm/corelib.h | 3 +- src/coreclr/vm/ecalllist.h | 8 +- .../System/Reflection/InvokeEmitTests.cs | 10 +- .../Reflection/InvokeInterpretedTests.cs | 20 +- .../src/Resources/Strings.resx | 6 + .../System.Private.CoreLib.Shared.projitems | 12 +- .../System/Reflection/ConstructorInvoker.cs | 335 +++++++++++-- .../System/Reflection/Emit/DynamicMethod.cs | 2 + .../src/System/Reflection/InvokeUtils.cs | 8 +- .../src/System/Reflection/InvokerEmitUtil.cs | 148 +++++- .../src/System/Reflection/MethodBase.cs | 189 +++----- .../MethodBaseInvoker.Constructor.cs | 84 ++++ .../System/Reflection/MethodBaseInvoker.cs | 422 +++++++++++++++++ .../src/System/Reflection/MethodInvoker.cs | 357 ++++++++++++-- .../System/Reflection/MethodInvokerCommon.cs | 145 ++++++ .../Reflection/ParameterCopyBackAction.cs | 15 - .../Reflection/RuntimeConstructorInfo.cs | 289 +---------- .../System/Reflection/RuntimeMethodInfo.cs | 162 +------ .../src/System/RuntimeType.cs | 120 ++--- .../System.Reflection/System.Reflection.sln | 317 +++++++------ .../tests/ConstructorInvokerTests.cs | 146 ++++++ .../tests/MethodInfoTests.cs | 3 +- .../tests/MethodInvokerTests.cs | 277 +++++++++++ .../tests/System.Reflection.Tests.csproj | 2 + .../System.Runtime/ref/System.Runtime.cs | 22 + .../System.Private.CoreLib.csproj | 2 + .../Reflection/ConstructorInvoker.Mono.cs | 12 +- .../Reflection/MethodBaseInvoker.Mono.cs | 40 ++ .../System/Reflection/MethodInvoker.Mono.cs | 33 +- .../src/System/Reflection/RuntimeFieldInfo.cs | 3 +- .../Reflection/RuntimeMethodInfo.Mono.cs | 28 +- .../CompilerServices/RuntimeHelpers.Mono.cs | 16 - .../src/System/RuntimeImports.Mono.cs | 26 + .../src/System/RuntimeType.Mono.cs | 18 +- .../src/System/RuntimeTypeHandle.cs | 6 + .../SmokeTests/Reflection/Reflection.cs | 180 ++++++- 81 files changed, 3504 insertions(+), 1329 deletions(-) create mode 100644 build create mode 100644 src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.CoreCLR.cs create mode 100644 src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs rename src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/{MethodInvoker.cs => MethodBaseInvoker.cs} (80%) create mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs create mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterCopyBackAction.cs create mode 100644 src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs create mode 100644 src/libraries/System.Reflection/tests/MethodInvokerTests.cs create mode 100644 src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs create mode 100644 src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs diff --git a/build b/build new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 1dd3eb3291ca9a..728855bbdca964 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -185,6 +185,7 @@ + @@ -219,6 +220,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.CoreCLR.cs index 05f69d2670e3ed..f58e24742dc500 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.CoreCLR.cs @@ -1,18 +1,21 @@ // 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 partial class ConstructorInvoker + public partial class ConstructorInvoker { - public InvocationFlags _invocationFlags; + private readonly Signature? _signature; + + internal unsafe ConstructorInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments) + { + _signature = constructor.Signature; + _invokeFunc_RefArgs = InterpretedInvoke; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe object? InterpretedInvoke(object? obj, IntPtr* arguments) + private unsafe object? InterpretedInvoke(object? obj, IntPtr* args) { - return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, _method.Signature, isConstructor: obj is null)!; + return RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null); } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs index dc764971c2604d..91a35e6a63e92d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs @@ -24,7 +24,7 @@ public sealed partial class DynamicMethod : MethodInfo private Module _module; internal bool _skipVisibility; internal RuntimeType? _typeOwner; - private MethodInvoker? _invoker; + private MethodBaseInvoker? _invoker; private Signature? _signature; private string _name; private MethodAttributes _attributes; @@ -85,12 +85,12 @@ internal RuntimeMethodHandle GetMethodDescriptor() return new RuntimeMethodHandle(_methodHandle!); } - private MethodInvoker Invoker + internal MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return _invoker ??= new MethodInvoker(this, Signature); + return _invoker ??= new MethodBaseInvoker(this, Signature); } } @@ -134,136 +134,28 @@ Signature LazyCreateSignature() throw new TargetParameterCountException(SR.Arg_ParmCnt); object? retValue; - - unsafe + switch (argCount) { - if (argCount == 0) - { - retValue = Invoker.InlinedInvoke(obj, args: default, invokeAttr); - } - else if (argCount > MaxStackAllocArgCount) - { - Debug.Assert(parameters != null); - retValue = InvokeWithManyArguments(this, argCount, obj, invokeAttr, binder, parameters, culture); - } - else - { - Debug.Assert(parameters != null); - StackAllocedArguments argStorage = default; - Span copyOfParameters = argStorage._args.AsSpan(argCount); - Span shouldCopyBackParameters = argStorage._copyBacks.AsSpan(argCount); - - StackAllocatedByRefs byrefStorage = default; -#pragma warning disable CS8500 - IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; -#pragma warning restore CS8500 - - CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - Signature.Arguments, - binder, - culture, - invokeAttr); - - retValue = Invoker.InlinedInvoke(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 (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]); - } - } - } - } + case 0: + retValue = Invoker.InvokeWithNoArgs(obj, invokeAttr); + break; + case 1: + retValue = Invoker.InvokeWithOneArg(obj, invokeAttr, binder, parameters!, culture); + break; + case 2: + case 3: + case 4: + retValue = Invoker.InvokeWithFewArgs(obj, invokeAttr, binder, parameters!, culture); + break; + default: + retValue = Invoker.InvokeWithManyArgs(obj, invokeAttr, binder, parameters!, culture); + break; } GC.KeepAlive(this); return retValue; } - // Slower path that does a heap alloc for copyOfParameters and registers byrefs to those objects. - // This is a separate method to support better performance for the faster paths. - private static unsafe object? InvokeWithManyArguments( - DynamicMethod mi, - int argCount, - object? obj, - BindingFlags invokeAttr, - Binder? binder, - object?[] parameters, - CultureInfo? culture) - { - object[] objHolder = new object[argCount]; - Span copyOfParameters = new(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]; - NativeMemory.Clear(pByRefStorage, (uint)(argCount * sizeof(IntPtr))); - - ParameterCopyBackAction* copyBackActions = stackalloc ParameterCopyBackAction[argCount]; - Span shouldCopyBackParameters = new(copyBackActions, argCount); - - GCFrameRegistration reg = new(pByRefStorage, (uint)argCount, areByRefs: true); - - object? retValue; - try - { - RegisterForGCReporting(®); - mi.CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - mi.Signature.Arguments, - binder, - culture, - invokeAttr); - - retValue = mi.Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr); - } - finally - { - UnregisterForGCReporting(®); - } - - // 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 (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]); - } - } - } - - return retValue; - } - public DynamicILInfo GetDynamicILInfo() { if (_dynamicILInfo == null) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.CoreCLR.cs new file mode 100644 index 00000000000000..85e9a63d6ecc63 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.CoreCLR.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Reflection.Emit; + +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; + } + + internal unsafe MethodBaseInvoker(DynamicMethod method, Signature signature) : this(method, signature.Arguments) + { + _signature = signature; + _invokeFunc_RefArgs = InterpretedInvoke_Method; + } + + 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) => + RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor : false); + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs index 671206f80e821c..4d3946a49cbac1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs @@ -1,36 +1,39 @@ // 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; +using System.Diagnostics; +using System.Reflection.Emit; namespace System.Reflection { - internal partial class MethodInvoker + public partial class MethodInvoker { - private readonly Signature _signature; - internal InvocationFlags _invocationFlags; + private readonly Signature? _signature; - public MethodInvoker(MethodBase method, Signature signature) + internal unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments) { - _method = method; - _signature = signature; + _signature = method.Signature; + _invokeFunc_RefArgs = InterpretedInvoke_Method; + _invocationFlags = method.ComputeAndUpdateInvocationFlags(); + } - if (LocalAppContextSwitches.ForceInterpretedInvoke && !LocalAppContextSwitches.ForceEmitInvoke) - { - // Always use the native invoke; useful for testing. - _strategyDetermined = true; - } - else if (LocalAppContextSwitches.ForceEmitInvoke && !LocalAppContextSwitches.ForceInterpretedInvoke) - { - // Always use emit invoke (if IsDynamicCodeSupported == true); useful for testing. - _invoked = true; - } + internal unsafe MethodInvoker(DynamicMethod method) : this(method, method.Signature.Arguments) + { + _signature = method.Signature; + _invokeFunc_RefArgs = InterpretedInvoke_Method; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe object? InterpretedInvoke(object? obj, IntPtr* arguments) + internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments) { - return RuntimeMethodHandle.InvokeMethod(obj, (void**)arguments, _signature, isConstructor: false); + _signature = constructor.Signature; + _invokeFunc_RefArgs = InterpretedInvoke_Constructor; + _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); } + + 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* args) => + RuntimeMethodHandle.InvokeMethod(obj, (void**)args, _signature!, isConstructor: obj is null); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs index a77102fc2b51fe..2059daa80674ac 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs @@ -194,18 +194,17 @@ public override void SetValue(object? obj, object? value, BindingFlags invokeAtt CheckConsistency(obj); - ParameterCopyBackAction _ref = default; RuntimeType fieldType = (RuntimeType)FieldType; if (value is null) { if (RuntimeTypeHandle.IsValueType(fieldType)) { - fieldType.CheckValue(ref value, copyBack: ref _ref, binder, culture, invokeAttr); + fieldType.CheckValue(ref value, binder, culture, invokeAttr); } } else if (!ReferenceEquals(value.GetType(), fieldType)) { - fieldType.CheckValue(ref value, copyBack: ref _ref, binder, culture, invokeAttr); + fieldType.CheckValue(ref value, binder, culture, invokeAttr); } bool domainInitialized = false; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs index 2fa7952e07a82d..ac0ad4886fad10 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Globalization; using System.Reflection.Metadata; using System.Runtime.CompilerServices; using System.Text; @@ -29,7 +28,7 @@ internal sealed partial class RuntimeConstructorInfo : ConstructorInfo, IRuntime private readonly MethodAttributes m_methodAttributes; private readonly BindingFlags m_bindingFlags; private Signature? m_signature; - private ConstructorInvoker? m_invoker; + private MethodBaseInvoker? m_invoker; internal InvocationFlags InvocationFlags { @@ -37,20 +36,17 @@ internal InvocationFlags InvocationFlags get { InvocationFlags flags = Invoker._invocationFlags; - if ((flags & InvocationFlags.Initialized) == 0) - { - flags = ComputeAndUpdateInvocationFlags(this, ref Invoker._invocationFlags); - } + Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized); return flags; } } - private ConstructorInvoker Invoker + internal MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - m_invoker ??= new ConstructorInvoker(this); + m_invoker ??= new MethodBaseInvoker(this); return m_invoker; } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index 7ec37002150389..ce9182cc4785bc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -1259,7 +1259,7 @@ private static void AddCustomAttributes( continue; } - setMethod.InvokeOneParameter(attribute, BindingFlags.Default, null, value, null); + setMethod.InvokePropertySetter(attribute, BindingFlags.Default, null, value, null); } else { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index 24634ed9715fe2..b3efa82dd7d191 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -27,7 +27,7 @@ internal sealed partial class RuntimeMethodInfo : MethodInfo, IRuntimeMethodInfo private Signature? m_signature; private readonly RuntimeType m_declaringType; private readonly object? m_keepalive; - private MethodInvoker? m_invoker; + private MethodBaseInvoker? m_invoker; internal InvocationFlags InvocationFlags { @@ -35,20 +35,17 @@ internal InvocationFlags InvocationFlags get { InvocationFlags flags = Invoker._invocationFlags; - if ((flags & InvocationFlags.Initialized) == 0) - { - flags = ComputeAndUpdateInvocationFlags(this, ref Invoker._invocationFlags); - } + Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized); return flags; } } - private MethodInvoker Invoker + internal MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - m_invoker ??= new MethodInvoker(this, Signature); + m_invoker ??= new MethodBaseInvoker(this); return m_invoker; } } @@ -287,7 +284,7 @@ public override MethodImplAttributes GetMethodImplementationFlags() #region Invocation Logic [DebuggerStepThrough] [DebuggerHidden] - internal object? InvokeOneParameter(object? obj, BindingFlags invokeAttr, Binder? binder, object? parameter, CultureInfo? culture) + internal void InvokePropertySetter(object? obj, BindingFlags invokeAttr, Binder? binder, object? parameter, CultureInfo? culture) { // ContainsStackPointers means that the struct (either the declaring type or the return type) // contains pointers that point to the stack. This is either a ByRef or a TypedReference. These structs cannot @@ -298,7 +295,10 @@ public override MethodImplAttributes GetMethodImplementationFlags() } // check basic method consistency. This call will throw if there are problems in the target/method relationship - ValidateInvokeTarget(obj); + if (!IsStatic) + { + MethodInvokerCommon.ValidateInvokeTarget(obj, this); + } Signature sig = Signature; if (sig.Arguments.Length != 1) @@ -306,38 +306,7 @@ public override MethodImplAttributes GetMethodImplementationFlags() throw new TargetParameterCountException(SR.Arg_ParmCnt); } - object? retValue; - - unsafe - { - StackAllocedArguments argStorage = default; - Span copyOfParameters = argStorage._args.AsSpan(1); - ReadOnlySpan parameters = new(in parameter); - Span shouldCopyBackParameters = argStorage._copyBacks.AsSpan(1); - - StackAllocatedByRefs byrefStorage = default; -#pragma warning disable 8500 - IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; -#pragma warning restore 8500 - - CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - ArgumentTypes, - binder, - culture, - invokeAttr); - -#if MONO // Temporary until Mono is updated. - retValue = Invoker.InlinedInvoke(obj, copyOfParameters, invokeAttr); -#else - retValue = Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr); -#endif - } - - return retValue; + Invoker.InvokePropertySetter(obj, invokeAttr, binder, parameter, culture); } #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index d2731883b02f89..eb83e8f410d6c8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -372,7 +372,7 @@ public override void SetValue(object? obj, object? value, BindingFlags invokeAtt if (index is null) { - m.InvokeOneParameter(obj, invokeAttr, binder, value, culture); + m.InvokePropertySetter(obj, invokeAttr, binder, value, culture); } else { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 831582694aa534..86f1f7d235609a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -380,34 +380,6 @@ private static unsafe void DispatchTailCalls( } } } - -#pragma warning disable 0414, IDE0044 - // Type that represents a managed view of the unmanaged GCFrame - // data structure in coreclr. The type layouts between the two should match. - internal unsafe ref struct GCFrameRegistration - { - private nuint m_reserved1; - private nuint m_reserved2; - private void* m_pObjRefs; - private uint m_numObjRefs; - private int m_MaybeInterior; - - public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = true) - { - m_reserved1 = 0; - m_reserved2 = 0; - m_pObjRefs = allocation; - m_numObjRefs = elemCount; - m_MaybeInterior = areByRefs ? 1 : 0; - } - } -#pragma warning restore 0414, IDE0044 - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration); } // Helper class to assist with unsafe pinning of arbitrary objects. // It's used by VM code. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs new file mode 100644 index 00000000000000..f807f270d84577 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs @@ -0,0 +1,39 @@ +// 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; +using System.Runtime.InteropServices; + +namespace System.Runtime +{ + internal static class RuntimeImports + { + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern unsafe void RhRegisterForGCReporting(GCFrameRegistration* pRegistration); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern unsafe void RhUnregisterForGCReporting(GCFrameRegistration* pRegistration); + +#pragma warning disable 0414, IDE0044 + // Type that represents a managed view of the unmanaged GCFrame + // data structure in coreclr. The type layouts between the two should match. + internal unsafe struct GCFrameRegistration + { + private nuint m_reserved1; + private nuint m_reserved2; + private void** m_pObjRefs; + private uint m_numObjRefs; + private int m_MaybeInterior; + + public GCFrameRegistration(void** allocation, uint elemCount, bool areByRefs = true) + { + m_reserved1 = 0; + m_reserved2 = 0; + m_pObjRefs = allocation; + m_numObjRefs = elemCount; + m_MaybeInterior = areByRefs ? 1 : 0; + } + } +#pragma warning restore 0414, IDE0044 + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 12b85edffacb6f..b56d32a0905922 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3639,37 +3639,33 @@ public override Type MakeArrayType(int rank) private static extern bool CanValueSpecialCast(RuntimeType valueType, RuntimeType targetType); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object AllocateValueType(RuntimeType type, object? value); + internal static extern object AllocateValueType(RuntimeType type, object? value); - private CheckValueStatus TryChangeTypeSpecial( - ref object value, - out bool isValueType) + private CheckValueStatus TryChangeTypeSpecial(ref object value) { - Pointer? pointer = value as Pointer; - RuntimeType srcType = pointer != null ? pointer.GetPointerType() : (RuntimeType)value.GetType(); + Pointer? pointer = value as Pointer; + RuntimeType srcType = pointer != null ? pointer.GetPointerType() : (RuntimeType)value.GetType(); - if (!CanValueSpecialCast(srcType, this)) - { - isValueType = false; - return CheckValueStatus.ArgumentException; - } + if (!CanValueSpecialCast(srcType, this)) + { + return CheckValueStatus.ArgumentException; + } - if (pointer != null) - { - value = pointer.GetPointerValue(); // Convert source pointer to IntPtr - } - else + if (pointer != null) + { + value = pointer.GetPointerValue(); // Convert source pointer to IntPtr + } + else + { + CorElementType srcElementType = GetUnderlyingType(srcType); + CorElementType dstElementType = GetUnderlyingType(this); + if (dstElementType != srcElementType) { - CorElementType srcElementType = GetUnderlyingType(srcType); - CorElementType dstElementType = GetUnderlyingType(this); - if (dstElementType != srcElementType) - { - value = InvokeUtils.ConvertOrWiden(srcType, value, this, dstElementType); - } + value = InvokeUtils.ConvertOrWiden(srcType, value, this, dstElementType); } + } - isValueType = true; - return CheckValueStatus.Success; + return CheckValueStatus.Success; } #endregion diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index c7905dd7141c63..c410fee4e530de 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -686,7 +686,7 @@ CP0001 - T:Internal.Reflection.Core.Execution.MethodInvoker + T:Internal.Reflection.Core.Execution.MethodBaseInvoker CP0001 diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs index cf93e6169f91b8..fee9f2509cead5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs @@ -72,7 +72,7 @@ public abstract class ExecutionEnvironment //============================================================================================== // Invoke and field access support. //============================================================================================== - public abstract MethodInvoker TryGetMethodInvoker(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles); + public abstract MethodBaseInvoker TryGetMethodInvoker(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles); public abstract FieldAccessor TryGetFieldAccessor(MetadataReader reader, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle fieldTypeHandle, FieldHandle fieldHandle); //============================================================================================== @@ -96,12 +96,12 @@ public abstract class ExecutionEnvironment //============================================================================================== public abstract FieldAccessor CreateLiteralFieldAccessor(object value, RuntimeTypeHandle fieldTypeHandle); public abstract void GetEnumInfo(RuntimeTypeHandle typeHandle, out string[] names, out object[] values, out bool isFlags); - public abstract IntPtr GetDynamicInvokeThunk(MethodInvoker invoker); + public abstract IntPtr GetDynamicInvokeThunk(MethodBaseInvoker invoker); //============================================================================================== // Non-public methods //============================================================================================== - internal MethodInvoker GetMethodInvoker(RuntimeTypeInfo declaringType, QMethodDefinition methodHandle, RuntimeTypeInfo[] genericMethodTypeArguments, MemberInfo exceptionPertainant, out Exception exception) + internal MethodBaseInvoker GetMethodInvoker(RuntimeTypeInfo declaringType, QMethodDefinition methodHandle, RuntimeTypeInfo[] genericMethodTypeArguments, MemberInfo exceptionPertainant, out Exception exception) { exception = null; @@ -120,13 +120,13 @@ internal MethodInvoker GetMethodInvoker(RuntimeTypeInfo declaringType, QMethodDe { genericMethodTypeArgumentHandles[i] = genericMethodTypeArguments[i].TypeHandle; } - MethodInvoker methodInvoker = TryGetMethodInvoker(typeDefinitionHandle, methodHandle, genericMethodTypeArgumentHandles); + MethodBaseInvoker methodInvoker = TryGetMethodInvoker(typeDefinitionHandle, methodHandle, genericMethodTypeArgumentHandles); if (methodInvoker == null) exception = ReflectionCoreExecution.ExecutionDomain.CreateNonInvokabilityException(exceptionPertainant); return methodInvoker; } - protected MethodInvoker GetMethodInvoker(MethodInfo methodInfo) + protected MethodBaseInvoker GetMethodInvoker(MethodInfo methodInfo) { return ((RuntimeMethodInfo)methodInfo).MethodInvoker; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/MethodInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/MethodBaseInvoker.cs similarity index 80% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/MethodInvoker.cs rename to src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/MethodBaseInvoker.cs index a208715adc9489..19589a2be4e6c5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/MethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/MethodBaseInvoker.cs @@ -13,12 +13,12 @@ namespace Internal.Reflection.Core.Execution { // - // This class polymorphically implements the MethodBase.Invoke() api and its close cousins. MethodInvokers are designed to be built once and cached + // This class polymorphically implements the MethodBase.Invoke() api and its close cousins. MethodBaseInvokers are designed to be built once and cached // for maximum Invoke() throughput. // - public abstract class MethodInvoker + public abstract class MethodBaseInvoker { - protected MethodInvoker() { } + protected MethodBaseInvoker() { } [DebuggerGuidedStepThrough] public object? Invoke(object thisObject, object?[] arguments, Binder? binder, BindingFlags invokeAttr, CultureInfo? cultureInfo) @@ -26,7 +26,7 @@ protected MethodInvoker() { } BinderBundle binderBundle = binder.ToBinderBundle(invokeAttr, cultureInfo); bool wrapInTargetInvocationException = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; object? result = Invoke(thisObject, arguments, binderBundle, wrapInTargetInvocationException); - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } @@ -42,7 +42,11 @@ public object CreateInstance(object?[] arguments, Binder? binder, BindingFlags i protected abstract object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException); protected abstract object CreateInstance(object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException); + protected internal abstract object CreateInstance(Span arguments); + protected internal abstract object CreateInstanceWithFewArgs(Span arguments); public abstract Delegate CreateDelegate(RuntimeTypeHandle delegateType, object target, bool isStatic, bool isVirtual, bool isOpen); + protected internal abstract object? Invoke(object? thisObject, Span arguments); + protected internal abstract object? InvokeDirectWithFewArgs(object? thisObject, Span arguments); // This property is used to retrieve the target method pointer. It is used by the RuntimeMethodHandle.GetFunctionPointer API public abstract IntPtr LdFtnResult { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index 39fda81c8a8388..3aaf11fd0ef336 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -678,7 +678,7 @@ public static bool CanPrimitiveWiden(RuntimeTypeHandle srcType, RuntimeTypeHandl return true; } - public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle) + public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle? binderBundle) { return InvokeUtils.CheckArgument(srcObject, dstType.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, binderBundle); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 896b92604d1a08..681f2b8557cb72 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -136,6 +136,7 @@ + @@ -149,6 +150,7 @@ + @@ -483,7 +485,7 @@ - + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs new file mode 100644 index 00000000000000..9410dc44610afd --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Reflection.Core.Execution; +using System.Reflection.Runtime.MethodInfos; +using static System.Reflection.DynamicInvokeInfo; + +namespace System.Reflection +{ + public sealed class ConstructorInvoker + { + private readonly MethodBaseInvoker _methodBaseInvoker; + private readonly RuntimeTypeHandle _declaringTypeHandle; + + internal ConstructorInvoker(RuntimeConstructorInfo constructor) + { + _methodBaseInvoker = constructor.MethodInvoker; + _declaringTypeHandle = constructor.DeclaringType.TypeHandle; + } + + public static ConstructorInvoker Create(ConstructorInfo constructor) + { + if (constructor is not RuntimeConstructorInfo runtimeConstructor) + { + throw new ArgumentException(SR.Argument_MustBeRuntimeConstructorInfo, nameof(constructor)); + } + + return new ConstructorInvoker(runtimeConstructor); + } + + public object? Invoke() + { + return _methodBaseInvoker.CreateInstanceWithFewArgs(new Span()); + } + + public object? Invoke(object? arg1) + { + return _methodBaseInvoker.CreateInstanceWithFewArgs(new Span(ref arg1)); + } + + public object? Invoke(object? arg1, object? arg2) + { + StackAllocatedArguments argStorage = default; + argStorage._args.Set(0, arg1); + argStorage._args.Set(1, arg2); + return _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(2)); + } + + public object? Invoke(object? arg1, object? arg2, object? arg3) + { + StackAllocatedArguments argStorage = default; + argStorage._args.Set(0, arg1); + argStorage._args.Set(1, arg2); + argStorage._args.Set(2, arg3); + return _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(3)); + } + + public object? Invoke(object? arg1, object? arg2, object? arg3, object? arg4) + { + StackAllocatedArguments argStorage = default; + argStorage._args.Set(0, arg1); + argStorage._args.Set(1, arg2); + argStorage._args.Set(2, arg3); + argStorage._args.Set(3, arg4); + return _methodBaseInvoker.CreateInstanceWithFewArgs(argStorage._args.AsSpan(4)); + } + + public object? Invoke(Span arguments) + { + + return _methodBaseInvoker.CreateInstance(arguments); + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs index 698b7a726cef97..e0a733f91de082 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -177,7 +178,7 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) public bool IsSupportedSignature => _argumentCount >= 0; - [DebuggerGuidedStepThroughAttribute] + [DebuggerGuidedStepThrough] public unsafe object? Invoke( object? thisPtr, IntPtr methodToCall, @@ -241,38 +242,167 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) } else if (argCount > MaxStackAllocArgCount) { - ret = ref InvokeWithManyArguments( methodToCall, ref thisArg, ref ret, + ret = ref InvokeWithManyArguments(methodToCall, ref thisArg, ref ret, parameters, binderBundle, wrapInTargetInvocationException); } else { - StackAllocedArguments argStorage = default; - StackAllocatedByRefs byrefStorage = default; + ret = ref InvokeWithFewArguments(methodToCall, ref thisArg, ref ret, + parameters, binderBundle, wrapInTargetInvocationException); + } -#pragma warning disable 8500 - CheckArguments(ref argStorage._arg0!, (ByReference*)&byrefStorage, parameters, binderBundle); -#pragma warning restore 8500 + return ((_returnTransform & (Transform.Nullable | Transform.Pointer | Transform.FunctionPointer | Transform.ByRef)) != 0) ? + ReturnTransform(ref ret, wrapInTargetInvocationException) : returnObject; + } - try + [DebuggerGuidedStepThrough] + public unsafe object? Invoke( + object? thisPtr, + IntPtr methodToCall, + Span parameters) + { + int argCount = parameters.Length; + if (argCount != _argumentCount) + { + if (_argumentCount < 0) { -#pragma warning disable 8500 - ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, &byrefStorage); -#pragma warning restore 8500 - DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + if (_argumentCount == ArgumentCount_NotSupported_ByRefLike) + throw new NotSupportedException(SR.NotSupported_ByRefLike); + throw new NotSupportedException(); } - catch (Exception e) when (wrapInTargetInvocationException) + + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + object? returnObject = null; + + scoped ref byte thisArg = ref Unsafe.NullRef(); + if (!_isStatic) + { + // The caller is expected to validate this + Debug.Assert(thisPtr != null); + + // See TODO comment in DynamicInvokeMethodThunk.NormalizeSignature + // if (_isValueTypeInstanceMethod) + // { + // // thisArg is a raw data byref for valuetype instance methods + // thisArg = ref thisPtr.GetRawData(); + // } + // else { - throw new TargetInvocationException(e); + thisArg = ref Unsafe.As(ref thisPtr); } - finally + } + + scoped ref byte ret = ref Unsafe.As(ref returnObject); + if ((_returnTransform & Transform.AllocateReturnBox) != 0) + { + returnObject = RuntimeImports.RhNewObject( + (_returnTransform & (Transform.Pointer | Transform.FunctionPointer)) != 0 ? + EETypePtr.EETypePtrOf() : _returnType); + ret = ref returnObject.GetRawData(); + } + + if (argCount == 0) + { + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, null); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + } + else if (argCount > MaxStackAllocArgCount) + { + ret = ref InvokeWithManyArguments(methodToCall, ref thisArg, ref ret, parameters); + } + else + { + ret = ref InvokeWithFewArguments(methodToCall, ref thisArg, ref ret, parameters); + } + + return ((_returnTransform & (Transform.Nullable | Transform.Pointer | Transform.FunctionPointer | Transform.ByRef)) != 0) ? + ReturnTransform(ref ret, wrapInTargetInvocationException: false) : returnObject; + } + + + [DebuggerGuidedStepThrough] + // This method is equivalent to the one above except that it takes 'Span' instead of 'object[]' + // for the parameters, does not require a copy of the parameters or CopyBack, and does not require + // re-throw capability. + public unsafe object? InvokeDirectWithFewArgs( + object? thisPtr, + IntPtr methodToCall, + Span parameters) + { + int argCount = parameters.Length; + + if (argCount != _argumentCount) + { + if (_argumentCount < 0) { - if (_needsCopyBack) - CopyBack(ref argStorage._arg0!, parameters); + if (_argumentCount == ArgumentCount_NotSupported_ByRefLike) + throw new NotSupportedException(SR.NotSupported_ByRefLike); + throw new NotSupportedException(); + } + + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + Debug.Assert(_argumentCount <= MaxStackAllocArgCount); + + object? returnObject = null; + + scoped ref byte thisArg = ref Unsafe.NullRef(); + if (!_isStatic) + { + // The caller is expected to validate this + Debug.Assert(thisPtr != null); + + // See TODO comment in DynamicInvokeMethodThunk.NormalizeSignature + // if (_isValueTypeInstanceMethod) + // { + // // thisArg is a raw data byref for valuetype instance methods + // thisArg = ref thisPtr.GetRawData(); + // } + // else + { + thisArg = ref Unsafe.As(ref thisPtr); } } + scoped ref byte ret = ref Unsafe.As(ref returnObject); + if ((_returnTransform & Transform.AllocateReturnBox) != 0) + { + returnObject = RuntimeImports.RhNewObject( + (_returnTransform & (Transform.Pointer | Transform.FunctionPointer)) != 0 ? + EETypePtr.EETypePtrOf() : _returnType); + ret = ref returnObject.GetRawData(); + } + + if (argCount == 0) + { + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, null); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + } + else if (argCount == 1) + { + ByReference br = ByReference.Create(ref parameters[0]); +#pragma warning disable CS8500 + void* pByrefStorage = &br; +#pragma warning restore CS8500 + + // Since no copy of args is required, pass 'parameters' for both arguments. + CheckArguments(parameters, pByrefStorage, parameters); + + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, pByrefStorage); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + + // No need to call CopyBack here since there are no ref values. + } + else + { + ret = ref InvokeDirectWithFewArguments(methodToCall, ref thisArg, ref ret, parameters); + } + return ((_returnTransform & (Transform.Nullable | Transform.Pointer | Transform.FunctionPointer | Transform.ByRef)) != 0) ? - ReturnTransform(ref ret, wrapInTargetInvocationException) : returnObject; + ReturnTransform(ref ret, wrapInTargetInvocationException: false) : returnObject; } private unsafe ref byte InvokeWithManyArguments( @@ -298,7 +428,8 @@ private unsafe ref byte InvokeWithManyArguments( RuntimeImports.RhRegisterForGCReporting(®ArgStorage); RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); - CheckArguments(ref Unsafe.As(ref *pStorage), pByRefStorage, parameters, binderBundle); + Span copyOfParameters = new(ref Unsafe.As(ref *pStorage), argCount); + CheckArguments(copyOfParameters, pByRefStorage, parameters, binderBundle); try { @@ -312,7 +443,7 @@ private unsafe ref byte InvokeWithManyArguments( finally { if (_needsCopyBack) - CopyBack(ref Unsafe.As(ref *pStorage), parameters); + CopyBackToArray(ref Unsafe.As(ref *pStorage), parameters); } } finally @@ -324,6 +455,136 @@ private unsafe ref byte InvokeWithManyArguments( return ref ret; } + // This method is equivalent to the one above except that it takes 'Span' instead of 'object[]' + // for the parameters and does not require re-throw capability. + private unsafe ref byte InvokeWithManyArguments( + IntPtr methodToCall, ref byte thisArg, ref byte ret, Span parameters) + { + int argCount = _argumentCount; + + // 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* pStorage = stackalloc IntPtr[2 * argCount]; + NativeMemory.Clear(pStorage, (nuint)(2 * argCount) * (nuint)sizeof(IntPtr)); + +#pragma warning disable 8500 + void* pByRefStorage = (ByReference*)(pStorage + argCount); +#pragma warning restore 8500 + + RuntimeImports.GCFrameRegistration regArgStorage = new(pStorage, (uint)argCount, areByRefs: false); + RuntimeImports.GCFrameRegistration regByRefStorage = new(pByRefStorage, (uint)argCount, areByRefs: true); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + + Span copyOfParameters = new(ref Unsafe.As(ref *pStorage), argCount); + CheckArguments(copyOfParameters, pByRefStorage, parameters); + + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, pByRefStorage); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + + if (_needsCopyBack) + CopyBackToSpan(copyOfParameters, parameters); + } + finally + { + RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + } + + return ref ret; + } + + // This is a separate method to localize the overhead of stack allocs for 'StackAllocatedByRefs' and 'StackAllocatedByRefs'. + private unsafe ref byte InvokeWithFewArguments( + IntPtr methodToCall, ref byte thisArg, ref byte ret, + object?[] parameters, BinderBundle? binderBundle, bool wrapInTargetInvocationException) + { + Debug.Assert(_argumentCount <= MaxStackAllocArgCount); + int argCount = _argumentCount; + + StackAllocatedArguments argStorage = default; + Span copyOfParameters = argStorage._args.AsSpan(argCount); + StackAllocatedByRefs byrefStorage = default; +#pragma warning disable CS8500 + void* pByRefStorage = (ByReference*)&byrefStorage; +#pragma warning restore CS8500 + + CheckArguments(copyOfParameters, pByRefStorage, parameters, binderBundle); + + try + { + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, pByRefStorage); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + } + catch (Exception e) when (wrapInTargetInvocationException) + { + throw new TargetInvocationException(e); + } + finally + { + if (_needsCopyBack) + CopyBackToArray(ref copyOfParameters[0], parameters); + } + + return ref ret; + } + + // This method is equivalent to the one above except that it takes 'Span' instead of 'object[]' + // for the parameters and does not require 'BinderBundle' or re-throw capability. + private unsafe ref byte InvokeWithFewArguments( + IntPtr methodToCall, ref byte thisArg, ref byte ret, Span parameters) + { + Debug.Assert(_argumentCount <= MaxStackAllocArgCount); + int argCount = _argumentCount; + + StackAllocatedArguments argStorage = default; + Span copyOfParameters = argStorage._args.AsSpan(argCount); + StackAllocatedByRefs byrefStorage = default; +#pragma warning disable CS8500 + void* pByRefStorage = (ByReference*)&byrefStorage; +#pragma warning restore CS8500 + + CheckArguments(copyOfParameters, pByRefStorage, parameters); + + try + { + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, pByRefStorage); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + } + finally + { + if (_needsCopyBack) + CopyBackToSpan(copyOfParameters, parameters); + } + + return ref ret; + } + + // This method is equivalent to the one above except that it does not require a copy of the args or CopyBack. + private unsafe ref byte InvokeDirectWithFewArguments( + IntPtr methodToCall, ref byte thisArg, ref byte ret, Span parameters) + { + Debug.Assert(_argumentCount <= MaxStackAllocArgCount); + + StackAllocatedByRefs byrefStorage = default; +#pragma warning disable CS8500 + void* pByRefStorage = (ByReference*)&byrefStorage; +#pragma warning restore CS8500 + + // Since no copy of args is required, pass 'parameters' for both arguments. + CheckArguments(parameters, pByRefStorage, parameters); + + ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, pByRefStorage); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + + // No need to call CopyBack here since there are no ref values. + + return ref ret; + } + private unsafe object? GetCoercedDefaultValue(int index, in ArgumentInfo argumentInfo) { object? defaultValue = Method.GetParametersNoCopy()[index].DefaultValue; @@ -345,10 +606,10 @@ private unsafe ref byte InvokeWithManyArguments( } private unsafe void CheckArguments( - ref object copyOfParameters, + Span copyOfParameters, void* byrefParameters, object?[] parameters, - BinderBundle binderBundle) + BinderBundle? binderBundle) { for (int i = 0; i < parameters.Length; i++) { @@ -416,16 +677,121 @@ private unsafe void CheckArguments( // is specified for value types, and also used to hold the results from conversions such as // from Int16 to Int32. - Unsafe.Add(ref copyOfParameters, i) = arg!; + copyOfParameters[i] = arg!; #pragma warning disable 8500, 9094 ((ByReference*)byrefParameters)[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ? - ref Unsafe.As(ref Unsafe.Add(ref copyOfParameters, i)) : ref arg.GetRawData()); + ref Unsafe.As(ref copyOfParameters[i]) : ref arg.GetRawData()); #pragma warning restore 8500, 9094 } } - private unsafe void CopyBack(ref object copyOfParameters, object?[] parameters) + // This method is equivalent to the one above except that it takes 'Span' instead of 'object[]' + // for the parameters and does not require the use of 'BinderBundle' or check for 'Type.Missing'. + private unsafe void CheckArguments( + Span copyOfParameters, + void* byrefParameters, + Span parameters) + { + for (int i = 0; i < parameters.Length; i++) + { + object? arg = parameters[i]; + + ref readonly ArgumentInfo argumentInfo = ref _arguments[i]; + + if (arg is null) + { + // null is substituded by zero-initialized value for non-reference type + if ((argumentInfo.Transform & Transform.Reference) == 0) + arg = RuntimeImports.RhNewObject( + (argumentInfo.Transform & (Transform.Pointer | Transform.FunctionPointer)) != 0 ? + EETypePtr.EETypePtrOf() : argumentInfo.Type); + } + else + { + EETypePtr srcEEType = arg.GetEETypePtr(); + EETypePtr dstEEType = argumentInfo.Type; + + if (!(srcEEType.RawValue == dstEEType.RawValue || + RuntimeImports.AreTypesAssignable(srcEEType, dstEEType) || + (dstEEType.IsInterface && arg is System.Runtime.InteropServices.IDynamicInterfaceCastable castable + && castable.IsInterfaceImplemented(new RuntimeTypeHandle(dstEEType), throwIfNotImplemented: false)))) + { + // ByRefs have to be exact match + if ((argumentInfo.Transform & Transform.ByRef) != 0) + throw InvokeUtils.CreateChangeTypeArgumentException(srcEEType, argumentInfo.Type, destinationIsByRef: true); + + arg = InvokeUtils.CheckArgumentConversions(arg, argumentInfo.Type, InvokeUtils.CheckArgumentSemantics.DynamicInvoke, binderBundle: null); + } + + if ((argumentInfo.Transform & Transform.Reference) == 0) + { + if ((argumentInfo.Transform & (Transform.ByRef | Transform.Nullable)) != 0) + { + // Rebox the value to avoid mutating the original box. This also takes care of + // T -> Nullable transformation as side-effect. + object box = RuntimeImports.RhNewObject(argumentInfo.Type); + RuntimeImports.RhUnbox(arg, ref box.GetRawData(), argumentInfo.Type); + arg = box; + } + } + } + + // We need to perform type safety validation against the incoming arguments, but we also need + // to be resilient against the possibility that some other thread (or even the binder itself!) + // may mutate the array after we've validated the arguments but before we've properly invoked + // the method. The solution is to copy the arguments to a different, not-user-visible buffer + // as we validate them. This separate array is also used to hold default values when 'null' + // is specified for value types, and also used to hold the results from conversions such as + // from Int16 to Int32. + + copyOfParameters[i] = arg; + +#pragma warning disable 8500, 9094 + ((ByReference*)byrefParameters)[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ? + ref Unsafe.As(ref copyOfParameters[i]) : ref arg.GetRawData()); +#pragma warning restore 8500, 9094 + } + } + + private unsafe void CopyBackToArray(ref object? src, object?[] dest) + { + ArgumentInfo[] arguments = _arguments; + + for (int i = 0; i < arguments.Length; i++) + { + ref readonly ArgumentInfo argumentInfo = ref arguments[i]; + + Transform transform = argumentInfo.Transform; + + if ((transform & Transform.ByRef) == 0) + continue; + + object? obj = Unsafe.Add(ref src, i); + + if ((transform & (Transform.Pointer | Transform.FunctionPointer | Transform.Nullable)) != 0) + { + if ((transform & Transform.Pointer) != 0) + { + Type type = Type.GetTypeFromMethodTable(argumentInfo.Type.ToPointer()); + Debug.Assert(type.IsPointer); + obj = Pointer.Box((void*)Unsafe.As(ref obj.GetRawData()), type); + } + if ((transform & Transform.FunctionPointer) != 0) + { + obj = RuntimeImports.RhBox(EETypePtr.EETypePtrOf(), ref obj.GetRawData()); + } + else + { + obj = RuntimeImports.RhBox(argumentInfo.Type, ref obj.GetRawData()); + } + } + + dest[i] = obj; + } + } + + private unsafe void CopyBackToSpan(Span src, Span dest) { ArgumentInfo[] arguments = _arguments; @@ -438,7 +804,7 @@ private unsafe void CopyBack(ref object copyOfParameters, object?[] parameters) if ((transform & Transform.ByRef) == 0) continue; - object obj = Unsafe.Add(ref copyOfParameters, i); + object? obj = src[i]; if ((transform & (Transform.Pointer | Transform.FunctionPointer | Transform.Nullable)) != 0) { @@ -458,7 +824,7 @@ private unsafe void CopyBack(ref object copyOfParameters, object?[] parameters) } } - parameters[i] = obj; + dest[i] = obj; } } @@ -495,20 +861,39 @@ private unsafe object ReturnTransform(ref byte byref, bool wrapInTargetInvocatio private const int MaxStackAllocArgCount = 4; + [InlineArray(MaxStackAllocArgCount)] + internal struct ArgumentData + { + private T _arg0; + + [UnscopedRef] + public Span AsSpan(int length) + { + Debug.Assert((uint)length <= MaxStackAllocArgCount); + return new Span(ref _arg0, length); + } + + public void Set(int index, T value) + { + Debug.Assert((uint)index < MaxStackAllocArgCount); + Unsafe.Add(ref _arg0, index) = value; + } + } + // Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack. // When argument count <= MaxStackAllocArgCount, define a local of type default(StackAllocatedByRefs) // and pass it to CheckArguments(). // For argument count > MaxStackAllocArgCount, do a stackalloc of void* pointers along with // GCReportingRegistration to safely track references. - [InlineArray(MaxStackAllocArgCount)] - private ref struct StackAllocedArguments + [StructLayout(LayoutKind.Sequential)] + internal ref struct StackAllocatedArguments { - internal object? _arg0; + internal ArgumentData _args; } // Helper struct to avoid intermediate IntPtr[] allocation and RegisterForGCReporting in calls to the native reflection stack. [InlineArray(MaxStackAllocArgCount)] - private ref struct StackAllocatedByRefs + internal ref struct StackAllocatedByRefs { internal ref byte _arg0; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs new file mode 100644 index 00000000000000..93efbe1f0470f4 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Reflection.Core.Execution; +using System.Diagnostics; +using System.Reflection.Runtime.MethodInfos; +using static System.Reflection.DynamicInvokeInfo; + +namespace System.Reflection +{ + public sealed class MethodInvoker + { + private readonly MethodBaseInvoker _methodBaseInvoker; + + internal MethodInvoker(RuntimeMethodInfo method) + { + _methodBaseInvoker = method.MethodInvoker; + } + + internal MethodInvoker(RuntimeConstructorInfo constructor) + { + _methodBaseInvoker = constructor.MethodInvoker; + } + + public static MethodInvoker Create(MethodBase method) + { + ArgumentNullException.ThrowIfNull(method, nameof(method)); + + if (method is RuntimeMethodInfo rmi) + { + return new MethodInvoker(rmi); + } + + if (method is RuntimeConstructorInfo rci) + { + // This is useful for calling a constructor on an already-initialized object + // such as created from RuntimeHelpers.GetUninitializedObject(Type). + return new MethodInvoker(rci); + } + + throw new ArgumentException(SR.Argument_MustBeRuntimeMethod, nameof(method)); + } + + public object? Invoke(object? obj) + { + object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, new Span()); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + public object? Invoke(object? obj, object? arg1) + { + object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, new Span(ref arg1)); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + public object? Invoke(object? obj, object? arg1, object? arg2) + { + StackAllocatedArguments argStorage = default; + argStorage._args.Set(0, arg1); + argStorage._args.Set(1, arg2); + + object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(2)); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3) + { + StackAllocatedArguments argStorage = default; + argStorage._args.Set(0, arg1); + argStorage._args.Set(1, arg2); + argStorage._args.Set(2, arg3); + + object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(3)); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3, object? arg4) + { + StackAllocatedArguments argStorage = default; + argStorage._args.Set(0, arg1); + argStorage._args.Set(1, arg2); + argStorage._args.Set(2, arg3); + argStorage._args.Set(3, arg4); + + object? result = _methodBaseInvoker.InvokeDirectWithFewArgs(obj, argStorage._args.AsSpan(4)); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + [DebuggerGuidedStepThrough] + public object? Invoke(object? obj, Span arguments) + { + object? result = _methodBaseInvoker.Invoke(obj, arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs index 11d820cfd054ad..c156d8e938d186 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs @@ -431,7 +431,7 @@ public sealed override DynamicInvokeInfo GetDelegateDynamicInvokeInfo(Type type) RuntimeMethodInfo invokeMethod = runtimeType.GetInvokeMethod(); - MethodInvoker methodInvoker = invokeMethod.MethodInvoker; + MethodBaseInvoker methodInvoker = invokeMethod.MethodInvoker; IntPtr invokeThunk = ReflectionCoreExecution.ExecutionDomain.ExecutionEnvironment.GetDynamicInvokeThunk(methodInvoker); info = new DynamicInvokeInfo(invokeMethod, invokeThunk); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs index 6d71dacfe5246c..ead65e3d6b15ba 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs @@ -11,7 +11,7 @@ namespace System.Reflection.Runtime.MethodInfos // // Custom invoker for edge case scenarios not handled by the toolchain. Examples: Strings and Nullables. // - internal sealed class CustomMethodInvoker : MethodInvoker + internal sealed class CustomMethodInvoker : MethodBaseInvoker { public CustomMethodInvoker(Type thisType, Type[] parameterTypes, InvokerOptions options, CustomMethodInvokerAction action) { @@ -21,7 +21,16 @@ public CustomMethodInvoker(Type thisType, Type[] parameterTypes, InvokerOptions _parameterTypes = parameterTypes; } - protected sealed override object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) + protected sealed override object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) => + InvokeSpecial(thisObject, arguments, binderBundle, wrapInTargetInvocationException); + + protected internal sealed override object? Invoke(object? thisObject, Span arguments) => + InvokeSpecial(thisObject, arguments, binderBundle: null, wrapInTargetInvocationException: false); + + protected internal sealed override object? InvokeDirectWithFewArgs(object? thisObject, Span arguments) => + InvokeSpecial(thisObject, arguments, binderBundle: null, wrapInTargetInvocationException: false); + + private object? InvokeSpecial(object? thisObject, ReadOnlySpan arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { // This does not handle optional parameters. None of the methods we use custom invocation for have them. if (!(thisObject == null && 0 != (_options & InvokerOptions.AllowNullThis))) @@ -55,6 +64,20 @@ protected sealed override object CreateInstance(object?[]? arguments, BinderBund return Invoke(null, arguments, binderBundle, wrapInTargetInvocationException); } + protected internal sealed override object CreateInstance(Span arguments) + { + // Custom method invokers need to also create the instance, so we just pass a null this. + Debug.Assert((_options & InvokerOptions.AllowNullThis) != 0); + return Invoke(null, arguments); + } + + protected internal sealed override object CreateInstanceWithFewArgs(Span arguments) + { + // Custom method invokers need to also create the instance, so we just pass a null this. + Debug.Assert((_options & InvokerOptions.AllowNullThis) != 0); + return InvokeDirectWithFewArgs(null, arguments); + } + public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, object target, bool isStatic, bool isVirtual, bool isOpen) { if (_thisType.IsConstructedGenericType && _thisType.GetGenericTypeDefinition() == typeof(Nullable<>)) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs index 6b81aaaeb2bf21..0de913d3bc8855 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs @@ -14,7 +14,7 @@ internal static partial class CustomMethodMapper // // Certain types and methods are edge-cases that require special handling. // - public static MethodInvoker GetCustomMethodInvokerIfNeeded(this MethodBase methodBase) + public static MethodBaseInvoker GetCustomMethodInvokerIfNeeded(this MethodBase methodBase) { Type declaringType = methodBase.DeclaringType!; bool isNullable = declaringType.IsConstructedGenericType && declaringType.GetGenericTypeDefinition() == typeof(Nullable<>); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs index 47cd8f18860a13..142c1d4fdca4cc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs @@ -45,7 +45,7 @@ internal interface IRuntimeMethodCommon where TRuntimeMeth string Name { get; } - MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant, out Exception exception); + MethodBaseInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant, out Exception exception); bool IsGenericMethodDefinition { get; } int GenericParameterCount { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs index 99be841a46b4b8..e126de60ca8fdf 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs @@ -25,7 +25,7 @@ internal struct NativeFormatMethodCommon : IRuntimeMethodCommon GenericParameterCount != 0; - public MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant, out Exception exception) + public MethodBaseInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant, out Exception exception) { return ReflectionCoreExecution.ExecutionEnvironment.GetMethodInvoker(DeclaringType, new QMethodDefinition(Reader, MethodHandle), methodArguments, exceptionPertainant, out exception); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs index cf81ce9d200144..5a8b74225ee16a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs @@ -12,7 +12,7 @@ namespace System.Reflection.Runtime.MethodInfos { - internal sealed class OpenMethodInvoker : MethodInvoker + internal sealed class OpenMethodInvoker : MethodBaseInvoker { protected sealed override object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { @@ -24,6 +24,26 @@ protected sealed override object CreateInstance(object?[]? arguments, BinderBund throw new InvalidOperationException(SR.Arg_UnboundGenParam); } + protected internal sealed override object CreateInstance(Span arguments) + { + throw new InvalidOperationException(SR.Arg_UnboundGenParam); + } + + protected internal sealed override object CreateInstanceWithFewArgs(Span arguments) + { + throw new InvalidOperationException(SR.Arg_UnboundGenParam); + } + + protected internal sealed override object? Invoke(object? thisObject, Span arguments) + { + throw new InvalidOperationException(SR.Arg_UnboundGenParam); + } + + protected internal sealed override object? InvokeDirectWithFewArgs(object? thisObject, Span arguments) + { + throw new InvalidOperationException(SR.Arg_UnboundGenParam); + } + public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, object target, bool isStatic, bool isVirtual, bool isOpen) { throw new InvalidOperationException(SR.Arg_UnboundGenParam); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs index 53cf1f0f963cca..793e85fd935e77 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs @@ -166,7 +166,7 @@ public sealed override RuntimeMethodHandle MethodHandle } } - protected sealed override MethodInvoker UncachedMethodInvoker + protected sealed override MethodBaseInvoker UncachedMethodInvoker { get { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs index 22eb2a62767293..1b56abb1e39b11 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs @@ -1,18 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Reflection; +using Internal.Reflection.Core.Execution; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Collections.Generic; -using System.Reflection.Runtime.General; -using System.Reflection.Runtime.TypeInfos; using System.Reflection.Runtime.ParameterInfos; -using Internal.Reflection.Core.Execution; - namespace System.Reflection.Runtime.MethodInfos { // @@ -72,7 +67,7 @@ public sealed override ParameterInfo[] GetParametersNoCopy() public sealed override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { parameters ??= Array.Empty(); - MethodInvoker methodInvoker; + MethodBaseInvoker methodInvoker; try { methodInvoker = this.MethodInvoker; @@ -98,7 +93,7 @@ public sealed override object Invoke(object? obj, BindingFlags invokeAttr, Binde } object? result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture); - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result!; } @@ -162,7 +157,7 @@ public sealed override Type ReflectedType public abstract override RuntimeMethodHandle MethodHandle { get; } - protected MethodInvoker MethodInvoker + protected internal MethodBaseInvoker MethodInvoker { get { @@ -174,8 +169,8 @@ protected MethodInvoker MethodInvoker protected abstract RuntimeParameterInfo[] RuntimeParameters { get; } - protected abstract MethodInvoker UncachedMethodInvoker { get; } + protected abstract MethodBaseInvoker UncachedMethodInvoker { get; } - private volatile MethodInvoker _lazyMethodInvoker; + private volatile MethodBaseInvoker _lazyMethodInvoker; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs index 409186ad654295..ddf736da1be642 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs @@ -38,14 +38,14 @@ private RuntimeDummyMethodInfo() { } public sealed override MethodBase MetadataDefinitionMethod { get { throw NotImplemented.ByDesign; } } public sealed override int MetadataToken { get { throw NotImplemented.ByDesign; } } public sealed override RuntimeMethodHandle MethodHandle { get { throw NotImplemented.ByDesign; } } - protected sealed override MethodInvoker UncachedMethodInvoker { get { throw NotImplemented.ByDesign; } } + protected sealed override MethodBaseInvoker UncachedMethodInvoker { get { throw NotImplemented.ByDesign; } } internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod, out RuntimeParameterInfo returnParameter) { throw NotImplemented.ByDesign; } internal sealed override RuntimeTypeInfo RuntimeDeclaringType { get { throw NotImplemented.ByDesign; } } internal sealed override string RuntimeName { get { throw NotImplemented.ByDesign; } } internal sealed override RuntimeTypeInfo[] RuntimeGenericArgumentsOrParameters { get { throw NotImplemented.ByDesign; } } protected internal sealed override string ComputeToString(RuntimeMethodInfo contextMethod) { throw NotImplemented.ByDesign; } - internal sealed override MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant) { throw NotImplemented.ByDesign; } + internal sealed override MethodBaseInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant) { throw NotImplemented.ByDesign; } internal sealed override RuntimeMethodHandle GetRuntimeMethodHandle(Type[] genericArgs) { throw NotImplemented.ByDesign; } internal sealed override RuntimeMethodInfo WithReflectedTypeSetToDeclaringType { get { throw NotImplemented.ByDesign; } } public static readonly RuntimeDummyMethodInfo Instance = new RuntimeDummyMethodInfo(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs index 8b5ff9baa6fc68..c22697cac28d88 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs @@ -158,12 +158,12 @@ public sealed override ParameterInfo[] GetParametersNoCopy() public abstract override bool HasSameMetadataDefinitionAs(MemberInfo other); - [DebuggerGuidedStepThroughAttribute] + [DebuggerGuidedStepThrough] public sealed override object? Invoke(object? obj, BindingFlags invokeAttr, Binder binder, object?[]? parameters, CultureInfo culture) { - MethodInvoker methodInvoker = this.MethodInvoker; + MethodBaseInvoker methodInvoker = this.MethodInvoker; object? result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture); - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } @@ -245,7 +245,7 @@ internal abstract string RuntimeName internal abstract RuntimeMethodInfo WithReflectedTypeSetToDeclaringType { get; } - protected abstract MethodInvoker UncachedMethodInvoker { get; } + protected abstract MethodBaseInvoker UncachedMethodInvoker { get; } // // The non-public version of MethodInfo.GetGenericArguments() (does not array-copy and has a more truthful name.) @@ -290,7 +290,7 @@ internal RuntimeParameterInfo RuntimeReturnParameter private volatile RuntimeParameterInfo[] _lazyParameters; private volatile RuntimeParameterInfo _lazyReturnParameter; - internal MethodInvoker MethodInvoker + internal MethodBaseInvoker MethodInvoker { get { @@ -300,7 +300,7 @@ internal MethodInvoker MethodInvoker internal IntPtr LdFtnResult => MethodInvoker.LdFtnResult; - private volatile MethodInvoker _lazyMethodInvoker; + private volatile MethodBaseInvoker _lazyMethodInvoker; /// /// Common CreateDelegate worker. NOTE: If the method signature is not compatible, this method returns null rather than throwing an ArgumentException. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs index 773412a70ff90f..25a0e21f9c9850 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs @@ -19,7 +19,7 @@ namespace System.Reflection.Runtime.MethodInfos internal abstract class RuntimeNamedMethodInfo : RuntimeMethodInfo { protected internal abstract string ComputeToString(RuntimeMethodInfo contextMethod); - internal abstract MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant); + internal abstract MethodBaseInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant); internal abstract RuntimeMethodHandle GetRuntimeMethodHandle(Type[] methodArguments); } @@ -144,7 +144,7 @@ public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments) if (typeArguments.Length != GenericTypeParameters.Length) throw new ArgumentException(SR.Format(SR.Argument_NotEnoughGenArguments, typeArguments.Length, GenericTypeParameters.Length)); RuntimeMethodInfo methodInfo = (RuntimeMethodInfo)RuntimeConstructedGenericMethodInfo.GetRuntimeConstructedGenericMethodInfo(this, genericTypeArguments); - MethodInvoker _ = methodInfo.MethodInvoker; // For compatibility with other Make* apis, trigger any missing metadata exceptions now rather than later. + MethodBaseInvoker _ = methodInfo.MethodInvoker; // For compatibility with other Make* apis, trigger any missing metadata exceptions now rather than later. return methodInfo; } @@ -292,20 +292,20 @@ private RuntimeTypeInfo[] GenericTypeParameters } } - internal sealed override MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant) + internal sealed override MethodBaseInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant) { - MethodInvoker invoker = _common.GetUncachedMethodInvoker(methodArguments, exceptionPertainant, out Exception exception); + MethodBaseInvoker invoker = _common.GetUncachedMethodInvoker(methodArguments, exceptionPertainant, out Exception exception); if (invoker == null) throw exception; return invoker; } - protected sealed override MethodInvoker UncachedMethodInvoker + protected sealed override MethodBaseInvoker UncachedMethodInvoker { get { - MethodInvoker invoker = this.GetCustomMethodInvokerIfNeeded(); + MethodBaseInvoker invoker = this.GetCustomMethodInvokerIfNeeded(); if (invoker != null) return invoker; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs index a4a8fd6e360a79..4544281a81455a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs @@ -152,7 +152,7 @@ protected sealed override RuntimeParameterInfo[] RuntimeParameters } } - protected sealed override MethodInvoker UncachedMethodInvoker + protected sealed override MethodBaseInvoker UncachedMethodInvoker { get { @@ -162,7 +162,7 @@ protected sealed override MethodInvoker UncachedMethodInvoker if (this.IsStatic) throw new MemberAccessException(SR.Acc_NotClassInit); - MethodInvoker invoker = this.GetCustomMethodInvokerIfNeeded(); + MethodBaseInvoker invoker = this.GetCustomMethodInvokerIfNeeded(); if (invoker != null) return invoker; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs index e74fdeb1694c4d..ddab93409dc8b6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs @@ -80,7 +80,7 @@ public sealed override int MetadataToken public sealed override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { object ctorAllocatedObject = this.MethodInvoker.Invoke(null, parameters, binder, invokeAttr, culture)!; - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return ctorAllocatedObject; } @@ -158,7 +158,7 @@ protected sealed override RuntimeParameterInfo[] RuntimeParameters } } - protected sealed override MethodInvoker UncachedMethodInvoker => new CustomMethodInvoker(_declaringType, _runtimeParameterTypes, _options, _action); + protected sealed override MethodBaseInvoker UncachedMethodInvoker => new CustomMethodInvoker(_declaringType, _runtimeParameterTypes, _options, _action); private volatile RuntimeParameterInfo[] _lazyParameters; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs index e7fc8b9a74e646..a10b14b3f0594c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs @@ -171,7 +171,7 @@ public sealed override RuntimeMethodHandle MethodHandle } } - protected sealed override MethodInvoker UncachedMethodInvoker => new CustomMethodInvoker(_declaringType, _runtimeParameterTypes, _options, _action); + protected sealed override MethodBaseInvoker UncachedMethodInvoker => new CustomMethodInvoker(_declaringType, _runtimeParameterTypes, _options, _action); internal sealed override RuntimeTypeInfo[] RuntimeGenericArgumentsOrParameters { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs index b9eec1e328abff..5a3584f16e6725 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs @@ -334,8 +334,8 @@ private object GetConstantValue(bool raw) return defaultValue; } - private volatile MethodInvoker _lazyGetterInvoker; - private volatile MethodInvoker _lazySetterInvoker; + private volatile MethodBaseInvoker _lazyGetterInvoker; + private volatile MethodBaseInvoker _lazySetterInvoker; private volatile RuntimeNamedMethodInfo _lazyGetter; private volatile RuntimeNamedMethodInfo _lazySetter; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs index 3e3b72557b7fff..0cdf16439cae0d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs @@ -120,5 +120,9 @@ public sealed override Array GetEnumValuesAsUnderlyingType() internal bool IsActualEnum => TryGetEEType(out EETypePtr eeType) && eeType.IsEnum; + +#pragma warning disable IDE0060 + internal static object AllocateValueType(RuntimeType type, object? value) => throw new NotSupportedException(); +#pragma warning restore IDE0060 } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 35d9cde9222faf..1fd37d6d7a90fa 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -25,7 +25,6 @@ using CanonicalFormKind = global::Internal.TypeSystem.CanonicalFormKind; - using Debug = System.Diagnostics.Debug; namespace Internal.Reflection.Execution @@ -304,7 +303,7 @@ public sealed override unsafe bool TryGetConstructedGenericTypeForComponentsNoCo return TypeLoaderEnvironment.Instance.TryGetConstructedGenericTypeForComponents(genericTypeDefinitionHandle, genericTypeArgumentHandles, out runtimeTypeHandle); } - public sealed override MethodInvoker TryGetMethodInvoker(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + public sealed override MethodBaseInvoker TryGetMethodInvoker(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { MethodBase methodInfo = ReflectionCoreExecution.ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles); diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs index 31eb0cf6656bd1..d2427e2eeff955 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.Runtime.cs @@ -152,7 +152,7 @@ public sealed override void GetEnumInfo(RuntimeTypeHandle typeHandle, out string return; } - public override IntPtr GetDynamicInvokeThunk(MethodInvoker invoker) + public override IntPtr GetDynamicInvokeThunk(MethodBaseInvoker invoker) { return ((MethodInvokerWithMethodInvokeInfo)invoker).MethodInvokeInfo.InvokeThunk ; diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/InstanceMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/InstanceMethodInvoker.cs index ad032363454e01..e07cf71b6dd192 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/InstanceMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/InstanceMethodInvoker.cs @@ -2,16 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using global::System; -using global::System.Threading; using global::System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using global::System.Diagnostics; -using global::System.Collections.Generic; using global::Internal.Runtime.Augments; -using global::Internal.Reflection.Execution; -using global::Internal.Reflection.Core.Execution; using global::Internal.Runtime.CompilerServices; namespace Internal.Reflection.Execution.MethodInvokers @@ -44,7 +40,7 @@ private static object ThrowTargetException(IntPtr _) throw new TargetException(); } - [DebuggerGuidedStepThroughAttribute] + [DebuggerGuidedStepThrough] protected sealed override object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { if (MethodInvokeInfo.IsSupportedSignature) // Workaround to match expected argument validation order @@ -58,7 +54,39 @@ private static object ThrowTargetException(IntPtr _) arguments, binderBundle, wrapInTargetInvocationException); - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + [DebuggerGuidedStepThrough] + protected sealed override object? Invoke(object? thisObject, Span arguments) + { + if (MethodInvokeInfo.IsSupportedSignature) // Workaround to match expected argument validation order + { + ValidateThis(thisObject, _declaringTypeHandle); + } + + object? result = MethodInvokeInfo.Invoke( + thisObject, + MethodInvokeInfo.LdFtnResult, + arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + [DebuggerGuidedStepThrough] + protected sealed override object? InvokeDirectWithFewArgs(object? thisObject, Span arguments) + { + if (MethodInvokeInfo.IsSupportedSignature) // Workaround to match expected argument validation order + { + ValidateThis(thisObject, _declaringTypeHandle); + } + + object? result = MethodInvokeInfo.InvokeDirectWithFewArgs( + thisObject, + MethodInvokeInfo.LdFtnResult, + arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } @@ -76,6 +104,20 @@ protected sealed override object CreateInstance(object[] arguments, BinderBundle return thisObject; } + protected sealed override object CreateInstance(Span arguments) + { + object thisObject = RawCalliHelper.Call(_allocatorMethod, _declaringTypeHandle.Value); + Invoke(thisObject, arguments); + return thisObject; + } + + protected sealed override object CreateInstanceWithFewArgs(Span arguments) + { + object thisObject = RawCalliHelper.Call(_allocatorMethod, _declaringTypeHandle.Value); + InvokeDirectWithFewArgs(thisObject, arguments); + return thisObject; + } + public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, object target, bool isStatic, bool isVirtual, bool isOpen) { if (isOpen) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs index 04bd56ea52c785..6877a0f46ddaf7 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/MethodInvokerWithMethodInvokeInfo.cs @@ -12,7 +12,7 @@ namespace Internal.Reflection.Execution.MethodInvokers { - internal abstract class MethodInvokerWithMethodInvokeInfo : MethodInvoker + internal abstract class MethodInvokerWithMethodInvokeInfo : MethodBaseInvoker { public MethodInvokerWithMethodInvokeInfo(MethodInvokeInfo methodInvokeInfo) { @@ -32,7 +32,7 @@ public override Delegate CreateDelegate(RuntimeTypeHandle delegateType, object t // // Creates the appropriate flavor of Invoker depending on the calling convention "shape" (static, instance or virtual.) // - internal static MethodInvoker CreateMethodInvoker(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, MethodInvokeInfo methodInvokeInfo) + internal static MethodBaseInvoker CreateMethodInvoker(RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, MethodInvokeInfo methodInvokeInfo) { bool isStatic = false; diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/StaticMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/StaticMethodInvoker.cs index 3e7a71a80862ea..2443e1848ef902 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/StaticMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/StaticMethodInvoker.cs @@ -2,14 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using global::System; -using global::System.Threading; using global::System.Reflection; using global::System.Diagnostics; -using global::System.Collections.Generic; - -using global::Internal.Runtime.Augments; -using global::Internal.Reflection.Execution; -using global::Internal.Reflection.Core.Execution; namespace Internal.Reflection.Execution.MethodInvokers { @@ -23,7 +17,7 @@ public StaticMethodInvoker(MethodInvokeInfo methodInvokeInfo) { } - [DebuggerGuidedStepThroughAttribute] + [DebuggerGuidedStepThrough] protected sealed override object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { object? result = MethodInvokeInfo.Invoke( @@ -32,15 +26,48 @@ public StaticMethodInvoker(MethodInvokeInfo methodInvokeInfo) arguments, binderBundle, wrapInTargetInvocationException); - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + [DebuggerGuidedStepThrough] + protected sealed override object? Invoke(object? thisObject, Span arguments) + { + object? result = MethodInvokeInfo.Invoke( + null, // this pointer is ignored for static methods + MethodInvokeInfo.LdFtnResult, + arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } + [DebuggerGuidedStepThrough] + protected sealed override object? InvokeDirectWithFewArgs(object? thisObject, Span arguments) + { + object? result = MethodInvokeInfo.InvokeDirectWithFewArgs( + null, // this pointer is ignored for static methods + MethodInvokeInfo.LdFtnResult, + arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + protected sealed override object CreateInstance(object[] arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { throw NotImplemented.ByDesign; } + protected sealed override object CreateInstance(Span arguments) + { + throw NotImplemented.ByDesign; + } + + protected sealed override object CreateInstanceWithFewArgs(Span arguments) + { + throw NotImplemented.ByDesign; + } + public sealed override IntPtr LdFtnResult => MethodInvokeInfo.LdFtnResult; } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/VirtualMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/VirtualMethodInvoker.cs index 09c3c53b24a216..f92c1ef3d6f700 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/VirtualMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/MethodInvokers/VirtualMethodInvoker.cs @@ -2,15 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using global::System; -using global::System.Threading; using global::System.Reflection; using global::System.Diagnostics; -using global::System.Collections.Generic; using global::Internal.Runtime.Augments; using global::Internal.Runtime.CompilerServices; -using global::Internal.Reflection.Execution; -using global::Internal.Reflection.Core.Execution; namespace Internal.Reflection.Execution.MethodInvokers { @@ -50,7 +46,7 @@ public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, o } } - [DebuggerGuidedStepThroughAttribute] + [DebuggerGuidedStepThrough] protected sealed override object? Invoke(object? thisObject, object?[]? arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { IntPtr resolvedVirtual = IntPtr.Zero; @@ -75,7 +71,45 @@ public sealed override Delegate CreateDelegate(RuntimeTypeHandle delegateType, o arguments, binderBundle, wrapInTargetInvocationException); - System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + [DebuggerGuidedStepThrough] + protected sealed override object? Invoke(object? thisObject, Span arguments) + { + IntPtr resolvedVirtual = IntPtr.Zero; + + if (MethodInvokeInfo.IsSupportedSignature) // Workaround to match expected argument validation order + { + ValidateThis(thisObject, _declaringTypeHandle); + resolvedVirtual = OpenMethodResolver.ResolveMethod(MethodInvokeInfo.VirtualResolveData, thisObject); + } + + object? result = MethodInvokeInfo.Invoke( + thisObject, + resolvedVirtual, + arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); + return result; + } + + [DebuggerGuidedStepThrough] + protected sealed override object? InvokeDirectWithFewArgs(object? thisObject, Span arguments) + { + IntPtr resolvedVirtual = IntPtr.Zero; + + if (MethodInvokeInfo.IsSupportedSignature) // Workaround to match expected argument validation order + { + ValidateThis(thisObject, _declaringTypeHandle); + resolvedVirtual = OpenMethodResolver.ResolveMethod(MethodInvokeInfo.VirtualResolveData, thisObject); + } + + object? result = MethodInvokeInfo.InvokeDirectWithFewArgs( + thisObject, + resolvedVirtual, + arguments); + DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } @@ -84,6 +118,16 @@ protected sealed override object CreateInstance(object[] arguments, BinderBundle throw NotImplemented.ByDesign; } + protected sealed override object CreateInstance(Span arguments) + { + throw NotImplemented.ByDesign; + } + + protected sealed override object CreateInstanceWithFewArgs(Span arguments) + { + throw NotImplemented.ByDesign; + } + internal IntPtr ResolveTarget(RuntimeTypeHandle type) { return OpenMethodResolver.ResolveMethod(MethodInvokeInfo.VirtualResolveData, type); diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index c11627614ea07c..7081ae2d1beb12 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1548,8 +1548,7 @@ bool SystemDomain::IsReflectionInvocationMethod(MethodDesc* pMeth) CLASS__DYNAMICMETHOD, CLASS__DELEGATE, CLASS__MULTICAST_DELEGATE, - CLASS__METHOD_INVOKER, - CLASS__CONSTRUCTOR_INVOKER, + CLASS__METHOD_INVOKERINTERNAL, }; static bool fInited = false; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 0fa94138ed46c9..902c6e4f7e80f6 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -492,8 +492,7 @@ DEFINE_CLASS(VECTORT, Numerics, Vector`1) DEFINE_CLASS(MEMBER, Reflection, MemberInfo) -DEFINE_CLASS(METHOD_INVOKER, Reflection, MethodInvoker) -DEFINE_CLASS(CONSTRUCTOR_INVOKER, Reflection, ConstructorInvoker) +DEFINE_CLASS(METHOD_INVOKERINTERNAL,Reflection, MethodBaseInvoker) DEFINE_CLASS_U(Reflection, RuntimeMethodInfo, NoClass) DEFINE_FIELD_U(m_handle, ReflectMethodObject, m_pMD) diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 9fc399c31cd5a3..47e635bed87588 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -556,11 +556,14 @@ FCFuncStart(gRuntimeHelpers) FCFuncElement("TryEnsureSufficientExecutionStack", ReflectionInvocation::TryEnsureSufficientExecutionStack) FCFuncElement("AllocTailCallArgBuffer", TailCallHelp::AllocTailCallArgBuffer) FCFuncElement("GetTailCallInfo", TailCallHelp::GetTailCallInfo) - FCFuncElement("RegisterForGCReporting", GCReporting::Register) - FCFuncElement("UnregisterForGCReporting", GCReporting::Unregister) FCFuncElement("Box", JIT_Box) FCFuncEnd() +FCFuncStart(gRuntimeImports) + FCFuncElement("RhRegisterForGCReporting", GCReporting::Register) + FCFuncElement("RhUnregisterForGCReporting", GCReporting::Unregister) +FCFuncEnd() + FCFuncStart(gMethodTableFuncs) FCFuncElement("GetNumInstanceFieldBytes", MethodTableNative::GetNumInstanceFieldBytes) FCFuncEnd() @@ -749,6 +752,7 @@ FCClassElement("ObjectMarshaler", "System.StubHelpers", gObjectMarshalerFuncs) FCClassElement("RuntimeAssembly", "System.Reflection", gRuntimeAssemblyFuncs) FCClassElement("RuntimeFieldHandle", "System", gCOMFieldHandleNewFuncs) FCClassElement("RuntimeHelpers", "System.Runtime.CompilerServices", gRuntimeHelpers) +FCClassElement("RuntimeImports", "System.Runtime", gRuntimeImports) FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) FCClassElement("RuntimeType", "System", gSystem_RuntimeType) diff --git a/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs b/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs index e95598dd47a666..c0c07b46defaaf 100644 --- a/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs +++ b/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs @@ -17,7 +17,7 @@ public static void VerifyInvokeIsUsingEmit_Method() Assert.Contains("Here", exInner.ToString()); Assert.Contains("InvokeStub_TestClassThatThrows", exInner.ToString()); - Assert.DoesNotContain(InterpretedMethodName, exInner.ToString()); + Assert.DoesNotContain("InterpretedInvoke_Method", exInner.ToString()); } [ConditionalFact(typeof(InvokeEmitTests), nameof(InvokeEmitTests.IsEmitInvokeSupported))] @@ -29,7 +29,7 @@ public static void VerifyInvokeIsUsingEmit_Constructor() Assert.Contains("Here", exInner.ToString()); Assert.Contains("InvokeStub_TestClassThatThrows", exInner.ToString()); - Assert.DoesNotContain(InterpretedMethodName, exInner.ToString()); + Assert.DoesNotContain("InterpretedInvoke_Constructor", exInner.ToString()); } private static bool IsEmitInvokeSupported() @@ -38,11 +38,7 @@ private static bool IsEmitInvokeSupported() return RuntimeFeature.IsDynamicCodeSupported; } - private static string InterpretedMethodName => PlatformDetection.IsMonoRuntime ? - "System.Reflection.MethodInvoker.InterpretedInvoke" : - "System.RuntimeMethodHandle.InvokeMethod"; - - private class TestClassThatThrows + private class TestClassThatThrows { public TestClassThatThrows() { diff --git a/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs b/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs index 355c154119cc13..67de322dc90762 100644 --- a/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs +++ b/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs @@ -16,12 +16,8 @@ public static void VerifyInvokeIsUsingEmit_Method() Exception exInner = ex.InnerException; Assert.Contains("Here", exInner.ToString()); - Assert.Contains(InterpretedMethodName(), exInner.ToString()); + Assert.Contains(InterpretedMethodName, exInner.ToString()); Assert.DoesNotContain("InvokeStub_TestClassThatThrows", exInner.ToString()); - - string InterpretedMethodName() => PlatformDetection.IsMonoRuntime ? - "System.Reflection.MethodInvoker.InterpretedInvoke" : - "System.RuntimeMethodHandle.InvokeMethod"; } [Fact] @@ -33,14 +29,18 @@ public static void VerifyInvokeIsUsingEmit_Constructor() Exception exInner = ex.InnerException; Assert.Contains("Here", exInner.ToString()); - Assert.Contains(InterpretedMethodName(), exInner.ToString()); + Assert.Contains(InterpretedConstructorName, exInner.ToString()); Assert.DoesNotContain("InvokeStub_TestClassThatThrows", exInner.ToString()); - - string InterpretedMethodName() => PlatformDetection.IsMonoRuntime ? - "System.Reflection.ConstructorInvoker.InterpretedInvoke" : - "System.RuntimeMethodHandle.InvokeMethod"; } + private static string InterpretedConstructorName => PlatformDetection.IsMonoRuntime ? + "InterpretedInvoke_Constructor" : + "System.RuntimeMethodHandle.InvokeMethod"; + + private static string InterpretedMethodName => PlatformDetection.IsMonoRuntime ? + "InterpretedInvoke_Method" : + "System.RuntimeMethodHandle.InvokeMethod"; + private class TestClassThatThrows { public TestClassThatThrows() diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 60ef1fbf28cad2..0b723db4398664 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -1393,9 +1393,15 @@ FieldInfo must be a runtime FieldInfo object. + + ConstructorInfo must be a runtime ConstructorInfo object. + MethodInfo must be a runtime MethodInfo object. + + Method must be a runtime MethodInfo, ConstructorInfo or DynamicMethod object. + Type must be a runtime Type object. diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 5cc1e4823e5e81..100105610416f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -684,11 +684,14 @@ + + + @@ -701,7 +704,6 @@ - @@ -2587,11 +2589,11 @@ - + - - + + @@ -2661,4 +2663,4 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs index 27ac00870c28a7..e27de1e67540df 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs @@ -3,95 +3,342 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime; +using static System.Reflection.InvokerEmitUtil; +using static System.Reflection.MethodBase; namespace System.Reflection { - internal sealed partial class ConstructorInvoker + public sealed partial class ConstructorInvoker { - private readonly RuntimeConstructorInfo _method; + internal InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; + internal InvokeFunc_Obj4Args? _invokeFunc_Obj4Args; + internal InvokeFunc_RefArgs? _invokeFunc_RefArgs; + internal InvokerStrategy _strategy; + internal readonly int _argCount; + internal readonly RuntimeType[] _argTypes; + internal readonly InvocationFlags _invocationFlags; + internal readonly InvokerArgFlags[] _invokerArgFlags; + internal readonly RuntimeConstructorInfo _method; + internal readonly bool _needsByRefStrategy; - private bool _invoked; - private bool _strategyDetermined; - private InvokerEmitUtil.InvokeFunc? _invokeFunc; + public static ConstructorInvoker Create(ConstructorInfo constructor) + { + ArgumentNullException.ThrowIfNull(constructor, nameof(constructor)); + + if (constructor is not RuntimeConstructorInfo runtimeConstructor) + { + throw new ArgumentException(SR.Argument_MustBeRuntimeConstructorInfo, nameof(constructor)); + } + + return new ConstructorInvoker(runtimeConstructor); + } + + private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] argumentTypes) + { + _method = constructor; + _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); + _argTypes = argumentTypes; + _argCount = _argTypes.Length; + + MethodInvokerCommon.Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); + } - public ConstructorInvoker(RuntimeConstructorInfo constructorInfo) + public object? Invoke() => Invoke(null, null, null, null); + public object? Invoke(object? arg1) => Invoke(arg1, null, null, null); + public object? Invoke(object? arg1, object? arg2) => Invoke(arg1, arg2, null, null); + public object? Invoke(object? arg1, object? arg2, object? arg3) => Invoke(arg1, arg2, arg3, null); + public object? Invoke(object? arg1, object? arg2, object? arg3, object? arg4) { - _method = constructorInfo; + if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) + { + _method.ThrowNoInvokeException(); + } - if (LocalAppContextSwitches.ForceInterpretedInvoke && !LocalAppContextSwitches.ForceEmitInvoke) + if (_argCount > MaxStackAllocArgCount) { - // Always use the native invoke; useful for testing. - _strategyDetermined = true; + MethodBaseInvoker.ThrowTargetParameterCountException(); } - else if (LocalAppContextSwitches.ForceEmitInvoke && !LocalAppContextSwitches.ForceInterpretedInvoke) + + switch (_argCount) { - // Always use emit invoke (if IsDynamicCodeSupported == true); useful for testing. - _invoked = true; + case 4: + CheckArgument(ref arg4, 3); + goto case 3; + case 3: + CheckArgument(ref arg3, 2); + goto case 2; + case 2: + CheckArgument(ref arg2, 1); + goto case 1; + case 1: + CheckArgument(ref arg1, 0); + break; } + + if (_invokeFunc_Obj4Args is not null) + { + // Fast path. + return _invokeFunc_Obj4Args(obj: null, arg1, arg2, arg3, arg4); + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_Obj4Args) == 0) + { + if (_needsByRefStrategy) + { + _strategy |= InvokerStrategy.StrategyDetermined_Obj4Args; + } + else + { + MethodInvokerCommon.DetermineInvokeStrategy_Obj4Args(ref _strategy, ref _invokeFunc_Obj4Args, _method, backwardsCompat: false); + if (_invokeFunc_Obj4Args is not null) + { + return _invokeFunc_Obj4Args(obj: null, arg1, arg2, arg3, arg4); + } + } + } + + return InvokeDirectByRef(arg1, arg2, arg3, arg4); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe object? InlinedInvoke(object? obj, IntPtr* args, BindingFlags invokeAttr) + public object? Invoke(Span arguments) { - if (_invokeFunc != null && (invokeAttr & BindingFlags.DoNotWrapExceptions) != 0 && obj == null) + if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) + { + _method.ThrowNoInvokeException(); + } + + if (arguments.Length != _argCount) + { + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + if (arguments.Length > MaxStackAllocArgCount) { - return _invokeFunc(target: null, args); + return InvokeWithManyArgs(arguments); + } + + if (_needsByRefStrategy) + { + return InvokeWithFewArgs(arguments); + } + + switch (_argCount) + { + case 0: + return Invoke(null, null, null, null); + case 1: + return Invoke(arguments[0], null, null, null); + case 2: + return Invoke(arguments[0], arguments[1], null, null); + case 3: + return Invoke(arguments[0], arguments[1], arguments[2], null); + default: + Debug.Assert(_argCount == 4); + return Invoke(arguments[0], arguments[1], arguments[2], arguments[3]); } - return Invoke(obj, args, invokeAttr); } - [DebuggerStepThrough] - [DebuggerHidden] - private unsafe object? Invoke(object? obj, IntPtr* args, BindingFlags invokeAttr) + internal object? InvokeWithFewArgs(Span arguments) { - if (!_strategyDetermined) + Debug.Assert(_argCount <= MaxStackAllocArgCount); + + StackAllocatedArgumentsWithCopyBack stackArgStorage = default; + Span copyOfArgs = stackArgStorage._args.AsSpan(_argCount); + scoped Span shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount); + + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + shouldCopyBack[i] = CheckArgument(ref arg, i); + copyOfArgs[i] = arg; + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + // Fast path. + return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); + // No need to call CopyBack here since there are no ref values. + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if (!_invoked) + if (_needsByRefStrategy) { - // The first time, ignoring race conditions, use the slow path. - _invoked = true; + _strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs; } else { - if (RuntimeFeature.IsDynamicCodeSupported) + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); + if (_invokeFunc_ObjSpanArgs is not null) { - _invokeFunc = InvokerEmitUtil.CreateInvokeDelegate(_method); + return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); } - _strategyDetermined = true; } } - object? ret; - if ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + object? ret = InvokeDirectByRefWithFewArgs(copyOfArgs); + CopyBack(arguments, copyOfArgs, shouldCopyBack); + return ret; + } + + internal object? InvokeDirectByRef(object? arg1 = null, object? arg2 = null, object? arg3 = null, object? arg4 = null) + { + StackAllocatedArguments stackStorage = new(arg1, arg2, arg3, arg4); + return InvokeDirectByRefWithFewArgs(stackStorage._args.AsSpan(_argCount)); + } + + internal unsafe object? InvokeDirectByRefWithFewArgs(Span copyOfArgs) + { + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + } + + scoped StackAllocatedByRefs byrefs = default; +#pragma warning disable CS8500 + IntPtr* pByRefFixedStorage = (IntPtr*)&byrefs; +#pragma warning restore CS8500 + + for (int i = 0; i < _argCount; i++) + { +#pragma warning disable CS8500 + *(ByReference*)(pByRefFixedStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref copyOfArgs[i]!.GetRawData()) : + ByReference.Create(ref copyOfArgs[i]); + } + + return _invokeFunc_RefArgs!(obj: null, pByRefFixedStorage); + } + + internal unsafe object? InvokeWithManyArgs(Span arguments) + { + Span copyOfArgs; + RuntimeImports.GCFrameRegistration regArgStorage; + + if (!_needsByRefStrategy) { - try + if ((_strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) { - // For the rarely used scenario of calling the constructor directly through MethodBase.Invoke() - // with a non-null 'obj', we use the slow path to avoid having two emit-based delegates. - if (_invokeFunc != null && obj == null) + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + IntPtr* pArgStorage = stackalloc IntPtr[_argCount]; + NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); + regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); + + try { - ret = _invokeFunc(target: null, args); + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + CheckArgument(ref arg, i); + copyOfArgs[i] = arg; + } + + return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); + // No need to call CopyBack here since there are no ref values. } - else + finally { - ret = InterpretedInvoke(obj, args); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); } } - catch (Exception e) + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + } + + IntPtr* pStorage = stackalloc IntPtr[2 * _argCount]; + NativeMemory.Clear(pStorage, (nuint)(2 * _argCount) * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); + + IntPtr* pByRefStorage = pStorage + _argCount; + scoped Span shouldCopyBack = stackalloc bool[_argCount]; + + regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); + RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + shouldCopyBack[i] = CheckArgument(ref arg, i); + copyOfArgs[i] = arg; +#pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + } + + object? ret = _invokeFunc_RefArgs!(obj: null, pByRefStorage); + CopyBack(arguments, copyOfArgs, shouldCopyBack); + return ret; + } + finally + { + RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + // Copy modified values out. This is only done with ByRef parameters. + internal void CopyBack(Span dest, Span copyOfParameters, Span shouldCopyBack) + { + for (int i = 0; i < dest.Length; i++) + { + if (shouldCopyBack[i]) { - throw new TargetInvocationException(e); + if ((_invokerArgFlags[i] & InvokerArgFlags.IsNullableOfT) != 0) + { + Debug.Assert(copyOfParameters[i] != null); + Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT); + dest![i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]); + } + else + { + dest![i] = copyOfParameters[i]; + } } } - else if (_invokeFunc != null && obj == null) + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal bool CheckArgument(ref object? arg, int i) + { + RuntimeType sigType = _argTypes[i]; + + // Convert the type if necessary. + // Note that Type.Missing is not supported. + if (arg is null) { - ret = _invokeFunc(target: null, args); + if ((_invokerArgFlags[i] & InvokerArgFlags.IsValueType_ByRef_Or_Pointer) != 0) + { + return sigType.CheckValue(ref arg); + } } - else + else if (!ReferenceEquals(arg.GetType(), sigType)) { - ret = InterpretedInvoke(obj, args); + return sigType.CheckValue(ref arg); } - return ret; + return false; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 1e0622e385931f..8a756b1ef1b0a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -413,6 +413,8 @@ public bool InitLocals set => _initLocals = value; } + internal RuntimeType[] ArgumentTypes => _parameterTypes; + private RuntimeParameterInfo[] LoadParameters() { if (_parameters == null) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokeUtils.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokeUtils.cs index 1471d1d977ef1e..b128d7068b82d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokeUtils.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokeUtils.cs @@ -111,12 +111,18 @@ public static object ConvertOrWiden(Type srcType, object srcObject, Type dstType private static bool TryConvertPointer(object srcObject, [NotNullWhen(true)] out object? dstPtr) { - if (srcObject is IntPtr or UIntPtr) + if (srcObject is IntPtr) { dstPtr = srcObject; return true; } + if (srcObject is UIntPtr) + { + dstPtr = (IntPtr)(UIntPtr)srcObject; + return true; + } + // The source pointer should already have been converted to an IntPtr. Debug.Assert(srcObject is not Pointer); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs index 0dac01f77a0e42..e99a79bc85b134 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Reflection.Emit; using System.Runtime.CompilerServices; @@ -13,9 +12,135 @@ internal static class InvokerEmitUtil // If changed, update native stack walking code that also uses this prefix to ignore reflection frames. private const string InvokeStubPrefix = "InvokeStub_"; - internal unsafe delegate object? InvokeFunc(object? target, IntPtr* arguments); + internal unsafe delegate object? InvokeFunc_RefArgs(object? obj, IntPtr* refArguments); + internal delegate object? InvokeFunc_ObjSpanArgs(object? obj, Span arguments); + internal delegate object? InvokeFunc_Obj4Args(object? obj, object? arg1, object? arg2, object? arg3, object? arg4); - public static unsafe InvokeFunc CreateInvokeDelegate(MethodBase method) + public static unsafe InvokeFunc_Obj4Args CreateInvokeDelegate_Obj4Args(MethodBase method, bool backwardsCompat) + { + Debug.Assert(!method.ContainsGenericParameters); + + bool emitNew = method is RuntimeConstructorInfo; + bool hasThis = !emitNew && !method.IsStatic; + + Type[] delegateParameters = new Type[5] { typeof(object), typeof(object), typeof(object), typeof(object), typeof(object) }; + + string declaringTypeName = method.DeclaringType != null ? method.DeclaringType.Name + "." : string.Empty; + var dm = new DynamicMethod( + InvokeStubPrefix + declaringTypeName + method.Name, + returnType: typeof(object), + delegateParameters, + typeof(object).Module, // Use system module to identify our DynamicMethods. + skipVisibility: true); + + ILGenerator il = dm.GetILGenerator(); + + // Handle instance methods. + if (hasThis) + { + il.Emit(OpCodes.Ldarg_0); + if (method.DeclaringType!.IsValueType) + { + il.Emit(OpCodes.Unbox, method.DeclaringType); + } + } + + // Push the arguments. + ParameterInfo[] parameters = method.GetParametersNoCopy(); + for (int i = 0; i < parameters.Length; i++) + { + RuntimeType parameterType = (RuntimeType)parameters[i].ParameterType; + + switch (i) + { + case 0: + il.Emit(OpCodes.Ldarg_1); + break; + case 1: + il.Emit(OpCodes.Ldarg_2); + break; + case 2: + il.Emit(OpCodes.Ldarg_3); + break; + default: + il.Emit(OpCodes.Ldarg_S, i + 1); + break; + } + + if (parameterType.IsPointer) + { + il.Emit(OpCodes.Unbox_Any, typeof(IntPtr)); + } + else if (parameterType.IsValueType) + { + il.Emit(OpCodes.Unbox_Any, parameterType); + } + } + + EmitCallAndReturnHandling(il, method, emitNew, backwardsCompat); + + // Create the delegate; it is also compiled at this point due to restrictedSkipVisibility=true. + return (InvokeFunc_Obj4Args)dm.CreateDelegate(typeof(InvokeFunc_Obj4Args), target: null); + } + + public static unsafe InvokeFunc_ObjSpanArgs CreateInvokeDelegate_ObjSpanArgs(MethodBase method, bool backwardsCompat) + { + Debug.Assert(!method.ContainsGenericParameters); + + bool emitNew = method is RuntimeConstructorInfo; + bool hasThis = !emitNew && !method.IsStatic; + + // The first parameter is unused but supports treating the DynamicMethod as an instance method which is slightly faster than a static. + Type[] delegateParameters = new Type[2] { typeof(object), typeof(Span) }; + + string declaringTypeName = method.DeclaringType != null ? method.DeclaringType.Name + "." : string.Empty; + var dm = new DynamicMethod( + InvokeStubPrefix + declaringTypeName + method.Name, + returnType: typeof(object), + delegateParameters, + typeof(object).Module, // Use system module to identify our DynamicMethods. + skipVisibility: true); + + ILGenerator il = dm.GetILGenerator(); + + // Handle instance methods. + if (hasThis) + { + il.Emit(OpCodes.Ldarg_0); + if (method.DeclaringType!.IsValueType) + { + il.Emit(OpCodes.Unbox, method.DeclaringType); + } + } + + // Push the arguments. + ParameterInfo[] parameters = method.GetParametersNoCopy(); + for (int i = 0; i < parameters.Length; i++) + { + RuntimeType parameterType = (RuntimeType)parameters[i].ParameterType; + + il.Emit(OpCodes.Ldarga_S, 1); + il.Emit(OpCodes.Ldc_I4, i); + il.Emit(OpCodes.Call, Methods.Span_get_Item()); + il.Emit(OpCodes.Ldind_Ref); + + if (parameterType.IsPointer) + { + il.Emit(OpCodes.Unbox_Any, typeof(IntPtr)); + } + else if (parameterType.IsValueType) + { + il.Emit(OpCodes.Unbox_Any, parameterType); + } + } + + EmitCallAndReturnHandling(il, method, emitNew, backwardsCompat); + + // Create the delegate; it is also compiled at this point due to restrictedSkipVisibility=true. + return (InvokeFunc_ObjSpanArgs)dm.CreateDelegate(typeof(InvokeFunc_ObjSpanArgs), target: null); + } + + public static unsafe InvokeFunc_RefArgs CreateInvokeDelegate_RefArgs(MethodBase method, bool backwardsCompat) { Debug.Assert(!method.ContainsGenericParameters); @@ -65,9 +190,17 @@ public static unsafe InvokeFunc CreateInvokeDelegate(MethodBase method) } } + EmitCallAndReturnHandling(il, method, emitNew, backwardsCompat); + + // Create the delegate; it is also compiled at this point due to restrictedSkipVisibility=true. + return (InvokeFunc_RefArgs)dm.CreateDelegate(typeof(InvokeFunc_RefArgs), target: null); + } + + private static void EmitCallAndReturnHandling(ILGenerator il, MethodBase method, bool emitNew, bool backwardsCompat) + { // For CallStack reasons, don't inline target method. // Mono interpreter does not support\need this. - if (RuntimeFeature.IsDynamicCodeCompiled) + if (backwardsCompat && RuntimeFeature.IsDynamicCodeCompiled) { #if MONO il.Emit(OpCodes.Call, Methods.DisableInline()); @@ -159,9 +292,6 @@ public static unsafe InvokeFunc CreateInvokeDelegate(MethodBase method) } il.Emit(OpCodes.Ret); - - // Create the delegate; it is also compiled at this point due to restrictedSkipVisibility=true. - return (InvokeFunc)dm.CreateDelegate(typeof(InvokeFunc), target: null); } private static class ThrowHelper @@ -178,6 +308,10 @@ private static class Methods public static FieldInfo ByReferenceOfByte_Value() => s_ByReferenceOfByte_Value ??= typeof(ByReference).GetField("Value")!; + private static MethodInfo? s_Span_get_Item; + public static MethodInfo Span_get_Item() => + s_Span_get_Item ??= typeof(Span).GetProperty("Item")!.GetGetMethod()!; + private static MethodInfo? s_ThrowHelper_Throw_NullReference_InvokeNullRefReturned; public static MethodInfo ThrowHelper_Throw_NullReference_InvokeNullRefReturned() => s_ThrowHelper_Throw_NullReference_InvokeNullRefReturned ??= typeof(ThrowHelper).GetMethod(nameof(ThrowHelper.Throw_NullReference_InvokeNullRefReturned))!; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs index 2a8349acb0061b..fb07f75f779b0e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs @@ -12,6 +12,8 @@ namespace System.Reflection { public abstract partial class MethodBase : MemberInfo { + internal const int MaxStackAllocArgCount = 4; + protected MethodBase() { } public abstract ParameterInfo[] GetParameters(); @@ -137,174 +139,103 @@ internal virtual Type[] GetParameterTypes() } #if !NATIVEAOT - private protected void ValidateInvokeTarget(object? target) + internal static object? HandleTypeMissing(ParameterInfo paramInfo, RuntimeType sigType) { - // Confirm member invocation has an instance and is of the correct type - if (!IsStatic) + if (paramInfo.DefaultValue == DBNull.Value) { - if (target == null) - { - throw new TargetException(SR.RFLCT_Targ_StatMethReqTarg); - } - - if (!DeclaringType!.IsInstanceOfType(target)) - { - throw new TargetException(SR.RFLCT_Targ_ITargMismatch); - } + throw new ArgumentException(SR.Arg_VarMissNull, "parameters"); } - } - private protected unsafe void CheckArguments( - Span copyOfParameters, - IntPtr* byrefParameters, - Span shouldCopyBack, - ReadOnlySpan parameters, - RuntimeType[] sigTypes, - Binder? binder, - CultureInfo? culture, - BindingFlags invokeAttr - ) - { - Debug.Assert(parameters.Length > 0); + object? arg = paramInfo.DefaultValue; - ParameterInfo[]? paramInfos = null; - for (int i = 0; i < parameters.Length; i++) + if (sigType.IsNullableOfT) { - ParameterCopyBackAction copyBackArg = default; - bool isValueType = false; - object? arg = parameters[i]; - RuntimeType sigType = sigTypes[i]; - - // Convert a Type.Missing to the default value. - if (ReferenceEquals(arg, Type.Missing)) + if (arg is not null) { - paramInfos ??= GetParametersNoCopy(); - ParameterInfo paramInfo = paramInfos[i]; - - if (paramInfo.DefaultValue == DBNull.Value) - { - throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters)); - } - - arg = paramInfo.DefaultValue; - - if (sigType.IsNullableOfT) - { - copyBackArg = ParameterCopyBackAction.CopyNullable; - - if (arg is not null) - { - // For nullable Enum types, the ParameterInfo.DefaultValue returns a raw value which - // needs to be parsed to the Enum type, for more info: https://github.com/dotnet/runtime/issues/12924 - Type argumentType = sigType.GetGenericArguments()[0]; - if (argumentType.IsEnum) - { - arg = Enum.ToObject(argumentType, arg); - } - } - } - else + // For nullable Enum types, the ParameterInfo.DefaultValue returns a raw value which + // needs to be parsed to the Enum type, for more info: https://github.com/dotnet/runtime/issues/12924 + Type argumentType = sigType.GetGenericArguments()[0]; + if (argumentType.IsEnum) { - copyBackArg = ParameterCopyBackAction.Copy; + arg = Enum.ToObject(argumentType, arg); } } + } - if (arg is null) - { - // Fast path for null reference types. - isValueType = RuntimeTypeHandle.IsValueType(sigType); - if (isValueType || RuntimeTypeHandle.IsByRef(sigType)) - { - isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr); - } - } - else - { - RuntimeType argType = (RuntimeType)arg.GetType(); + return arg; + } - if (ReferenceEquals(argType, sigType)) - { - // Fast path when the value's type matches the signature type. - isValueType = RuntimeTypeHandle.IsValueType(argType); - } - else if (sigType.TryByRefFastPath(ref arg, ref isValueType)) - { - // Fast path when the value's type matches the signature type of a byref parameter. - copyBackArg = ParameterCopyBackAction.Copy; - } - else - { - // Slow path that supports type conversions. - isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr); - } - } + [Flags] + internal enum InvokerStrategy : int + { + HasBeenInvoked_ObjSpanArgs = 0x1, + StrategyDetermined_ObjSpanArgs = 0x2, - // We need to perform type safety validation against the incoming arguments, but we also need - // to be resilient against the possibility that some other thread (or even the binder itself!) - // may mutate the array after we've validated the arguments but before we've properly invoked - // the method. The solution is to copy the arguments to a different, not-user-visible buffer - // as we validate them. n.b. This disallows use of ArrayPool, as ArrayPool-rented arrays are - // considered user-visible to threads which may still be holding on to returned instances. - // This separate array is also used to hold default values when 'null' is specified for value - // types, and also used to hold the results from conversions such as from Int16 to Int32. For - // compat, these default values and conversions are not be applied to the incoming arguments. - shouldCopyBack[i] = copyBackArg; - copyOfParameters[i] = arg; - -#pragma warning disable 8500 - if (isValueType) - { - Debug.Assert(arg != null); - Debug.Assert( - arg.GetType() == sigType || - (sigType.IsPointer && (arg.GetType() == typeof(IntPtr) || arg.GetType() == typeof(UIntPtr))) || - (sigType.IsByRef && arg.GetType() == RuntimeTypeHandle.GetElementType(sigType)) || - ((sigType.IsEnum || arg.GetType().IsEnum) && RuntimeType.GetUnderlyingType((RuntimeType)arg.GetType()) == RuntimeType.GetUnderlyingType(sigType))); - ByReference valueTypeRef = ByReference.Create(ref copyOfParameters[i]!.GetRawData()); - *(ByReference*)(byrefParameters + i) = valueTypeRef; - } - else - { - ByReference objRef = ByReference.Create(ref copyOfParameters[i]); - *(ByReference*)(byrefParameters + i) = objRef; - } -#pragma warning restore 8500 - } + HasBeenInvoked_Obj4Args = 0x4, + StrategyDetermined_Obj4Args = 0x8, + + HasBeenInvoked_RefArgs = 0x10, + StrategyDetermined_RefArgs = 0x20, } - internal const int MaxStackAllocArgCount = 4; + [Flags] + internal enum InvokerArgFlags : int + { + IsValueType = 0x1, + IsValueType_ByRef_Or_Pointer = 0x2, + IsNullableOfT = 0x4, + } [InlineArray(MaxStackAllocArgCount)] - private protected struct ArgumentData + internal struct ArgumentData { private T _arg0; [UnscopedRef] public Span AsSpan(int length) { - Debug.Assert((uint)length <= (uint) MaxStackAllocArgCount); + Debug.Assert((uint)length <= MaxStackAllocArgCount); return new Span(ref _arg0, length); } + + public void Set(int index, T value) + { + Debug.Assert((uint)index < MaxStackAllocArgCount); + Unsafe.Add(ref _arg0, index) = value; + } } // Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack. - // When argument count <= MaxStackAllocArgCount, define a local of type default(StackAllocatedByRefs) - // and pass it to CheckArguments(). + // When argument count <= MaxStackAllocArgCount, define a local of these helper structs. // For argument count > MaxStackAllocArgCount, do a stackalloc of void* pointers along with // GCReportingRegistration to safely track references. [StructLayout(LayoutKind.Sequential)] - private protected ref struct StackAllocedArguments + internal ref struct StackAllocatedArguments { + public StackAllocatedArguments(object? obj1, object? obj2, object? obj3, object? obj4) + { + _args.Set(0, obj1); + _args.Set(1, obj2); + _args.Set(2, obj3); + _args.Set(3, obj4); + } + internal ArgumentData _args; - internal ArgumentData _copyBacks; + } + + [StructLayout(LayoutKind.Sequential)] + internal ref struct StackAllocatedArgumentsWithCopyBack + { + internal ArgumentData _args; + internal ArgumentData _shouldCopyBack; } // Helper struct to avoid intermediate IntPtr[] allocation and RegisterForGCReporting in calls to the native reflection stack. [InlineArray(MaxStackAllocArgCount)] - private protected ref struct StackAllocatedByRefs + internal ref struct StackAllocatedByRefs { internal ref byte _arg0; } #endif - } + } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs new file mode 100644 index 00000000000000..01ae56e690cb63 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs @@ -0,0 +1,84 @@ +// 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.Globalization; +using System.Runtime; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using static System.Reflection.MethodBase; + +namespace System.Reflection +{ + internal sealed partial class MethodBaseInvoker + { + // The rarely used scenario of calling the constructor on an existing instance. + internal unsafe object? InvokeConstructorWithoutAlloc( + object? obj, + BindingFlags invokeAttr, + Binder? binder, + object?[] parameters, + CultureInfo? culture) + { + bool wrapInTargetInvocationException = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; + object? ret; + int argCount = _argCount; + + scoped Span shouldCopyBack = stackalloc bool[argCount]; + IntPtr* pStorage = stackalloc IntPtr[2 * argCount]; + NativeMemory.Clear(pStorage, (nuint)(2 * argCount) * (nuint)sizeof(IntPtr)); + Span copyOfArgs = new(ref Unsafe.AsRef(pStorage), argCount); + RuntimeImports.GCFrameRegistration regArgStorage = new((void**)pStorage, (uint)argCount, areByRefs: false); + IntPtr* pByRefStorage = pStorage + argCount; + RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)argCount, areByRefs: true); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + + CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + for (int i = 0; i < argCount; i++) + { +#pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + } + + try + { + // Use the interpreted version to avoid having to generate a new method that doesn't allocate. + ret = InterpretedInvoke_Constructor(obj, pByRefStorage); + } + catch (Exception e) when (wrapInTargetInvocationException) + { + throw new TargetInvocationException(e); + } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + finally + { + RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + } + } + + internal unsafe object? InvokeConstructorWithoutAlloc(object? obj, bool wrapInTargetInvocationException) + { + try + { + // Use the interpreted version to avoid having to generate a new method that doesn't allocate. + return InterpretedInvoke_Constructor(obj, null); + } + catch (Exception e) when (wrapInTargetInvocationException) + { + throw new TargetInvocationException(e); + } + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs new file mode 100644 index 00000000000000..6256face575c8f --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs @@ -0,0 +1,422 @@ +// 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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime; +using static System.Reflection.InvokerEmitUtil; +using static System.Reflection.MethodBase; +using System.Globalization; + +namespace System.Reflection +{ + internal sealed partial class MethodBaseInvoker + { + internal const int MaxStackAllocArgCount = 4; + + internal InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; + internal InvokeFunc_RefArgs? _invokeFunc_RefArgs; + internal InvokerStrategy _strategy; + internal readonly InvocationFlags _invocationFlags; + internal readonly InvokerArgFlags[] _invokerArgFlags; + internal readonly RuntimeType[] _argTypes; + internal readonly MethodBase _method; + internal readonly int _argCount; + internal readonly bool _needsByRefStrategy; + + private MethodBaseInvoker(MethodBase method, RuntimeType[] argumentTypes) + { + _method = method; + _argTypes = argumentTypes; + _argCount = _argTypes.Length; + + MethodInvokerCommon.Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); + } + + [DoesNotReturn] + internal static void ThrowTargetParameterCountException() + { + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + + #region MethodBase APIs + internal unsafe object? InvokeWithNoArgs(object? obj, BindingFlags invokeAttr) + { + Debug.Assert(_argCount == 0); + + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); + } + + try + { + return _invokeFunc_RefArgs!(obj, refArguments: null); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + } + + internal unsafe object? InvokeWithOneArg( + object? obj, + BindingFlags invokeAttr, + Binder? binder, + object?[] parameters, + CultureInfo? culture) + { + Debug.Assert(_argCount == 1); + + object? arg = parameters[0]; + ReadOnlySpan parametersSpan = new(arg); + + object? copyOfArg = null; + Span copyOfArgs = new(ref copyOfArg); + + bool copyBack = false; + Span shouldCopyBack = new(ref copyBack); + + CheckArguments(parametersSpan, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + object? ret; + if (!_needsByRefStrategy) + { + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + try + { + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + } + + ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr); + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + + internal unsafe object? InvokeWithFewArgs( + object? obj, + BindingFlags invokeAttr, + Binder? binder, + object?[] parameters, + CultureInfo? culture) + { + Debug.Assert(_argCount <= MaxStackAllocArgCount); + + StackAllocatedArgumentsWithCopyBack stackArgStorage = default; + Span copyOfArgs = stackArgStorage._args.AsSpan(_argCount); + Span shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount); + + CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + object? ret; + if (!_needsByRefStrategy) + { + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + try + { + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + } + + ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr); + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + + internal unsafe object? InvokeDirectByRefWithFewArgs(object? obj, Span copyOfArgs, BindingFlags invokeAttr) + { + Debug.Assert(_argCount <= MaxStackAllocArgCount); + + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); + } + + StackAllocatedByRefs byrefs = default; +#pragma warning disable CS8500 + IntPtr* pByRefFixedStorage = (IntPtr*)&byrefs; +#pragma warning restore CS8500 + + for (int i = 0; i < _argCount; i++) + { +#pragma warning disable CS8500 + *(ByReference*)(pByRefFixedStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref copyOfArgs[i]!.GetRawData()) : + ByReference.Create(ref copyOfArgs[i]); + } + + try + { + return _invokeFunc_RefArgs!(obj, pByRefFixedStorage); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + } + + internal unsafe object? InvokeWithManyArgs( + object? obj, + BindingFlags invokeAttr, + Binder? binder, + object?[] parameters, + CultureInfo? culture) + { + Debug.Assert(_argCount > MaxStackAllocArgCount); + + Span copyOfArgs; + object? ret; + RuntimeImports.GCFrameRegistration regArgStorage; + Span shouldCopyBack; + + if (!_needsByRefStrategy) + { + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + IntPtr* pArgStorage = stackalloc IntPtr[_argCount * 2]; + NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr) * 2); + copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); + regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); + shouldCopyBack = new Span(pArgStorage + _argCount, _argCount); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + + CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + try + { + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + finally + { + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + } + } + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); + } + + IntPtr* pStorage = stackalloc IntPtr[3 * _argCount]; + NativeMemory.Clear(pStorage, (nuint)(3 * _argCount) * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); + regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); + IntPtr* pByRefStorage = pStorage + _argCount; + RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + shouldCopyBack = new Span(pStorage + _argCount * 2, _argCount); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + + CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + for (int i = 0; i < _argCount; i++) + { +#pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + } + + try + { + ret = _invokeFunc_RefArgs!(obj, pByRefStorage); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; + } + finally + { + RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void InvokePropertySetter( + object? obj, + BindingFlags invokeAttr, + Binder? binder, + object? parameter, + CultureInfo? culture) + { + Debug.Assert(_argCount == 1); + + object? copyOfArg = null; + Span copyOfArgs = new(ref copyOfArg, 1); + + bool copyBack = false; + Span shouldCopyBack = new(ref copyBack, 1); // Not used for setters + + CheckArguments(new ReadOnlySpan(parameter), copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + if (_invokeFunc_ObjSpanArgs is not null) // Fast path check + { + try + { + _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + } + else + { + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) + { + // Initialize for next time. + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + } + + InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr); + } + } + + // Copy modified values out. This is done with ByRef, Type.Missing and parameters changed by the Binder. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void CopyBack(object?[] dest, Span copyOfParameters, Span shouldCopyBack) + { + for (int i = 0; i < dest.Length; i++) + { + if (shouldCopyBack[i]) + { + if ((_invokerArgFlags[i] & InvokerArgFlags.IsNullableOfT) != 0) + { + Debug.Assert(copyOfParameters[i] != null); + Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT); + dest![i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]); + } + else + { + dest![i] = copyOfParameters[i]; + } + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void CheckArguments( + ReadOnlySpan parameters, + Span copyOfParameters, + Span shouldCopyBack, + Binder? binder, + CultureInfo? culture, + BindingFlags invokeAttr + ) + { + for (int i = 0; i < parameters.Length; i++) + { + object? arg = parameters[i]; + RuntimeType sigType = _argTypes[i]; + + // Convert a Type.Missing to the default value. + if (ReferenceEquals(arg, Type.Missing)) + { + arg = HandleTypeMissing(_method.GetParametersNoCopy()[i], sigType); + shouldCopyBack[i] = true; + } + + // Convert the type if necessary. + if (arg is null) + { + if ((_invokerArgFlags[i] & InvokerArgFlags.IsValueType_ByRef_Or_Pointer) != 0) + { + shouldCopyBack[i] = sigType.CheckValue(ref arg, binder, culture, invokeAttr); + } + } + else if (!ReferenceEquals(arg.GetType(), sigType)) + { + // Determine if we can use the fast path for byref types + if (TryByRefFastPath(sigType, ref arg)) + { + // Fast path when the value's type matches the signature type of a byref parameter. + shouldCopyBack[i] = true; + } + else + { + shouldCopyBack[i] = sigType.CheckValue(ref arg, binder, culture, invokeAttr); + } + } + + copyOfParameters[i] = arg; + } + } + + internal static bool TryByRefFastPath(RuntimeType type, ref object arg) + { + if (RuntimeType.TryGetByRefElementType(type, out RuntimeType? sigElementType) && + ReferenceEquals(sigElementType, arg.GetType())) + { + if (sigElementType.IsValueType) + { + // Make a copy to prevent the boxed instance from being directly modified by the method. + arg = RuntimeType.AllocateValueType(sigElementType, arg); + } + + return true; + } + + return false; + } + #endregion + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs index 15a0c195308286..8a031a3664fc55 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs @@ -2,78 +2,367 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using static System.Reflection.InvokerEmitUtil; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime; +using static System.Reflection.MethodBase; +using System.Reflection.Emit; namespace System.Reflection { - internal sealed partial class MethodInvoker + public sealed partial class MethodInvoker { - private readonly MethodBase _method; + internal InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; + internal InvokeFunc_Obj4Args? _invokeFunc_Obj4Args; + internal InvokeFunc_RefArgs? _invokeFunc_RefArgs; + internal InvokerStrategy _strategy; + internal readonly int _argCount; + internal readonly RuntimeType[] _argTypes; + internal readonly InvocationFlags _invocationFlags; + internal readonly InvokerArgFlags[] _invokerArgFlags; + internal readonly MethodBase _method; + internal readonly bool _needsByRefStrategy; + internal readonly bool _isStatic; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe object? InlinedInvoke(object? obj, IntPtr* args, BindingFlags invokeAttr) + public static MethodInvoker Create(MethodBase method) { - if (_invokeFunc != null && (invokeAttr & BindingFlags.DoNotWrapExceptions) != 0) + ArgumentNullException.ThrowIfNull(method, nameof(method)); + + if (method is RuntimeMethodInfo rmi) + { + return new MethodInvoker(rmi); + } + + if (method is DynamicMethod dm) + { + return new MethodInvoker(dm); + } + + if (method is RuntimeConstructorInfo rci) { - return _invokeFunc(obj, args); + // This is useful for calling a constructor on an already-initialized object + // such as created from RuntimeHelpers.GetUninitializedObject(Type). + return new MethodInvoker(rci); } - return Invoke(obj, args, invokeAttr); + + throw new ArgumentException(SR.Argument_MustBeRuntimeMethod, nameof(method)); } - private bool _invoked; - private bool _strategyDetermined; - private InvokerEmitUtil.InvokeFunc? _invokeFunc; + private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) + { + _method = method; + _argTypes = argumentTypes; + _argCount = _argTypes.Length; + _isStatic = _method.IsStatic; + + MethodInvokerCommon.Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); + } - [DebuggerStepThrough] - [DebuggerHidden] - private unsafe object? Invoke(object? obj, IntPtr* args, BindingFlags invokeAttr) + public object? Invoke(object? obj) => Invoke(obj, null, null, null, null); + public object? Invoke(object? obj, object? arg1) => Invoke(obj, arg1, null, null, null); + public object? Invoke(object? obj, object? arg1, object? arg2) => Invoke(obj, arg1, arg2, null, null); + public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3) => Invoke(obj, arg1, arg2, arg3, null); + public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3, object? arg4) { - if (!_strategyDetermined) + if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) + { + ((RuntimeMethodInfo)_method).ThrowNoInvokeException(); + } + + if (_argCount > MaxStackAllocArgCount) + { + MethodBaseInvoker.ThrowTargetParameterCountException(); + } + + if (!_isStatic) + { + MethodInvokerCommon.ValidateInvokeTarget(obj, _method); + } + + switch (_argCount) + { + case 4: + CheckArgument(ref arg4, 3); + goto case 3; + case 3: + CheckArgument(ref arg3, 2); + goto case 2; + case 2: + CheckArgument(ref arg2, 1); + goto case 1; + case 1: + CheckArgument(ref arg1, 0); + break; + } + + if (_invokeFunc_Obj4Args is not null) { - if (!_invoked) + // Fast path. + return _invokeFunc_Obj4Args(obj, arg1, arg2, arg3, arg4); + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_Obj4Args) == 0) + { + if (_needsByRefStrategy) { - // The first time, ignoring race conditions, use the slow path. - _invoked = true; + _strategy |= InvokerStrategy.StrategyDetermined_Obj4Args; } else { - if (RuntimeFeature.IsDynamicCodeSupported) + MethodInvokerCommon.DetermineInvokeStrategy_Obj4Args(ref _strategy, ref _invokeFunc_Obj4Args, _method, backwardsCompat: false); + if (_invokeFunc_Obj4Args is not null) { - _invokeFunc = InvokerEmitUtil.CreateInvokeDelegate(_method); + return _invokeFunc_Obj4Args(obj, arg1, arg2, arg3, arg4); } - _strategyDetermined = true; } } - object? ret; - if ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + return InvokeDirectByRef(obj, arg1, arg2, arg3, arg4); + } + + public object? Invoke(object? obj, Span arguments) + { + if (!_needsByRefStrategy) + { + switch (_argCount) + { + case 0: + return Invoke(obj, null, null, null, null); + case 1: + return Invoke(obj, arguments[0], null, null, null); + case 2: + return Invoke(obj, arguments[0], arguments[1], null, null); + case 3: + return Invoke(obj, arguments[0], arguments[1], arguments[2], null); + case 4: + return Invoke(obj, arguments[0], arguments[1], arguments[2], arguments[3]); + default: + break; + } + } + + if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) + { + ((RuntimeMethodInfo)_method).ThrowNoInvokeException(); + } + + if (arguments.Length != _argCount) + { + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + if (!_isStatic) + { + MethodInvokerCommon.ValidateInvokeTarget(obj, _method); + } + + if (arguments.Length > MaxStackAllocArgCount) + { + return InvokeWithManyArgs(obj, arguments); + } + + return InvokeWithFewArgs(obj, arguments); + } + + internal object? InvokeWithFewArgs(object? obj, Span arguments) + { + Debug.Assert(_argCount <= MaxStackAllocArgCount); + + StackAllocatedArgumentsWithCopyBack stackArgStorage = default; + Span copyOfArgs = stackArgStorage._args.AsSpan(_argCount); + scoped Span shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount); + + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + shouldCopyBack[i] = CheckArgument(ref arg, i); + copyOfArgs[i] = arg; + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + // Fast path. + return _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + // No need to call CopyBack here since there are no ref values. + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - try + if (_needsByRefStrategy) + { + _strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs; + } + else { - if (_invokeFunc != null) + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); + if (_invokeFunc_ObjSpanArgs is not null) { - ret = _invokeFunc(obj, args); + return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); } - else + } + } + + object? ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs); + CopyBack(arguments, copyOfArgs, shouldCopyBack); + return ret; + } + + internal object? InvokeDirectByRef(object? obj, object? arg1 = null, object? arg2 = null, object? arg3 = null, object? arg4 = null) + { + StackAllocatedArguments stackStorage = new(arg1, arg2, arg3, arg4); + return InvokeDirectByRefWithFewArgs(obj, stackStorage._args.AsSpan(_argCount)); + } + + internal unsafe object? InvokeDirectByRefWithFewArgs(object? obj, Span copyOfArgs) + { + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + } + + scoped StackAllocatedByRefs byrefs = default; +#pragma warning disable CS8500 + IntPtr* pByRefFixedStorage = (IntPtr*)&byrefs; +#pragma warning restore CS8500 + + for (int i = 0; i < _argCount; i++) + { +#pragma warning disable CS8500 + *(ByReference*)(pByRefFixedStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref copyOfArgs[i]!.GetRawData()) : + ByReference.Create(ref copyOfArgs[i]); + } + + return _invokeFunc_RefArgs!(obj, pByRefFixedStorage); + } + + internal unsafe object? InvokeWithManyArgs(object? obj, Span arguments) + { + Span copyOfArgs; + RuntimeImports.GCFrameRegistration regArgStorage; + + if (!_needsByRefStrategy) + { + if ((_strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + IntPtr* pArgStorage = stackalloc IntPtr[_argCount]; + NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); + regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + CheckArgument(ref arg, i); + copyOfArgs[i] = arg; + } + + return _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + // No need to call CopyBack here since there are no ref values. + } + finally { - ret = InterpretedInvoke(obj, args); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); } } - catch (Exception e) + } + + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + } + + IntPtr* pStorage = stackalloc IntPtr[2 * _argCount]; + NativeMemory.Clear(pStorage, (nuint)(2 * _argCount) * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); + + IntPtr* pByRefStorage = pStorage + _argCount; + scoped Span shouldCopyBack = stackalloc bool[_argCount]; + + regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); + RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + + try + { + RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + + for (int i = 0; i < _argCount; i++) { - throw new TargetInvocationException(e); + object? arg = arguments[i]; + shouldCopyBack[i] = CheckArgument(ref arg, i); + copyOfArgs[i] = arg; +#pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? +#pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); } + + object? ret = _invokeFunc_RefArgs!(obj, pByRefStorage); + CopyBack(arguments, copyOfArgs, shouldCopyBack); + return ret; } - else if (_invokeFunc != null) + finally { - ret = _invokeFunc(obj, args); + RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); + RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); } - else + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + // Copy modified values out. This is only done with ByRef parameters. + internal void CopyBack(Span dest, Span copyOfParameters, Span shouldCopyBack) + { + for (int i = 0; i < dest.Length; i++) { - ret = InterpretedInvoke(obj, args); + if (shouldCopyBack[i]) + { + if ((_invokerArgFlags[i] & InvokerArgFlags.IsNullableOfT) != 0) + { + Debug.Assert(copyOfParameters[i] != null); + Debug.Assert(((RuntimeType)copyOfParameters[i]!.GetType()).IsNullableOfT); + dest![i] = RuntimeMethodHandle.ReboxFromNullable(copyOfParameters[i]); + } + else + { + dest![i] = copyOfParameters[i]; + } + } } + } - return ret; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal bool CheckArgument(ref object? arg, int i) + { + RuntimeType sigType = _argTypes[i]; + + // Convert the type if necessary. + // Note that Type.Missing is not supported. + if (arg is null) + { + if ((_invokerArgFlags[i] & InvokerArgFlags.IsValueType_ByRef_Or_Pointer) != 0) + { + return sigType.CheckValue(ref arg); + } + } + else if (!ReferenceEquals(arg.GetType(), sigType)) + { + return sigType.CheckValue(ref arg); + } + + return false; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs new file mode 100644 index 00000000000000..0b91a491eae33d --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs @@ -0,0 +1,145 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using static System.Reflection.InvokerEmitUtil; +using System.Runtime.CompilerServices; +using static System.Reflection.MethodBase; +using System.Diagnostics; + +namespace System.Reflection +{ + internal static class MethodInvokerCommon + { + internal static void Initialize( + RuntimeType[] argumentTypes, + out InvokerStrategy strategy, + out InvokerArgFlags[] invokerFlags, + out bool needsByRefStrategy) + { + if (LocalAppContextSwitches.ForceInterpretedInvoke && !LocalAppContextSwitches.ForceEmitInvoke) + { + // Always use the native invoke; useful for testing. + strategy = InvokerStrategy.StrategyDetermined_Obj4Args | InvokerStrategy.StrategyDetermined_ObjSpanArgs | InvokerStrategy.StrategyDetermined_RefArgs; + } + else if (LocalAppContextSwitches.ForceEmitInvoke && !LocalAppContextSwitches.ForceInterpretedInvoke) + { + // Always use emit invoke (if IsDynamicCodeSupported == true); useful for testing. + strategy = InvokerStrategy.HasBeenInvoked_Obj4Args | InvokerStrategy.HasBeenInvoked_ObjSpanArgs | InvokerStrategy.HasBeenInvoked_RefArgs; + } + else + { + strategy = default; + } + + int argCount = argumentTypes.Length; + invokerFlags = new InvokerArgFlags[argCount]; + needsByRefStrategy = false; + + for (int i = 0; i < argCount; i++) + { + RuntimeType type = argumentTypes[i]; + if (RuntimeTypeHandle.IsByRef(type)) + { + type = (RuntimeType)type.GetElementType(); + invokerFlags[i] |= InvokerArgFlags.IsValueType_ByRef_Or_Pointer; + needsByRefStrategy = true; + if (type.IsNullableOfT) + { + invokerFlags[i] |= InvokerArgFlags.IsNullableOfT; + } + } + + if (RuntimeTypeHandle.IsPointer(type)) + { + invokerFlags[i] |= InvokerArgFlags.IsValueType | InvokerArgFlags.IsValueType_ByRef_Or_Pointer; + } + else if (RuntimeTypeHandle.IsFunctionPointer(type)) + { + invokerFlags[i] |= InvokerArgFlags.IsValueType; + } + else if (RuntimeTypeHandle.IsValueType(type)) + { + invokerFlags[i] |= InvokerArgFlags.IsValueType | InvokerArgFlags.IsValueType_ByRef_Or_Pointer; + + if (type.IsNullableOfT) + { + invokerFlags[i] |= InvokerArgFlags.IsNullableOfT; + } + } + } + } + + /// + /// Confirm member invocation has an instance and is of the correct type + /// + internal static void ValidateInvokeTarget(object? target, MethodBase method) + { + Debug.Assert(!method.IsStatic); + + if (target == null) + { + throw new TargetException(SR.RFLCT_Targ_StatMethReqTarg); + } + + if (!method.DeclaringType!.IsInstanceOfType(target)) + { + throw new TargetException(SR.RFLCT_Targ_ITargMismatch); + } + } + + internal static void DetermineInvokeStrategy_ObjSpanArgs(ref InvokerStrategy strategy, ref InvokeFunc_ObjSpanArgs? invokeFunc_ObjSpanArgs, MethodBase method, bool backwardsCompat) + { + if ((strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) + { + // The first time, ignoring race conditions, use the slow path. + strategy |= InvokerStrategy.HasBeenInvoked_ObjSpanArgs; + } + else + { +#if !MONO // Temporary until Mono can unbox a true Nullable + if (RuntimeFeature.IsDynamicCodeSupported) + { + invokeFunc_ObjSpanArgs = CreateInvokeDelegate_ObjSpanArgs(method, backwardsCompat); + } +#endif + strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs; + } + } + + internal static void DetermineInvokeStrategy_Obj4Args(ref InvokerStrategy strategy, ref InvokeFunc_Obj4Args? invokeFunc_Obj4Args, MethodBase method, bool backwardsCompat) + { + if ((strategy & InvokerStrategy.HasBeenInvoked_Obj4Args) == 0) + { + // The first time, ignoring race conditions, use the slow path. + strategy |= InvokerStrategy.HasBeenInvoked_Obj4Args; + } + else + { +#if !MONO // Temporary until Mono can unbox a true Nullable + if (RuntimeFeature.IsDynamicCodeSupported) + { + invokeFunc_Obj4Args = CreateInvokeDelegate_Obj4Args(method, backwardsCompat); + } +#endif + strategy |= InvokerStrategy.StrategyDetermined_Obj4Args; + } + } + + internal static void DetermineInvokeStrategy_RefArgs(ref InvokerStrategy strategy, ref InvokeFunc_RefArgs? invokeFunc_RefArgs, MethodBase method, bool backwardsCompat) + { + if ((strategy & InvokerStrategy.HasBeenInvoked_RefArgs) == 0) + { + // The first time, ignoring race conditions, use the slow path. + strategy |= InvokerStrategy.HasBeenInvoked_RefArgs; + } + else + { + if (RuntimeFeature.IsDynamicCodeSupported) + { + invokeFunc_RefArgs = CreateInvokeDelegate_RefArgs(method, backwardsCompat); + } + strategy |= InvokerStrategy.StrategyDetermined_RefArgs; + } + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterCopyBackAction.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterCopyBackAction.cs deleted file mode 100644 index e7a9692a7449a2..00000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/ParameterCopyBackAction.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Reflection -{ - /// - /// Determines how an invoke parameter needs to be copied back to the caller's object[] parameters. - /// - internal enum ParameterCopyBackAction : byte - { - None = 0, - Copy = 1, - CopyNullable = 2 - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index d9b5ae564bafe4..af741f377b55b7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -4,29 +4,27 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.Runtime.InteropServices; using System.Runtime.CompilerServices; -using static System.Runtime.CompilerServices.RuntimeHelpers; namespace System.Reflection { internal sealed partial class RuntimeConstructorInfo : ConstructorInfo { [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path - private static InvocationFlags ComputeAndUpdateInvocationFlags(ConstructorInfo constructorInfo, ref InvocationFlags flagsToUpdate) + internal InvocationFlags ComputeAndUpdateInvocationFlags() { InvocationFlags invocationFlags = InvocationFlags.IsConstructor; // this is a given - Type? declaringType = constructorInfo.DeclaringType; + Type? declaringType = DeclaringType; if (declaringType == typeof(void) || declaringType != null && declaringType.ContainsGenericParameters // Enclosing type has unbound generics - || (constructorInfo.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs + || (CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs ) { invocationFlags |= InvocationFlags.NoInvoke; } - else if (constructorInfo.IsStatic) + else if (IsStatic) { invocationFlags |= InvocationFlags.RunClassConstructor | InvocationFlags.NoConstructorInvoke; } @@ -41,12 +39,11 @@ private static InvocationFlags ComputeAndUpdateInvocationFlags(ConstructorInfo c invocationFlags |= InvocationFlags.ContainsStackPointers; // Check for attempt to create a delegate class. - if (typeof(Delegate).IsAssignableFrom(constructorInfo.DeclaringType)) + if (typeof(Delegate).IsAssignableFrom(DeclaringType)) invocationFlags |= InvocationFlags.IsDelegateConstructor; } invocationFlags |= InvocationFlags.Initialized; - flagsToUpdate = invocationFlags; // accesses are guaranteed atomic return invocationFlags; } @@ -98,6 +95,7 @@ internal void ThrowNoInvokeException() [DebuggerStepThrough] [DebuggerHidden] + // This is a rarely-used Invoke since it calls a constructor on an existing instance. public override object? Invoke( object? obj, BindingFlags invokeAttr, @@ -108,7 +106,10 @@ internal void ThrowNoInvokeException() if ((InvocationFlags & InvocationFlags.NoInvoke) != 0) ThrowNoInvokeException(); - ValidateInvokeTarget(obj); + if (!IsStatic) + { + MethodInvokerCommon.ValidateInvokeTarget(obj, this); + } // Correct number of arguments supplied int argCount = (parameters is null) ? 0 : parameters.Length; @@ -125,133 +126,9 @@ internal void ThrowNoInvokeException() return null; } - Debug.Assert(obj != null); - - unsafe - { - if (argCount == 0) - { - Invoker.InlinedInvoke(obj, args: default, invokeAttr); - } - else if (argCount > MaxStackAllocArgCount) - { - Debug.Assert(parameters != null); - InvokeWithManyArguments(this, argCount, obj, invokeAttr, binder, parameters, culture); - } - else - { - Debug.Assert(parameters != null); - StackAllocedArguments argStorage = default; - Span copyOfParameters = argStorage._args.AsSpan(argCount); - Span shouldCopyBackParameters = argStorage._copyBacks.AsSpan(argCount); - - StackAllocatedByRefs byrefStorage = default; -#pragma warning disable 8500 - IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; -#pragma warning restore 8500 - - CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - ArgumentTypes, - binder, - culture, - invokeAttr); - - Invoker.InlinedInvoke(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 (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]); - } - } - } - } - } - - return null; - } - - // Slower path that does a heap alloc for copyOfParameters and registers byrefs to those objects. - // This is a separate method to support better performance for the faster paths. - [DebuggerStepThrough] - [DebuggerHidden] - private static unsafe void InvokeWithManyArguments( - RuntimeConstructorInfo ci, - int argCount, - object? obj, - BindingFlags invokeAttr, - Binder? binder, - object?[] parameters, - CultureInfo? culture) - { - object[] objHolder = new object[argCount]; - Span copyOfParameters = new(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]; - NativeMemory.Clear(pByRefStorage, (uint)(argCount * sizeof(IntPtr))); - - ParameterCopyBackAction* copyBackActions = stackalloc ParameterCopyBackAction[argCount]; - Span shouldCopyBackParameters = new(copyBackActions, argCount); - - GCFrameRegistration reg = new(pByRefStorage, (uint)argCount, areByRefs: true); - - try - { - RegisterForGCReporting(®); - ci.CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - ci.ArgumentTypes, - binder, - culture, - invokeAttr); - - ci.Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr); - } - finally - { - UnregisterForGCReporting(®); - } - - // 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 (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]); - } - } - } + return argCount == 0 ? + Invoker.InvokeConstructorWithoutAlloc(obj!, (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) : + Invoker.InvokeConstructorWithoutAlloc(obj!, invokeAttr, binder, parameters!, culture); } [DebuggerStepThrough] @@ -273,137 +150,19 @@ public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[] throw new TargetParameterCountException(SR.Arg_ParmCnt); } - object? retValue; - - unsafe - { - if (argCount == 0) - { - retValue = Invoker.InlinedInvoke(obj: null, args: default, invokeAttr); - } - else if (argCount > MaxStackAllocArgCount) - { - retValue = InvokeWithManyArguments(this, argCount, invokeAttr, binder, parameters, culture); - } - else - { - Debug.Assert(parameters != null); - StackAllocedArguments argStorage = default; - Span copyOfParameters = argStorage._args.AsSpan(argCount); - Span shouldCopyBackParameters = argStorage._copyBacks.AsSpan(argCount); - - StackAllocatedByRefs byrefStorage = default; -#pragma warning disable 8500 - IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; -#pragma warning restore 8500 - - CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - ArgumentTypes, - binder, - culture, - invokeAttr); - - retValue = Invoker.InlinedInvoke(obj: null, 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 (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]); - } - } - } - } - } - - Debug.Assert(retValue != null); - return retValue; - } - - // Slower path that does a heap alloc for copyOfParameters and registers byrefs to those objects. - // This is a separate method to encourage more efficient IL for the faster paths. - [DebuggerStepThrough] - [DebuggerHidden] - private static unsafe object? InvokeWithManyArguments( - RuntimeConstructorInfo ci, - int argCount, - BindingFlags invokeAttr, - Binder? binder, - object?[]? parameters, - CultureInfo? culture) - { - Debug.Assert(parameters != null); - - object[] objHolder = new object[argCount]; - Span copyOfParameters = new(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]; - NativeMemory.Clear(pByRefStorage, (uint)(argCount * sizeof(IntPtr))); - - ParameterCopyBackAction* copyBackActions = stackalloc ParameterCopyBackAction[argCount]; - Span shouldCopyBackParameters = new(copyBackActions, argCount); - - GCFrameRegistration reg = new(pByRefStorage, (uint)argCount, areByRefs: true); - - object? retValue; - try - { - RegisterForGCReporting(®); - ci.CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - ci.ArgumentTypes, - binder, - culture, - invokeAttr); - - retValue = ci.Invoker.InlinedInvoke(obj: null, pByRefStorage, invokeAttr); - } - finally - { - UnregisterForGCReporting(®); - } - - // Copy modified values out. This should be done only with ByRef or Type.Missing parameters. - for (int i = 0; i < argCount; i++) + switch (argCount) { - ParameterCopyBackAction action = shouldCopyBackParameters[i]; - if (action != ParameterCopyBackAction.None) - { - 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]); - } - } + case 0: + return Invoker.InvokeWithNoArgs(obj: null, invokeAttr)!; + case 1: + return Invoker.InvokeWithOneArg(obj: null, invokeAttr, binder, parameters!, culture)!; + case 2: + case 3: + case 4: + return Invoker.InvokeWithFewArgs(obj: null, invokeAttr, binder, parameters!, culture)!; + default: + return Invoker.InvokeWithManyArgs(obj: null, invokeAttr, binder, parameters!, culture)!; } - - return retValue; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 62e62b1550c9ad..d22bf589cf3e0d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -5,24 +5,21 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -using static System.Runtime.CompilerServices.RuntimeHelpers; namespace System.Reflection { internal sealed partial class RuntimeMethodInfo : MethodInfo { [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path - private static InvocationFlags ComputeAndUpdateInvocationFlags(MethodInfo methodInfo, ref InvocationFlags flagsToUpdate) + internal InvocationFlags ComputeAndUpdateInvocationFlags() { InvocationFlags invocationFlags = InvocationFlags.Unknown; - Type? declaringType = methodInfo.DeclaringType; + Type? declaringType = DeclaringType; - if (methodInfo.ContainsGenericParameters // Method has unbound generics - || IsDisallowedByRefType(methodInfo.ReturnType) // Return type is an invalid by-ref (i.e., by-ref-like or void*) - || (methodInfo.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs + if (ContainsGenericParameters // Method has unbound generics + || IsDisallowedByRefType(ReturnType) // Return type is an invalid by-ref (i.e., by-ref-like or void*) + || (CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs ) { invocationFlags = InvocationFlags.NoInvoke; @@ -41,14 +38,13 @@ private static InvocationFlags ComputeAndUpdateInvocationFlags(MethodInfo method } } - if (methodInfo.ReturnType.IsByRefLike) // Check for byref-like types for return + if (ReturnType.IsByRefLike) // Check for byref-like types for return { invocationFlags |= InvocationFlags.ContainsStackPointers; } } invocationFlags |= InvocationFlags.Initialized; - flagsToUpdate = invocationFlags; // accesses are guaranteed atomic return invocationFlags; static bool IsDisallowedByRefType(Type type) @@ -62,7 +58,7 @@ static bool IsDisallowedByRefType(Type type) } [DoesNotReturn] - private void ThrowNoInvokeException() + internal void ThrowNoInvokeException() { // method is on a class that contains stack pointers if ((InvocationFlags & InvocationFlags.ContainsStackPointers) != 0) @@ -113,7 +109,10 @@ private void ThrowNoInvokeException() ThrowNoInvokeException(); } - ValidateInvokeTarget(obj); + if (!IsStatic) + { + MethodInvokerCommon.ValidateInvokeTarget(obj, this); + } // Correct number of arguments supplied int argCount = (parameters is null) ? 0 : parameters.Length; @@ -122,136 +121,19 @@ private void ThrowNoInvokeException() throw new TargetParameterCountException(SR.Arg_ParmCnt); } - object? retValue; - - unsafe + switch (argCount) { - if (argCount == 0) - { - retValue = Invoker.InlinedInvoke(obj, args: default, invokeAttr); - } - else if (argCount > MaxStackAllocArgCount) - { - Debug.Assert(parameters != null); - retValue = InvokeWithManyArguments(this, argCount, obj, invokeAttr, binder, parameters, culture); - } - else - { - Debug.Assert(parameters != null); - StackAllocedArguments argStorage = default; - Span copyOfParameters = argStorage._args.AsSpan(argCount); - Span shouldCopyBackParameters = argStorage._copyBacks.AsSpan(argCount); - - StackAllocatedByRefs byrefStorage = default; -#pragma warning disable 8500 - IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; -#pragma warning restore 8500 - - CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - ArgumentTypes, - binder, - culture, - invokeAttr); - - retValue = Invoker.InlinedInvoke(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 (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]); - } - } - } - } + case 0: + return Invoker.InvokeWithNoArgs(obj, invokeAttr); + case 1: + return Invoker.InvokeWithOneArg(obj, invokeAttr, binder, parameters!, culture); + case 2: + case 3: + case 4: + return Invoker.InvokeWithFewArgs(obj, invokeAttr, binder, parameters!, culture); + default: + return Invoker.InvokeWithManyArgs(obj, invokeAttr, binder, parameters!, culture); } - - return retValue; - } - - // Slower path that does a heap alloc for copyOfParameters and registers byrefs to those objects. - // This is a separate method to support better performance for the faster paths. - [DebuggerStepThrough] - [DebuggerHidden] - private static unsafe object? InvokeWithManyArguments( - RuntimeMethodInfo mi, - int argCount, - object? obj, - BindingFlags invokeAttr, - Binder? binder, - object?[] parameters, - CultureInfo? culture) - { - object[] objHolder = new object[argCount]; - Span copyOfParameters = new(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]; - NativeMemory.Clear(pByRefStorage, (uint)(argCount * sizeof(IntPtr))); - - ParameterCopyBackAction* copyBackActions = stackalloc ParameterCopyBackAction[argCount]; - Span shouldCopyBackParameters = new(copyBackActions, argCount); - - GCFrameRegistration reg = new(pByRefStorage, (uint)argCount, areByRefs: true); - - object? retValue; - try - { - RegisterForGCReporting(®); - mi.CheckArguments( - copyOfParameters, - pByRefStorage, - shouldCopyBackParameters, - parameters, - mi.ArgumentTypes, - binder, - culture, - invokeAttr); - - retValue = mi.Invoker.InlinedInvoke(obj, pByRefStorage, invokeAttr); - } - finally - { - UnregisterForGCReporting(®); - } - - // 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 (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]); - } - } - } - - return retValue; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index b7da6009495c24..c44e69d03a03d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -761,6 +761,9 @@ internal static CorElementType GetUnderlyingType(RuntimeType type) return RuntimeTypeHandle.GetCorElementType(type); } + + // AggressiveInlining used since on hot path for reflection. + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool TryGetByRefElementType(RuntimeType type, [NotNullWhen(true)] out RuntimeType? elementType) { CorElementType corElemType = RuntimeTypeHandle.GetCorElementType(type); @@ -784,19 +787,53 @@ private enum CheckValueStatus /// /// Verify and optionally convert the value for special cases. /// - /// True if is a value type, False otherwise + /// True if the value requires a copy-back to the original object[]. + internal bool CheckValue(ref object? value) + { + Debug.Assert(!IsGenericParameter); + + // Fast path to whether a value can be assigned without conversion. + if (IsInstanceOfType(value)) + { + if (IsNullableOfT) + { + // Pass as a true boxed Nullable, not as a T or null. + value = RuntimeMethodHandle.ReboxToNullable(value, this); + return true; + } + + return false; + } + + bool copyBack = false; + CheckValueStatus result = TryChangeType(ref value, ref copyBack); + if (result == CheckValueStatus.Success) + { + return copyBack; + } + + switch (result) + { + case CheckValueStatus.ArgumentException: + throw new ArgumentException(SR.Format(SR.Arg_ObjObjEx, value?.GetType(), this)); + case CheckValueStatus.NotSupported_ByRefLike: + throw new NotSupportedException(SR.NotSupported_ByRefLike); + } + + Debug.Fail("Error result not expected"); + return false; + } + + /// + /// Verify and optionally convert the value for special cases. + /// + /// True if the value requires a copy-back to the original object[] or Span{object}. internal bool CheckValue( ref object? value, - ref ParameterCopyBackAction copyBack, Binder? binder, CultureInfo? culture, BindingFlags invokeAttr) { - // Already fast-pathed by the caller. - Debug.Assert(!ReferenceEquals(value?.GetType(), this)); - - // Since this cannot be a generic parameter, we use RuntimeTypeHandle.IsValueType here - // because it is faster than IsValueType Debug.Assert(!IsGenericParameter); // Fast path to whether a value can be assigned without conversion. @@ -809,17 +846,14 @@ internal bool CheckValue( return true; } - // Other value types won't get here since Type equality was previous checked. - Debug.Assert(!RuntimeTypeHandle.IsValueType(this)); - return false; } - bool isValueType; - CheckValueStatus result = TryChangeType(ref value, ref copyBack, out isValueType); + bool copyBack = false; + CheckValueStatus result = TryChangeType(ref value, ref copyBack); if (result == CheckValueStatus.Success) { - return isValueType; + return copyBack; } if (result == CheckValueStatus.ArgumentException && (invokeAttr & BindingFlags.ExactBinding) == 0) @@ -836,20 +870,15 @@ internal bool CheckValue( { // Pass as a true boxed Nullable, not as a T or null. value = RuntimeMethodHandle.ReboxToNullable(value, this); - copyBack = ParameterCopyBackAction.CopyNullable; - } - else - { - copyBack = ParameterCopyBackAction.Copy; } - return IsValueType; // Note the call to IsValueType, not the variable. + return true; } - result = TryChangeType(ref value, ref copyBack, out isValueType); + result = TryChangeType(ref value, ref copyBack); if (result == CheckValueStatus.Success) { - return isValueType; + return copyBack; } } } @@ -866,27 +895,22 @@ internal bool CheckValue( return false; } - private CheckValueStatus TryChangeType( - ref object? value, - ref ParameterCopyBackAction copyBack, - out bool isValueType) + private CheckValueStatus TryChangeType(ref object? value, ref bool copyBack) { RuntimeType? sigElementType; if (TryGetByRefElementType(this, out sigElementType)) { - copyBack = ParameterCopyBackAction.Copy; Debug.Assert(!sigElementType.IsGenericParameter); + copyBack = true; if (sigElementType.IsInstanceOfType(value)) { - isValueType = RuntimeTypeHandle.IsValueType(sigElementType); - if (isValueType) + if (RuntimeTypeHandle.IsValueType(sigElementType)) { if (sigElementType.IsNullableOfT) { // Pass as a true boxed Nullable, not as a T or null. value = RuntimeMethodHandle.ReboxToNullable(value, sigElementType); - copyBack = ParameterCopyBackAction.CopyNullable; } else { @@ -900,10 +924,8 @@ private CheckValueStatus TryChangeType( if (value == null) { - isValueType = RuntimeTypeHandle.IsValueType(sigElementType); - if (!isValueType) + if (!RuntimeTypeHandle.IsValueType(sigElementType)) { - // Normally we don't get here since 'null' was previosuly checked, but due to binders we can. return CheckValueStatus.Success; } @@ -914,20 +936,23 @@ private CheckValueStatus TryChangeType( // Allocate default. value = AllocateValueType(sigElementType, value: null); - copyBack = sigElementType.IsNullableOfT ? ParameterCopyBackAction.CopyNullable : ParameterCopyBackAction.Copy; return CheckValueStatus.Success; } - isValueType = false; return CheckValueStatus.ArgumentException; } if (value == null) { - isValueType = RuntimeTypeHandle.IsValueType(this); - if (!isValueType) + if (IsPointer) + { + // Pass an IntPtr instead of null for pointers. + value = default(IntPtr); + return CheckValueStatus.Success; + } + + if (!RuntimeTypeHandle.IsValueType(this)) { - // Normally we don't get here since 'null' was previosuly checked, but due to binders we can. return CheckValueStatus.Success; } @@ -947,28 +972,9 @@ private CheckValueStatus TryChangeType( // - Pointer (*) types to IntPtr (if dest is IntPtr) // - System.Reflection.Pointer to appropriate pointer (*) type (if dest is pointer type) if (IsPointer || IsEnum || IsPrimitive) - return TryChangeTypeSpecial(ref value, out isValueType); + return TryChangeTypeSpecial(ref value); - isValueType = false; return CheckValueStatus.ArgumentException; } - - internal bool TryByRefFastPath(ref object arg, ref bool isValueType) - { - if (TryGetByRefElementType(this, out RuntimeType? sigElementType) && - ReferenceEquals(sigElementType, arg.GetType())) - { - isValueType = sigElementType.IsValueType; - if (isValueType) - { - // Make a copy to prevent the boxed instance from being directly modified by the method. - arg = AllocateValueType(sigElementType, arg); - } - - return true; - } - - return false; - } } } diff --git a/src/libraries/System.Reflection/System.Reflection.sln b/src/libraries/System.Reflection/System.Reflection.sln index 2cd11065f1ae71..62c2cb74337bf4 100644 --- a/src/libraries/System.Reflection/System.Reflection.sln +++ b/src/libraries/System.Reflection/System.Reflection.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{27A1A006-6882-4C70-AB81-775D3D2C95A2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{C5A7E7E7-E43B-4C87-9A92-13C3C817E714}" @@ -65,6 +69,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{548F3513-E3A EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|arm = Checked|arm + Checked|arm64 = Checked|arm64 + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|arm = Debug|arm Debug|arm64 = Debug|arm64 @@ -75,13 +84,18 @@ Global Release|arm64 = Release|arm64 Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|arm = Checked|arm - Checked|arm64 = Checked|arm64 - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.ActiveCfg = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.Build.0 = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.ActiveCfg = Checked|arm + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.Build.0 = Checked|arm + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.ActiveCfg = Checked|arm64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.Build.0 = Checked|arm64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.ActiveCfg = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.Build.0 = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.ActiveCfg = Checked|x86 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.Build.0 = Checked|x86 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Debug|Any CPU.ActiveCfg = Debug|x64 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Debug|Any CPU.Build.0 = Debug|x64 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Debug|arm.ActiveCfg = Debug|arm @@ -102,16 +116,11 @@ Global {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Release|x64.Build.0 = Release|x64 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Release|x86.ActiveCfg = Release|x86 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Release|x86.Build.0 = Release|x86 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.ActiveCfg = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.Build.0 = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.ActiveCfg = Checked|arm - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.Build.0 = Checked|arm - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.ActiveCfg = Checked|arm64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.Build.0 = Checked|arm64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.ActiveCfg = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.Build.0 = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.ActiveCfg = Checked|x86 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.Build.0 = Checked|x86 + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x64.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x86.ActiveCfg = Debug|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -128,11 +137,11 @@ Global {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Release|x64.Build.0 = Release|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Release|x86.ActiveCfg = Release|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Release|x86.Build.0 = Release|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x64.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x86.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm64.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x64.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x86.ActiveCfg = Debug|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -149,11 +158,11 @@ Global {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Release|x64.Build.0 = Release|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Release|x86.ActiveCfg = Release|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Release|x86.Build.0 = Release|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm64.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x64.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x86.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x64.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x86.ActiveCfg = Debug|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Debug|Any CPU.Build.0 = Debug|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -170,11 +179,11 @@ Global {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Release|x64.Build.0 = Release|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Release|x86.ActiveCfg = Release|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Release|x86.Build.0 = Release|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x64.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x86.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm64.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x64.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x86.ActiveCfg = Debug|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Debug|Any CPU.Build.0 = Debug|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -191,11 +200,11 @@ Global {319997BC-5DF6-4E23-A768-ED9905690EF4}.Release|x64.Build.0 = Release|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Release|x86.ActiveCfg = Release|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Release|x86.Build.0 = Release|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm64.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x64.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x86.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm64.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x64.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x86.ActiveCfg = Debug|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -212,11 +221,11 @@ Global {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Release|x64.Build.0 = Release|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Release|x86.ActiveCfg = Release|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Release|x86.Build.0 = Release|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm64.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x64.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x86.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x64.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x86.ActiveCfg = Debug|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -233,11 +242,11 @@ Global {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Release|x64.Build.0 = Release|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Release|x86.ActiveCfg = Release|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Release|x86.Build.0 = Release|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x64.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x86.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x64.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x86.ActiveCfg = Debug|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Debug|Any CPU.Build.0 = Debug|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -254,11 +263,11 @@ Global {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Release|x64.Build.0 = Release|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Release|x86.ActiveCfg = Release|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Release|x86.Build.0 = Release|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x64.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x86.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm64.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x64.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x86.ActiveCfg = Debug|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -275,11 +284,11 @@ Global {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Release|x64.Build.0 = Release|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Release|x86.ActiveCfg = Release|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Release|x86.Build.0 = Release|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm64.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x64.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x86.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x64.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x86.ActiveCfg = Debug|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -296,11 +305,11 @@ Global {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Release|x64.Build.0 = Release|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Release|x86.ActiveCfg = Release|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Release|x86.Build.0 = Release|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x64.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x86.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x64.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x86.ActiveCfg = Debug|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Debug|Any CPU.Build.0 = Debug|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -317,11 +326,11 @@ Global {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Release|x64.Build.0 = Release|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Release|x86.ActiveCfg = Release|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Release|x86.Build.0 = Release|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x64.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x86.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x64.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x86.ActiveCfg = Debug|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -338,11 +347,11 @@ Global {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Release|x64.Build.0 = Release|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Release|x86.ActiveCfg = Release|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Release|x86.Build.0 = Release|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x64.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x86.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm64.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x64.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x86.ActiveCfg = Debug|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Debug|Any CPU.Build.0 = Debug|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -359,11 +368,11 @@ Global {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Release|x64.Build.0 = Release|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Release|x86.ActiveCfg = Release|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Release|x86.Build.0 = Release|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm64.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x64.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x86.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm64.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x64.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x86.ActiveCfg = Debug|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Debug|Any CPU.Build.0 = Debug|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -380,11 +389,11 @@ Global {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Release|x64.Build.0 = Release|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Release|x86.ActiveCfg = Release|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Release|x86.Build.0 = Release|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm64.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x64.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x86.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x64.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x86.ActiveCfg = Debug|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -401,11 +410,11 @@ Global {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Release|x64.Build.0 = Release|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Release|x86.ActiveCfg = Release|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Release|x86.Build.0 = Release|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x64.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x86.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x64.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x86.ActiveCfg = Debug|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Debug|Any CPU.Build.0 = Debug|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -422,11 +431,11 @@ Global {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Release|x64.Build.0 = Release|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Release|x86.ActiveCfg = Release|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Release|x86.Build.0 = Release|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x64.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x86.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x64.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x86.ActiveCfg = Debug|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Debug|Any CPU.Build.0 = Debug|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -443,11 +452,11 @@ Global {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Release|x64.Build.0 = Release|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Release|x86.ActiveCfg = Release|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Release|x86.Build.0 = Release|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x64.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x86.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x64.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x86.ActiveCfg = Debug|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -464,11 +473,11 @@ Global {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Release|x64.Build.0 = Release|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Release|x86.ActiveCfg = Release|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Release|x86.Build.0 = Release|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x64.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x86.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm64.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x64.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x86.ActiveCfg = Debug|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Debug|Any CPU.Build.0 = Debug|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -485,11 +494,11 @@ Global {006DEC5A-067B-4099-934E-830ABB10BC26}.Release|x64.Build.0 = Release|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Release|x86.ActiveCfg = Release|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Release|x86.Build.0 = Release|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm64.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x64.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x86.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x64.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x86.ActiveCfg = Debug|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -506,11 +515,11 @@ Global {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Release|x64.Build.0 = Release|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Release|x86.ActiveCfg = Release|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Release|x86.Build.0 = Release|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x64.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x86.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x64.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x86.ActiveCfg = Debug|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -527,11 +536,11 @@ Global {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Release|x64.Build.0 = Release|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Release|x86.ActiveCfg = Release|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Release|x86.Build.0 = Release|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x64.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x86.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x64.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x86.ActiveCfg = Debug|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -548,11 +557,11 @@ Global {F2E5F428-418B-41B9-BF14-36EB67486A71}.Release|x64.Build.0 = Release|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Release|x86.ActiveCfg = Release|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Release|x86.Build.0 = Release|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x64.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x86.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm64.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x64.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x86.ActiveCfg = Debug|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Debug|Any CPU.Build.0 = Debug|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -569,11 +578,11 @@ Global {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Release|x64.Build.0 = Release|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Release|x86.ActiveCfg = Release|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Release|x86.Build.0 = Release|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm64.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x64.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x86.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm64.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x64.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x86.ActiveCfg = Debug|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Debug|Any CPU.Build.0 = Debug|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -590,11 +599,11 @@ Global {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Release|x64.Build.0 = Release|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Release|x86.ActiveCfg = Release|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Release|x86.Build.0 = Release|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm64.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x64.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x86.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x64.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x86.ActiveCfg = Debug|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -611,11 +620,11 @@ Global {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Release|x64.Build.0 = Release|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Release|x86.ActiveCfg = Release|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Release|x86.Build.0 = Release|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x64.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x86.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x64.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x86.ActiveCfg = Debug|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Debug|Any CPU.Build.0 = Debug|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -632,11 +641,11 @@ Global {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Release|x64.Build.0 = Release|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Release|x86.ActiveCfg = Release|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Release|x86.Build.0 = Release|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x64.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x86.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm64.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x64.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x86.ActiveCfg = Debug|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -653,11 +662,11 @@ Global {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Release|x64.Build.0 = Release|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Release|x86.ActiveCfg = Release|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Release|x86.Build.0 = Release|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm64.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x64.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x86.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm64.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x64.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x86.ActiveCfg = Debug|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -674,19 +683,17 @@ Global {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Release|x64.Build.0 = Release|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Release|x86.ActiveCfg = Release|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Release|x86.Build.0 = Release|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm64.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x64.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x86.ActiveCfg = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {27A1A006-6882-4C70-AB81-775D3D2C95A2} = {1BD23B5E-9944-4133-A162-94D4697616DD} - {2A4650E3-E199-41E4-AD2B-32818E57D1C7} = {1BD23B5E-9944-4133-A162-94D4697616DD} {C5A7E7E7-E43B-4C87-9A92-13C3C817E714} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} + {319997BC-5DF6-4E23-A768-ED9905690EF4} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} + {2A4650E3-E199-41E4-AD2B-32818E57D1C7} = {1BD23B5E-9944-4133-A162-94D4697616DD} {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {7873C6BF-74FA-4DCF-ADCD-15C75B20132D} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} @@ -706,14 +713,14 @@ Global {E6F16442-FB0F-4666-8309-F8B1EBA5B860} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} {A2B3A339-4792-4561-A973-11FE5EEEB54A} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} {7625A3EB-C76C-41FE-85DC-C8B792062F9C} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} - {319997BC-5DF6-4E23-A768-ED9905690EF4} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} {95C7E01D-B35D-431C-A50E-D52956ABBFB3} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8439AF1D-1B47-4BB3-A6C5-3B34D114C9F3} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{27a1a006-6882-4c70-ab81-775d3d2c95a2}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs b/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs new file mode 100644 index 00000000000000..8d209967522ba0 --- /dev/null +++ b/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs @@ -0,0 +1,146 @@ +// 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; +using Xunit; + +namespace System.Reflection.Tests +{ + public class ConstructorInvokerTests + { + + [Fact] + public void Args_0() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClass).GetConstructor(new Type[] { })); + Assert.Equal("0", ((TestClass)invoker.Invoke())._args); + Assert.Equal("0", ((TestClass)invoker.Invoke(new Span()))._args); + } + + [Fact] + public void Args_1() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClass).GetConstructor(new Type[] { typeof(string) })); + Assert.Equal("1", ((TestClass)invoker.Invoke("1"))._args); + Assert.Equal("1", ((TestClass)invoker.Invoke(new Span(new object[] { "1" })))._args); + } + + [Fact] + public void Args_2() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClass).GetConstructor( + new Type[] { typeof(string), typeof(string) })); + + Assert.Equal("12", ((TestClass)invoker.Invoke("1", "2"))._args); + Assert.Equal("12", ((TestClass)invoker.Invoke(new Span(new object[] { "1", "2" })))._args); + } + + [Fact] + public void Args_3() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClass).GetConstructor( + new Type[] { typeof(string), typeof(string), typeof(string) })); + + Assert.Equal("123", ((TestClass)invoker.Invoke("1", "2", "3"))._args); + Assert.Equal("123", ((TestClass)invoker.Invoke(new Span(new object[] { "1", "2", "3" })))._args); + } + + [Fact] + public void Args_4() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClass).GetConstructor( + new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) })); + + Assert.Equal("1234", ((TestClass)invoker.Invoke("1", "2", "3", "4"))._args); + Assert.Equal("1234", ((TestClass)invoker.Invoke(new Span(new object[] { "1", "2", "3", "4" })))._args); + } + + [Fact] + public void Args_5() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClass).GetConstructor( + new Type[] { typeof(string), typeof(string), typeof(string), typeof(string), typeof(string) })); + + Assert.Equal("12345", ((TestClass)invoker.Invoke(new Span(new object[] { "1", "2", "3", "4", "5" })))._args); + } + + [Fact] + public void ThrowsNonWrappedException_0() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClassThrowsOnCreate).GetConstructor(new Type[] { })); + Assert.Throws(invoker.Invoke); + } + + [Fact] + public void ThrowsNonWrappedException_1() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClassThrowsOnCreate).GetConstructor(new Type[] { typeof(string) })); + Assert.Throws(() => invoker.Invoke("0")); + } + + [Fact] + public void ThrowsNonWrappedException_5() + { + ConstructorInvoker invoker = ConstructorInvoker.Create(typeof(TestClassThrowsOnCreate).GetConstructor( + new Type[] { typeof(string), typeof(string), typeof(string), typeof(string), typeof(string) })); + + Assert.Throws(() => invoker.Invoke(new Span(new object[] { "1", "2", "3", "4", "5" }))); + } + + [Fact] + public void ExistingInstance() + { + ConstructorInfo ci = typeof(TestClass).GetConstructor(BindingFlags.Public | BindingFlags.Instance, Type.EmptyTypes); + TestClass tc = (TestClass)RuntimeHelpers.GetUninitializedObject(typeof(TestClass)); + Assert.Null(tc._args); + + MethodInvoker invoker = MethodInvoker.Create(ci); + invoker.Invoke(tc); + Assert.Equal("0", tc._args); + } + + private class TestClass + { + public string _args; + + public TestClass() { _args = "0"; } + + public void SomeMethod() { } + + public TestClass(string arg1) + { + _args = arg1; + } + + public TestClass(string arg1, string arg2) + { + _args = arg1 + arg2; + } + + public TestClass(string arg1, string arg2, string arg3) + { + _args = arg1 + arg2 + arg3; + } + + public TestClass(string arg1, string arg2, string arg3, string arg4) + { + _args = arg1 + arg2 + arg3 + arg4; + } + + public TestClass(string arg1, string arg2, string arg3, string arg4, string arg5) + { + _args = arg1 + arg2 + arg3 + arg4 + arg5; + } + } + + private class TestClassThrowsOnCreate + { + public TestClassThrowsOnCreate() => + throw new InvalidOperationException(); + public TestClassThrowsOnCreate(string arg1) => + throw new InvalidOperationException(); + public TestClassThrowsOnCreate(string arg1, string arg2, string arg3, string arg4, string arg5) => + throw new InvalidOperationException(); + } + } +} diff --git a/src/libraries/System.Reflection/tests/MethodInfoTests.cs b/src/libraries/System.Reflection/tests/MethodInfoTests.cs index 270dccc4fbbc33..ed8499dc251a1c 100644 --- a/src/libraries/System.Reflection/tests/MethodInfoTests.cs +++ b/src/libraries/System.Reflection/tests/MethodInfoTests.cs @@ -717,7 +717,7 @@ public static void InvokeNullableEnumParameterDefaultNo() Assert.Equal(YesNo.No, method.Invoke(null, new object?[] { YesNo.No })); Assert.Equal(YesNo.Yes, method.Invoke(null, new object?[] { YesNo.Yes })); Assert.Equal(YesNo.No, method.Invoke(null, new object?[] { Type.Missing })); - } + } [Fact] public static void InvokeNullableEnumParameterDefaultYes() @@ -1356,4 +1356,3 @@ public static unsafe bool CallFcnPtr_Void(void* fn, int value) } #pragma warning restore 0414 } - diff --git a/src/libraries/System.Reflection/tests/MethodInvokerTests.cs b/src/libraries/System.Reflection/tests/MethodInvokerTests.cs new file mode 100644 index 00000000000000..9c28247658bdc3 --- /dev/null +++ b/src/libraries/System.Reflection/tests/MethodInvokerTests.cs @@ -0,0 +1,277 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace System.Reflection.Tests +{ + public class MethodInvokerTests + { + [Fact] + public void NullTypeValidation() + { + Assert.Throws(() => MethodInvoker.Create(null)); + } + + [Fact] + public void Args_0() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_0))); + Assert.Equal("0", invoker.Invoke(obj: null)); + Assert.Equal("0", invoker.Invoke(obj: null, new Span())); + } + + [Fact] + public void Args_1() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_1))); + Assert.Equal("1", invoker.Invoke(obj: null, "1")); + Assert.Equal("1", invoker.Invoke(obj: null, new Span(new object[] { "1" }))); + } + + [Fact] + public void Args_2() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_2))); + Assert.Equal("12", invoker.Invoke(obj: null, "1", "2")); + Assert.Equal("12", invoker.Invoke(obj: null, new Span(new object[] { "1", "2" }))); + } + + [Fact] + public void Args_3() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_3))); + Assert.Equal("123", invoker.Invoke(obj: null, "1", "2", "3")); + Assert.Equal("123", invoker.Invoke(obj: null, new Span(new object[] { "1", "2", "3" }))); + } + + [Fact] + public void Args_4() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_4))); + Assert.Equal("1234", invoker.Invoke(obj: null, "1", "2", "3", "4")); + Assert.Equal("1234", invoker.Invoke(obj: null, new Span(new object[] { "1", "2", "3", "4" }))); + } + + [Fact] + public void Args_5() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_5))); + Assert.Equal("12345", invoker.Invoke(obj: null, new Span(new object[] { "1", "2", "3", "4", "5" }))); + } + + [Fact] + public void Args_ByRef() + { + string argValue = "Value"; + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_ByRef))); + + // Although no copy-back, verify we can call. + Assert.Equal("Hello", invoker.Invoke(obj: null, argValue)); + + // The Span version supports copy-back. + object[] args = new object[] { argValue }; + invoker.Invoke(obj: null, new Span(args)); + Assert.Equal("Hello", args[0]); + + args[0] = null; + invoker.Invoke(obj: null, new Span(args)); + Assert.Equal("Hello", args[0]); + } + + [Fact] + public unsafe void Args_Pointer() + { + int i = 7; + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_ByPointer))); + + invoker.Invoke(obj: null, (IntPtr)(void*)&i); + Assert.Equal(8, i); + + object[] args = new object[] { (IntPtr)(void*)&i }; + invoker.Invoke(obj: null, new Span(args)); + Assert.Equal(9, i); + } + + [Fact] + public unsafe void Args_SystemPointer() + { + int i = 7; + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Args_BySystemPointer))); + + object pointer = Pointer.Box(&i, typeof(int).MakePointerType()); + invoker.Invoke(obj: null, pointer); + Assert.Equal(8, i); + + object[] args = new object[] { pointer }; + invoker.Invoke(obj: null, new Span(args)); + Assert.Equal(9, i); + } + + [Theory] + [MemberData(nameof(Invoke_TestData))] + public void ArgumentConversions(Type methodDeclaringType, string methodName, object obj, object[] parameters, object result) + { + MethodInvoker invoker = MethodInvoker.Create(GetMethod(methodDeclaringType, methodName)); + + // Since Type.Missing is not supported, and Span requires an object-back array, adapt the input. + if (parameters is null) + { + Assert.Equal(result, invoker.Invoke(obj, new Span())); + Assert.Equal(result, invoker.Invoke(obj)); + } + else if (HasTypeMissing()) + { + if (parameters.GetType().GetElementType() == typeof(object)) + { + Assert.Throws(() => invoker.Invoke(obj, new Span(parameters))); + } + else + { + // Using 'string[]', for example, is not supported with Span. + Assert.Throws(() => invoker.Invoke(obj, new Span(parameters))); + } + } + else + { + if (parameters.GetType().GetElementType() == typeof(object)) + { + Assert.Equal(result, invoker.Invoke(obj, new Span(parameters))); + + // Also verify explicit length parameters. + switch (parameters.Length) + { + case 0: + Assert.Equal(result, invoker.Invoke(obj)); + break; + case 1: + Assert.Equal(result, invoker.Invoke(obj, parameters[0])); + break; + case 2: + Assert.Equal(result, invoker.Invoke(obj, parameters[0], parameters[1])); + break; + case 3: + Assert.Equal(result, invoker.Invoke(obj, parameters[0], parameters[1], parameters[2])); + break; + case 4: + Assert.Equal(result, invoker.Invoke(obj, parameters[0], parameters[1], parameters[2], parameters[3])); + break; + } + } + else + { + Assert.Throws(() => invoker.Invoke(obj, new Span(parameters))); + } + } + + bool HasTypeMissing() + { + if (parameters is not null) + { + for (int i = 0; i < parameters.Length; i++) + { + if (ReferenceEquals(parameters[i], Type.Missing)) + { + return true; + } + } + } + + return false; + } + } + + [Fact] + public void ThrowsNonWrappedException_0() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Throw_0))); + Assert.Throws(() => invoker.Invoke(obj: null)); + Assert.Throws(() => invoker.Invoke(obj: null, new Span())); + } + + [Fact] + public void ThrowsNonWrappedException_1() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Throw_1))); + Assert.Throws(() => invoker.Invoke(obj: null, "1")); + Assert.Throws(() => invoker.Invoke(obj: null, new Span(new object[] { "1" }))); + } + + [Fact] + public void ThrowsNonWrappedException_5() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.Throw_5))); + Assert.Throws(() => invoker.Invoke(obj: null, new Span(new object[] { "1", "2", "3", "4", "5" }))); + } + + [Fact] + public void VerifyThisObj_WrongType() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.VerifyThisObj))); + Assert.Throws(() => invoker.Invoke(obj: 42)); + } + + [Fact] + public void VerifyThisObj_Null() + { + MethodInvoker invoker = MethodInvoker.Create(typeof(TestClass).GetMethod(nameof(TestClass.VerifyThisObj))); + Assert.Throws(() => invoker.Invoke(obj: null)); + } + + private static MethodInfo GetMethod(Type type, string name) + { + return type.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).First(method => method.Name.Equals(name)); + } + + public static IEnumerable Invoke_TestData() => MethodInfoTests.Invoke_TestData(); + + private class TestClass + { + private int _i = 42; + + public static string Args_0() => "0"; + public static string Args_1(string arg) => arg; + public static string Args_2(string arg1, string arg2) => arg1 + arg2; + public static string Args_3(string arg1, string arg2, string arg3) => arg1 + arg2 + arg3; + public static string Args_4(string arg1, string arg2, string arg3, string arg4) => arg1 + arg2 + arg3 + arg4; + public static string Args_5(string arg1, string arg2, string arg3, string arg4, string arg5) => arg1 + arg2 + arg3 + arg4 + arg5; + + public static string Args_ByRef(ref string arg) + { + arg = "Hello"; + return arg; + } + + public static unsafe void Args_ByPointer(int* arg) + { + *arg = (*arg) +1; + } + + public static unsafe void Args_BySystemPointer(Pointer arg) + { + int* p = (int*)Pointer.Unbox(arg); + *p = (*p) + 1; + } + + public static int TypeMissing(int i = 42) + { + return i; + } + + public void VerifyThisObj() + { + Assert.Equal(42, _i); + } + + public static void Throw_0() => + throw new InvalidOperationException(); + public static void Throw_1(string arg1) => + throw new InvalidOperationException(); + public static void Throw_5(string arg1, string arg2, string arg3, string arg4, string arg5) => + throw new InvalidOperationException(); + } + + } +} diff --git a/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj b/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj index d6ebfb0081296b..876bbb63fd2b03 100644 --- a/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj +++ b/src/libraries/System.Reflection/tests/System.Reflection.Tests.csproj @@ -23,6 +23,7 @@ + @@ -31,6 +32,7 @@ + diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 4bd5bab05788ec..9f74201a3e791d 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -11208,6 +11208,17 @@ protected ConstructorInfo() { } public static bool operator ==(System.Reflection.ConstructorInfo? left, System.Reflection.ConstructorInfo? right) { throw null; } public static bool operator !=(System.Reflection.ConstructorInfo? left, System.Reflection.ConstructorInfo? right) { throw null; } } + public sealed partial class ConstructorInvoker + { + internal ConstructorInvoker() { } + public object? Invoke(System.Span arguments) { throw null; } + public object? Invoke() { throw null; } + public object? Invoke(object? arg1) { throw null; } + public object? Invoke(object? arg1, object? arg2) { throw null; } + public object? Invoke(object? arg1, object? arg2, object? arg3) { throw null; } + public object? Invoke(object? arg1, object? arg2, object? arg3, object? arg4) { throw null; } + public static System.Reflection.ConstructorInvoker Create(System.Reflection.ConstructorInfo constructor) { throw null; } + } public partial class CustomAttributeData { protected CustomAttributeData() { } @@ -11676,6 +11687,17 @@ protected MethodInfo() { } public static bool operator ==(System.Reflection.MethodInfo? left, System.Reflection.MethodInfo? right) { throw null; } public static bool operator !=(System.Reflection.MethodInfo? left, System.Reflection.MethodInfo? right) { throw null; } } + public sealed partial class MethodInvoker + { + internal MethodInvoker() { } + public object? Invoke(object? obj, System.Span arguments) { throw null; } + public object? Invoke(object? obj) { throw null; } + public object? Invoke(object? obj, object? arg1) { throw null; } + public object? Invoke(object? obj, object? arg1, object? arg2) { throw null; } + public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3) { throw null; } + public object? Invoke(object? obj, object? arg1, object? arg2, object? arg3, object? arg4) { throw null; } + public static System.Reflection.MethodInvoker Create(System.Reflection.MethodBase method) { throw null; } + } public sealed partial class Missing : System.Runtime.Serialization.ISerializable { internal Missing() { } diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 2dc26dbe71fdce..49b8038954659a 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -178,6 +178,7 @@ + @@ -205,6 +206,7 @@ + diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.Mono.cs index 3bde0806a5c6ee..e829600332e34d 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.Mono.cs @@ -1,16 +1,18 @@ // 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 partial class ConstructorInvoker + public partial class ConstructorInvoker { + internal unsafe ConstructorInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.ArgumentTypes) + { + _invokeFunc_RefArgs = InterpretedInvoke; + } + private unsafe object? InterpretedInvoke(object? obj, IntPtr *args) { - Exception exc; - object? o = _method.InternalInvoke(obj, args, out exc); + object? o = _method.InternalInvoke(obj, args, out Exception? exc); if (exc != null) throw exc; diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs new file mode 100644 index 00000000000000..07e520d7146fab --- /dev/null +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Reflection +{ + internal partial class MethodBaseInvoker + { + internal unsafe MethodBaseInvoker(RuntimeMethodInfo method) : this(method, method.ArgumentTypes) + { + _invocationFlags = method.ComputeAndUpdateInvocationFlags(); + _invokeFunc_RefArgs = InterpretedInvoke_Method; + } + + internal unsafe MethodBaseInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.ArgumentTypes) + { + _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); + _invokeFunc_RefArgs = InterpretedInvoke_Constructor; + } + + internal unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) + { + object? o = ((RuntimeConstructorInfo)_method).InternalInvoke(obj, args, out Exception? exc); + + if (exc != null) + throw exc; + + return obj == null ? o : null; + } + + private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr *args) + { + object? o = ((RuntimeMethodInfo)_method).InternalInvoke(obj, args, out Exception? exc); + + if (exc != null) + throw exc; + + return o; + } + } +} diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs index b6a2a83b5514a3..2a5281912e5190 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs @@ -1,33 +1,32 @@ // 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; +using System.Reflection.Emit; namespace System.Reflection { - internal partial class MethodInvoker + public partial class MethodInvoker { - public MethodInvoker(MethodBase method) + internal unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.ArgumentTypes) { - _method = method; + _invocationFlags = method.ComputeAndUpdateInvocationFlags(); + _invokeFunc_RefArgs = InterpretedInvoke; + } - if (LocalAppContextSwitches.ForceInterpretedInvoke && !LocalAppContextSwitches.ForceEmitInvoke) - { - // Always use the native invoke; useful for testing. - _strategyDetermined = true; - } - else if (LocalAppContextSwitches.ForceEmitInvoke && !LocalAppContextSwitches.ForceInterpretedInvoke) - { - // Always use emit invoke (if IsDynamicCodeSupported == true); useful for testing. - _invoked = true; - } + internal unsafe MethodInvoker(DynamicMethod method) : this(method, method.ArgumentTypes) + { + _invokeFunc_RefArgs = InterpretedInvoke; } - private unsafe object? InterpretedInvoke(object? obj, IntPtr *args) + internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.ArgumentTypes) { - Exception? exc; + _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); + _invokeFunc_RefArgs = InterpretedInvoke; + } - object? o = ((RuntimeMethodInfo)_method).InternalInvoke(obj, args, out exc); + private unsafe object? InterpretedInvoke(object? obj, IntPtr *args) + { + object? o = ((RuntimeMethodInfo)_method).InternalInvoke(obj, args, out Exception? exc); if (exc != null) throw exc; diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs index 665e83d4533f56..a5b3f651ac67a4 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeFieldInfo.cs @@ -241,11 +241,10 @@ public override void SetValue(object? obj, object? val, BindingFlags invokeAttr, if (val != null) { RuntimeType fieldType = (RuntimeType)FieldType; - ParameterCopyBackAction _ = default; if (!ReferenceEquals(val.GetType(), fieldType)) { - fieldType.CheckValue(ref val, ref _, binder, culture, invokeAttr); + fieldType.CheckValue(ref val, binder, culture, invokeAttr); } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs index 13460b63cf49fe..a71acd1281d795 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs @@ -150,29 +150,25 @@ internal sealed unsafe partial class RuntimeMethodInfo : MethodInfo #endregion private string? toString; private RuntimeType[]? parameterTypes; - private InvocationFlags invocationFlags; - private MethodInvoker? invoker; + private MethodBaseInvoker? invoker; internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - InvocationFlags flags = invocationFlags; - if ((flags & InvocationFlags.Initialized) == 0) - { - flags = ComputeAndUpdateInvocationFlags(this, ref invocationFlags); - } + InvocationFlags flags = Invoker._invocationFlags; + Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized); return flags; } } - private MethodInvoker Invoker + internal MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - invoker ??= new MethodInvoker(this); + invoker ??= new MethodBaseInvoker(this); return invoker; } } @@ -720,29 +716,25 @@ internal sealed unsafe partial class RuntimeConstructorInfo : ConstructorInfo #endregion private string? toString; private RuntimeType[]? parameterTypes; - private InvocationFlags invocationFlags; - private ConstructorInvoker? invoker; + private MethodBaseInvoker? invoker; internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - InvocationFlags flags = invocationFlags; - if ((flags & InvocationFlags.Initialized) == 0) - { - flags = ComputeAndUpdateInvocationFlags(this, ref invocationFlags); - } + InvocationFlags flags = Invoker._invocationFlags; + Debug.Assert((flags & InvocationFlags.Initialized) == InvocationFlags.Initialized); return flags; } } - internal ConstructorInvoker Invoker + internal MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - invoker ??= new ConstructorInvoker(this); + invoker ??= new MethodBaseInvoker(this); return invoker; } } diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs index 732ebb26d8922a..8fa80262e4903c 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs @@ -168,22 +168,6 @@ internal static bool ObjectHasReferences(object obj) return RuntimeTypeHandle.HasReferences((obj.GetType() as RuntimeType)!); } - // A conservative GC already scans the stack looking for potential object-refs or by-refs. - // Mono uses a conservative GC so there is no need for this API to be full implemented. - internal unsafe ref struct GCFrameRegistration - { -#pragma warning disable IDE0060 - public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = true) - { - } -#pragma warning restore IDE0060 - } - - [Conditional("unnecessary")] - internal static unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } - [Conditional("unnecessary")] - internal static unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } - public static object GetUninitializedObject( // This API doesn't call any constructors, but the type needs to be seen as constructed. // A type is seen as constructed if a constructor is kept. diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs new file mode 100644 index 00000000000000..0e8a2e0fdf2842 --- /dev/null +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs @@ -0,0 +1,26 @@ +// 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; + +namespace System +{ + internal sealed class RuntimeImports + { + // A conservative GC already scans the stack looking for potential object-refs or by-refs. + // Mono uses a conservative GC so there is no need for this API to be full implemented. + internal unsafe struct GCFrameRegistration + { +#pragma warning disable IDE0060 + public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = true) + { + } +#pragma warning restore IDE0060 + } + + [Conditional("unnecessary")] + internal static unsafe void RhRegisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } + [Conditional("unnecessary")] + internal static unsafe void RhUnregisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } + } +} diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index e34b3788e76a8e..0322094b0e0735 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1761,21 +1761,13 @@ internal override FieldInfo GetField(FieldInfo fromNoninstanciated) throw new MissingMethodException(SR.Format(SR.Acc_CreateAbstEx, this)); } - unsafe - { - return ctor.Invoker.InlinedInvoke( - obj: null, - args: default, - wrapExceptions ? BindingFlags.Default : BindingFlags.DoNotWrapExceptions); - } + return ctor.Invoker.InvokeWithNoArgs(obj: null, wrapExceptions ? BindingFlags.Default : BindingFlags.DoNotWrapExceptions); } // FIXME Reuse with coreclr private CheckValueStatus TryChangeTypeSpecial( - ref object value, - out bool isValueType) + ref object value) { - isValueType = true; if (IsEnum) { Type? type = Enum.GetUnderlyingType(this); @@ -1814,7 +1806,6 @@ private CheckValueStatus TryChangeTypeSpecial( } } - isValueType = false; return CheckValueStatus.ArgumentException; } @@ -2080,10 +2071,7 @@ internal static object CreateInstanceForAnotherGenericParameter( if (ctor is null || !ctor.IsPublic) throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, gt!)); - unsafe - { - return ctor.Invoker.InlinedInvoke(obj: null, args: default, BindingFlags.Default)!; - } + return ctor.Invoker.InvokeWithNoArgs(obj: null, invokeAttr: default)!; } [MethodImplAttribute(MethodImplOptions.InternalCall)] diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index 6754ba616073aa..bacc4638dd990a 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -170,6 +170,12 @@ internal static bool IsPointer(RuntimeType type) return corElemType == CorElementType.ELEMENT_TYPE_PTR; } + internal static bool IsFunctionPointer(RuntimeType type) + { + CorElementType corElemType = GetCorElementType(type); + return corElemType == CorElementType.ELEMENT_TYPE_FNPTR; + } + internal static bool IsArray(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 06faaef6ed37ab..eea7cc85859605 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -72,6 +72,7 @@ private static int Main() TestGetUninitializedObject.Run(); TestInstanceFields.Run(); TestReflectionInvoke.Run(); + TestConstructors.Run(); TestInvokeMemberParamsCornerCase.Run(); TestDefaultInterfaceInvoke.Run(); TestCovariantReturnInvoke.Run(); @@ -187,90 +188,214 @@ public static unsafe void Run() } { + object? arg = "world"; MethodInfo helloMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHello"); - string result = (string)helloMethod.Invoke(null, new object[] { "world" }); + + string result = (string)helloMethod.Invoke(null, new object[] { arg }); + if (result != "Hello world") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloMethod).Invoke(null, arg); + if (result != "Hello world") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloMethod).Invoke(null, new Span(ref arg)); if (result != "Hello world") throw new Exception(); } { + object? arg = 12345; MethodInfo helloGenericMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloGeneric").MakeGenericMethod(typeof(int)); - string result = (string)helloGenericMethod.Invoke(null, new object[] { 12345 }); + string result = (string)helloGenericMethod.Invoke(null, new object[] { arg }); + if (result != "Hello 12345") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(null, arg); + if (result != "Hello 12345") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(null, new Span(ref arg)); if (result != "Hello 12345") throw new Exception(); } { + object? arg = "buddy"; MethodInfo helloGenericMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloGeneric").MakeGenericMethod(typeof(string)); - string result = (string)helloGenericMethod.Invoke(null, new object[] { "buddy" }); + string result = (string)helloGenericMethod.Invoke(null, new object[] { arg }); + if (result != "Hello buddy") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(null, arg); + if (result != "Hello buddy") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(null, new Span(ref arg)); if (result != "Hello buddy") throw new Exception(); } { + object? arg = typeof(string); MethodInfo helloGenericMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloGeneric").MakeGenericMethod(typeof(Type)); - string result = (string)helloGenericMethod.Invoke(null, new object[] { typeof(string) }); + string result = (string)helloGenericMethod.Invoke(null, new object[] { arg }); + if (result != "Hello System.String") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(null, arg); + if (result != "Hello System.String") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(null, new Span(ref arg)); if (result != "Hello System.String") throw new Exception(); } { + object? arg = "world"; MethodInfo helloByRefMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloByRef"); - object[] args = new object[] { "world", null }; + object[] args = new object[] { arg, null }; + helloByRefMethod.Invoke(null, args); if ((string)args[1] != "Hello world") throw new Exception(); + + args = new object[] { arg, null }; + MethodInvoker.Create(helloByRefMethod).Invoke(null, new Span(args)); + if ((string)args[1] != "Hello world") + throw new Exception(); } { MethodInfo helloPointerMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloPointer"); + string resultNull = (string)helloPointerMethod.Invoke(null, new object[] { null }); if (resultNull != "Hello 0") throw new Exception(); - string resultVal = (string)helloPointerMethod.Invoke(null, new object[] { Pointer.Box((void*)42, typeof(char*)) }); + resultNull = (string)MethodInvoker.Create(helloPointerMethod).Invoke(null, arg1: null); + if (resultNull != "Hello 0") + throw new Exception(); + + object? arg = null; + resultNull = (string)MethodInvoker.Create(helloPointerMethod).Invoke(null, new Span(ref arg)); + if (resultNull != "Hello 0") + throw new Exception(); + + arg = Pointer.Box((void*)42, typeof(char*)); + string resultVal = (string)helloPointerMethod.Invoke(null, new object[] { arg }); + if (resultVal != "Hello 42") + throw new Exception(); + + resultNull = (string)MethodInvoker.Create(helloPointerMethod).Invoke(null, arg); + if (resultVal != "Hello 42") + throw new Exception(); + + resultNull = (string)MethodInvoker.Create(helloPointerMethod).Invoke(null, new Span(ref arg)); if (resultVal != "Hello 42") throw new Exception(); } { MethodInfo helloPointerTooMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloPointerToo"); - string result = (string)helloPointerTooMethod.Invoke(null, new object[] { Pointer.Box((void*)85, typeof(char**)) }); + object? arg = Pointer.Box((void*)85, typeof(char**)); + + string result = (string)helloPointerTooMethod.Invoke(null, new object[] { arg }); + if (result != "Hello 85") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloPointerTooMethod).Invoke(null, arg); + if (result != "Hello 85") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloPointerTooMethod).Invoke(null, new Span(ref arg)); if (result != "Hello 85") throw new Exception(); } { MethodInfo getPointerMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetPointer"); - object result = getPointerMethod.Invoke(null, new object[] { Pointer.Box((void*)2018, typeof(void*)), null }); + object? arg = Pointer.Box((void*)2018, typeof(void*)); + object[] args = new object[] { arg, null }; + + object result = getPointerMethod.Invoke(null, args); + if (Pointer.Unbox(result) != (void*)2018) + throw new Exception(); + + result = MethodInvoker.Create(getPointerMethod).Invoke(null, arg, null); + if (Pointer.Unbox(result) != (void*)2018) + throw new Exception(); + + result = MethodInvoker.Create(getPointerMethod).Invoke(null, new Span(args)); if (Pointer.Unbox(result) != (void*)2018) throw new Exception(); } { MethodInfo helloMethod = typeof(InvokeTestsGeneric).GetTypeInfo().GetDeclaredMethod("GetHello"); - string result = (string)helloMethod.Invoke(new InvokeTestsGeneric(), new object[] { "world" }); + object? arg = "world"; + + string result = (string)helloMethod.Invoke(new InvokeTestsGeneric(), new object[] { arg }); + if (result != "Hello world System.String") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloMethod).Invoke(new InvokeTestsGeneric(), arg); + if (result != "Hello world System.String") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloMethod).Invoke(new InvokeTestsGeneric(), new Span(ref arg)); if (result != "Hello world System.String") throw new Exception(); } { MethodInfo helloGenericMethod = typeof(InvokeTestsGeneric).GetTypeInfo().GetDeclaredMethod("GetHelloGeneric").MakeGenericMethod(typeof(object)); - string result = (string)helloGenericMethod.Invoke(new InvokeTestsGeneric(), new object[] { "world" }); + object? arg = "world"; + + string result = (string)helloGenericMethod.Invoke(new InvokeTestsGeneric(), new object[] { arg }); + if (result != "Hello world System.Object") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(new InvokeTestsGeneric(), arg); + if (result != "Hello world System.Object") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(new InvokeTestsGeneric(), new Span(ref arg)); if (result != "Hello world System.Object") throw new Exception(); } { MethodInfo helloMethod = typeof(InvokeTestsGeneric).GetTypeInfo().GetDeclaredMethod("GetHello"); - string result = (string)helloMethod.Invoke(new InvokeTestsGeneric(), new object[] { "world" }); + object? arg = "world"; + + string result = (string)helloMethod.Invoke(new InvokeTestsGeneric(), new object[] { arg }); + if (result != "Hello world System.Int32") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloMethod).Invoke(new InvokeTestsGeneric(), arg); + if (result != "Hello world System.Int32") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloMethod).Invoke(new InvokeTestsGeneric(), new Span(ref arg)); if (result != "Hello world System.Int32") throw new Exception(); } { MethodInfo helloGenericMethod = typeof(InvokeTestsGeneric).GetTypeInfo().GetDeclaredMethod("GetHelloGeneric").MakeGenericMethod(typeof(double)); - string result = (string)helloGenericMethod.Invoke(new InvokeTestsGeneric(), new object[] { 1.0 }); + object? arg = 1.0; + + string result = (string)helloGenericMethod.Invoke(new InvokeTestsGeneric(), new object[] { arg }); + if (result != "Hello 1 System.Double") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(new InvokeTestsGeneric(), arg); + if (result != "Hello 1 System.Double") + throw new Exception(); + + result = (string)MethodInvoker.Create(helloGenericMethod).Invoke(new InvokeTestsGeneric(), new Span(ref arg)); if (result != "Hello 1 System.Double") throw new Exception(); } @@ -862,6 +987,33 @@ public static void Run() } } + class TestConstructors + { + public static void Run() + { + Console.WriteLine(nameof(TestConstructors)); + + ConstructorInfo ctor = typeof(ClassToConstruct).GetConstructor(new Type[] { typeof(int) }); + ClassToConstruct obj = (ClassToConstruct)ctor.Invoke(new object[] { 1 }); + if (obj._i != 1) + throw new Exception(); + + obj = (ClassToConstruct)ConstructorInvoker.Create(ctor).Invoke(1); + if (obj._i != 1) + throw new Exception(); + } + + public class ClassToConstruct + { + public int _i; + + public ClassToConstruct(int i) + { + _i = i; + } + } + } + class TestStringConstructor { public static void Run() @@ -872,6 +1024,10 @@ public static void Run() object str = ctor.Invoke(new object[] { new char[] { 'a' }, 0, 1 }); if ((string)str != "a") throw new Exception(); + + str = ConstructorInvoker.Create(ctor).Invoke(new char[] { 'a' }, 0, 1 ); + if ((string)str != "a") + throw new Exception(); } } From 2393158d507893185b28320787ad84ee24ee17fd Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Wed, 12 Jul 2023 12:29:29 -0500 Subject: [PATCH 2/6] Fix issue with Mono; misc feedback --- build | 0 .../Reflection/MethodInvoker.CoreCLR.cs | 1 - .../System/Runtime/RuntimeImports.CoreCLR.cs | 26 +- .../System/Reflection/DynamicInvokeInfo.cs | 8 +- .../src/System/Runtime/RuntimeImports.cs | 18 - src/coreclr/vm/ecalllist.h | 4 +- .../Reflection/InvokeInterpretedTests.cs | 4 +- .../System.Private.CoreLib.Shared.projitems | 1 + .../System/Reflection/ConstructorInvoker.cs | 39 ++- .../MethodBaseInvoker.Constructor.cs | 12 +- .../System/Reflection/MethodBaseInvoker.cs | 34 +- .../src/System/Reflection/MethodInvoker.cs | 40 +-- .../src/System/Runtime/GCFrameRegistration.cs | 27 ++ .../System.Reflection/System.Reflection.sln | 317 +++++++++--------- .../tests/ConstructorInvokerTests.cs | 3 +- .../System.Private.CoreLib.csproj | 2 +- .../Reflection/Emit/DynamicMethod.Mono.cs | 10 +- .../Reflection/MethodBaseInvoker.Mono.cs | 12 +- .../System/Reflection/MethodInvoker.Mono.cs | 20 +- .../Runtime/GCFrameRegistration.Mono.cs | 27 ++ .../src/System/RuntimeImports.Mono.cs | 26 -- 21 files changed, 313 insertions(+), 318 deletions(-) delete mode 100644 build create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs create mode 100644 src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs delete mode 100644 src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs diff --git a/build b/build deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs index 4d3946a49cbac1..b4960da0d5871a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs @@ -1,7 +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.Reflection.Emit; namespace System.Reflection diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs index f807f270d84577..b9f5bac52651cf 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs @@ -9,31 +9,9 @@ namespace System.Runtime internal static class RuntimeImports { [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void RhRegisterForGCReporting(GCFrameRegistration* pRegistration); + internal static extern unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void RhUnregisterForGCReporting(GCFrameRegistration* pRegistration); - -#pragma warning disable 0414, IDE0044 - // Type that represents a managed view of the unmanaged GCFrame - // data structure in coreclr. The type layouts between the two should match. - internal unsafe struct GCFrameRegistration - { - private nuint m_reserved1; - private nuint m_reserved2; - private void** m_pObjRefs; - private uint m_numObjRefs; - private int m_MaybeInterior; - - public GCFrameRegistration(void** allocation, uint elemCount, bool areByRefs = true) - { - m_reserved1 = 0; - m_reserved2 = 0; - m_pObjRefs = allocation; - m_numObjRefs = elemCount; - m_MaybeInterior = areByRefs ? 1 : 0; - } - } -#pragma warning restore 0414, IDE0044 + internal static extern unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs index e0a733f91de082..cbf407434c324a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs @@ -420,8 +420,8 @@ private unsafe ref byte InvokeWithManyArguments( void* pByRefStorage = (ByReference*)(pStorage + argCount); #pragma warning restore 8500 - RuntimeImports.GCFrameRegistration regArgStorage = new(pStorage, (uint)argCount, areByRefs: false); - RuntimeImports.GCFrameRegistration regByRefStorage = new(pByRefStorage, (uint)argCount, areByRefs: true); + GCFrameRegistration regArgStorage = new((void**)pStorage, (uint)argCount, areByRefs: false); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)argCount, areByRefs: true); try { @@ -471,8 +471,8 @@ private unsafe ref byte InvokeWithManyArguments( void* pByRefStorage = (ByReference*)(pStorage + argCount); #pragma warning restore 8500 - RuntimeImports.GCFrameRegistration regArgStorage = new(pStorage, (uint)argCount, areByRefs: false); - RuntimeImports.GCFrameRegistration regByRefStorage = new(pByRefStorage, (uint)argCount, areByRefs: true); + GCFrameRegistration regArgStorage = new((void**)pStorage, (uint)argCount, areByRefs: false); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)argCount, areByRefs: true); try { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index c6ac7d60c9990b..93a33d9f298834 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -630,24 +630,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [RuntimeImport(RuntimeLibrary, "RhBulkMoveWithWriteBarrier")] internal static extern unsafe void RhBulkMoveWithWriteBarrier(ref byte dmem, ref byte smem, nuint size); - internal unsafe struct GCFrameRegistration - { - private nuint m_reserved1; - private nuint m_reserved2; - private void* m_pObjRefs; - private uint m_numObjRefs; - private int m_MaybeInterior; - - public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = true) - { - m_reserved1 = 0; - m_reserved2 = 0; - m_pObjRefs = allocation; - m_numObjRefs = elemCount; - m_MaybeInterior = areByRefs ? 1 : 0; - } - } - [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhRegisterForGCReporting")] internal static extern unsafe void RhRegisterForGCReporting(GCFrameRegistration* pRegistration); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 47e635bed87588..b14f1b5df55b8f 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -560,8 +560,8 @@ FCFuncStart(gRuntimeHelpers) FCFuncEnd() FCFuncStart(gRuntimeImports) - FCFuncElement("RhRegisterForGCReporting", GCReporting::Register) - FCFuncElement("RhUnregisterForGCReporting", GCReporting::Unregister) + FCFuncElement("RegisterForGCReporting", GCReporting::Register) + FCFuncElement("UnregisterForGCReporting", GCReporting::Unregister) FCFuncEnd() FCFuncStart(gMethodTableFuncs) diff --git a/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs b/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs index 67de322dc90762..573211876b0fb7 100644 --- a/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs +++ b/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs @@ -9,7 +9,7 @@ public class InvokeInterpretedTests { [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/50957", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoAOT))] - public static void VerifyInvokeIsUsingEmit_Method() + public static void VerifyInvokeIsUsingInterpreter_Method() { MethodInfo method = typeof(TestClassThatThrows).GetMethod(nameof(TestClassThatThrows.Throw))!; TargetInvocationException ex = Assert.Throws(() => method.Invoke(null, null)); @@ -22,7 +22,7 @@ public static void VerifyInvokeIsUsingEmit_Method() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/50957", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoAOT))] - public static void VerifyInvokeIsUsingEmit_Constructor() + public static void VerifyInvokeIsUsingInterpreter_Constructor() { ConstructorInfo ctor = typeof(TestClassThatThrows).GetConstructor(Type.EmptyTypes)!; TargetInvocationException ex = Assert.Throws(() => ctor.Invoke(null)); diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 100105610416f2..c0e88c56753452 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -859,6 +859,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs index e27de1e67540df..8614b81e750595 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs @@ -12,16 +12,16 @@ namespace System.Reflection { public sealed partial class ConstructorInvoker { - internal InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; - internal InvokeFunc_Obj4Args? _invokeFunc_Obj4Args; - internal InvokeFunc_RefArgs? _invokeFunc_RefArgs; - internal InvokerStrategy _strategy; - internal readonly int _argCount; - internal readonly RuntimeType[] _argTypes; - internal readonly InvocationFlags _invocationFlags; - internal readonly InvokerArgFlags[] _invokerArgFlags; - internal readonly RuntimeConstructorInfo _method; - internal readonly bool _needsByRefStrategy; + private InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; + private InvokeFunc_Obj4Args? _invokeFunc_Obj4Args; + private InvokeFunc_RefArgs? _invokeFunc_RefArgs; + private InvokerStrategy _strategy; + private readonly int _argCount; + private readonly RuntimeType[] _argTypes; + private readonly InvocationFlags _invocationFlags; + private readonly InvokerArgFlags[] _invokerArgFlags; + private readonly RuntimeConstructorInfo _method; + private readonly bool _needsByRefStrategy; public static ConstructorInvoker Create(ConstructorInfo constructor) { @@ -216,7 +216,7 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg internal unsafe object? InvokeWithManyArgs(Span arguments) { Span copyOfArgs; - RuntimeImports.GCFrameRegistration regArgStorage; + GCFrameRegistration regArgStorage; if (!_needsByRefStrategy) { @@ -234,7 +234,7 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); for (int i = 0; i < _argCount; i++) { @@ -248,7 +248,7 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg } finally { - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } } @@ -266,12 +266,12 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg scoped Span shouldCopyBack = stackalloc bool[_argCount]; regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); - RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); - RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ByRefStorage); for (int i = 0; i < _argCount; i++) { @@ -291,8 +291,8 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg } finally { - RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.UnregisterForGCReporting(®ByRefStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } @@ -318,9 +318,8 @@ internal void CopyBack(Span dest, Span copyOfParameters, Span< } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool CheckArgument(ref object? arg, int i) + private bool CheckArgument(ref object? arg, int i) { RuntimeType sigType = _argTypes[i]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs index 01ae56e690cb63..bc7a746c2dd48a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs @@ -28,14 +28,14 @@ internal sealed partial class MethodBaseInvoker IntPtr* pStorage = stackalloc IntPtr[2 * argCount]; NativeMemory.Clear(pStorage, (nuint)(2 * argCount) * (nuint)sizeof(IntPtr)); Span copyOfArgs = new(ref Unsafe.AsRef(pStorage), argCount); - RuntimeImports.GCFrameRegistration regArgStorage = new((void**)pStorage, (uint)argCount, areByRefs: false); + GCFrameRegistration regArgStorage = new((void**)pStorage, (uint)argCount, areByRefs: false); IntPtr* pByRefStorage = pStorage + argCount; - RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)argCount, areByRefs: true); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)argCount, areByRefs: true); try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); - RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ByRefStorage); CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); @@ -63,8 +63,8 @@ internal sealed partial class MethodBaseInvoker } finally { - RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ByRefStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs index 6256face575c8f..0c5f18a947e1f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs @@ -16,15 +16,15 @@ internal sealed partial class MethodBaseInvoker { internal const int MaxStackAllocArgCount = 4; - internal InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; - internal InvokeFunc_RefArgs? _invokeFunc_RefArgs; - internal InvokerStrategy _strategy; + private InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; + private InvokeFunc_RefArgs? _invokeFunc_RefArgs; + private InvokerStrategy _strategy; internal readonly InvocationFlags _invocationFlags; - internal readonly InvokerArgFlags[] _invokerArgFlags; - internal readonly RuntimeType[] _argTypes; - internal readonly MethodBase _method; - internal readonly int _argCount; - internal readonly bool _needsByRefStrategy; + private readonly InvokerArgFlags[] _invokerArgFlags; + private readonly RuntimeType[] _argTypes; + private readonly MethodBase _method; + private readonly int _argCount; + private readonly bool _needsByRefStrategy; private MethodBaseInvoker(MethodBase method, RuntimeType[] argumentTypes) { @@ -199,7 +199,7 @@ internal static void ThrowTargetParameterCountException() Span copyOfArgs; object? ret; - RuntimeImports.GCFrameRegistration regArgStorage; + GCFrameRegistration regArgStorage; Span shouldCopyBack; if (!_needsByRefStrategy) @@ -219,7 +219,7 @@ internal static void ThrowTargetParameterCountException() try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); @@ -237,7 +237,7 @@ internal static void ThrowTargetParameterCountException() } finally { - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } } @@ -252,13 +252,13 @@ internal static void ThrowTargetParameterCountException() copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); IntPtr* pByRefStorage = pStorage + _argCount; - RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); shouldCopyBack = new Span(pStorage + _argCount * 2, _argCount); try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); - RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ByRefStorage); CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); @@ -285,8 +285,8 @@ internal static void ThrowTargetParameterCountException() } finally { - RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.UnregisterForGCReporting(®ByRefStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } @@ -401,7 +401,7 @@ BindingFlags invokeAttr } } - internal static bool TryByRefFastPath(RuntimeType type, ref object arg) + private static bool TryByRefFastPath(RuntimeType type, ref object arg) { if (RuntimeType.TryGetByRefElementType(type, out RuntimeType? sigElementType) && ReferenceEquals(sigElementType, arg.GetType())) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs index 8a031a3664fc55..93f96a59ae8140 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs @@ -13,17 +13,17 @@ namespace System.Reflection { public sealed partial class MethodInvoker { - internal InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; - internal InvokeFunc_Obj4Args? _invokeFunc_Obj4Args; - internal InvokeFunc_RefArgs? _invokeFunc_RefArgs; - internal InvokerStrategy _strategy; - internal readonly int _argCount; - internal readonly RuntimeType[] _argTypes; - internal readonly InvocationFlags _invocationFlags; - internal readonly InvokerArgFlags[] _invokerArgFlags; - internal readonly MethodBase _method; - internal readonly bool _needsByRefStrategy; - internal readonly bool _isStatic; + private InvokeFunc_ObjSpanArgs? _invokeFunc_ObjSpanArgs; + private InvokeFunc_Obj4Args? _invokeFunc_Obj4Args; + private InvokeFunc_RefArgs? _invokeFunc_RefArgs; + private InvokerStrategy _strategy; + private readonly int _argCount; + private readonly RuntimeType[] _argTypes; + private readonly InvocationFlags _invocationFlags; + private readonly InvokerArgFlags[] _invokerArgFlags; + private readonly MethodBase _method; + private readonly bool _needsByRefStrategy; + private readonly bool _isStatic; public static MethodInvoker Create(MethodBase method) { @@ -241,7 +241,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) internal unsafe object? InvokeWithManyArgs(object? obj, Span arguments) { Span copyOfArgs; - RuntimeImports.GCFrameRegistration regArgStorage; + GCFrameRegistration regArgStorage; if (!_needsByRefStrategy) { @@ -259,7 +259,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); for (int i = 0; i < _argCount; i++) { @@ -273,7 +273,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) } finally { - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } } @@ -291,12 +291,12 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) scoped Span shouldCopyBack = stackalloc bool[_argCount]; regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); - RuntimeImports.GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); try { - RuntimeImports.RhRegisterForGCReporting(®ArgStorage); - RuntimeImports.RhRegisterForGCReporting(®ByRefStorage); + RuntimeImports.RegisterForGCReporting(®ArgStorage); + RuntimeImports.RegisterForGCReporting(®ByRefStorage); for (int i = 0; i < _argCount; i++) { @@ -316,8 +316,8 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) } finally { - RuntimeImports.RhUnregisterForGCReporting(®ByRefStorage); - RuntimeImports.RhUnregisterForGCReporting(®ArgStorage); + RuntimeImports.UnregisterForGCReporting(®ByRefStorage); + RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } @@ -344,7 +344,7 @@ internal void CopyBack(Span dest, Span copyOfParameters, Span< } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool CheckArgument(ref object? arg, int i) + private bool CheckArgument(ref object? arg, int i) { RuntimeType sigType = _argTypes[i]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs new file mode 100644 index 00000000000000..4afbda34a119bb --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs @@ -0,0 +1,27 @@ +// 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.Loader; + +namespace System.Runtime +{ +#pragma warning disable 0414, IDE0044 + internal unsafe struct GCFrameRegistration + { + private nuint m_reserved1; + private nuint m_reserved2; + private void** m_pObjRefs; + private uint m_numObjRefs; + private int m_MaybeInterior; + + public GCFrameRegistration(void** allocation, uint elemCount, bool areByRefs = true) + { + m_reserved1 = 0; + m_reserved2 = 0; + m_pObjRefs = allocation; + m_numObjRefs = elemCount; + m_MaybeInterior = areByRefs ? 1 : 0; + } + } +#pragma warning restore 0414, IDE0044 +} diff --git a/src/libraries/System.Reflection/System.Reflection.sln b/src/libraries/System.Reflection/System.Reflection.sln index 62c2cb74337bf4..2cd11065f1ae71 100644 --- a/src/libraries/System.Reflection/System.Reflection.sln +++ b/src/libraries/System.Reflection/System.Reflection.sln @@ -1,8 +1,4 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.6.33815.320 -MinimumVisualStudioVersion = 10.0.40219.1 +Microsoft Visual Studio Solution File, Format Version 12.00 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{27A1A006-6882-4C70-AB81-775D3D2C95A2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{C5A7E7E7-E43B-4C87-9A92-13C3C817E714}" @@ -69,11 +65,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{548F3513-E3A EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Checked|Any CPU = Checked|Any CPU - Checked|arm = Checked|arm - Checked|arm64 = Checked|arm64 - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|arm = Debug|arm Debug|arm64 = Debug|arm64 @@ -84,18 +75,13 @@ Global Release|arm64 = Release|arm64 Release|x64 = Release|x64 Release|x86 = Release|x86 + Checked|Any CPU = Checked|Any CPU + Checked|arm = Checked|arm + Checked|arm64 = Checked|arm64 + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.ActiveCfg = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.Build.0 = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.ActiveCfg = Checked|arm - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.Build.0 = Checked|arm - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.ActiveCfg = Checked|arm64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.Build.0 = Checked|arm64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.ActiveCfg = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.Build.0 = Checked|x64 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.ActiveCfg = Checked|x86 - {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.Build.0 = Checked|x86 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Debug|Any CPU.ActiveCfg = Debug|x64 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Debug|Any CPU.Build.0 = Debug|x64 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Debug|arm.ActiveCfg = Debug|arm @@ -116,11 +102,16 @@ Global {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Release|x64.Build.0 = Release|x64 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Release|x86.ActiveCfg = Release|x86 {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Release|x86.Build.0 = Release|x86 - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x64.ActiveCfg = Debug|Any CPU - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x86.ActiveCfg = Debug|Any CPU + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.ActiveCfg = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|Any CPU.Build.0 = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.ActiveCfg = Checked|arm + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm.Build.0 = Checked|arm + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.ActiveCfg = Checked|arm64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|arm64.Build.0 = Checked|arm64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.ActiveCfg = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x64.Build.0 = Checked|x64 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.ActiveCfg = Checked|x86 + {27A1A006-6882-4C70-AB81-775D3D2C95A2}.Checked|x86.Build.0 = Checked|x86 {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -137,11 +128,11 @@ Global {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Release|x64.Build.0 = Release|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Release|x86.ActiveCfg = Release|Any CPU {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Release|x86.Build.0 = Release|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm64.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x64.ActiveCfg = Debug|Any CPU - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x86.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x64.ActiveCfg = Debug|Any CPU + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714}.Checked|x86.ActiveCfg = Debug|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -158,11 +149,11 @@ Global {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Release|x64.Build.0 = Release|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Release|x86.ActiveCfg = Release|Any CPU {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Release|x86.Build.0 = Release|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x64.ActiveCfg = Debug|Any CPU - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x86.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|arm64.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x64.ActiveCfg = Debug|Any CPU + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489}.Checked|x86.ActiveCfg = Debug|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Debug|Any CPU.Build.0 = Debug|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -179,11 +170,11 @@ Global {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Release|x64.Build.0 = Release|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Release|x86.ActiveCfg = Release|Any CPU {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Release|x86.Build.0 = Release|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm64.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x64.ActiveCfg = Debug|Any CPU - {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x86.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x64.ActiveCfg = Debug|Any CPU + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A}.Checked|x86.ActiveCfg = Debug|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Debug|Any CPU.Build.0 = Debug|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -200,11 +191,11 @@ Global {319997BC-5DF6-4E23-A768-ED9905690EF4}.Release|x64.Build.0 = Release|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Release|x86.ActiveCfg = Release|Any CPU {319997BC-5DF6-4E23-A768-ED9905690EF4}.Release|x86.Build.0 = Release|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm64.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x64.ActiveCfg = Debug|Any CPU - {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x86.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|arm64.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x64.ActiveCfg = Debug|Any CPU + {319997BC-5DF6-4E23-A768-ED9905690EF4}.Checked|x86.ActiveCfg = Debug|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -221,11 +212,11 @@ Global {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Release|x64.Build.0 = Release|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Release|x86.ActiveCfg = Release|Any CPU {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Release|x86.Build.0 = Release|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x64.ActiveCfg = Debug|Any CPU - {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x86.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|arm64.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x64.ActiveCfg = Debug|Any CPU + {2A4650E3-E199-41E4-AD2B-32818E57D1C7}.Checked|x86.ActiveCfg = Debug|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -242,11 +233,11 @@ Global {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Release|x64.Build.0 = Release|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Release|x86.ActiveCfg = Release|Any CPU {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Release|x86.Build.0 = Release|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x64.ActiveCfg = Debug|Any CPU - {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x86.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x64.ActiveCfg = Debug|Any CPU + {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64}.Checked|x86.ActiveCfg = Debug|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Debug|Any CPU.Build.0 = Debug|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -263,11 +254,11 @@ Global {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Release|x64.Build.0 = Release|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Release|x86.ActiveCfg = Release|Any CPU {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Release|x86.Build.0 = Release|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm64.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x64.ActiveCfg = Debug|Any CPU - {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x86.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x64.ActiveCfg = Debug|Any CPU + {7873C6BF-74FA-4DCF-ADCD-15C75B20132D}.Checked|x86.ActiveCfg = Debug|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -284,11 +275,11 @@ Global {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Release|x64.Build.0 = Release|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Release|x86.ActiveCfg = Release|Any CPU {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Release|x86.Build.0 = Release|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x64.ActiveCfg = Debug|Any CPU - {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x86.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|arm64.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x64.ActiveCfg = Debug|Any CPU + {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1}.Checked|x86.ActiveCfg = Debug|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -305,11 +296,11 @@ Global {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Release|x64.Build.0 = Release|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Release|x86.ActiveCfg = Release|Any CPU {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Release|x86.Build.0 = Release|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x64.ActiveCfg = Debug|Any CPU - {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x86.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x64.ActiveCfg = Debug|Any CPU + {C14AA1F5-6319-4F35-967F-B76E3E7283B0}.Checked|x86.ActiveCfg = Debug|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Debug|Any CPU.Build.0 = Debug|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -326,11 +317,11 @@ Global {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Release|x64.Build.0 = Release|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Release|x86.ActiveCfg = Release|Any CPU {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Release|x86.Build.0 = Release|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x64.ActiveCfg = Debug|Any CPU - {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x86.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x64.ActiveCfg = Debug|Any CPU + {BB496AA6-1841-4A40-A5B5-2DFB7F04CC7A}.Checked|x86.ActiveCfg = Debug|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -347,11 +338,11 @@ Global {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Release|x64.Build.0 = Release|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Release|x86.ActiveCfg = Release|Any CPU {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Release|x86.Build.0 = Release|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm64.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x64.ActiveCfg = Debug|Any CPU - {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x86.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x64.ActiveCfg = Debug|Any CPU + {F0864C35-F7D0-41BD-B7E8-A54630D9537B}.Checked|x86.ActiveCfg = Debug|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Debug|Any CPU.Build.0 = Debug|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -368,11 +359,11 @@ Global {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Release|x64.Build.0 = Release|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Release|x86.ActiveCfg = Release|Any CPU {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Release|x86.Build.0 = Release|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm64.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x64.ActiveCfg = Debug|Any CPU - {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x86.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|arm64.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x64.ActiveCfg = Debug|Any CPU + {6DACBD8C-A8FF-490D-9434-AB78283C1BDA}.Checked|x86.ActiveCfg = Debug|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Debug|Any CPU.Build.0 = Debug|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -389,11 +380,11 @@ Global {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Release|x64.Build.0 = Release|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Release|x86.ActiveCfg = Release|Any CPU {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Release|x86.Build.0 = Release|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x64.ActiveCfg = Debug|Any CPU - {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x86.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|arm64.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x64.ActiveCfg = Debug|Any CPU + {882B2F3F-31C0-4BB0-8289-AEF4378864B4}.Checked|x86.ActiveCfg = Debug|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -410,11 +401,11 @@ Global {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Release|x64.Build.0 = Release|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Release|x86.ActiveCfg = Release|Any CPU {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Release|x86.Build.0 = Release|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x64.ActiveCfg = Debug|Any CPU - {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x86.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x64.ActiveCfg = Debug|Any CPU + {0082F4DC-2BB1-4119-9678-64CE0315B04D}.Checked|x86.ActiveCfg = Debug|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Debug|Any CPU.Build.0 = Debug|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -431,11 +422,11 @@ Global {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Release|x64.Build.0 = Release|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Release|x86.ActiveCfg = Release|Any CPU {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Release|x86.Build.0 = Release|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x64.ActiveCfg = Debug|Any CPU - {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x86.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x64.ActiveCfg = Debug|Any CPU + {CFF89A7E-E462-4A34-9352-86C908E0F34C}.Checked|x86.ActiveCfg = Debug|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Debug|Any CPU.Build.0 = Debug|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -452,11 +443,11 @@ Global {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Release|x64.Build.0 = Release|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Release|x86.ActiveCfg = Release|Any CPU {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Release|x86.Build.0 = Release|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x64.ActiveCfg = Debug|Any CPU - {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x86.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x64.ActiveCfg = Debug|Any CPU + {F262C9E1-EBC3-4EC2-9CF7-AD266BDD9F58}.Checked|x86.ActiveCfg = Debug|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Debug|Any CPU.Build.0 = Debug|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -473,11 +464,11 @@ Global {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Release|x64.Build.0 = Release|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Release|x86.ActiveCfg = Release|Any CPU {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Release|x86.Build.0 = Release|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm64.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x64.ActiveCfg = Debug|Any CPU - {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x86.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x64.ActiveCfg = Debug|Any CPU + {CCB3A96A-9DCA-49F1-A1D6-80D0395C1DD3}.Checked|x86.ActiveCfg = Debug|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Debug|Any CPU.Build.0 = Debug|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -494,11 +485,11 @@ Global {006DEC5A-067B-4099-934E-830ABB10BC26}.Release|x64.Build.0 = Release|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Release|x86.ActiveCfg = Release|Any CPU {006DEC5A-067B-4099-934E-830ABB10BC26}.Release|x86.Build.0 = Release|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x64.ActiveCfg = Debug|Any CPU - {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x86.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|arm64.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x64.ActiveCfg = Debug|Any CPU + {006DEC5A-067B-4099-934E-830ABB10BC26}.Checked|x86.ActiveCfg = Debug|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -515,11 +506,11 @@ Global {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Release|x64.Build.0 = Release|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Release|x86.ActiveCfg = Release|Any CPU {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Release|x86.Build.0 = Release|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x64.ActiveCfg = Debug|Any CPU - {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x86.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x64.ActiveCfg = Debug|Any CPU + {EE38FA51-BA38-4FC9-9655-C8EBB768969D}.Checked|x86.ActiveCfg = Debug|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -536,11 +527,11 @@ Global {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Release|x64.Build.0 = Release|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Release|x86.ActiveCfg = Release|Any CPU {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Release|x86.Build.0 = Release|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm64.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x64.ActiveCfg = Debug|Any CPU - {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x86.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x64.ActiveCfg = Debug|Any CPU + {CB2060E9-094A-4E8A-851B-84EF56491F5D}.Checked|x86.ActiveCfg = Debug|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -557,11 +548,11 @@ Global {F2E5F428-418B-41B9-BF14-36EB67486A71}.Release|x64.Build.0 = Release|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Release|x86.ActiveCfg = Release|Any CPU {F2E5F428-418B-41B9-BF14-36EB67486A71}.Release|x86.Build.0 = Release|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm64.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x64.ActiveCfg = Debug|Any CPU - {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x86.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|arm64.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x64.ActiveCfg = Debug|Any CPU + {F2E5F428-418B-41B9-BF14-36EB67486A71}.Checked|x86.ActiveCfg = Debug|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Debug|Any CPU.Build.0 = Debug|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -578,11 +569,11 @@ Global {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Release|x64.Build.0 = Release|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Release|x86.ActiveCfg = Release|Any CPU {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Release|x86.Build.0 = Release|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm64.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x64.ActiveCfg = Debug|Any CPU - {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x86.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|arm64.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x64.ActiveCfg = Debug|Any CPU + {E6F16442-FB0F-4666-8309-F8B1EBA5B860}.Checked|x86.ActiveCfg = Debug|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Debug|Any CPU.Build.0 = Debug|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -599,11 +590,11 @@ Global {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Release|x64.Build.0 = Release|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Release|x86.ActiveCfg = Release|Any CPU {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Release|x86.Build.0 = Release|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x64.ActiveCfg = Debug|Any CPU - {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x86.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|arm64.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x64.ActiveCfg = Debug|Any CPU + {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88}.Checked|x86.ActiveCfg = Debug|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -620,11 +611,11 @@ Global {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Release|x64.Build.0 = Release|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Release|x86.ActiveCfg = Release|Any CPU {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Release|x86.Build.0 = Release|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x64.ActiveCfg = Debug|Any CPU - {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x86.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x64.ActiveCfg = Debug|Any CPU + {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0}.Checked|x86.ActiveCfg = Debug|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Debug|Any CPU.Build.0 = Debug|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -641,11 +632,11 @@ Global {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Release|x64.Build.0 = Release|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Release|x86.ActiveCfg = Release|Any CPU {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Release|x86.Build.0 = Release|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm64.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x64.ActiveCfg = Debug|Any CPU - {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x86.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x64.ActiveCfg = Debug|Any CPU + {A2B3A339-4792-4561-A973-11FE5EEEB54A}.Checked|x86.ActiveCfg = Debug|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -662,11 +653,11 @@ Global {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Release|x64.Build.0 = Release|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Release|x86.ActiveCfg = Release|Any CPU {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Release|x86.Build.0 = Release|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm64.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x64.ActiveCfg = Debug|Any CPU - {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x86.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|arm64.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x64.ActiveCfg = Debug|Any CPU + {7625A3EB-C76C-41FE-85DC-C8B792062F9C}.Checked|x86.ActiveCfg = Debug|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -683,17 +674,19 @@ Global {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Release|x64.Build.0 = Release|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Release|x86.ActiveCfg = Release|Any CPU {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Release|x86.Build.0 = Release|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|arm64.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x64.ActiveCfg = Debug|Any CPU + {95C7E01D-B35D-431C-A50E-D52956ABBFB3}.Checked|x86.ActiveCfg = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {27A1A006-6882-4C70-AB81-775D3D2C95A2} = {1BD23B5E-9944-4133-A162-94D4697616DD} - {C5A7E7E7-E43B-4C87-9A92-13C3C817E714} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} - {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} - {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} - {319997BC-5DF6-4E23-A768-ED9905690EF4} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} {2A4650E3-E199-41E4-AD2B-32818E57D1C7} = {1BD23B5E-9944-4133-A162-94D4697616DD} + {C5A7E7E7-E43B-4C87-9A92-13C3C817E714} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {F5998D9E-69A3-4F43-9AA5-B1BB33B54C64} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {7873C6BF-74FA-4DCF-ADCD-15C75B20132D} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {9A5D32AB-91C7-4439-8ACA-4F17252EA3F1} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} @@ -713,14 +706,14 @@ Global {E6F16442-FB0F-4666-8309-F8B1EBA5B860} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {42BEE4BD-C378-41C5-A94F-4EA01F8D6E88} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} {C4AF78A8-28D7-434B-8F85-0B0E902AF8E0} = {64590D3A-D464-4764-ABE3-EF62722D8FA7} + {1F5C28EE-FA69-4A3A-934C-88FEBBDE2489} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} {A2B3A339-4792-4561-A973-11FE5EEEB54A} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} {7625A3EB-C76C-41FE-85DC-C8B792062F9C} = {5BEA3DA5-3D9A-4642-B049-C04392B78D4B} + {D01D932F-2B0A-4AE3-AC2D-5D4B766FC15A} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} + {319997BC-5DF6-4E23-A768-ED9905690EF4} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} {95C7E01D-B35D-431C-A50E-D52956ABBFB3} = {548F3513-E3A5-4741-A8C5-00D0CF99B2D3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8439AF1D-1B47-4BB3-A6C5-3B34D114C9F3} EndGlobalSection - GlobalSection(SharedMSBuildProjectFiles) = preSolution - ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{27a1a006-6882-4c70-ab81-775d3d2c95a2}*SharedItemsImports = 5 - EndGlobalSection EndGlobal diff --git a/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs b/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs index 8d209967522ba0..056bb592687163 100644 --- a/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs +++ b/src/libraries/System.Reflection/tests/ConstructorInvokerTests.cs @@ -95,8 +95,9 @@ public void ExistingInstance() Assert.Null(tc._args); MethodInvoker invoker = MethodInvoker.Create(ci); - invoker.Invoke(tc); + object? obj = invoker.Invoke(tc); Assert.Equal("0", tc._args); + Assert.Null(obj); } private class TestClass diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 49b8038954659a..a8612905085a6c 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -178,7 +178,6 @@ - @@ -250,6 +249,7 @@ + diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs index d0f8984b2ffec9..5a97e73dcd7d34 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs @@ -74,9 +74,7 @@ private RuntimeILGenerator GetILGeneratorInternal(int streamSize) => try { CreateDynMethod(); - _method ??= new RuntimeMethodInfo(_mhandle); - - return _method.Invoke(obj, invokeAttr, binder, parameters, culture); + return GetRuntimeMethodInfo().Invoke(obj, invokeAttr, binder, parameters, culture); } catch (MethodAccessException mae) { @@ -84,6 +82,12 @@ private RuntimeILGenerator GetILGeneratorInternal(int streamSize) => } } + internal RuntimeMethodInfo GetRuntimeMethodInfo() + { + _method ??= new RuntimeMethodInfo(_mhandle); + return _method; + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void create_dynamic_method(DynamicMethod m, string name, MethodAttributes attributes, CallingConventions callingConvention); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs index 07e520d7146fab..e4c4b533900042 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs @@ -17,24 +17,24 @@ internal unsafe MethodBaseInvoker(RuntimeConstructorInfo constructor) : this(con _invokeFunc_RefArgs = InterpretedInvoke_Constructor; } - internal unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) + private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr *args) { - object? o = ((RuntimeConstructorInfo)_method).InternalInvoke(obj, args, out Exception? exc); + object? o = ((RuntimeMethodInfo)_method).InternalInvoke(obj, args, out Exception? exc); if (exc != null) throw exc; - return obj == null ? o : null; + return o; } - private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr *args) + internal unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr* args) { - object? o = ((RuntimeMethodInfo)_method).InternalInvoke(obj, args, out Exception? exc); + object? o = ((RuntimeConstructorInfo)_method).InternalInvoke(obj, args, out Exception? exc); if (exc != null) throw exc; - return o; + return obj == null ? o : null; } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs index 2a5281912e5190..5e5fb10412905b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs @@ -10,21 +10,21 @@ public partial class MethodInvoker internal unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.ArgumentTypes) { _invocationFlags = method.ComputeAndUpdateInvocationFlags(); - _invokeFunc_RefArgs = InterpretedInvoke; + _invokeFunc_RefArgs = InterpretedInvoke_Method; } - internal unsafe MethodInvoker(DynamicMethod method) : this(method, method.ArgumentTypes) + internal unsafe MethodInvoker(DynamicMethod method) : this(method.GetRuntimeMethodInfo(), method.ArgumentTypes) { - _invokeFunc_RefArgs = InterpretedInvoke; + _invokeFunc_RefArgs = InterpretedInvoke_Method; } internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.ArgumentTypes) { _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); - _invokeFunc_RefArgs = InterpretedInvoke; + _invokeFunc_RefArgs = InterpretedInvoke_Constructor; } - private unsafe object? InterpretedInvoke(object? obj, IntPtr *args) + private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr *args) { object? o = ((RuntimeMethodInfo)_method).InternalInvoke(obj, args, out Exception? exc); @@ -33,5 +33,15 @@ internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constru return o; } + + private unsafe object? InterpretedInvoke_Constructor(object? obj, IntPtr *args) + { + object? o = ((RuntimeConstructorInfo)_method).InternalInvoke(obj, args, out Exception? exc); + + if (exc != null) + throw exc; + + return obj == null ? o : null; + } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs new file mode 100644 index 00000000000000..ce630ef50ea31d --- /dev/null +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs @@ -0,0 +1,27 @@ +// 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; + +namespace System.Runtime +{ + // A conservative GC already scans the stack looking for potential object-refs or by-refs. + // Mono uses a conservative GC so there is no need for this API to be full implemented. + internal unsafe struct GCFrameRegistration + { +#pragma warning disable IDE0060 + public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = true) + { + } +#pragma warning restore IDE0060 + } + + internal static partial class RuntimeImports + { + [Conditional("unnecessary")] + internal static unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } + + [Conditional("unnecessary")] + internal static unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } + } +} diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs deleted file mode 100644 index 0e8a2e0fdf2842..00000000000000 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeImports.Mono.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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; - -namespace System -{ - internal sealed class RuntimeImports - { - // A conservative GC already scans the stack looking for potential object-refs or by-refs. - // Mono uses a conservative GC so there is no need for this API to be full implemented. - internal unsafe struct GCFrameRegistration - { -#pragma warning disable IDE0060 - public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = true) - { - } -#pragma warning restore IDE0060 - } - - [Conditional("unnecessary")] - internal static unsafe void RhRegisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } - [Conditional("unnecessary")] - internal static unsafe void RhUnregisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } - } -} From 2e59700a26122e16cfad1c8a036d77c9ce61f59f Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Wed, 12 Jul 2023 14:46:14 -0500 Subject: [PATCH 3/6] Fix typo from last commit --- .../src/System/Reflection/MethodBaseInvoker.Constructor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs index bc7a746c2dd48a..ef940c69e82ef4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs @@ -63,7 +63,7 @@ internal sealed partial class MethodBaseInvoker } finally { - RuntimeImports.RegisterForGCReporting(®ByRefStorage); + RuntimeImports.UnregisterForGCReporting(®ByRefStorage); RuntimeImports.UnregisterForGCReporting(®ArgStorage); } } From e7ddbae4927a9d489134dbaa6e4cc97e5ad7a949 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Fri, 14 Jul 2023 11:57:59 -0500 Subject: [PATCH 4/6] Remove RuntimeImports;misc naming+feedback; simplify invoker strategy --- .../System.Private.CoreLib.csproj | 1 - .../Reflection/Emit/DynamicMethod.CoreCLR.cs | 2 +- .../Reflection/MethodInvoker.CoreCLR.cs | 7 +- .../RuntimeConstructorInfo.CoreCLR.cs | 2 +- .../Reflection/RuntimeMethodInfo.CoreCLR.cs | 2 +- .../System/Runtime/RuntimeImports.CoreCLR.cs | 17 -- .../System/Reflection/DynamicInvokeInfo.cs | 40 ++-- .../src/System/RuntimeType.cs | 4 - src/coreclr/vm/appdomain.cpp | 2 +- src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/ecalllist.h | 12 +- .../System/Reflection/ConstructorInvoker.cs | 199 +++++++++-------- .../MethodBaseInvoker.Constructor.cs | 9 +- .../System/Reflection/MethodBaseInvoker.cs | 200 +++++++++--------- .../src/System/Reflection/MethodInvoker.cs | 181 ++++++++-------- .../System/Reflection/MethodInvokerCommon.cs | 45 +++- .../src/System/Runtime/GCFrameRegistration.cs | 34 +-- .../tests/MethodInvokerTests.cs | 2 +- .../System/Reflection/MethodInvoker.Mono.cs | 11 +- .../Reflection/RuntimeMethodInfo.Mono.cs | 2 +- .../Runtime/GCFrameRegistration.Mono.cs | 4 - 21 files changed, 384 insertions(+), 394 deletions(-) delete mode 100644 src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 728855bbdca964..f99a2842e7fcad 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -220,7 +220,6 @@ - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs index 91a35e6a63e92d..0a4ebb1c5140c8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs @@ -85,7 +85,7 @@ internal RuntimeMethodHandle GetMethodDescriptor() return new RuntimeMethodHandle(_methodHandle!); } - internal MethodBaseInvoker Invoker + private MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs index b4960da0d5871a..644364a77266e2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs @@ -9,20 +9,21 @@ public partial class MethodInvoker { private readonly Signature? _signature; - internal unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments) + private unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments) { _signature = method.Signature; _invokeFunc_RefArgs = InterpretedInvoke_Method; _invocationFlags = method.ComputeAndUpdateInvocationFlags(); } - internal unsafe MethodInvoker(DynamicMethod method) : this(method, method.Signature.Arguments) + private unsafe MethodInvoker(DynamicMethod method) : this(method, method.Signature.Arguments) { _signature = method.Signature; _invokeFunc_RefArgs = InterpretedInvoke_Method; + // No _invocationFlags for DynamicMethod. } - internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments) + private unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.Signature.Arguments) { _signature = constructor.Signature; _invokeFunc_RefArgs = InterpretedInvoke_Constructor; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs index ac0ad4886fad10..500581553a3cb1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs @@ -41,7 +41,7 @@ internal InvocationFlags InvocationFlags } } - internal MethodBaseInvoker Invoker + private MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index b3efa82dd7d191..1fd8da7fe5f66d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -40,7 +40,7 @@ internal InvocationFlags InvocationFlags } } - internal MethodBaseInvoker Invoker + private MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs deleted file mode 100644 index b9f5bac52651cf..00000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/RuntimeImports.CoreCLR.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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; -using System.Runtime.InteropServices; - -namespace System.Runtime -{ - internal static class RuntimeImports - { - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration); - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs index cbf407434c324a..2cda655a816d6a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs @@ -189,14 +189,7 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) int argCount = parameters?.Length ?? 0; if (argCount != _argumentCount) { - if (_argumentCount < 0) - { - if (_argumentCount == ArgumentCount_NotSupported_ByRefLike) - throw new NotSupportedException(SR.NotSupported_ByRefLike); - throw new NotSupportedException(); - } - - throw new TargetParameterCountException(SR.Arg_ParmCnt); + ThrowForArgCountMismatch(); } object? returnObject = null; @@ -264,14 +257,7 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) int argCount = parameters.Length; if (argCount != _argumentCount) { - if (_argumentCount < 0) - { - if (_argumentCount == ArgumentCount_NotSupported_ByRefLike) - throw new NotSupportedException(SR.NotSupported_ByRefLike); - throw new NotSupportedException(); - } - - throw new TargetParameterCountException(SR.Arg_ParmCnt); + ThrowForArgCountMismatch(); } object? returnObject = null; @@ -335,14 +321,7 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) if (argCount != _argumentCount) { - if (_argumentCount < 0) - { - if (_argumentCount == ArgumentCount_NotSupported_ByRefLike) - throw new NotSupportedException(SR.NotSupported_ByRefLike); - throw new NotSupportedException(); - } - - throw new TargetParameterCountException(SR.Arg_ParmCnt); + ThrowForArgCountMismatch(); } Debug.Assert(_argumentCount <= MaxStackAllocArgCount); @@ -405,6 +384,19 @@ public DynamicInvokeInfo(MethodBase method, IntPtr invokeThunk) ReturnTransform(ref ret, wrapInTargetInvocationException: false) : returnObject; } + private void ThrowForArgCountMismatch() + { + if (_argumentCount < 0) + { + if (_argumentCount == ArgumentCount_NotSupported_ByRefLike) + throw new NotSupportedException(SR.NotSupported_ByRefLike); + + throw new NotSupportedException(); + } + + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + private unsafe ref byte InvokeWithManyArguments( IntPtr methodToCall, ref byte thisArg, ref byte ret, object?[] parameters, BinderBundle binderBundle, bool wrapInTargetInvocationException) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs index 0cdf16439cae0d..3e3b72557b7fff 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs @@ -120,9 +120,5 @@ public sealed override Array GetEnumValuesAsUnderlyingType() internal bool IsActualEnum => TryGetEEType(out EETypePtr eeType) && eeType.IsEnum; - -#pragma warning disable IDE0060 - internal static object AllocateValueType(RuntimeType type, object? value) => throw new NotSupportedException(); -#pragma warning restore IDE0060 } } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 7081ae2d1beb12..5b13a735343a83 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1548,7 +1548,7 @@ bool SystemDomain::IsReflectionInvocationMethod(MethodDesc* pMeth) CLASS__DYNAMICMETHOD, CLASS__DELEGATE, CLASS__MULTICAST_DELEGATE, - CLASS__METHOD_INVOKERINTERNAL, + CLASS__METHODBASEINVOKER, }; static bool fInited = false; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 902c6e4f7e80f6..a70f07936ce5fe 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -492,7 +492,7 @@ DEFINE_CLASS(VECTORT, Numerics, Vector`1) DEFINE_CLASS(MEMBER, Reflection, MemberInfo) -DEFINE_CLASS(METHOD_INVOKERINTERNAL,Reflection, MethodBaseInvoker) +DEFINE_CLASS(METHODBASEINVOKER, Reflection, MethodBaseInvoker) DEFINE_CLASS_U(Reflection, RuntimeMethodInfo, NoClass) DEFINE_FIELD_U(m_handle, ReflectMethodObject, m_pMD) diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index b14f1b5df55b8f..39e9a3a44d1cd4 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -435,6 +435,11 @@ FCFuncStart(gBufferFuncs) FCFuncElement("__BulkMoveWithWriteBarrier", Buffer::BulkMoveWithWriteBarrier) FCFuncEnd() +FCFuncStart(gGCFrameRegistration) + FCFuncElement("RegisterForGCReporting", GCReporting::Register) + FCFuncElement("UnregisterForGCReporting", GCReporting::Unregister) +FCFuncEnd() + FCFuncStart(gGCInterfaceFuncs) FCFuncElement("GetGenerationWR", GCInterface::GetGenerationWR) FCFuncElement("_RegisterForFullGCNotification", GCInterface::RegisterForFullGCNotification) @@ -559,11 +564,6 @@ FCFuncStart(gRuntimeHelpers) FCFuncElement("Box", JIT_Box) FCFuncEnd() -FCFuncStart(gRuntimeImports) - FCFuncElement("RegisterForGCReporting", GCReporting::Register) - FCFuncElement("UnregisterForGCReporting", GCReporting::Unregister) -FCFuncEnd() - FCFuncStart(gMethodTableFuncs) FCFuncElement("GetNumInstanceFieldBytes", MethodTableNative::GetNumInstanceFieldBytes) FCFuncEnd() @@ -718,6 +718,7 @@ FCClassElement("Enum", "System", gEnumFuncs) FCClassElement("Environment", "System", gEnvironmentFuncs) FCClassElement("Exception", "System", gExceptionFuncs) FCClassElement("GC", "System", gGCInterfaceFuncs) +FCClassElement("GCFrameRegistration", "System.Runtime", gGCFrameRegistration) FCClassElement("GCHandle", "System.Runtime.InteropServices", gGCHandleFuncs) FCClassElement("GCSettings", "System.Runtime", gGCSettingsFuncs) #ifdef FEATURE_COMINTEROP @@ -752,7 +753,6 @@ FCClassElement("ObjectMarshaler", "System.StubHelpers", gObjectMarshalerFuncs) FCClassElement("RuntimeAssembly", "System.Reflection", gRuntimeAssemblyFuncs) FCClassElement("RuntimeFieldHandle", "System", gCOMFieldHandleNewFuncs) FCClassElement("RuntimeHelpers", "System.Runtime.CompilerServices", gRuntimeHelpers) -FCClassElement("RuntimeImports", "System.Runtime", gRuntimeImports) FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) FCClassElement("RuntimeType", "System", gSystem_RuntimeType) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs index 8614b81e750595..f728ac96d0f2e0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/ConstructorInvoker.cs @@ -7,6 +7,7 @@ using System.Runtime; using static System.Reflection.InvokerEmitUtil; using static System.Reflection.MethodBase; +using static System.Reflection.MethodInvokerCommon; namespace System.Reflection { @@ -42,7 +43,7 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg _argTypes = argumentTypes; _argCount = _argTypes.Length; - MethodInvokerCommon.Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); + Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); } public object? Invoke() => Invoke(null, null, null, null); @@ -56,6 +57,7 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg _method.ThrowNoInvokeException(); } + // Allow additional non-used arguments to simplify caller's logic. if (_argCount > MaxStackAllocArgCount) { MethodBaseInvoker.ThrowTargetParameterCountException(); @@ -77,25 +79,18 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg break; } + // Check fast path first. if (_invokeFunc_Obj4Args is not null) { - // Fast path. return _invokeFunc_Obj4Args(obj: null, arg1, arg2, arg3, arg4); } if ((_strategy & InvokerStrategy.StrategyDetermined_Obj4Args) == 0) { - if (_needsByRefStrategy) + DetermineStrategy_Obj4Args(ref _strategy, ref _invokeFunc_Obj4Args, _method, _needsByRefStrategy, backwardsCompat: false); + if (_invokeFunc_Obj4Args is not null) { - _strategy |= InvokerStrategy.StrategyDetermined_Obj4Args; - } - else - { - MethodInvokerCommon.DetermineInvokeStrategy_Obj4Args(ref _strategy, ref _invokeFunc_Obj4Args, _method, backwardsCompat: false); - if (_invokeFunc_Obj4Args is not null) - { - return _invokeFunc_Obj4Args(obj: null, arg1, arg2, arg3, arg4); - } + return _invokeFunc_Obj4Args(obj: null, arg1, arg2, arg3, arg4); } } @@ -104,6 +99,26 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg public object? Invoke(Span arguments) { + if (!_needsByRefStrategy) + { + // Switch to fast path if possible. + switch (_argCount) + { + case 0: + return Invoke(null, null, null, null); + case 1: + return Invoke(arguments[0], null, null, null); + case 2: + return Invoke(arguments[0], arguments[1], null, null); + case 3: + return Invoke(arguments[0], arguments[1], arguments[2], null); + case 4: + return Invoke(arguments[0], arguments[1], arguments[2], arguments[3]); + default: + break; + } + } + if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) { _method.ThrowNoInvokeException(); @@ -119,25 +134,7 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg return InvokeWithManyArgs(arguments); } - if (_needsByRefStrategy) - { - return InvokeWithFewArgs(arguments); - } - - switch (_argCount) - { - case 0: - return Invoke(null, null, null, null); - case 1: - return Invoke(arguments[0], null, null, null); - case 2: - return Invoke(arguments[0], arguments[1], null, null); - case 3: - return Invoke(arguments[0], arguments[1], arguments[2], null); - default: - Debug.Assert(_argCount == 4); - return Invoke(arguments[0], arguments[1], arguments[2], arguments[3]); - } + return InvokeWithFewArgs(arguments); } internal object? InvokeWithFewArgs(Span arguments) @@ -155,26 +152,19 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg copyOfArgs[i] = arg; } + // Check fast path first. if (_invokeFunc_ObjSpanArgs is not null) { - // Fast path. - return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); + return _invokeFunc_ObjSpanArgs(obj : null, copyOfArgs); // No need to call CopyBack here since there are no ref values. } if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if (_needsByRefStrategy) - { - _strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs; - } - else + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: false); + if (_invokeFunc_ObjSpanArgs is not null) { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); - if (_invokeFunc_ObjSpanArgs is not null) - { - return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); - } + return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); } } @@ -193,10 +183,10 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg { if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); } - scoped StackAllocatedByRefs byrefs = default; + StackAllocatedByRefs byrefs = default; #pragma warning disable CS8500 IntPtr* pByRefFixedStorage = (IntPtr*)&byrefs; #pragma warning restore CS8500 @@ -217,83 +207,84 @@ private ConstructorInvoker(RuntimeConstructorInfo constructor, RuntimeType[] arg { Span copyOfArgs; GCFrameRegistration regArgStorage; + object? ret; - if (!_needsByRefStrategy) + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if ((_strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) - { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); - } - - if (_invokeFunc_ObjSpanArgs is not null) - { - IntPtr* pArgStorage = stackalloc IntPtr[_argCount]; - NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr)); - copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); - regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: false); + } - try - { - RuntimeImports.RegisterForGCReporting(®ArgStorage); + if (_invokeFunc_ObjSpanArgs is not null) + { + IntPtr* pArgStorage = stackalloc IntPtr[_argCount]; + NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); + regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); - for (int i = 0; i < _argCount; i++) - { - object? arg = arguments[i]; - CheckArgument(ref arg, i); - copyOfArgs[i] = arg; - } + try + { + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); - return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); - // No need to call CopyBack here since there are no ref values. - } - finally + for (int i = 0; i < _argCount; i++) { - RuntimeImports.UnregisterForGCReporting(®ArgStorage); + object? arg = arguments[i]; + CheckArgument(ref arg, i); + copyOfArgs[i] = arg; } + + ret = _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); + // No need to call CopyBack here since there are no ref values. + } + finally + { + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); } } - - if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + else { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); - } + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + } - IntPtr* pStorage = stackalloc IntPtr[2 * _argCount]; - NativeMemory.Clear(pStorage, (nuint)(2 * _argCount) * (nuint)sizeof(IntPtr)); - copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); + IntPtr* pStorage = stackalloc IntPtr[2 * _argCount]; + NativeMemory.Clear(pStorage, (nuint)(2 * _argCount) * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); - IntPtr* pByRefStorage = pStorage + _argCount; - scoped Span shouldCopyBack = stackalloc bool[_argCount]; + IntPtr* pByRefStorage = pStorage + _argCount; + scoped Span shouldCopyBack = stackalloc bool[_argCount]; - regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); - GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); - try - { - RuntimeImports.RegisterForGCReporting(®ArgStorage); - RuntimeImports.RegisterForGCReporting(®ByRefStorage); + try + { + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); + GCFrameRegistration.RegisterForGCReporting(®ByRefStorage); - for (int i = 0; i < _argCount; i++) + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + shouldCopyBack[i] = CheckArgument(ref arg, i); + copyOfArgs[i] = arg; + #pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? + #pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + } + + ret = _invokeFunc_RefArgs!(obj: null, pByRefStorage); + CopyBack(arguments, copyOfArgs, shouldCopyBack); + } + finally { - object? arg = arguments[i]; - shouldCopyBack[i] = CheckArgument(ref arg, i); - copyOfArgs[i] = arg; -#pragma warning disable CS8500 - *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? -#pragma warning restore CS8500 - ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : - ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + GCFrameRegistration.UnregisterForGCReporting(®ByRefStorage); + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); } - - object? ret = _invokeFunc_RefArgs!(obj: null, pByRefStorage); - CopyBack(arguments, copyOfArgs, shouldCopyBack); - return ret; - } - finally - { - RuntimeImports.UnregisterForGCReporting(®ByRefStorage); - RuntimeImports.UnregisterForGCReporting(®ArgStorage); } + + return ret; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs index ef940c69e82ef4..2202fabfdc821b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Constructor.cs @@ -1,7 +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.Globalization; using System.Runtime; using System.Runtime.CompilerServices; @@ -34,8 +33,8 @@ internal sealed partial class MethodBaseInvoker try { - RuntimeImports.RegisterForGCReporting(®ArgStorage); - RuntimeImports.RegisterForGCReporting(®ByRefStorage); + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); + GCFrameRegistration.RegisterForGCReporting(®ByRefStorage); CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); @@ -63,8 +62,8 @@ internal sealed partial class MethodBaseInvoker } finally { - RuntimeImports.UnregisterForGCReporting(®ByRefStorage); - RuntimeImports.UnregisterForGCReporting(®ArgStorage); + GCFrameRegistration.UnregisterForGCReporting(®ByRefStorage); + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs index 0c5f18a947e1f6..d82b71886a72f7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs @@ -3,12 +3,13 @@ using System.Diagnostics.CodeAnalysis; using System.Diagnostics; +using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime; using static System.Reflection.InvokerEmitUtil; using static System.Reflection.MethodBase; -using System.Globalization; +using static System.Reflection.MethodInvokerCommon; namespace System.Reflection { @@ -32,7 +33,7 @@ private MethodBaseInvoker(MethodBase method, RuntimeType[] argumentTypes) _argTypes = argumentTypes; _argCount = _argTypes.Length; - MethodInvokerCommon.Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); + Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); } [DoesNotReturn] @@ -42,14 +43,13 @@ internal static void ThrowTargetParameterCountException() } - #region MethodBase APIs internal unsafe object? InvokeWithNoArgs(object? obj, BindingFlags invokeAttr) { Debug.Assert(_argCount == 0); if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); } try @@ -83,27 +83,24 @@ internal static void ThrowTargetParameterCountException() CheckArguments(parametersSpan, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); object? ret; - if (!_needsByRefStrategy) + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: true); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + try { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); } - - if (_invokeFunc_ObjSpanArgs is not null) + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) { - try - { - ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); - } - catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) - { - throw new TargetInvocationException(e); - } - - CopyBack(parameters, copyOfArgs, shouldCopyBack); - return ret; + throw new TargetInvocationException(e); } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; } ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr); @@ -127,27 +124,24 @@ internal static void ThrowTargetParameterCountException() CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); object? ret; - if (!_needsByRefStrategy) + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: true); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + try { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); } - - if (_invokeFunc_ObjSpanArgs is not null) + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) { - try - { - ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); - } - catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) - { - throw new TargetInvocationException(e); - } - - CopyBack(parameters, copyOfArgs, shouldCopyBack); - return ret; + throw new TargetInvocationException(e); } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); + return ret; } ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr); @@ -161,7 +155,7 @@ internal static void ThrowTargetParameterCountException() if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); } StackAllocatedByRefs byrefs = default; @@ -202,92 +196,91 @@ internal static void ThrowTargetParameterCountException() GCFrameRegistration regArgStorage; Span shouldCopyBack; - if (!_needsByRefStrategy) + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) - { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); - } + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: true); + } + + if (_invokeFunc_ObjSpanArgs is not null) + { + IntPtr* pArgStorage = stackalloc IntPtr[_argCount * 2]; + NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr) * 2); + copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); + regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); + shouldCopyBack = new Span(pArgStorage + _argCount, _argCount); - if (_invokeFunc_ObjSpanArgs is not null) + try { - IntPtr* pArgStorage = stackalloc IntPtr[_argCount * 2]; - NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr) * 2); - copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); - regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); - shouldCopyBack = new Span(pArgStorage + _argCount, _argCount); + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); + + CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); try { - RuntimeImports.RegisterForGCReporting(®ArgStorage); - - CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); - - try - { - ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); - } - catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) - { - throw new TargetInvocationException(e); - } - - CopyBack(parameters, copyOfArgs, shouldCopyBack); - return ret; + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); } - finally + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) { - RuntimeImports.UnregisterForGCReporting(®ArgStorage); + throw new TargetInvocationException(e); } - } - } - if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) - { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); + CopyBack(parameters, copyOfArgs, shouldCopyBack); + } + finally + { + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); + } } - - IntPtr* pStorage = stackalloc IntPtr[3 * _argCount]; - NativeMemory.Clear(pStorage, (nuint)(3 * _argCount) * (nuint)sizeof(IntPtr)); - copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); - regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); - IntPtr* pByRefStorage = pStorage + _argCount; - GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); - shouldCopyBack = new Span(pStorage + _argCount * 2, _argCount); - - try + else { - RuntimeImports.RegisterForGCReporting(®ArgStorage); - RuntimeImports.RegisterForGCReporting(®ByRefStorage); - - CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); - - for (int i = 0; i < _argCount; i++) + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) { -#pragma warning disable CS8500 - *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? -#pragma warning restore CS8500 - ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : - ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: true); } + IntPtr* pStorage = stackalloc IntPtr[3 * _argCount]; + NativeMemory.Clear(pStorage, (nuint)(3 * _argCount) * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); + regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); + IntPtr* pByRefStorage = pStorage + _argCount; + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + shouldCopyBack = new Span(pStorage + _argCount * 2, _argCount); + try { - ret = _invokeFunc_RefArgs!(obj, pByRefStorage); + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); + GCFrameRegistration.RegisterForGCReporting(®ByRefStorage); + + CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr); + + for (int i = 0; i < _argCount; i++) + { + #pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? + #pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + } + + try + { + ret = _invokeFunc_RefArgs!(obj, pByRefStorage); + } + catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + { + throw new TargetInvocationException(e); + } + + CopyBack(parameters, copyOfArgs, shouldCopyBack); } - catch (Exception e) when ((invokeAttr & BindingFlags.DoNotWrapExceptions) == 0) + finally { - throw new TargetInvocationException(e); + GCFrameRegistration.UnregisterForGCReporting(®ByRefStorage); + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); } - - CopyBack(parameters, copyOfArgs, shouldCopyBack); - return ret; - } - finally - { - RuntimeImports.UnregisterForGCReporting(®ByRefStorage); - RuntimeImports.UnregisterForGCReporting(®ArgStorage); } + + return ret; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -324,7 +317,7 @@ internal void InvokePropertySetter( if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { // Initialize for next time. - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: true); + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: true); } InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr); @@ -417,6 +410,5 @@ private static bool TryByRefFastPath(RuntimeType type, ref object arg) return false; } - #endregion } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs index 93f96a59ae8140..76483f646c53a1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvoker.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using static System.Reflection.InvokerEmitUtil; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime; -using static System.Reflection.MethodBase; using System.Reflection.Emit; +using static System.Reflection.InvokerEmitUtil; +using static System.Reflection.MethodBase; +using static System.Reflection.MethodInvokerCommon; namespace System.Reflection { @@ -56,7 +57,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) _argCount = _argTypes.Length; _isStatic = _method.IsStatic; - MethodInvokerCommon.Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); + Initialize(argumentTypes, out _strategy, out _invokerArgFlags, out _needsByRefStrategy); } public object? Invoke(object? obj) => Invoke(obj, null, null, null, null); @@ -67,9 +68,10 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) { if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) { - ((RuntimeMethodInfo)_method).ThrowNoInvokeException(); + ThrowForBadInvocationFlags(); } + // Allow additional non-used arguments to simplify caller's logic. if (_argCount > MaxStackAllocArgCount) { MethodBaseInvoker.ThrowTargetParameterCountException(); @@ -77,7 +79,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) if (!_isStatic) { - MethodInvokerCommon.ValidateInvokeTarget(obj, _method); + ValidateInvokeTarget(obj, _method); } switch (_argCount) @@ -96,25 +98,18 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) break; } + // Check fast path first. if (_invokeFunc_Obj4Args is not null) { - // Fast path. return _invokeFunc_Obj4Args(obj, arg1, arg2, arg3, arg4); } if ((_strategy & InvokerStrategy.StrategyDetermined_Obj4Args) == 0) { - if (_needsByRefStrategy) + DetermineStrategy_Obj4Args(ref _strategy, ref _invokeFunc_Obj4Args, _method, _needsByRefStrategy, backwardsCompat: false); + if (_invokeFunc_Obj4Args is not null) { - _strategy |= InvokerStrategy.StrategyDetermined_Obj4Args; - } - else - { - MethodInvokerCommon.DetermineInvokeStrategy_Obj4Args(ref _strategy, ref _invokeFunc_Obj4Args, _method, backwardsCompat: false); - if (_invokeFunc_Obj4Args is not null) - { - return _invokeFunc_Obj4Args(obj, arg1, arg2, arg3, arg4); - } + return _invokeFunc_Obj4Args(obj, arg1, arg2, arg3, arg4); } } @@ -125,6 +120,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) { if (!_needsByRefStrategy) { + // Switch to fast path if possible. switch (_argCount) { case 0: @@ -144,7 +140,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) if ((_invocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) { - ((RuntimeMethodInfo)_method).ThrowNoInvokeException(); + ThrowForBadInvocationFlags(); } if (arguments.Length != _argCount) @@ -154,7 +150,7 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) if (!_isStatic) { - MethodInvokerCommon.ValidateInvokeTarget(obj, _method); + ValidateInvokeTarget(obj, _method); } if (arguments.Length > MaxStackAllocArgCount) @@ -165,6 +161,17 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) return InvokeWithFewArgs(obj, arguments); } + private void ThrowForBadInvocationFlags() + { + if (_method is RuntimeMethodInfo rmi) + { + rmi.ThrowNoInvokeException(); + } + + Debug.Assert(_method is RuntimeConstructorInfo); + ((RuntimeConstructorInfo)_method).ThrowNoInvokeException(); + } + internal object? InvokeWithFewArgs(object? obj, Span arguments) { Debug.Assert(_argCount <= MaxStackAllocArgCount); @@ -180,26 +187,19 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) copyOfArgs[i] = arg; } + // Check fast path first. if (_invokeFunc_ObjSpanArgs is not null) { - // Fast path. return _invokeFunc_ObjSpanArgs(obj, copyOfArgs); // No need to call CopyBack here since there are no ref values. } if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if (_needsByRefStrategy) + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: false); + if (_invokeFunc_ObjSpanArgs is not null) { - _strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs; - } - else - { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); - if (_invokeFunc_ObjSpanArgs is not null) - { - return _invokeFunc_ObjSpanArgs(obj: null, copyOfArgs); - } + return _invokeFunc_ObjSpanArgs(obj, copyOfArgs); } } @@ -218,10 +218,10 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) { if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); } - scoped StackAllocatedByRefs byrefs = default; + StackAllocatedByRefs byrefs = default; #pragma warning disable CS8500 IntPtr* pByRefFixedStorage = (IntPtr*)&byrefs; #pragma warning restore CS8500 @@ -242,83 +242,84 @@ private MethodInvoker(MethodBase method, RuntimeType[] argumentTypes) { Span copyOfArgs; GCFrameRegistration regArgStorage; + object? ret; - if (!_needsByRefStrategy) + if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0) { - if ((_strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) - { - MethodInvokerCommon.DetermineInvokeStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, backwardsCompat: false); - } - - if (_invokeFunc_ObjSpanArgs is not null) - { - IntPtr* pArgStorage = stackalloc IntPtr[_argCount]; - NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr)); - copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); - regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); + DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: false); + } - try - { - RuntimeImports.RegisterForGCReporting(®ArgStorage); + if (_invokeFunc_ObjSpanArgs is not null) + { + IntPtr* pArgStorage = stackalloc IntPtr[_argCount]; + NativeMemory.Clear(pArgStorage, (nuint)_argCount * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pArgStorage), _argCount); + regArgStorage = new((void**)pArgStorage, (uint)_argCount, areByRefs: false); - for (int i = 0; i < _argCount; i++) - { - object? arg = arguments[i]; - CheckArgument(ref arg, i); - copyOfArgs[i] = arg; - } + try + { + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); - return _invokeFunc_ObjSpanArgs(obj, copyOfArgs); - // No need to call CopyBack here since there are no ref values. - } - finally + for (int i = 0; i < _argCount; i++) { - RuntimeImports.UnregisterForGCReporting(®ArgStorage); + object? arg = arguments[i]; + CheckArgument(ref arg, i); + copyOfArgs[i] = arg; } + + ret = _invokeFunc_ObjSpanArgs(obj, copyOfArgs); + // No need to call CopyBack here since there are no ref values. + } + finally + { + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); } } - - if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + else { - MethodInvokerCommon.DetermineInvokeStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); - } + if ((_strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0) + { + DetermineStrategy_RefArgs(ref _strategy, ref _invokeFunc_RefArgs, _method, backwardsCompat: false); + } - IntPtr* pStorage = stackalloc IntPtr[2 * _argCount]; - NativeMemory.Clear(pStorage, (nuint)(2 * _argCount) * (nuint)sizeof(IntPtr)); - copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); + IntPtr* pStorage = stackalloc IntPtr[2 * _argCount]; + NativeMemory.Clear(pStorage, (nuint)(2 * _argCount) * (nuint)sizeof(IntPtr)); + copyOfArgs = new(ref Unsafe.AsRef(pStorage), _argCount); - IntPtr* pByRefStorage = pStorage + _argCount; - scoped Span shouldCopyBack = stackalloc bool[_argCount]; + IntPtr* pByRefStorage = pStorage + _argCount; + scoped Span shouldCopyBack = stackalloc bool[_argCount]; - regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); - GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); + regArgStorage = new((void**)pStorage, (uint)_argCount, areByRefs: false); + GCFrameRegistration regByRefStorage = new((void**)pByRefStorage, (uint)_argCount, areByRefs: true); - try - { - RuntimeImports.RegisterForGCReporting(®ArgStorage); - RuntimeImports.RegisterForGCReporting(®ByRefStorage); + try + { + GCFrameRegistration.RegisterForGCReporting(®ArgStorage); + GCFrameRegistration.RegisterForGCReporting(®ByRefStorage); - for (int i = 0; i < _argCount; i++) + for (int i = 0; i < _argCount; i++) + { + object? arg = arguments[i]; + shouldCopyBack[i] = CheckArgument(ref arg, i); + copyOfArgs[i] = arg; + #pragma warning disable CS8500 + *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? + #pragma warning restore CS8500 + ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : + ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + } + + ret = _invokeFunc_RefArgs!(obj, pByRefStorage); + CopyBack(arguments, copyOfArgs, shouldCopyBack); + } + finally { - object? arg = arguments[i]; - shouldCopyBack[i] = CheckArgument(ref arg, i); - copyOfArgs[i] = arg; -#pragma warning disable CS8500 - *(ByReference*)(pByRefStorage + i) = (_invokerArgFlags[i] & InvokerArgFlags.IsValueType) != 0 ? -#pragma warning restore CS8500 - ByReference.Create(ref Unsafe.AsRef(pStorage + i).GetRawData()) : - ByReference.Create(ref Unsafe.AsRef(pStorage + i)); + GCFrameRegistration.UnregisterForGCReporting(®ByRefStorage); + GCFrameRegistration.UnregisterForGCReporting(®ArgStorage); } - - object? ret = _invokeFunc_RefArgs!(obj, pByRefStorage); - CopyBack(arguments, copyOfArgs, shouldCopyBack); - return ret; - } - finally - { - RuntimeImports.UnregisterForGCReporting(®ByRefStorage); - RuntimeImports.UnregisterForGCReporting(®ArgStorage); } + + return ret; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs index 0b91a491eae33d..27841260be8641 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using static System.Reflection.InvokerEmitUtil; +using System.Diagnostics; using System.Runtime.CompilerServices; +using static System.Reflection.InvokerEmitUtil; using static System.Reflection.MethodBase; -using System.Diagnostics; namespace System.Reflection { @@ -87,9 +87,22 @@ internal static void ValidateInvokeTarget(object? target, MethodBase method) } } - internal static void DetermineInvokeStrategy_ObjSpanArgs(ref InvokerStrategy strategy, ref InvokeFunc_ObjSpanArgs? invokeFunc_ObjSpanArgs, MethodBase method, bool backwardsCompat) + internal static void DetermineStrategy_ObjSpanArgs( + ref InvokerStrategy strategy, + ref InvokeFunc_ObjSpanArgs? + invokeFunc_ObjSpanArgs, + MethodBase method, + bool needsByRefStrategy, + bool backwardsCompat) { - if ((strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) + Debug.Assert((strategy &= InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0); + + if (needsByRefStrategy) + { + // If ByRefs are used, we can't use this strategy. + strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs; + } + else if ((strategy & InvokerStrategy.HasBeenInvoked_ObjSpanArgs) == 0) { // The first time, ignoring race conditions, use the slow path. strategy |= InvokerStrategy.HasBeenInvoked_ObjSpanArgs; @@ -106,9 +119,21 @@ internal static void DetermineInvokeStrategy_ObjSpanArgs(ref InvokerStrategy str } } - internal static void DetermineInvokeStrategy_Obj4Args(ref InvokerStrategy strategy, ref InvokeFunc_Obj4Args? invokeFunc_Obj4Args, MethodBase method, bool backwardsCompat) + internal static void DetermineStrategy_Obj4Args( + ref InvokerStrategy strategy, + ref InvokeFunc_Obj4Args? invokeFunc_Obj4Args, + MethodBase method, + bool needsByRefStrategy, + bool backwardsCompat) { - if ((strategy & InvokerStrategy.HasBeenInvoked_Obj4Args) == 0) + Debug.Assert((strategy &= InvokerStrategy.StrategyDetermined_Obj4Args) == 0); + + if (needsByRefStrategy) + { + // If ByRefs are used, we can't use this strategy. + strategy |= InvokerStrategy.StrategyDetermined_Obj4Args; + } + else if ((strategy & InvokerStrategy.HasBeenInvoked_Obj4Args) == 0) { // The first time, ignoring race conditions, use the slow path. strategy |= InvokerStrategy.HasBeenInvoked_Obj4Args; @@ -125,8 +150,14 @@ internal static void DetermineInvokeStrategy_Obj4Args(ref InvokerStrategy strate } } - internal static void DetermineInvokeStrategy_RefArgs(ref InvokerStrategy strategy, ref InvokeFunc_RefArgs? invokeFunc_RefArgs, MethodBase method, bool backwardsCompat) + internal static void DetermineStrategy_RefArgs( + ref InvokerStrategy strategy, + ref InvokeFunc_RefArgs? invokeFunc_RefArgs, + MethodBase method, + bool backwardsCompat) { + Debug.Assert((strategy &= InvokerStrategy.StrategyDetermined_RefArgs) == 0); + if ((strategy & InvokerStrategy.HasBeenInvoked_RefArgs) == 0) { // The first time, ignoring race conditions, use the slow path. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs index 4afbda34a119bb..28e2e8db76a945 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.cs @@ -1,27 +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.Runtime.Loader; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Runtime { -#pragma warning disable 0414, IDE0044 + [StructLayout(LayoutKind.Sequential)] internal unsafe struct GCFrameRegistration { - private nuint m_reserved1; - private nuint m_reserved2; - private void** m_pObjRefs; - private uint m_numObjRefs; - private int m_MaybeInterior; + private nuint _reserved1; + private nuint _reserved2; + private void** _pObjRefs; + private uint _numObjRefs; + private int _maybeInterior; public GCFrameRegistration(void** allocation, uint elemCount, bool areByRefs = true) { - m_reserved1 = 0; - m_reserved2 = 0; - m_pObjRefs = allocation; - m_numObjRefs = elemCount; - m_MaybeInterior = areByRefs ? 1 : 0; + _reserved1 = 0; + _reserved2 = 0; + _pObjRefs = allocation; + _numObjRefs = elemCount; + _maybeInterior = areByRefs ? 1 : 0; } + +#if CORECLR + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration); +#endif } -#pragma warning restore 0414, IDE0044 } diff --git a/src/libraries/System.Reflection/tests/MethodInvokerTests.cs b/src/libraries/System.Reflection/tests/MethodInvokerTests.cs index 9c28247658bdc3..0eb20799d2cb7c 100644 --- a/src/libraries/System.Reflection/tests/MethodInvokerTests.cs +++ b/src/libraries/System.Reflection/tests/MethodInvokerTests.cs @@ -116,7 +116,7 @@ public void ArgumentConversions(Type methodDeclaringType, string methodName, obj { MethodInvoker invoker = MethodInvoker.Create(GetMethod(methodDeclaringType, methodName)); - // Since Type.Missing is not supported, and Span requires an object-back array, adapt the input. + // Adapt the input since Type.Missing is not supported, and Span requires an object[] array (e.g. not string[]). if (parameters is null) { Assert.Equal(result, invoker.Invoke(obj, new Span())); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs index 5e5fb10412905b..1b20c8bdf76fd6 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/MethodInvoker.Mono.cs @@ -7,21 +7,22 @@ namespace System.Reflection { public partial class MethodInvoker { - internal unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.ArgumentTypes) + private unsafe MethodInvoker(RuntimeMethodInfo method) : this(method, method.ArgumentTypes) { - _invocationFlags = method.ComputeAndUpdateInvocationFlags(); _invokeFunc_RefArgs = InterpretedInvoke_Method; + _invocationFlags = method.ComputeAndUpdateInvocationFlags(); } - internal unsafe MethodInvoker(DynamicMethod method) : this(method.GetRuntimeMethodInfo(), method.ArgumentTypes) + private unsafe MethodInvoker(DynamicMethod method) : this(method.GetRuntimeMethodInfo(), method.ArgumentTypes) { _invokeFunc_RefArgs = InterpretedInvoke_Method; + // No _invocationFlags for DynamicMethod. } - internal unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.ArgumentTypes) + private unsafe MethodInvoker(RuntimeConstructorInfo constructor) : this(constructor, constructor.ArgumentTypes) { - _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); _invokeFunc_RefArgs = InterpretedInvoke_Constructor; + _invocationFlags = constructor.ComputeAndUpdateInvocationFlags(); } private unsafe object? InterpretedInvoke_Method(object? obj, IntPtr *args) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs index a71acd1281d795..20a20b2eefc3bc 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs @@ -163,7 +163,7 @@ internal InvocationFlags InvocationFlags } } - internal MethodBaseInvoker Invoker + private MethodBaseInvoker Invoker { [MethodImpl(MethodImplOptions.AggressiveInlining)] get diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs index ce630ef50ea31d..dd19ffa6a8df3e 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/GCFrameRegistration.Mono.cs @@ -14,13 +14,9 @@ public GCFrameRegistration(void* allocation, uint elemCount, bool areByRefs = tr { } #pragma warning restore IDE0060 - } - internal static partial class RuntimeImports - { [Conditional("unnecessary")] internal static unsafe void RegisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } - [Conditional("unnecessary")] internal static unsafe void UnregisterForGCReporting(GCFrameRegistration* pRegistration) { /* nop */ } } From 8df6338547365a0bc116e6e2875f957219511d33 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Fri, 14 Jul 2023 14:48:39 -0500 Subject: [PATCH 5/6] Fix typo on debug build --- .../Common/tests/System/Reflection/InvokeEmitTests.cs | 4 ++-- .../src/System/Reflection/MethodInvokerCommon.cs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs b/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs index c0c07b46defaaf..149be11a982597 100644 --- a/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs +++ b/src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Tests { public class InvokeEmitTests { - [ConditionalFact(typeof(InvokeEmitTests), nameof(InvokeEmitTests.IsEmitInvokeSupported))] + [ConditionalFact(typeof(InvokeEmitTests), nameof(IsEmitInvokeSupported))] public static void VerifyInvokeIsUsingEmit_Method() { MethodInfo method = typeof(TestClassThatThrows).GetMethod(nameof(TestClassThatThrows.Throw))!; @@ -20,7 +20,7 @@ public static void VerifyInvokeIsUsingEmit_Method() Assert.DoesNotContain("InterpretedInvoke_Method", exInner.ToString()); } - [ConditionalFact(typeof(InvokeEmitTests), nameof(InvokeEmitTests.IsEmitInvokeSupported))] + [ConditionalFact(typeof(InvokeEmitTests), nameof(IsEmitInvokeSupported))] public static void VerifyInvokeIsUsingEmit_Constructor() { ConstructorInfo ctor = typeof(TestClassThatThrows).GetConstructor(Type.EmptyTypes)!; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs index 27841260be8641..eb55c5f194788a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs @@ -95,7 +95,7 @@ ref InvokeFunc_ObjSpanArgs? bool needsByRefStrategy, bool backwardsCompat) { - Debug.Assert((strategy &= InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0); + Debug.Assert((strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0); if (needsByRefStrategy) { @@ -126,7 +126,7 @@ internal static void DetermineStrategy_Obj4Args( bool needsByRefStrategy, bool backwardsCompat) { - Debug.Assert((strategy &= InvokerStrategy.StrategyDetermined_Obj4Args) == 0); + Debug.Assert((strategy & InvokerStrategy.StrategyDetermined_Obj4Args) == 0); if (needsByRefStrategy) { @@ -156,7 +156,7 @@ internal static void DetermineStrategy_RefArgs( MethodBase method, bool backwardsCompat) { - Debug.Assert((strategy &= InvokerStrategy.StrategyDetermined_RefArgs) == 0); + Debug.Assert((strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0); if ((strategy & InvokerStrategy.HasBeenInvoked_RefArgs) == 0) { @@ -169,6 +169,7 @@ internal static void DetermineStrategy_RefArgs( { invokeFunc_RefArgs = CreateInvokeDelegate_RefArgs(method, backwardsCompat); } + strategy |= InvokerStrategy.StrategyDetermined_RefArgs; } } From 7849619830eaad139dbb173008f59e4d7a61c665 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Fri, 14 Jul 2023 17:12:53 -0500 Subject: [PATCH 6/6] Remove newly added Asserts which can fail with multiple threads --- .../src/System/Reflection/MethodInvokerCommon.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs index eb55c5f194788a..b21900ad00b271 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodInvokerCommon.cs @@ -95,8 +95,6 @@ ref InvokeFunc_ObjSpanArgs? bool needsByRefStrategy, bool backwardsCompat) { - Debug.Assert((strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0); - if (needsByRefStrategy) { // If ByRefs are used, we can't use this strategy. @@ -126,8 +124,6 @@ internal static void DetermineStrategy_Obj4Args( bool needsByRefStrategy, bool backwardsCompat) { - Debug.Assert((strategy & InvokerStrategy.StrategyDetermined_Obj4Args) == 0); - if (needsByRefStrategy) { // If ByRefs are used, we can't use this strategy. @@ -156,8 +152,6 @@ internal static void DetermineStrategy_RefArgs( MethodBase method, bool backwardsCompat) { - Debug.Assert((strategy & InvokerStrategy.StrategyDetermined_RefArgs) == 0); - if ((strategy & InvokerStrategy.HasBeenInvoked_RefArgs) == 0) { // The first time, ignoring race conditions, use the slow path.