From 345b5a7bf78c1a8a31aca0c1bfd7e2d4a81ad2f1 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 14:43:29 -0700 Subject: [PATCH 01/16] Updates to libraries/ --- .../System.Private.CoreLib.Shared.projitems | 3 + .../src/System/Reflection/INVOCATION_FLAGS.cs | 0 .../src/System/Reflection/MethodBase.cs | 73 ++++++- .../Reflection/RuntimeConstructorInfo.cs | 180 ++++++++++++++++++ .../System/Reflection/RuntimeMethodInfo.cs | 128 +++++++++++++ 5 files changed, 383 insertions(+), 1 deletion(-) rename src/{coreclr => libraries}/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs (100%) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs 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 867e13262ba6a3..dd2da7fb826898 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 @@ -603,6 +603,7 @@ + @@ -635,7 +636,9 @@ + + diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs rename to src/libraries/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs 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 4db2c19e3b23c7..d14d3339b05e11 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs @@ -1,11 +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.Globalization; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; +using Internal.Runtime.CompilerServices; namespace System.Reflection { @@ -120,5 +122,74 @@ internal static void AppendParameters(ref ValueStringBuilder sbParamList, Type[] sbParamList.Append("..."); } } + + private protected void ValidateInvokeTarget(object? target) + { + // Confirm member invocation has an instance and is of the correct type + if (!IsStatic) + { + if (target == null) + { + throw new TargetException(SR.RFLCT_Targ_StatMethReqTarg); + } + + if (!DeclaringType!.IsInstanceOfType(target)) + { + throw new TargetException(SR.RFLCT_Targ_ITargMismatch); + } + } + } + + private protected Span CheckArguments(ref StackAllocedArguments stackArgs, ReadOnlySpan parameters, Binder? binder, + BindingFlags invokeAttr, CultureInfo? culture, RuntimeType[] sigTypes) + { + Debug.Assert(Unsafe.SizeOf() == StackAllocedArguments.MaxStackAllocArgCount * Unsafe.SizeOf(), + "MaxStackAllocArgCount not properly defined."); + Debug.Assert(!parameters.IsEmpty); + + // 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. + + Span copyOfParameters = (parameters.Length <= StackAllocedArguments.MaxStackAllocArgCount) + ? MemoryMarshal.CreateSpan(ref stackArgs._arg0, parameters.Length) + : new Span(new object?[parameters.Length]); + + ParameterInfo[]? p = null; + for (int i = 0; i < parameters.Length; i++) + { + object? arg = parameters[i]; + RuntimeType argRT = sigTypes[i]; + + if (arg == Type.Missing) + { + p ??= GetParametersNoCopy(); + if (p[i].DefaultValue == System.DBNull.Value) + throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters)); + arg = p[i].DefaultValue!; + } + copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr); + } + + return copyOfParameters; + } + + // Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack. + // Typical usage is to define a local of type default(StackAllocedArguments), then pass 'ref theLocal' + // as the first parameter to CheckArguments. CheckArguments will try to utilize storage within this + // struct instance if there's sufficient space; otherwise CheckArguments will allocate a temp array. + private protected struct StackAllocedArguments + { + internal const int MaxStackAllocArgCount = 4; + internal object? _arg0; +#pragma warning disable CA1823, CS0169, IDE0051 // accessed via 'CheckArguments' ref arithmetic + private object? _arg1; + private object? _arg2; + private object? _arg3; +#pragma warning restore CA1823, CS0169, IDE0051 + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs new file mode 100644 index 00000000000000..f0b7265e4298b8 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -0,0 +1,180 @@ +// 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.CompilerServices; + +namespace System.Reflection +{ + internal sealed partial class RuntimeConstructorInfo : ConstructorInfo + { + [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path + private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(ConstructorInfo constructorInfo, ref INVOCATION_FLAGS flagsToUpdate) + { + INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR; // this is a given + + Type? declaringType = constructorInfo.DeclaringType; + + if (declaringType == typeof(void) + || declaringType != null && declaringType.ContainsGenericParameters // Enclosing type has unbound generics + || (constructorInfo.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs + ) + { + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + } + else if (constructorInfo.IsStatic) + { + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR | + INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE; + } + else if (declaringType != null && declaringType.IsAbstract) + { + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE; + } + else + { + // Check for byref-like types + if (declaringType != null && declaringType.IsByRefLike) + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; + + // Check for attempt to create a delegate class. + if (typeof(Delegate).IsAssignableFrom(constructorInfo.DeclaringType)) + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR; + } + + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; + flagsToUpdate = invocationFlags; // accesses are guaranteed atomic + return invocationFlags; + } + + internal static void CheckCanCreateInstance(Type declaringType, bool isVarArg) + { + if (declaringType == null) + throw new ArgumentNullException(nameof(declaringType)); + + // ctor is declared on interface class + if (declaringType.IsInterface) + throw new MemberAccessException( + SR.Format(SR.Acc_CreateInterfaceEx, declaringType)); + + // ctor is on an abstract class + else if (declaringType.IsAbstract) + throw new MemberAccessException( + SR.Format(SR.Acc_CreateAbstEx, declaringType)); + + // ctor is on a class that contains stack pointers + else if (declaringType.GetRootElementType() == typeof(ArgIterator)) + throw new NotSupportedException(); + + // ctor is vararg + else if (isVarArg) + throw new NotSupportedException(); + + // ctor is generic or on a generic class + else if (declaringType.ContainsGenericParameters) + { + throw new MemberAccessException( + SR.Format(SR.Acc_CreateGenericEx, declaringType)); + } + + // ctor is declared on System.Void + else if (declaringType == typeof(void)) + throw new MemberAccessException(SR.Access_Void); + } + + [DoesNotReturn] + internal void ThrowNoInvokeException() + { + CheckCanCreateInstance(DeclaringType!, (CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs); + + // ctor is .cctor + if ((Attributes & MethodAttributes.Static) == MethodAttributes.Static) + throw new MemberAccessException(SR.Acc_NotClassInit); + + throw new TargetException(); + } + + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2059:RunClassConstructor", + Justification = "This ConstructorInfo instance represents the static constructor itself, so if this object was created, the static constructor exists.")] + public override object? Invoke( + object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + { + if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0) + ThrowNoInvokeException(); + + ValidateInvokeTarget(obj); + + if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR) != 0) + { + // Run the class constructor through the class constructor mechanism instead of the Invoke path. + // This avoids allowing mutation of readonly static fields, and initializes the type correctly. + return InvokeClassConstructor(); + } + + // Correct number of arguments supplied + int actualCount = (parameters is null) ? 0 : parameters.Length; + if (ArgumentTypes.Length != actualCount) + { + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + StackAllocedArguments stackArgs = default; + Span arguments = default; + if (actualCount != 0) + { + arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, ArgumentTypes); + } + + object? retValue = InvokeWorker(obj, invokeAttr, arguments); + + // copy out. This should be made only if ByRef are present. + // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[]) + for (int index = 0; index < arguments.Length; index++) + { + parameters![index] = arguments[index]; + } + + return retValue; + } + + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + { + if ((InvocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS | INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE)) != 0) + { + ThrowNoInvokeException(); + } + + // We don't need to explicitly invoke the class constructor here, + // JIT will insert the call to .cctor in the instance ctor. + + // Correct number of arguments supplied + int actualCount = (parameters is null) ? 0 : parameters.Length; + if (ArgumentTypes.Length != actualCount) + { + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + StackAllocedArguments stackArgs = default; + Span arguments = default; + if (actualCount != 0) + { + arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, ArgumentTypes); + } + + object retValue = InvokeCtorWorker(invokeAttr, arguments); + + // copy out. This should be made only if ByRef are present. + // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[]) + for (int index = 0; index < arguments.Length; index++) + parameters![index] = arguments[index]; + + return retValue; + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs new file mode 100644 index 00000000000000..f5783afad9b54d --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -0,0 +1,128 @@ +// 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.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.CompilerServices; + +namespace System.Reflection +{ + internal sealed partial class RuntimeMethodInfo : MethodInfo + { + [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path + private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(MethodInfo methodInfo, ref INVOCATION_FLAGS flagsToUpdate) + { + INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN; + + Type? declaringType = methodInfo.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 + ) + { + invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + } + else if (declaringType != null) + { + if (declaringType.ContainsGenericParameters) // Enclosing type has unbound generics + { + invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + } + else if (declaringType.IsByRefLike) // Check for byref-like types + { + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; + } + } + + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; + flagsToUpdate = invocationFlags; // accesses are guaranteed atomic + return invocationFlags; + + static bool IsDisallowedByRefType(Type type) + { + if (!type.IsByRef) + return false; + + Type elementType = type.GetElementType()!; + return elementType.IsByRefLike || elementType == typeof(void); + } + } + + [DoesNotReturn] + private void ThrowNoInvokeException() + { + // method is on a class that contains stack pointers + if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS) != 0) + { + throw new NotSupportedException(); + } + // method is vararg + else if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) + { + throw new NotSupportedException(); + } + // method is generic or on a generic class + else if (DeclaringType!.ContainsGenericParameters || ContainsGenericParameters) + { + throw new InvalidOperationException(SR.Arg_UnboundGenParam); + } + // method is abstract class + else if (IsAbstract) + { + throw new MemberAccessException(); + } + else if (ReturnType.IsByRef) + { + Type elementType = ReturnType.GetElementType()!; + if (elementType.IsByRefLike) + throw new NotSupportedException(SR.NotSupported_ByRefToByRefLikeReturn); + if (elementType == typeof(void)) + throw new NotSupportedException(SR.NotSupported_ByRefToVoidReturn); + } + + throw new TargetException(); + } + + [DebuggerStepThroughAttribute] + [Diagnostics.DebuggerHidden] + public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + { + // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS 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 + // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects. + if ((InvocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0) + { + ThrowNoInvokeException(); + } + + ValidateInvokeTarget(obj); + + // Correct number of arguments supplied + int actualCount = (parameters is null) ? 0 : parameters.Length; + if (ArgumentTypes.Length != actualCount) + { + throw new TargetParameterCountException(SR.Arg_ParmCnt); + } + + StackAllocedArguments stackArgs = default; // try to avoid intermediate array allocation if possible + Span arguments = default; + if (actualCount != 0) + { + arguments = CheckArguments(ref stackArgs, parameters!, binder, invokeAttr, culture, ArgumentTypes); + } + + object? retValue = InvokeWorker(obj, invokeAttr, arguments); + + // copy out. This should be made only if ByRef are present. + // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[]) + for (int index = 0; index < arguments.Length; index++) + { + parameters![index] = arguments[index]; + } + + return retValue; + } + } +} \ No newline at end of file From 29789d21bd5527776bb9bc9503302225d3627a34 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 14:43:55 -0700 Subject: [PATCH 02/16] Updates to coreclr/ --- .../System.Private.CoreLib.csproj | 1 - .../System/Reflection/Emit/DynamicMethod.cs | 2 +- .../System/Reflection/MethodBase.CoreCLR.cs | 52 ----- .../Reflection/RuntimeConstructorInfo.cs | 211 ++---------------- .../System/Reflection/RuntimeMethodInfo.cs | 132 +---------- 5 files changed, 28 insertions(+), 370 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 727ed12604990b..5114c10ee714bd 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -176,7 +176,6 @@ - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 8b6a412abed329..0e4741ea643d03 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -463,7 +463,7 @@ internal RuntimeMethodHandle GetMethodDescriptor() Span arguments = default; if (actualCount != 0) { - arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig); + arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig.Arguments); } object? retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false, wrapExceptions); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs index 89829cba3479e5..ef988b742a88ec 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs @@ -66,58 +66,6 @@ internal virtual Type[] GetParameterTypes() return parameterTypes; } - - private protected Span CheckArguments(ref StackAllocedArguments stackArgs, ReadOnlySpan parameters, Binder? binder, - BindingFlags invokeAttr, CultureInfo? culture, Signature sig) - { - Debug.Assert(Unsafe.SizeOf() == StackAllocedArguments.MaxStackAllocArgCount * Unsafe.SizeOf(), - "MaxStackAllocArgCount not properly defined."); - Debug.Assert(!parameters.IsEmpty); - - // 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. - - Span copyOfParameters = (parameters.Length <= StackAllocedArguments.MaxStackAllocArgCount) - ? MemoryMarshal.CreateSpan(ref stackArgs._arg0, parameters.Length) - : new Span(new object?[parameters.Length]); - - ParameterInfo[]? p = null; - for (int i = 0; i < parameters.Length; i++) - { - object? arg = parameters[i]; - RuntimeType argRT = sig.Arguments[i]; - - if (arg == Type.Missing) - { - p ??= GetParametersNoCopy(); - if (p[i].DefaultValue == System.DBNull.Value) - throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters)); - arg = p[i].DefaultValue!; - } - copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr); - } - - return copyOfParameters; - } - - // Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack. - // Typical usage is to define a local of type default(StackAllocedArguments), then pass 'ref theLocal' - // as the first parameter to CheckArguments. CheckArguments will try to utilize storage within this - // struct instance if there's sufficient space; otherwise CheckArguments will allocate a temp array. - private protected struct StackAllocedArguments - { - internal const int MaxStackAllocArgCount = 4; - internal object? _arg0; -#pragma warning disable CA1823, CS0169, IDE0051 // accessed via 'CheckArguments' ref arithmetic - private object? _arg1; - private object? _arg2; - private object? _arg3; -#pragma warning restore CA1823, CS0169, IDE0051 - } #endregion } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index a930e0964a895e..e03fc2748ba63c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -12,7 +12,7 @@ namespace System.Reflection { - internal sealed class RuntimeConstructorInfo : ConstructorInfo, IRuntimeMethodInfo + internal sealed partial class RuntimeConstructorInfo : ConstructorInfo, IRuntimeMethodInfo { #region Private Data Members private volatile RuntimeType m_declaringType; @@ -35,51 +35,10 @@ internal INVOCATION_FLAGS InvocationFlags [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path - INVOCATION_FLAGS LazyCreateInvocationFlags() - { - INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR; // this is a given - - Type? declaringType = DeclaringType; - - // - // first take care of all the NO_INVOKE cases. - if (declaringType == typeof(void) || - (declaringType != null && declaringType.ContainsGenericParameters) || - ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)) - { - // We don't need other flags if this method cannot be invoked - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; - } - else if (IsStatic) - { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR | - INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE; - } - else if (declaringType != null && declaringType.IsAbstract) - { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE; - } - else - { - // Check for byref-like types - if (declaringType != null && declaringType.IsByRefLike) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; - - // Check for attempt to create a delegate class. - if (typeof(Delegate).IsAssignableFrom(DeclaringType)) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR; - } - - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; - m_invocationFlags = invocationFlags; // accesses are guaranteed atomic - return invocationFlags; - } - INVOCATION_FLAGS flags = m_invocationFlags; if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) { - flags = LazyCreateInvocationFlags(); + flags = ComputeAndUpdateInvocationFlags(this, ref m_invocationFlags); } return flags; } @@ -124,20 +83,6 @@ Signature LazyCreateSignature() private RuntimeType ReflectedTypeInternal => m_reflectedTypeCache.GetRuntimeType(); - private void CheckConsistency(object? target) - { - if (target == null && IsStatic) - return; - - if (!m_declaringType.IsInstanceOfType(target)) - { - if (target == null) - throw new TargetException(SR.RFLCT_Targ_StatMethReqTarg); - - throw new TargetException(SR.RFLCT_Targ_ITargMismatch); - } - } - internal BindingFlags BindingFlags => m_bindingFlags; #endregion @@ -247,109 +192,33 @@ public override MethodImplAttributes GetMethodImplementationFlags() public override CallingConventions CallingConvention => Signature.CallingConvention; - internal static void CheckCanCreateInstance(Type declaringType, bool isVarArg) - { - if (declaringType == null) - throw new ArgumentNullException(nameof(declaringType)); - - // ctor is declared on interface class - if (declaringType.IsInterface) - throw new MemberAccessException( - SR.Format(SR.Acc_CreateInterfaceEx, declaringType)); - - // ctor is on an abstract class - else if (declaringType.IsAbstract) - throw new MemberAccessException( - SR.Format(SR.Acc_CreateAbstEx, declaringType)); - - // ctor is on a class that contains stack pointers - else if (declaringType.GetRootElementType() == typeof(ArgIterator)) - throw new NotSupportedException(); + private RuntimeType[] ArgumentTypes => Signature.Arguments; - // ctor is vararg - else if (isVarArg) - throw new NotSupportedException(); + private object? InvokeClassConstructor() + { + Debug.Assert((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR) != 0); + var declaringType = DeclaringType; - // ctor is generic or on a generic class - else if (declaringType.ContainsGenericParameters) - { - throw new MemberAccessException( - SR.Format(SR.Acc_CreateGenericEx, declaringType)); - } + if (declaringType != null) + RuntimeHelpers.RunClassConstructor(declaringType.TypeHandle); + else + RuntimeHelpers.RunModuleConstructor(Module.ModuleHandle); - // ctor is declared on System.Void - else if (declaringType == typeof(void)) - throw new MemberAccessException(SR.Access_Void); + return null; } - [DoesNotReturn] - internal void ThrowNoInvokeException() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span arguments) { - CheckCanCreateInstance(DeclaringType!, (CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs); - - // ctor is .cctor - if ((Attributes & MethodAttributes.Static) == MethodAttributes.Static) - throw new MemberAccessException(SR.Acc_NotClassInit); - - throw new TargetException(); + bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; + return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions); } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2059:RunClassConstructor", - Justification = "This ConstructorInfo instance represents the static constructor itself, so if this object was created, the static constructor exists.")] - public override object? Invoke( - object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private object InvokeCtorWorker(BindingFlags invokeAttr, Span arguments) { - INVOCATION_FLAGS invocationFlags = InvocationFlags; - - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0) - ThrowNoInvokeException(); - - // check basic method consistency. This call will throw if there are problems in the target/method relationship - CheckConsistency(obj); - - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR) != 0) - { - // Run the class constructor through the class constructor mechanism instead of the Invoke path. - // This avoids allowing mutation of readonly static fields, and initializes the type correctly. - - var declaringType = DeclaringType; - - if (declaringType != null) - RuntimeHelpers.RunClassConstructor(declaringType.TypeHandle); - else - RuntimeHelpers.RunModuleConstructor(Module.ModuleHandle); - - return null; - } - - Signature sig = Signature; - - // get the signature - int formalCount = sig.Arguments.Length; - int actualCount = (parameters != null) ? parameters.Length : 0; - if (formalCount != actualCount) - throw new TargetParameterCountException(SR.Arg_ParmCnt); - - // if we are here we passed all the previous checks. Time to look at the arguments bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; - - StackAllocedArguments stackArgs = default; - Span arguments = default; - if (actualCount != 0) - { - arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig); - } - - object? retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, sig, false, wrapExceptions); - - // copy out. This should be made only if ByRef are present. - // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[]) - for (int index = 0; index < arguments.Length; index++) - parameters![index] = arguments[index]; - - return retValue; + return RuntimeMethodHandle.InvokeMethod(null, arguments, Signature, true, wrapExceptions)!; } [RequiresUnreferencedCode("Trimming may change method bodies. For example it can change some instructions, remove branches or local variables.")] @@ -369,47 +238,5 @@ internal void ThrowNoInvokeException() public override bool ContainsGenericParameters => DeclaringType != null && DeclaringType.ContainsGenericParameters; #endregion - - #region ConstructorInfo Overrides - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] - public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) - { - INVOCATION_FLAGS invocationFlags = InvocationFlags; - - if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS | INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE)) != 0) - ThrowNoInvokeException(); - - // get the signature - Signature sig = Signature; - - int formalCount = sig.Arguments.Length; - int actualCount = (parameters != null) ? parameters.Length : 0; - if (formalCount != actualCount) - throw new TargetParameterCountException(SR.Arg_ParmCnt); - - // We don't need to explicitly invoke the class constructor here, - // JIT/NGen will insert the call to .cctor in the instance ctor. - - // if we are here we passed all the previous checks. Time to look at the arguments - bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; - - StackAllocedArguments stackArgs = default; - Span arguments = default; - if (actualCount != 0) - { - arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig); - } - - object retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, true, wrapExceptions)!; // ctor must return non-null - - // copy out. This should be made only if ByRef are present. - // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[]) - for (int index = 0; index < arguments.Length; index++) - parameters![index] = arguments[index]; - - return retValue; - } - #endregion } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 7810c94dcc9e17..cb99ed3d59f63c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -13,7 +13,7 @@ namespace System.Reflection { - internal sealed class RuntimeMethodInfo : MethodInfo, IRuntimeMethodInfo + internal sealed partial class RuntimeMethodInfo : MethodInfo, IRuntimeMethodInfo { #region Private Data Members private IntPtr m_handle; @@ -34,52 +34,14 @@ internal INVOCATION_FLAGS InvocationFlags [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path - INVOCATION_FLAGS LazyCreateInvocationFlags() - { - INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN; - - Type? declaringType = DeclaringType; - - // - // first take care of all the NO_INVOKE cases. - if (ContainsGenericParameters || - IsDisallowedByRefType(ReturnType) || - (declaringType != null && declaringType.ContainsGenericParameters) || - ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)) - { - // We don't need other flags if this method cannot be invoked - invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; - } - else - { - // Check for byref-like types - if ((declaringType != null && declaringType.IsByRefLike) || ReturnType.IsByRefLike) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; - } - - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; - m_invocationFlags = invocationFlags; // accesses are guaranteed atomic - return invocationFlags; - } - INVOCATION_FLAGS flags = m_invocationFlags; if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) { - flags = LazyCreateInvocationFlags(); + flags = ComputeAndUpdateInvocationFlags(this, ref m_invocationFlags); } return flags; } } - - private static bool IsDisallowedByRefType(Type type) - { - if (!type.IsByRef) - return false; - - Type elementType = type.GetElementType()!; - return elementType.IsByRefLike || elementType == typeof(void); - } #endregion #region Constructor @@ -339,6 +301,8 @@ public override MethodImplAttributes GetMethodImplementationFlags() public override CallingConventions CallingConvention => Signature.CallingConvention; + private RuntimeType[] ArgumentTypes => Signature.Arguments; + [RequiresUnreferencedCode("Trimming may change method bodies. For example it can change some instructions, remove branches or local variables.")] public override MethodBody? GetMethodBody() { @@ -352,90 +316,10 @@ public override MethodImplAttributes GetMethodImplementationFlags() #region Invocation Logic(On MemberBase) [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CheckConsistency(object? target) - { - // only test instance methods - if ((m_methodAttributes & MethodAttributes.Static) == 0) - { - if (!m_declaringType.IsInstanceOfType(target)) - { - if (target == null) - throw new TargetException(SR.RFLCT_Targ_StatMethReqTarg); - else - throw new TargetException(SR.RFLCT_Targ_ITargMismatch); - } - } - } - - [DoesNotReturn] - private void ThrowNoInvokeException() - { - // method is on a class that contains stack pointers - if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS) != 0) - { - throw new NotSupportedException(); - } - // method is vararg - else if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) - { - throw new NotSupportedException(); - } - // method is generic or on a generic class - else if (DeclaringType!.ContainsGenericParameters || ContainsGenericParameters) - { - throw new InvalidOperationException(SR.Arg_UnboundGenParam); - } - // method is abstract class - else if (IsAbstract) - { - throw new MemberAccessException(); - } - else if (ReturnType.IsByRef) - { - Type elementType = ReturnType.GetElementType()!; - if (elementType.IsByRefLike) - throw new NotSupportedException(SR.NotSupported_ByRefToByRefLikeReturn); - if (elementType == typeof(void)) - throw new NotSupportedException(SR.NotSupported_ByRefToVoidReturn); - } - - throw new TargetException(); - } - - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] - public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + private object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span arguments) { - // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS 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 - // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects. - if ((InvocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0) - ThrowNoInvokeException(); - - // check basic method consistency. This call will throw if there are problems in the target/method relationship - CheckConsistency(obj); - - Signature sig = Signature; - int actualCount = (parameters != null) ? parameters.Length : 0; - if (sig.Arguments.Length != actualCount) - throw new TargetParameterCountException(SR.Arg_ParmCnt); - - StackAllocedArguments stackArgs = default; // try to avoid intermediate array allocation if possible - Span arguments = default; - if (actualCount != 0) - { - arguments = CheckArguments(ref stackArgs, parameters!, binder, invokeAttr, culture, sig); - } - bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; - object? retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions); - - // copy out. This should be made only if ByRef are present. - // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[]) - for (int index = 0; index < arguments.Length; index++) - parameters![index] = arguments[index]; - - return retValue; + return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions); } [DebuggerStepThroughAttribute] @@ -451,7 +335,7 @@ private void ThrowNoInvokeException() } // check basic method consistency. This call will throw if there are problems in the target/method relationship - CheckConsistency(obj); + ValidateInvokeTarget(obj); Signature sig = Signature; if (sig.Arguments.Length != 1) @@ -460,7 +344,7 @@ private void ThrowNoInvokeException() } StackAllocedArguments stackArgs = default; - Span arguments = CheckArguments(ref stackArgs, new ReadOnlySpan(ref parameter, 1), binder, invokeAttr, culture, sig); + Span arguments = CheckArguments(ref stackArgs, new ReadOnlySpan(ref parameter, 1), binder, invokeAttr, culture, sig.Arguments); bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, constructor: false, wrapExceptions); From 9a95120e7576418d8a21b93658f07245f407d129 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 14:44:06 -0700 Subject: [PATCH 03/16] Updates to mono/ --- .../System/Reflection/RuntimeMethodInfo.cs | 166 +++++++------ .../src/System/RuntimeType.Mono.cs | 6 +- src/mono/mono/metadata/boehm-gc.c | 6 + src/mono/mono/metadata/icall-def-netcore.h | 2 +- src/mono/mono/metadata/icall-table.h | 1 + src/mono/mono/metadata/icall.c | 52 +--- src/mono/mono/metadata/null-gc.c | 6 + src/mono/mono/metadata/object-internals.h | 39 ++- src/mono/mono/metadata/object.c | 231 +++++++++--------- src/mono/mono/metadata/sgen-mono.c | 20 ++ 10 files changed, 291 insertions(+), 238 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index a6568737354d4d..7089e5b4bfc754 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -32,6 +32,7 @@ using System.Runtime.InteropServices; using System.Reflection.Emit; using System.Text; +using System.Threading; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using InteropServicesCallingConvention = System.Runtime.InteropServices.CallingConvention; @@ -139,7 +140,7 @@ internal static ParameterInfo GetReturnParameterInfo(RuntimeMethodInfo method) #region Sync with _MonoReflectionMethod in object-internals.h [StructLayout(LayoutKind.Sequential)] - internal sealed class RuntimeMethodInfo : MethodInfo + internal sealed partial class RuntimeMethodInfo : MethodInfo { #pragma warning disable 649 internal IntPtr mhandle; @@ -148,6 +149,22 @@ internal sealed class RuntimeMethodInfo : MethodInfo #pragma warning restore 649 #endregion private string? toString; + private RuntimeType[]? parameterTypes; + private INVOCATION_FLAGS invocationFlags; + + internal INVOCATION_FLAGS InvocationFlags + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + INVOCATION_FLAGS flags = invocationFlags; + if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + { + flags = ComputeAndUpdateInvocationFlags(this, ref invocationFlags); + } + return flags; + } + } public override Module Module { @@ -326,6 +343,27 @@ internal override int GetParametersCount() return MonoMethodInfo.GetParametersInfo(mhandle, this).Length; } + private RuntimeType[] ArgumentTypes + { + get + { + if (parameterTypes != null) + { + return parameterTypes; + } + + ParameterInfo[] src = GetParametersInternal(); + RuntimeType[] dest = new RuntimeType[src.Length]; + for (int i = 0; i < dest.Length; ++i) + { + dest[i] = (RuntimeType)src[i].ParameterType; + } + + Interlocked.CompareExchange(ref parameterTypes, dest, null); + return dest; + } + } + /* * InternalInvoke() receives the parameters correctly converted by the * binder to match the types of the method signature. @@ -333,33 +371,11 @@ internal override int GetParametersCount() * Exceptions thrown by the called method propagate normally. */ [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern object? InternalInvoke(object? obj, object?[]? parameters, out Exception? exc); + internal extern object? InternalInvoke(object? obj, Span parameters, out Exception? exc); - [DebuggerHidden] - [DebuggerStepThrough] - public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span parameters) { - if (!IsStatic) - { - if (!DeclaringType.IsInstanceOfType(obj)) - { - if (obj == null) - throw new TargetException("Non-static method requires a target."); - else - throw new TargetException("Object does not match target type."); - } - } - - if (binder == null) - binder = Type.DefaultBinder; - - /*Avoid allocating an array every time*/ - ParameterInfo[] pinfo = GetParametersInternal(); - ConvertValues(binder, parameters, pinfo, culture, invokeAttr); - - if (ContainsGenericParameters) - throw new InvalidOperationException("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true."); - Exception? exc; object? o = null; @@ -758,7 +774,7 @@ public override IList GetCustomAttributesData() } #region Sync with _MonoReflectionMethod in object-internals.h [StructLayout(LayoutKind.Sequential)] - internal sealed class RuntimeConstructorInfo : ConstructorInfo + internal sealed partial class RuntimeConstructorInfo : ConstructorInfo { #pragma warning disable 649 internal IntPtr mhandle; @@ -767,6 +783,22 @@ internal sealed class RuntimeConstructorInfo : ConstructorInfo #pragma warning restore 649 #endregion private string? toString; + private RuntimeType[]? parameterTypes; + private INVOCATION_FLAGS invocationFlags; + + internal INVOCATION_FLAGS InvocationFlags + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + INVOCATION_FLAGS flags = invocationFlags; + if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + { + flags = ComputeAndUpdateInvocationFlags(this, ref invocationFlags); + } + return flags; + } + } public override Module Module { @@ -802,51 +834,54 @@ internal override int GetParametersCount() return pi == null ? 0 : pi.Length; } - /* - * InternalInvoke() receives the parameters correctly converted by the binder - * to match the types of the method signature. - */ - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern object InternalInvoke(object? obj, object?[]? parameters, out Exception exc); - - [DebuggerHidden] - [DebuggerStepThrough] - public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + private RuntimeType[] ArgumentTypes { - if (obj == null) - { - if (!IsStatic) - throw new TargetException("Instance constructor requires a target"); - } - else if (!DeclaringType.IsInstanceOfType(obj)) + get { - throw new TargetException("Constructor does not match target type"); - } + if (parameterTypes != null) + { + return parameterTypes; + } - return DoInvoke(obj, invokeAttr, binder, parameters, culture); + ParameterInfo[] src = GetParametersInternal(); + RuntimeType[] dest = new RuntimeType[src.Length]; + for (int i = 0; i < dest.Length; ++i) + { + dest[i] = (RuntimeType)src[i].ParameterType; + } + + Interlocked.CompareExchange(ref parameterTypes, dest, null); + return dest; + } } - private object DoInvoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + private object? InvokeClassConstructor() { - if (binder == null) - binder = Type.DefaultBinder; - - ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo(mhandle, this); - - RuntimeMethodInfo.ConvertValues(binder, parameters, pinfo, culture, invokeAttr); - - if (obj == null && DeclaringType.ContainsGenericParameters) - throw new MemberAccessException("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true."); + return null; + } - if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) - { - throw new MemberAccessException(string.Format("Cannot create an instance of {0} because it is an abstract class", DeclaringType)); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span arguments) + { + bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; + return InternalInvoke(obj, arguments, wrapExceptions); + } - return InternalInvoke(obj, parameters, (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0)!; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal object InvokeCtorWorker(BindingFlags invokeAttr, Span arguments) + { + bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; + return InternalInvoke(null, arguments, wrapExceptions)!; } - public object? InternalInvoke(object? obj, object?[]? parameters, bool wrapExceptions) + /* + * InternalInvoke() receives the parameters correctly converted by the binder + * to match the types of the method signature. + */ + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal extern object InternalInvoke(object? obj, Span parameters, out Exception exc); + + private object? InternalInvoke(object? obj, Span parameters, bool wrapExceptions) { Exception exc; object? o = null; @@ -881,13 +916,6 @@ private object DoInvoke(object? obj, BindingFlags invokeAttr, Binder? binder, ob return obj == null ? o : null; } - [DebuggerHidden] - [DebuggerStepThrough] - public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) - { - return DoInvoke(null, invokeAttr, binder, parameters, culture); - } - public override RuntimeMethodHandle MethodHandle { get 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 151ad2fb63b24a..dff7e639cb2bce 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1653,10 +1653,10 @@ internal override FieldInfo GetField(FieldInfo fromNoninstanciated) throw new MissingMethodException("Cannot create an abstract class '{0}'.", FullName); } - return ctor.InternalInvoke(null, null, wrapExceptions); + return ctor.InvokeWorker(null, wrapExceptions ? BindingFlags.Default : BindingFlags.DoNotWrapExceptions, Span.Empty); } - internal object? CheckValue(object? value, Binder binder, CultureInfo? culture, BindingFlags invokeAttr) + internal object? CheckValue(object? value, Binder? binder, CultureInfo? culture, BindingFlags invokeAttr) { bool failed = false; object? res = TryConvertToType(value, ref failed); @@ -1968,7 +1968,7 @@ internal static object CreateInstanceForAnotherGenericParameter( if (ctor is null || !ctor.IsPublic) throw new MissingMethodException(SR.Format(SR.Arg_NoDefCTor, gt)); - return ctor.InternalInvoke(null, null, wrapExceptions: true)!; + return ctor.InvokeCtorWorker(BindingFlags.Default, Span.Empty)!; } [MethodImplAttribute(MethodImplOptions.InternalCall)] diff --git a/src/mono/mono/metadata/boehm-gc.c b/src/mono/mono/metadata/boehm-gc.c index bdda3e69b8b028..ead6e81f084d80 100644 --- a/src/mono/mono/metadata/boehm-gc.c +++ b/src/mono/mono/metadata/boehm-gc.c @@ -871,6 +871,12 @@ mono_gc_wbarrier_set_field_internal (MonoObject *obj, gpointer field_ptr, MonoOb *(void**)field_ptr = value; } +void +mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value) +{ + *(void**)slot_ptr = value; +} + void mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, gpointer slot_ptr, MonoObject* value) { diff --git a/src/mono/mono/metadata/icall-def-netcore.h b/src/mono/mono/metadata/icall-def-netcore.h index a4340404b82a07..2e86b5e05ffaf2 100644 --- a/src/mono/mono/metadata/icall-def-netcore.h +++ b/src/mono/mono/metadata/icall-def-netcore.h @@ -254,7 +254,7 @@ HANDLES(RASSEM_12, "get_location", ves_icall_System_Reflection_RuntimeAssembly_g ICALL_TYPE(MCMETH, "System.Reflection.RuntimeConstructorInfo", MCMETH_1) HANDLES(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition, MonoReflectionMethod, 1, (MonoReflectionMethod)) -HANDLES(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoArray, MonoExceptionOut)) +HANDLES(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoSpanOfObjects, MonoExceptionOut)) HANDLES_REUSE_WRAPPER(MCMETH_4, "get_metadata_token", ves_icall_reflection_get_token) ICALL_TYPE(CATTR_DATA, "System.Reflection.RuntimeCustomAttributeData", CATTR_DATA_1) diff --git a/src/mono/mono/metadata/icall-table.h b/src/mono/mono/metadata/icall-table.h index 31aa3aba238a04..23870dd5f595ba 100644 --- a/src/mono/mono/metadata/icall-table.h +++ b/src/mono/mono/metadata/icall-table.h @@ -150,6 +150,7 @@ typedef MonoStringHandle MonoStringOutHandle; #define MONO_HANDLE_TYPE_WRAP_MonoProperty_ptr ICALL_HANDLES_WRAP_NONE #define MONO_HANDLE_TYPE_WRAP_size_t ICALL_HANDLES_WRAP_NONE #define MONO_HANDLE_TYPE_WRAP_MonoVTable_ptr ICALL_HANDLES_WRAP_NONE +#define MONO_HANDLE_TYPE_WRAP_MonoSpanOfObjects ICALL_HANDLES_WRAP_NONE #define MONO_HANDLE_TYPE_WRAP_MonoAssemblyName_ref ICALL_HANDLES_WRAP_VALUETYPE_REF #define MONO_HANDLE_TYPE_WRAP_MonoBoolean_ref ICALL_HANDLES_WRAP_VALUETYPE_REF diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index c48f2b1199a0df..cdcc20d521ee81 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -3354,11 +3354,10 @@ ves_icall_RuntimeMethodInfo_GetGenericArguments (MonoReflectionMethodHandle ref_ MonoObjectHandle ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHandle this_arg_handle, - MonoArrayHandle params_handle, MonoExceptionHandleOut exception_out, MonoError *error) + MonoSpanOfObjects params_span, MonoExceptionHandleOut exception_out, MonoError *error) { MonoReflectionMethod* const method = MONO_HANDLE_RAW (method_handle); MonoObject* const this_arg = MONO_HANDLE_RAW (this_arg_handle); - MonoArray* const params = MONO_HANDLE_RAW (params_handle); /* * Invoke from reflection is supposed to always be a virtual call (the API @@ -3388,17 +3387,6 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa } if (this_arg) { - if (!mono_object_isinst_checked (this_arg, m->klass, error)) { - if (!is_ok (error)) { - exception = mono_error_convert_to_exception (error); - goto return_null; - } - this_name = mono_type_get_full_name (mono_object_class (this_arg)); - target_name = mono_type_get_full_name (m->klass); - msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name); - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg); - goto return_null; - } m = mono_object_get_virtual_method_internal (this_arg, m); /* must pass the pointer to the value for valuetype methods */ if (m_class_is_valuetype (m->klass)) { @@ -3411,43 +3399,15 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa } } - if ((m->klass != NULL && m_class_is_byreflike (m->klass)) || m_class_is_byreflike (mono_class_from_mono_type_internal (sig->ret))) { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method with stack pointers via reflection"); - goto return_null; - } - - if (sig->ret->byref) { - MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); - if (ret_byval->type == MONO_TYPE_VOID) { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "ByRef to void return values are not supported in reflection invocation"); - goto return_null; - } - if (m_class_is_byreflike (mono_class_from_mono_type_internal (ret_byval))) { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef to ByRefLike type via reflection"); - goto return_null; - } - } - - pcount = params? mono_array_length_internal (params): 0; - if (pcount != sig->param_count) { - exception = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"); - goto return_null; - } - - if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) { - exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."); - goto return_null; - } - image = m_class_get_image (m->klass); if (m_class_get_rank (m->klass) && !strcmp (m->name, ".ctor")) { int i; - pcount = mono_array_length_internal (params); + pcount = mono_span_length_internal (params_span); uintptr_t * const lengths = g_newa (uintptr_t, pcount); /* Note: the synthetized array .ctors have int32 as argument type */ for (i = 0; i < pcount; ++i) - lengths [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, i) + sizeof (MonoObject)); + lengths [i] = *(int32_t*) ((char*)mono_span_get_internal (params_span, MonoObject*, i) + sizeof (MonoObject)); if (m_class_get_rank (m->klass) == 1 && sig->param_count == 2 && m_class_get_rank (m_class_get_element_class (m->klass))) { /* This is a ctor for jagged arrays. MS creates an array of arrays. */ @@ -3476,8 +3436,8 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa intptr_t * const lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount); for (i = 0; i < pcount / 2; ++i) { - lower_bounds [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, (i * 2)) + sizeof (MonoObject)); - lengths [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, (i * 2) + 1) + sizeof (MonoObject)); + lower_bounds [i] = *(int32_t*) ((char*)mono_span_get_internal (params_span, MonoObject*, (i * 2)) + sizeof (MonoObject)); + lengths [i] = *(int32_t*) ((char*)mono_span_get_internal (params_span, MonoObject*, (i * 2) + 1) + sizeof (MonoObject)); } arr = mono_array_new_full_checked (m->klass, lengths, lower_bounds, error); @@ -3485,7 +3445,7 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa goto exit; } } - result = mono_runtime_invoke_array_checked (m, obj, params, error); + result = mono_runtime_invoke_span_checked (m, obj, params_span, error); goto exit; return_null: result = NULL; diff --git a/src/mono/mono/metadata/null-gc.c b/src/mono/mono/metadata/null-gc.c index 343756d2c67da4..511a1d2d35f440 100644 --- a/src/mono/mono/metadata/null-gc.c +++ b/src/mono/mono/metadata/null-gc.c @@ -282,6 +282,12 @@ mono_gc_wbarrier_set_field_internal (MonoObject *obj, gpointer field_ptr, MonoOb *(void**)field_ptr = value; } +void +mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value) +{ + *(void**)slot_ptr = value; +} + void mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, gpointer slot_ptr, MonoObject* value) { diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index b50ed3c47d8bdc..a44f072d1b7186 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -175,6 +175,12 @@ struct _MonoArray { mono_64bitaligned_t vector [MONO_ZERO_LEN_ARRAY]; }; +/* match the layout of the managed definition of Span */ +typedef struct { + MonoObject** _pointer; + int _length; +} MonoSpanOfObjects; + #define MONO_SIZEOF_MONO_ARRAY (MONO_STRUCT_OFFSET_CONSTANT (MonoArray, vector)) struct _MonoString { @@ -276,6 +282,32 @@ mono_handle_array_get_bounds_dim (MonoArrayHandle arr, gint32 dim, MonoArrayBoun *bounds = MONO_HANDLE_GETVAL (arr, bounds [dim]); } +#define mono_span_length_internal(span) (span._length) + +#define mono_span_get_internal(span,type,idx) (type)(!span._pointer ? NULL : span._pointer[idx]) + +#define mono_span_addr_internal(span,type,idx) (type*)(span._pointer + idx) + +#define mono_span_setref_internal(span,index,value) \ + do { \ + void **__p = (void **) mono_span_addr_internal ((span), void*, (index)); \ + mono_gc_wbarrier_set_spanref_internal ((&span), __p, (MonoObject*)(value)); \ + /* *__p = (value);*/ \ + } while (0) + +static inline MonoSpanOfObjects mono_span_create_from_object_array_internal (MonoArray *arr) { + MonoSpanOfObjects span; + if (arr != NULL) { + span._length = (int)mono_array_length_internal (arr); + span._pointer = mono_array_addr_fast (arr, MonoObject*, 0); + } + else { + span._length = 0; + span._pointer = NULL; + } + return span; +} + typedef struct { MonoObject obj; } MonoMarshalByRefObject; @@ -1838,7 +1870,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, MonoObject **exc, MonoError *error); MonoObject* -mono_runtime_invoke_array_checked (MonoMethod *method, void *obj, MonoArray *params, +mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects params, MonoError *error); void* @@ -2059,7 +2091,10 @@ void mono_gc_wbarrier_set_field_internal (MonoObject *obj, void* field_ptr, MonoObject* value); void -mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, void* slot_ptr, MonoObject* value); +mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value); + +void +mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, void* slot_ptr, MonoObject* value); void mono_gc_wbarrier_arrayref_copy_internal (void* dest_ptr, const void* src_ptr, int count); diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 70c967df384b5a..f4549dc5ce0927 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -4516,8 +4516,8 @@ mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **ex return do_try_exec_main (method, args, exc); } -/** invoke_array_extract_argument: - * @params: array of arguments to the method. +/** invoke_span_extract_argument: + * @params: span of object arguments to the method. * @i: the index of the argument to extract. * @t: ith type from the method signature. * @has_byref_nullables: outarg - TRUE if method expects a byref nullable argument @@ -4529,7 +4529,7 @@ mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **ex * On failure sets @error and returns NULL. */ static gpointer -invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject **pa_obj, gboolean* has_byref_nullables, MonoError *error) +invoke_span_extract_argument (MonoSpanOfObjects params_span, int i, MonoType *t, MonoObject **pa_obj, gboolean* has_byref_nullables, MonoError *error) { MonoType *t_orig = t; gpointer result = NULL; @@ -4554,17 +4554,17 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject case MONO_TYPE_VALUETYPE: if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type_internal (t_orig))) { /* The runtime invoke wrapper needs the original boxed vtype, it does handle byref values as well. */ - *pa_obj = mono_array_get_internal (params, MonoObject*, i); + *pa_obj = mono_span_get_internal (params_span, MonoObject*, i); result = *pa_obj; if (t->byref) *has_byref_nullables = TRUE; } else { /* MS seems to create the objects if a null is passed in */ gboolean was_null = FALSE; - if (!mono_array_get_internal (params, MonoObject*, i)) { + if (!mono_span_get_internal (params_span, MonoObject*, i)) { MonoObject *o = mono_object_new_checked (mono_class_from_mono_type_internal (t_orig), error); return_val_if_nok (error, NULL); - mono_array_setref_internal (params, i, o); + mono_span_setref_internal (params_span, i, o); was_null = TRUE; } @@ -4576,15 +4576,15 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject * object, pass that to the callee, and replace the original * boxed object in the arg array with the copy. */ - MonoObject *orig = mono_array_get_internal (params, MonoObject*, i); + MonoObject *orig = mono_span_get_internal (params_span, MonoObject*, i); MonoObject *copy = mono_value_box_checked (orig->vtable->klass, mono_object_unbox_internal (orig), error); return_val_if_nok (error, NULL); - mono_array_setref_internal (params, i, copy); + mono_span_setref_internal (params_span, i, copy); } - *pa_obj = mono_array_get_internal (params, MonoObject*, i); + *pa_obj = mono_span_get_internal (params_span, MonoObject*, i); result = mono_object_unbox_internal (*pa_obj); if (!t->byref && was_null) - mono_array_setref_internal (params, i, NULL); + mono_span_setref_internal (params_span, i, NULL); } break; case MONO_TYPE_STRING: @@ -4593,10 +4593,10 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: if (t->byref) { - result = mono_array_addr_internal (params, MonoObject*, i); + result = mono_span_addr_internal (params_span, MonoObject*, i); // FIXME: I need to check this code path } else { - *pa_obj = mono_array_get_internal (params, MonoObject*, i); + *pa_obj = mono_span_get_internal (params_span, MonoObject*, i); result = *pa_obj; } break; @@ -4610,7 +4610,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject MonoObject *arg; /* The argument should be an IntPtr */ - arg = mono_array_get_internal (params, MonoObject*, i); + arg = mono_span_get_internal (params_span, MonoObject*, i); if (arg == NULL) { result = NULL; } else { @@ -4683,93 +4683,10 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params, return res; } -/** - * mono_runtime_invoke_array_checked: - * \param method method to invoke - * \param obj object instance - * \param params arguments to the method - * \param error set on failure. - * Invokes the method represented by \p method on the object \p obj. - * - * \p obj is the \c this pointer, it should be NULL for static - * methods, a \c MonoObject* for object instances and a pointer to - * the value type for value types. - * - * The \p params array contains the arguments to the method with the - * same convention: \c MonoObject* pointers for object instances and - * pointers to the value type otherwise. The \c _invoke_array - * variant takes a C# \c object[] as the \p params argument (\c MonoArray*): - * in this case the value types are boxed inside the - * respective reference representation. - * - * From unmanaged code you'll usually use the - * mono_runtime_invoke_checked() variant. - * - * Note that this function doesn't handle virtual methods for - * you, it will exec the exact method you pass: we still need to - * expose a function to lookup the derived class implementation - * of a virtual method (there are examples of this in the code, - * though). - * - * On failure or exception, \p error will be set. In that case, you - * can't use the \c MonoObject* result from the function. - * - * If the method returns a value type, it is boxed in an object - * reference. - */ -MonoObject* -mono_runtime_invoke_array_checked (MonoMethod *method, void *obj, MonoArray *params, - MonoError *error) -{ - error_init (error); - return mono_runtime_try_invoke_array (method, obj, params, NULL, error); -} - -/** - * mono_runtime_try_invoke_array: - * \param method method to invoke - * \param obj object instance - * \param params arguments to the method - * \param exc exception information. - * \param error set on failure. - * Invokes the method represented by \p method on the object \p obj. - * - * \p obj is the \c this pointer, it should be NULL for static - * methods, a \c MonoObject* for object instances and a pointer to - * the value type for value types. - * - * The \p params array contains the arguments to the method with the - * same convention: \c MonoObject* pointers for object instances and - * pointers to the value type otherwise. The \c _invoke_array - * variant takes a C# \c object[] as the params argument (\c MonoArray*): - * in this case the value types are boxed inside the - * respective reference representation. - * - * From unmanaged code you'll usually use the - * mono_runtime_invoke_checked() variant. - * - * Note that this function doesn't handle virtual methods for - * you, it will exec the exact method you pass: we still need to - * expose a function to lookup the derived class implementation - * of a virtual method (there are examples of this in the code, - * though). - * - * You can pass NULL as the \p exc argument if you don't want to catch - * exceptions, otherwise, \c *exc will be set to the exception thrown, if - * any. On other failures, \p error will be set. If an exception is - * thrown or there's an error, you can't use the \c MonoObject* result - * from the function. - * - * If the method returns a value type, it is boxed in an object - * reference. - */ -MonoObject* -mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, +static MonoObject* +mono_runtime_try_invoke_span (MonoMethod *method, void *obj, MonoSpanOfObjects params_span, MonoObject **exc, MonoError *error) { - MONO_REQ_GC_UNSAFE_MODE; - HANDLE_FUNCTION_ENTER (); - error_init (error); MonoMethodSignature *sig = mono_method_signature_internal (method); @@ -4777,13 +4694,14 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, MonoObject *res = NULL; int i; gboolean has_byref_nullables = FALSE; + int params_length = mono_span_length_internal (params_span); - if (NULL != params) { - pa = g_newa (gpointer, mono_array_length_internal (params)); - for (i = 0; i < mono_array_length_internal (params); i++) { + if (params_length > 0) { + pa = g_newa (gpointer, params_length); + for (i = 0; i < params_length; i++) { MonoType *t = sig->params [i]; MonoObject *pa_obj; - pa [i] = invoke_array_extract_argument (params, i, t, &pa_obj, &has_byref_nullables, error); + pa [i] = invoke_span_extract_argument (params_span, i, t, &pa_obj, &has_byref_nullables, error); if (pa_obj) MONO_HANDLE_PIN (pa_obj); goto_if_nok (error, exit_null); @@ -4797,7 +4715,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, /* Need to create a boxed vtype instead */ g_assert (!obj); - if (!params) { + if (params_length == 0) { goto_if_nok (error, exit_null); } else { res = mono_value_box_checked (m_class_get_cast_class (method->klass), pa [0], error); @@ -4892,25 +4810,104 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, g_assert (box_exc == NULL); mono_error_assert_ok (error); } - - if (has_byref_nullables) { - /* - * The runtime invoke wrapper already converted byref nullables back, - * and stored them in pa, we just need to copy them back to the - * managed array. - */ - for (i = 0; i < mono_array_length_internal (params); i++) { - MonoType *t = sig->params [i]; - - if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) - mono_array_setref_internal (params, i, pa [i]); - } - } } goto exit; exit_null: res = NULL; exit: + return res; +} + +/** + * mono_runtime_invoke_array_checked: + * \param method method to invoke + * \param obj object instance + * \param params arguments to the method + * \param error set on failure. + * Invokes the method represented by \p method on the object \p obj. + * + * \p obj is the \c this pointer, it should be NULL for static + * methods, a \c MonoObject* for object instances and a pointer to + * the value type for value types. + * + * The \p params span contains the arguments to the method with the + * same convention: \c MonoObject* pointers for object instances and + * pointers to the value type otherwise. The \c _invoke_array + * variant takes a C# \c object[] as the \p params argument (\c MonoArray*): + * in this case the value types are boxed inside the + * respective reference representation. + * + * From unmanaged code you'll usually use the + * mono_runtime_invoke_checked() variant. + * + * Note that this function doesn't handle virtual methods for + * you, it will exec the exact method you pass: we still need to + * expose a function to lookup the derived class implementation + * of a virtual method (there are examples of this in the code, + * though). + * + * On failure or exception, \p error will be set. In that case, you + * can't use the \c MonoObject* result from the function. + * + * If the method returns a value type, it is boxed in an object + * reference. + */ +MonoObject* +mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects params, + MonoError *error) +{ + error_init (error); + return mono_runtime_try_invoke_span (method, obj, params, NULL, error); +} + +/** + * mono_runtime_try_invoke_array: + * \param method method to invoke + * \param obj object instance + * \param params arguments to the method + * \param exc exception information. + * \param error set on failure. + * Invokes the method represented by \p method on the object \p obj. + * + * \p obj is the \c this pointer, it should be NULL for static + * methods, a \c MonoObject* for object instances and a pointer to + * the value type for value types. + * + * The \p params array contains the arguments to the method with the + * same convention: \c MonoObject* pointers for object instances and + * pointers to the value type otherwise. The \c _invoke_array + * variant takes a C# \c object[] as the params argument (\c MonoArray*): + * in this case the value types are boxed inside the + * respective reference representation. + * + * From unmanaged code you'll usually use the + * mono_runtime_invoke_checked() variant. + * + * Note that this function doesn't handle virtual methods for + * you, it will exec the exact method you pass: we still need to + * expose a function to lookup the derived class implementation + * of a virtual method (there are examples of this in the code, + * though). + * + * You can pass NULL as the \p exc argument if you don't want to catch + * exceptions, otherwise, \c *exc will be set to the exception thrown, if + * any. On other failures, \p error will be set. If an exception is + * thrown or there's an error, you can't use the \c MonoObject* result + * from the function. + * + * If the method returns a value type, it is boxed in an object + * reference. + */ +MonoObject* +mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, + MonoObject **exc, MonoError *error) +{ + MONO_REQ_GC_UNSAFE_MODE; + HANDLE_FUNCTION_ENTER (); + + MonoSpanOfObjects params_span = mono_span_create_from_object_array_internal (params); + MonoObject *res = mono_runtime_try_invoke_span (method, obj, params_span, exc, error); + HANDLE_FUNCTION_RETURN_VAL (res); } diff --git a/src/mono/mono/metadata/sgen-mono.c b/src/mono/mono/metadata/sgen-mono.c index c04e5dba6a57f6..7a37b6a5c8fbc4 100644 --- a/src/mono/mono/metadata/sgen-mono.c +++ b/src/mono/mono/metadata/sgen-mono.c @@ -44,6 +44,7 @@ #endif #ifdef HEAVY_STATISTICS +static guint64 stat_wbarrier_set_spanref = 0; static guint64 stat_wbarrier_set_arrayref = 0; static guint64 stat_wbarrier_value_copy = 0; static guint64 stat_wbarrier_object_copy = 0; @@ -165,6 +166,24 @@ mono_gc_wbarrier_object_copy_internal (MonoObject* obj, MonoObject *src) sgen_get_remset ()->wbarrier_object_copy (obj, src); } +/** + * mono_gc_wbarrier_set_spanref_internal: + */ +void +mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value) +{ + HEAVY_STAT (++stat_wbarrier_set_spanref); + if (sgen_ptr_in_nursery (slot_ptr)) { + *(void**)slot_ptr = value; + return; + } + SGEN_LOG (8, "Adding remset at %p", slot_ptr); + if (value) + sgen_binary_protocol_wbarrier (slot_ptr, value, value->vtable); + + sgen_get_remset ()->wbarrier_set_field (NULL, slot_ptr, value); +} + /** * mono_gc_wbarrier_set_arrayref_internal: */ @@ -3106,6 +3125,7 @@ mono_gc_base_init (void) mono_counters_register ("los array cards scanned ", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_cards); mono_counters_register ("los array remsets", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_remsets); + mono_counters_register ("WBarrier set spanref", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_set_spanref); mono_counters_register ("WBarrier set arrayref", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_set_arrayref); mono_counters_register ("WBarrier value copy", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_value_copy); mono_counters_register ("WBarrier object copy", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_object_copy); From 51976fe034d6323dac3eda97ae0e6ba9bfc4a59a Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 15:31:30 -0700 Subject: [PATCH 04/16] Misplaced trimmer warning suppression. --- .../src/System/Reflection/RuntimeConstructorInfo.cs | 2 ++ .../src/System/Reflection/RuntimeConstructorInfo.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index e03fc2748ba63c..17471dbc6c8e84 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -194,6 +194,8 @@ public override MethodImplAttributes GetMethodImplementationFlags() private RuntimeType[] ArgumentTypes => Signature.Arguments; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2059:RunClassConstructor", + Justification = "This ConstructorInfo instance represents the static constructor itself, so if this object was created, the static constructor exists.")] private object? InvokeClassConstructor() { Debug.Assert((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR) != 0); 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 f0b7265e4298b8..197863ce2edaa6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -98,8 +98,6 @@ internal void ThrowNoInvokeException() [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2059:RunClassConstructor", - Justification = "This ConstructorInfo instance represents the static constructor itself, so if this object was created, the static constructor exists.")] public override object? Invoke( object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { From eebfc1e99110ca208b33625e11deeeb4ad5884c3 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 17:30:22 -0700 Subject: [PATCH 05/16] Intentionally check if return type is ByRefLike. --- .../src/System/Reflection/RuntimeMethodInfo.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) 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 f5783afad9b54d..adec507f40eba5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -24,13 +24,21 @@ private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(MethodInfo metho { invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; } - else if (declaringType != null) + else { - if (declaringType.ContainsGenericParameters) // Enclosing type has unbound generics + if (declaringType != null) { - invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + if (declaringType.ContainsGenericParameters) // Enclosing type has unbound generics + { + invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + } + else if (declaringType.IsByRefLike) // Check for byref-like types + { + invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; + } } - else if (declaringType.IsByRefLike) // Check for byref-like types + + if (methodInfo.ReturnType.IsByRefLike) // Check for byref-like types for return { invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; } From af2f5b11268fdfc8f17f84197b6d6ab1df78fb0b Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 17:30:42 -0700 Subject: [PATCH 06/16] Remove ActiveIssues from some mono tests. --- src/libraries/System.Memory/tests/Span/Reflection.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libraries/System.Memory/tests/Span/Reflection.cs b/src/libraries/System.Memory/tests/Span/Reflection.cs index dbdcc7dbdcd336..89fc722414348e 100644 --- a/src/libraries/System.Memory/tests/Span/Reflection.cs +++ b/src/libraries/System.Memory/tests/Span/Reflection.cs @@ -65,7 +65,6 @@ public static void MemoryMarshal_GenericStaticReturningSpan() } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/14993", TestRuntimes.Mono)] public static void Span_Constructor() { Type type = typeof(Span); @@ -102,7 +101,6 @@ public static void Span_StaticOperator() } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/14998", TestRuntimes.Mono)] public static void Span_InstanceMethod() { Type type = typeof(Span); @@ -112,7 +110,6 @@ public static void Span_InstanceMethod() } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/14993", TestRuntimes.Mono)] public static void ReadOnlySpan_Constructor() { Type type = typeof(ReadOnlySpan); @@ -149,7 +146,6 @@ public static void ReadOnlySpan_Operator() } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/14998", TestRuntimes.Mono)] public static void ReadOnlySpan_InstanceMethod() { Type type = typeof(ReadOnlySpan); @@ -159,7 +155,6 @@ public static void ReadOnlySpan_InstanceMethod() } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/14998", TestRuntimes.Mono)] public static void Memory_PropertyReturningSpan() { Type type = typeof(Memory); @@ -169,7 +164,6 @@ public static void Memory_PropertyReturningSpan() } [Fact] - [ActiveIssue("https://github.com/mono/mono/issues/14962", TestRuntimes.Mono)] public static void ReadOnlyMemory_PropertyReturningReadOnlySpan() { Type type = typeof(ReadOnlyMemory); From c5777d6a31f30f09b17c364ce5de21efe1140992 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 11 Oct 2021 17:59:14 -0700 Subject: [PATCH 07/16] Convert INVOCATION_FLAGS enum to repo style casing. --- .../src/System/Reflection/RtFieldInfo.cs | 28 +++++++++---------- .../Reflection/RuntimeConstructorInfo.cs | 10 +++---- .../System/Reflection/RuntimeMethodInfo.cs | 12 ++++---- .../System.Private.CoreLib.Shared.projitems | 2 +- ...INVOCATION_FLAGS.cs => InvocationFlags.cs} | 27 ++++++++---------- .../Reflection/RuntimeConstructorInfo.cs | 24 ++++++++-------- .../System/Reflection/RuntimeMethodInfo.cs | 20 ++++++------- .../System/Reflection/RuntimeMethodInfo.cs | 16 +++++------ 8 files changed, 67 insertions(+), 72 deletions(-) rename src/libraries/System.Private.CoreLib/src/System/Reflection/{INVOCATION_FLAGS.cs => InvocationFlags.cs} (50%) 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 9aac5488e60de7..1e41f2eb01b6aa 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs @@ -17,26 +17,26 @@ internal sealed unsafe class RtFieldInfo : RuntimeFieldInfo, IRuntimeFieldInfo // lazy caching private string? m_name; private RuntimeType? m_fieldType; - private INVOCATION_FLAGS m_invocationFlags; + private InvocationFlags m_invocationFlags; - internal INVOCATION_FLAGS InvocationFlags + internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) != 0 ? + get => (m_invocationFlags & InvocationFlags.Initialized) != 0 ? m_invocationFlags : InitializeInvocationFlags(); } [MethodImpl(MethodImplOptions.NoInlining)] - private INVOCATION_FLAGS InitializeInvocationFlags() + private InvocationFlags InitializeInvocationFlags() { Type? declaringType = DeclaringType; - INVOCATION_FLAGS invocationFlags = 0; + InvocationFlags invocationFlags = 0; // first take care of all the NO_INVOKE cases if (declaringType != null && declaringType.ContainsGenericParameters) { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + invocationFlags |= InvocationFlags.NoInvoke; } // If the invocationFlags are still 0, then @@ -44,19 +44,19 @@ private INVOCATION_FLAGS InitializeInvocationFlags() if (invocationFlags == 0) { if ((m_fieldAttributes & FieldAttributes.InitOnly) != (FieldAttributes)0) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD; + invocationFlags |= InvocationFlags.SpecialField; if ((m_fieldAttributes & FieldAttributes.HasFieldRVA) != (FieldAttributes)0) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD; + invocationFlags |= InvocationFlags.SpecialField; // find out if the field type is one of the following: Primitive, Enum or Pointer Type fieldType = FieldType; if (fieldType.IsPointer || fieldType.IsEnum || fieldType.IsPrimitive) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_FIELD_SPECIAL_CAST; + invocationFlags |= InvocationFlags.FieldSpecialCast; } // must be last to avoid threading problems - return m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; + return m_invocationFlags = invocationFlags | InvocationFlags.Initialized; } #endregion @@ -124,10 +124,10 @@ internal override RuntimeModule GetRuntimeModule() [Diagnostics.DebuggerHidden] public override object? GetValue(object? obj) { - INVOCATION_FLAGS invocationFlags = InvocationFlags; + InvocationFlags invocationFlags = InvocationFlags; RuntimeType? declaringType = DeclaringType as RuntimeType; - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0) + if ((invocationFlags & InvocationFlags.NoInvoke) != 0) { if (declaringType != null && DeclaringType!.ContainsGenericParameters) throw new InvalidOperationException(SR.Arg_UnboundGenField); @@ -170,10 +170,10 @@ internal override RuntimeModule GetRuntimeModule() [Diagnostics.DebuggerHidden] public override void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture) { - INVOCATION_FLAGS invocationFlags = InvocationFlags; + InvocationFlags invocationFlags = InvocationFlags; RuntimeType? declaringType = DeclaringType as RuntimeType; - if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0) + if ((invocationFlags & InvocationFlags.NoInvoke) != 0) { if (declaringType != null && declaringType.ContainsGenericParameters) throw new InvalidOperationException(SR.Arg_UnboundGenField); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index 17471dbc6c8e84..afb73a74a53185 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -28,15 +28,15 @@ internal sealed partial class RuntimeConstructorInfo : ConstructorInfo, IRuntime private MethodAttributes m_methodAttributes; private BindingFlags m_bindingFlags; private Signature? m_signature; - private INVOCATION_FLAGS m_invocationFlags; + private InvocationFlags m_invocationFlags; - internal INVOCATION_FLAGS InvocationFlags + internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - INVOCATION_FLAGS flags = m_invocationFlags; - if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + InvocationFlags flags = m_invocationFlags; + if ((flags & InvocationFlags.Initialized) == 0) { flags = ComputeAndUpdateInvocationFlags(this, ref m_invocationFlags); } @@ -198,7 +198,7 @@ public override MethodImplAttributes GetMethodImplementationFlags() Justification = "This ConstructorInfo instance represents the static constructor itself, so if this object was created, the static constructor exists.")] private object? InvokeClassConstructor() { - Debug.Assert((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR) != 0); + Debug.Assert((InvocationFlags & InvocationFlags.RunClassConstructor) != 0); var declaringType = DeclaringType; if (declaringType != null) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index cb99ed3d59f63c..1fc33fdb1b00a6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -27,15 +27,15 @@ internal sealed partial class RuntimeMethodInfo : MethodInfo, IRuntimeMethodInfo private Signature? m_signature; private RuntimeType m_declaringType; private object? m_keepalive; - private INVOCATION_FLAGS m_invocationFlags; + private InvocationFlags m_invocationFlags; - internal INVOCATION_FLAGS InvocationFlags + internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - INVOCATION_FLAGS flags = m_invocationFlags; - if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + InvocationFlags flags = m_invocationFlags; + if ((flags & InvocationFlags.Initialized) == 0) { flags = ComputeAndUpdateInvocationFlags(this, ref m_invocationFlags); } @@ -326,10 +326,10 @@ public override MethodImplAttributes GetMethodImplementationFlags() [Diagnostics.DebuggerHidden] internal object? InvokeOneParameter(object? obj, BindingFlags invokeAttr, Binder? binder, object? parameter, CultureInfo? culture) { - // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS means that the struct (either the declaring type or the return type) + // 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 // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects. - if ((InvocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0) + if ((InvocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) { ThrowNoInvokeException(); } 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 4c098f408460b5..600f29f4efaabe 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 @@ -602,7 +602,7 @@ - + diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvocationFlags.cs similarity index 50% rename from src/libraries/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs rename to src/libraries/System.Private.CoreLib/src/System/Reflection/InvocationFlags.cs index b6a55518914a22..1288e853aeed5c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/INVOCATION_FLAGS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvocationFlags.cs @@ -8,31 +8,26 @@ namespace System.Reflection // so be careful if you change them // [Flags] - internal enum INVOCATION_FLAGS : uint + internal enum InvocationFlags : uint { - INVOCATION_FLAGS_UNKNOWN = 0x00000000, - INVOCATION_FLAGS_INITIALIZED = 0x00000001, + Unknown = 0x00000000, + Initialized = 0x00000001, // it's used for both method and field to signify that no access is allowed - INVOCATION_FLAGS_NO_INVOKE = 0x00000002, + NoInvoke = 0x00000002, // Set for static ctors, to ensure that the static ctor is run as a static ctor before it is explicitly executed via reflection - INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR = 0x00000004, + RunClassConstructor = 0x00000004, // Set for static ctors and ctors on abstract types, which // can be invoked only if the "this" object is provided (even if it's null). - INVOCATION_FLAGS_NO_CTOR_INVOKE = 0x00000008, + NoConstructorInvoke = 0x00000008, // because field and method are different we can reuse the same bits // method - INVOCATION_FLAGS_IS_CTOR = 0x00000010, + IsConstructor = 0x00000010, /* unused 0x00000020 */ /* unused 0x00000040 */ - INVOCATION_FLAGS_IS_DELEGATE_CTOR = 0x00000080, - INVOCATION_FLAGS_CONTAINS_STACK_POINTERS = 0x00000100, + IsDelegateConstructor = 0x00000080, + ContainsStackPointers = 0x00000100, // field - INVOCATION_FLAGS_SPECIAL_FIELD = 0x00000010, - INVOCATION_FLAGS_FIELD_SPECIAL_CAST = 0x00000020, - - // temporary flag used for flagging invocation of method vs ctor - // this flag never appears on the instance m_invocationFlag and is simply - // passed down from within ConstructorInfo.Invoke() - INVOCATION_FLAGS_CONSTRUCTOR_INVOKE = 0x10000000, + SpecialField = 0x00000010, + FieldSpecialCast = 0x00000020, } } 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 197863ce2edaa6..ff97409dc07233 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -11,9 +11,9 @@ namespace System.Reflection internal sealed partial class RuntimeConstructorInfo : ConstructorInfo { [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path - private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(ConstructorInfo constructorInfo, ref INVOCATION_FLAGS flagsToUpdate) + private static InvocationFlags ComputeAndUpdateInvocationFlags(ConstructorInfo constructorInfo, ref InvocationFlags flagsToUpdate) { - INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR; // this is a given + InvocationFlags invocationFlags = InvocationFlags.IsConstructor; // this is a given Type? declaringType = constructorInfo.DeclaringType; @@ -22,29 +22,29 @@ private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(ConstructorInfo || (constructorInfo.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs ) { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + invocationFlags |= InvocationFlags.NoInvoke; } else if (constructorInfo.IsStatic) { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR | - INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE; + invocationFlags |= InvocationFlags.RunClassConstructor | + InvocationFlags.NoConstructorInvoke; } else if (declaringType != null && declaringType.IsAbstract) { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE; + invocationFlags |= InvocationFlags.NoConstructorInvoke; } else { // Check for byref-like types if (declaringType != null && declaringType.IsByRefLike) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; + invocationFlags |= InvocationFlags.ContainsStackPointers; // Check for attempt to create a delegate class. if (typeof(Delegate).IsAssignableFrom(constructorInfo.DeclaringType)) - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR; + invocationFlags |= InvocationFlags.IsDelegateConstructor; } - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; + invocationFlags |= InvocationFlags.Initialized; flagsToUpdate = invocationFlags; // accesses are guaranteed atomic return invocationFlags; } @@ -101,12 +101,12 @@ internal void ThrowNoInvokeException() public override object? Invoke( object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { - if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0) + if ((InvocationFlags & InvocationFlags.NoInvoke) != 0) ThrowNoInvokeException(); ValidateInvokeTarget(obj); - if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RUN_CLASS_CONSTRUCTOR) != 0) + if ((InvocationFlags & InvocationFlags.RunClassConstructor) != 0) { // Run the class constructor through the class constructor mechanism instead of the Invoke path. // This avoids allowing mutation of readonly static fields, and initializes the type correctly. @@ -143,7 +143,7 @@ internal void ThrowNoInvokeException() [Diagnostics.DebuggerHidden] public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { - if ((InvocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS | INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE)) != 0) + if ((InvocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers | InvocationFlags.NoConstructorInvoke)) != 0) { ThrowNoInvokeException(); } 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 adec507f40eba5..7d2f60c2a78167 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -11,9 +11,9 @@ namespace System.Reflection internal sealed partial class RuntimeMethodInfo : MethodInfo { [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path - private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(MethodInfo methodInfo, ref INVOCATION_FLAGS flagsToUpdate) + private static InvocationFlags ComputeAndUpdateInvocationFlags(MethodInfo methodInfo, ref InvocationFlags flagsToUpdate) { - INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN; + InvocationFlags invocationFlags = InvocationFlags.Unknown; Type? declaringType = methodInfo.DeclaringType; @@ -22,7 +22,7 @@ private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(MethodInfo metho || (methodInfo.CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs // Managed varargs ) { - invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + invocationFlags = InvocationFlags.NoInvoke; } else { @@ -30,21 +30,21 @@ private static INVOCATION_FLAGS ComputeAndUpdateInvocationFlags(MethodInfo metho { if (declaringType.ContainsGenericParameters) // Enclosing type has unbound generics { - invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE; + invocationFlags = InvocationFlags.NoInvoke; } else if (declaringType.IsByRefLike) // Check for byref-like types { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; + invocationFlags |= InvocationFlags.ContainsStackPointers; } } if (methodInfo.ReturnType.IsByRefLike) // Check for byref-like types for return { - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS; + invocationFlags |= InvocationFlags.ContainsStackPointers; } } - invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED; + invocationFlags |= InvocationFlags.Initialized; flagsToUpdate = invocationFlags; // accesses are guaranteed atomic return invocationFlags; @@ -62,7 +62,7 @@ static bool IsDisallowedByRefType(Type type) private void ThrowNoInvokeException() { // method is on a class that contains stack pointers - if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS) != 0) + if ((InvocationFlags & InvocationFlags.ContainsStackPointers) != 0) { throw new NotSupportedException(); } @@ -97,10 +97,10 @@ private void ThrowNoInvokeException() [Diagnostics.DebuggerHidden] public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { - // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS means that the struct (either the declaring type or the return type) + // 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 // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects. - if ((InvocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0) + if ((InvocationFlags & (InvocationFlags.NoInvoke | InvocationFlags.ContainsStackPointers)) != 0) { ThrowNoInvokeException(); } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 7089e5b4bfc754..2b3b81d70bb46c 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -150,15 +150,15 @@ internal sealed partial class RuntimeMethodInfo : MethodInfo #endregion private string? toString; private RuntimeType[]? parameterTypes; - private INVOCATION_FLAGS invocationFlags; + private InvocationFlags invocationFlags; - internal INVOCATION_FLAGS InvocationFlags + internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - INVOCATION_FLAGS flags = invocationFlags; - if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + InvocationFlags flags = invocationFlags; + if ((flags & InvocationFlags.Initialized) == 0) { flags = ComputeAndUpdateInvocationFlags(this, ref invocationFlags); } @@ -784,15 +784,15 @@ internal sealed partial class RuntimeConstructorInfo : ConstructorInfo #endregion private string? toString; private RuntimeType[]? parameterTypes; - private INVOCATION_FLAGS invocationFlags; + private InvocationFlags invocationFlags; - internal INVOCATION_FLAGS InvocationFlags + internal InvocationFlags InvocationFlags { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - INVOCATION_FLAGS flags = invocationFlags; - if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0) + InvocationFlags flags = invocationFlags; + if ((flags & InvocationFlags.Initialized) == 0) { flags = ComputeAndUpdateInvocationFlags(this, ref invocationFlags); } From 009ae6805c9858e1296d311ede8d46ef5dfc0309 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 12 Oct 2021 16:56:19 -0700 Subject: [PATCH 08/16] Feedback for coreclr/ --- .../src/System/Reflection/RuntimeConstructorInfo.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index afb73a74a53185..9cd7f91f23e01e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -196,17 +196,19 @@ public override MethodImplAttributes GetMethodImplementationFlags() [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2059:RunClassConstructor", Justification = "This ConstructorInfo instance represents the static constructor itself, so if this object was created, the static constructor exists.")] - private object? InvokeClassConstructor() + private void InvokeClassConstructor() { Debug.Assert((InvocationFlags & InvocationFlags.RunClassConstructor) != 0); var declaringType = DeclaringType; if (declaringType != null) + { RuntimeHelpers.RunClassConstructor(declaringType.TypeHandle); + } else + { RuntimeHelpers.RunModuleConstructor(Module.ModuleHandle); - - return null; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] From e619773679cd93b662ac02ca9604a42edb9e4909 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 12 Oct 2021 16:56:40 -0700 Subject: [PATCH 09/16] Feedback for libraries/ --- .../src/System/Reflection/RuntimeConstructorInfo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 ff97409dc07233..430071eb32def0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -110,7 +110,8 @@ internal void ThrowNoInvokeException() { // Run the class constructor through the class constructor mechanism instead of the Invoke path. // This avoids allowing mutation of readonly static fields, and initializes the type correctly. - return InvokeClassConstructor(); + InvokeClassConstructor(); + return null; } // Correct number of arguments supplied From 655b9e37f1909f7e2341811a02f2fa5012d29265 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 12 Oct 2021 16:58:04 -0700 Subject: [PATCH 10/16] Updates to mono/ --- .../System/Reflection/RuntimeMethodInfo.cs | 5 ++-- src/mono/mono/metadata/boehm-gc.c | 6 ----- src/mono/mono/metadata/icall.c | 8 +++---- src/mono/mono/metadata/null-gc.c | 6 ----- src/mono/mono/metadata/object-internals.h | 23 ++++++++---------- src/mono/mono/metadata/object.c | 24 +++++++++---------- src/mono/mono/metadata/sgen-mono.c | 20 ---------------- 7 files changed, 29 insertions(+), 63 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 2b3b81d70bb46c..9ddd3e7a0bfadc 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -855,9 +855,10 @@ private RuntimeType[] ArgumentTypes } } - private object? InvokeClassConstructor() + private void InvokeClassConstructor() { - return null; + // [TODO] Mechanism for invoking class constructor + // See https://github.com/dotnet/runtime/issues/40351 } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/mono/mono/metadata/boehm-gc.c b/src/mono/mono/metadata/boehm-gc.c index ead6e81f084d80..bdda3e69b8b028 100644 --- a/src/mono/mono/metadata/boehm-gc.c +++ b/src/mono/mono/metadata/boehm-gc.c @@ -871,12 +871,6 @@ mono_gc_wbarrier_set_field_internal (MonoObject *obj, gpointer field_ptr, MonoOb *(void**)field_ptr = value; } -void -mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value) -{ - *(void**)slot_ptr = value; -} - void mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, gpointer slot_ptr, MonoObject* value) { diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 60b3c5323f576c..546c788af83de7 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -3403,11 +3403,11 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa if (m_class_get_rank (m->klass) && !strcmp (m->name, ".ctor")) { int i; - pcount = mono_span_length_internal (params_span); + pcount = mono_span_length (params_span); uintptr_t * const lengths = g_newa (uintptr_t, pcount); /* Note: the synthetized array .ctors have int32 as argument type */ for (i = 0; i < pcount; ++i) - lengths [i] = *(int32_t*) ((char*)mono_span_get_internal (params_span, MonoObject*, i) + sizeof (MonoObject)); + lengths [i] = *(int32_t*) ((char*)mono_span_get (params_span, MonoObject*, i) + sizeof (MonoObject)); if (m_class_get_rank (m->klass) == 1 && sig->param_count == 2 && m_class_get_rank (m_class_get_element_class (m->klass))) { /* This is a ctor for jagged arrays. MS creates an array of arrays. */ @@ -3436,8 +3436,8 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa intptr_t * const lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount); for (i = 0; i < pcount / 2; ++i) { - lower_bounds [i] = *(int32_t*) ((char*)mono_span_get_internal (params_span, MonoObject*, (i * 2)) + sizeof (MonoObject)); - lengths [i] = *(int32_t*) ((char*)mono_span_get_internal (params_span, MonoObject*, (i * 2) + 1) + sizeof (MonoObject)); + lower_bounds [i] = *(int32_t*) ((char*)mono_span_get (params_span, MonoObject*, (i * 2)) + sizeof (MonoObject)); + lengths [i] = *(int32_t*) ((char*)mono_span_get (params_span, MonoObject*, (i * 2) + 1) + sizeof (MonoObject)); } arr = mono_array_new_full_checked (m->klass, lengths, lower_bounds, error); diff --git a/src/mono/mono/metadata/null-gc.c b/src/mono/mono/metadata/null-gc.c index 511a1d2d35f440..343756d2c67da4 100644 --- a/src/mono/mono/metadata/null-gc.c +++ b/src/mono/mono/metadata/null-gc.c @@ -282,12 +282,6 @@ mono_gc_wbarrier_set_field_internal (MonoObject *obj, gpointer field_ptr, MonoOb *(void**)field_ptr = value; } -void -mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value) -{ - *(void**)slot_ptr = value; -} - void mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, gpointer slot_ptr, MonoObject* value) { diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index a44f072d1b7186..c120bfec72ff7f 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -178,7 +178,7 @@ struct _MonoArray { /* match the layout of the managed definition of Span */ typedef struct { MonoObject** _pointer; - int _length; + int32_t _length; } MonoSpanOfObjects; #define MONO_SIZEOF_MONO_ARRAY (MONO_STRUCT_OFFSET_CONSTANT (MonoArray, vector)) @@ -282,26 +282,26 @@ mono_handle_array_get_bounds_dim (MonoArrayHandle arr, gint32 dim, MonoArrayBoun *bounds = MONO_HANDLE_GETVAL (arr, bounds [dim]); } -#define mono_span_length_internal(span) (span._length) +#define mono_span_length(span) (span._length) -#define mono_span_get_internal(span,type,idx) (type)(!span._pointer ? NULL : span._pointer[idx]) +#define mono_span_get(span,type,idx) (type)(!span._pointer ? NULL : span._pointer[idx]) -#define mono_span_addr_internal(span,type,idx) (type*)(span._pointer + idx) +#define mono_span_addr(span,type,idx) (type*)(span._pointer + idx) -#define mono_span_setref_internal(span,index,value) \ +#define mono_span_setref(span,index,value) \ do { \ - void **__p = (void **) mono_span_addr_internal ((span), void*, (index)); \ - mono_gc_wbarrier_set_spanref_internal ((&span), __p, (MonoObject*)(value)); \ + void **__p = (void **) mono_span_addr ((span), void*, (index)); \ + mono_gc_wbarrier_generic_store_internal (__p, (MonoObject*)(value)); \ /* *__p = (value);*/ \ } while (0) -static inline MonoSpanOfObjects mono_span_create_from_object_array_internal (MonoArray *arr) { +static inline MonoSpanOfObjects +mono_span_create_from_object_array (MonoArray *arr) { MonoSpanOfObjects span; if (arr != NULL) { span._length = (int)mono_array_length_internal (arr); span._pointer = mono_array_addr_fast (arr, MonoObject*, 0); - } - else { + } else { span._length = 0; span._pointer = NULL; } @@ -2090,9 +2090,6 @@ mono_gc_reference_queue_add_internal (MonoReferenceQueue *queue, MonoObject *obj void mono_gc_wbarrier_set_field_internal (MonoObject *obj, void* field_ptr, MonoObject* value); -void -mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value); - void mono_gc_wbarrier_set_arrayref_internal (MonoArray *arr, void* slot_ptr, MonoObject* value); diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 71a8ed136f2f82..aa6c90dcce6732 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -4554,17 +4554,17 @@ invoke_span_extract_argument (MonoSpanOfObjects params_span, int i, MonoType *t, case MONO_TYPE_VALUETYPE: if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type_internal (t_orig))) { /* The runtime invoke wrapper needs the original boxed vtype, it does handle byref values as well. */ - *pa_obj = mono_span_get_internal (params_span, MonoObject*, i); + *pa_obj = mono_span_get (params_span, MonoObject*, i); result = *pa_obj; if (t->byref) *has_byref_nullables = TRUE; } else { /* MS seems to create the objects if a null is passed in */ gboolean was_null = FALSE; - if (!mono_span_get_internal (params_span, MonoObject*, i)) { + if (!mono_span_get (params_span, MonoObject*, i)) { MonoObject *o = mono_object_new_checked (mono_class_from_mono_type_internal (t_orig), error); return_val_if_nok (error, NULL); - mono_span_setref_internal (params_span, i, o); + mono_span_setref (params_span, i, o); was_null = TRUE; } @@ -4576,15 +4576,15 @@ invoke_span_extract_argument (MonoSpanOfObjects params_span, int i, MonoType *t, * object, pass that to the callee, and replace the original * boxed object in the arg array with the copy. */ - MonoObject *orig = mono_span_get_internal (params_span, MonoObject*, i); + MonoObject *orig = mono_span_get (params_span, MonoObject*, i); MonoObject *copy = mono_value_box_checked (orig->vtable->klass, mono_object_unbox_internal (orig), error); return_val_if_nok (error, NULL); - mono_span_setref_internal (params_span, i, copy); + mono_span_setref (params_span, i, copy); } - *pa_obj = mono_span_get_internal (params_span, MonoObject*, i); + *pa_obj = mono_span_get (params_span, MonoObject*, i); result = mono_object_unbox_internal (*pa_obj); if (!t->byref && was_null) - mono_span_setref_internal (params_span, i, NULL); + mono_span_setref (params_span, i, NULL); } break; case MONO_TYPE_STRING: @@ -4593,10 +4593,10 @@ invoke_span_extract_argument (MonoSpanOfObjects params_span, int i, MonoType *t, case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: if (t->byref) { - result = mono_span_addr_internal (params_span, MonoObject*, i); + result = mono_span_addr (params_span, MonoObject*, i); // FIXME: I need to check this code path } else { - *pa_obj = mono_span_get_internal (params_span, MonoObject*, i); + *pa_obj = mono_span_get (params_span, MonoObject*, i); result = *pa_obj; } break; @@ -4610,7 +4610,7 @@ invoke_span_extract_argument (MonoSpanOfObjects params_span, int i, MonoType *t, MonoObject *arg; /* The argument should be an IntPtr */ - arg = mono_span_get_internal (params_span, MonoObject*, i); + arg = mono_span_get (params_span, MonoObject*, i); if (arg == NULL) { result = NULL; } else { @@ -4694,7 +4694,7 @@ mono_runtime_try_invoke_span (MonoMethod *method, void *obj, MonoSpanOfObjects p MonoObject *res = NULL; int i; gboolean has_byref_nullables = FALSE; - int params_length = mono_span_length_internal (params_span); + int params_length = mono_span_length (params_span); if (params_length > 0) { pa = g_newa (gpointer, params_length); @@ -4905,7 +4905,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, MONO_REQ_GC_UNSAFE_MODE; HANDLE_FUNCTION_ENTER (); - MonoSpanOfObjects params_span = mono_span_create_from_object_array_internal (params); + MonoSpanOfObjects params_span = mono_span_create_from_object_array (params); MonoObject *res = mono_runtime_try_invoke_span (method, obj, params_span, exc, error); HANDLE_FUNCTION_RETURN_VAL (res); diff --git a/src/mono/mono/metadata/sgen-mono.c b/src/mono/mono/metadata/sgen-mono.c index 7a37b6a5c8fbc4..c04e5dba6a57f6 100644 --- a/src/mono/mono/metadata/sgen-mono.c +++ b/src/mono/mono/metadata/sgen-mono.c @@ -44,7 +44,6 @@ #endif #ifdef HEAVY_STATISTICS -static guint64 stat_wbarrier_set_spanref = 0; static guint64 stat_wbarrier_set_arrayref = 0; static guint64 stat_wbarrier_value_copy = 0; static guint64 stat_wbarrier_object_copy = 0; @@ -166,24 +165,6 @@ mono_gc_wbarrier_object_copy_internal (MonoObject* obj, MonoObject *src) sgen_get_remset ()->wbarrier_object_copy (obj, src); } -/** - * mono_gc_wbarrier_set_spanref_internal: - */ -void -mono_gc_wbarrier_set_spanref_internal (MonoSpanOfObjects *span, void* slot_ptr, MonoObject* value) -{ - HEAVY_STAT (++stat_wbarrier_set_spanref); - if (sgen_ptr_in_nursery (slot_ptr)) { - *(void**)slot_ptr = value; - return; - } - SGEN_LOG (8, "Adding remset at %p", slot_ptr); - if (value) - sgen_binary_protocol_wbarrier (slot_ptr, value, value->vtable); - - sgen_get_remset ()->wbarrier_set_field (NULL, slot_ptr, value); -} - /** * mono_gc_wbarrier_set_arrayref_internal: */ @@ -3125,7 +3106,6 @@ mono_gc_base_init (void) mono_counters_register ("los array cards scanned ", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_cards); mono_counters_register ("los array remsets", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_remsets); - mono_counters_register ("WBarrier set spanref", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_set_spanref); mono_counters_register ("WBarrier set arrayref", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_set_arrayref); mono_counters_register ("WBarrier value copy", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_value_copy); mono_counters_register ("WBarrier object copy", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_wbarrier_object_copy); From 54bc44d24d810309d3b2f80bd65743be59dea80d Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 13 Oct 2021 09:58:19 -0700 Subject: [PATCH 11/16] Style for flags. --- .../src/System/Reflection/RuntimeConstructorInfo.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 430071eb32def0..e3502601407cff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -26,8 +26,7 @@ private static InvocationFlags ComputeAndUpdateInvocationFlags(ConstructorInfo c } else if (constructorInfo.IsStatic) { - invocationFlags |= InvocationFlags.RunClassConstructor | - InvocationFlags.NoConstructorInvoke; + invocationFlags |= InvocationFlags.RunClassConstructor | InvocationFlags.NoConstructorInvoke; } else if (declaringType != null && declaringType.IsAbstract) { From e2db34067dad3a8eff75f864c3f25628c374b6ad Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 13 Oct 2021 14:03:33 -0700 Subject: [PATCH 12/16] Updates to coreclr/ --- .../src/System/Reflection/RuntimeConstructorInfo.cs | 4 ++-- .../src/System/Reflection/RuntimeMethodInfo.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index 9cd7f91f23e01e..8ac8a44be9448c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -212,14 +212,14 @@ private void InvokeClassConstructor() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span arguments) + private object? InvokeWorker(object? obj, BindingFlags invokeAttr, in Span arguments) { bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private object InvokeCtorWorker(BindingFlags invokeAttr, Span arguments) + private object InvokeCtorWorker(BindingFlags invokeAttr, in Span arguments) { bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; return RuntimeMethodHandle.InvokeMethod(null, arguments, Signature, true, wrapExceptions)!; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 1fc33fdb1b00a6..4710e6d3b7e6e2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -316,7 +316,7 @@ public override MethodImplAttributes GetMethodImplementationFlags() #region Invocation Logic(On MemberBase) [MethodImpl(MethodImplOptions.AggressiveInlining)] - private object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span arguments) + private object? InvokeWorker(object? obj, BindingFlags invokeAttr, in Span arguments) { bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions); From 6a853b7cc55e61a2f0b67515f44b3507e5c1ae8e Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 13 Oct 2021 14:03:44 -0700 Subject: [PATCH 13/16] Updates to mono/ --- .../src/System/Reflection/RuntimeMethodInfo.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 9ddd3e7a0bfadc..1c6e10f1db2339 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -371,10 +371,10 @@ private RuntimeType[] ArgumentTypes * Exceptions thrown by the called method propagate normally. */ [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern object? InternalInvoke(object? obj, Span parameters, out Exception? exc); + internal extern object? InternalInvoke(object? obj, in Span parameters, out Exception? exc); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span parameters) + private object? InvokeWorker(object? obj, BindingFlags invokeAttr, in Span parameters) { Exception? exc; object? o = null; @@ -862,7 +862,7 @@ private void InvokeClassConstructor() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal object? InvokeWorker(object? obj, BindingFlags invokeAttr, Span arguments) + internal object? InvokeWorker(object? obj, BindingFlags invokeAttr, in Span arguments) { bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; return InternalInvoke(obj, arguments, wrapExceptions); @@ -880,7 +880,7 @@ internal object InvokeCtorWorker(BindingFlags invokeAttr, Span argument * to match the types of the method signature. */ [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern object InternalInvoke(object? obj, Span parameters, out Exception exc); + internal extern object InternalInvoke(object? obj, in Span parameters, out Exception exc); private object? InternalInvoke(object? obj, Span parameters, bool wrapExceptions) { From e650f4fa609f9672272b81bc59ccff17ab792b45 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 13 Oct 2021 16:18:13 -0700 Subject: [PATCH 14/16] Updates to mono/ for CALLI signatures to use 'in by-ref'. --- src/mono/mono/metadata/icall-def-netcore.h | 2 +- src/mono/mono/metadata/icall-table.h | 3 ++- src/mono/mono/metadata/icall.c | 3 ++- src/mono/mono/metadata/object-internals.h | 8 ++++---- src/mono/mono/metadata/object.c | 8 ++++---- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/mono/mono/metadata/icall-def-netcore.h b/src/mono/mono/metadata/icall-def-netcore.h index 2e86b5e05ffaf2..983cc5330f0cba 100644 --- a/src/mono/mono/metadata/icall-def-netcore.h +++ b/src/mono/mono/metadata/icall-def-netcore.h @@ -254,7 +254,7 @@ HANDLES(RASSEM_12, "get_location", ves_icall_System_Reflection_RuntimeAssembly_g ICALL_TYPE(MCMETH, "System.Reflection.RuntimeConstructorInfo", MCMETH_1) HANDLES(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition, MonoReflectionMethod, 1, (MonoReflectionMethod)) -HANDLES(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoSpanOfObjects, MonoExceptionOut)) +HANDLES(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke, MonoObject, 4, (MonoReflectionMethod, MonoObject, MonoSpanOfObjects_ref, MonoExceptionOut)) HANDLES_REUSE_WRAPPER(MCMETH_4, "get_metadata_token", ves_icall_reflection_get_token) ICALL_TYPE(CATTR_DATA, "System.Reflection.RuntimeCustomAttributeData", CATTR_DATA_1) diff --git a/src/mono/mono/metadata/icall-table.h b/src/mono/mono/metadata/icall-table.h index 23870dd5f595ba..f5d303d392304e 100644 --- a/src/mono/mono/metadata/icall-table.h +++ b/src/mono/mono/metadata/icall-table.h @@ -69,6 +69,7 @@ typedef MonoVTable *MonoVTable_ptr; typedef unsigned *unsigned_ptr; typedef mono_unichar2 *mono_unichar2_ptr; typedef mono_unichar4 *mono_unichar4_ptr; +typedef MonoSpanOfObjects *MonoSpanOfObjects_ref; typedef char **char_ptr_ref; typedef gint32 *gint32_ref; @@ -150,7 +151,6 @@ typedef MonoStringHandle MonoStringOutHandle; #define MONO_HANDLE_TYPE_WRAP_MonoProperty_ptr ICALL_HANDLES_WRAP_NONE #define MONO_HANDLE_TYPE_WRAP_size_t ICALL_HANDLES_WRAP_NONE #define MONO_HANDLE_TYPE_WRAP_MonoVTable_ptr ICALL_HANDLES_WRAP_NONE -#define MONO_HANDLE_TYPE_WRAP_MonoSpanOfObjects ICALL_HANDLES_WRAP_NONE #define MONO_HANDLE_TYPE_WRAP_MonoAssemblyName_ref ICALL_HANDLES_WRAP_VALUETYPE_REF #define MONO_HANDLE_TYPE_WRAP_MonoBoolean_ref ICALL_HANDLES_WRAP_VALUETYPE_REF @@ -174,6 +174,7 @@ typedef MonoStringHandle MonoStringOutHandle; #define MONO_HANDLE_TYPE_WRAP_char_ptr_ref ICALL_HANDLES_WRAP_VALUETYPE_REF #define MONO_HANDLE_TYPE_WRAP_guint8_ptr_ref ICALL_HANDLES_WRAP_VALUETYPE_REF #define MONO_HANDLE_TYPE_WRAP_MonoResolveTokenError_ref ICALL_HANDLES_WRAP_VALUETYPE_REF +#define MONO_HANDLE_TYPE_WRAP_MonoSpanOfObjects_ref ICALL_HANDLES_WRAP_VALUETYPE_REF // HANDLE is not used just to avoid duplicate typedef warnings with some compilers. // gpointer == void* == HANDLE == FILE_HANDLE == PROCESS_HANDLE. diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 546c788af83de7..898d66a1a195c5 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -3354,10 +3354,11 @@ ves_icall_RuntimeMethodInfo_GetGenericArguments (MonoReflectionMethodHandle ref_ MonoObjectHandle ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHandle this_arg_handle, - MonoSpanOfObjects params_span, MonoExceptionHandleOut exception_out, MonoError *error) + MonoSpanOfObjects *params_span, MonoExceptionHandleOut exception_out, MonoError *error) { MonoReflectionMethod* const method = MONO_HANDLE_RAW (method_handle); MonoObject* const this_arg = MONO_HANDLE_RAW (this_arg_handle); + g_assert (params_span != NULL); /* * Invoke from reflection is supposed to always be a virtual call (the API diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index c120bfec72ff7f..cc111c50c60a71 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -282,11 +282,11 @@ mono_handle_array_get_bounds_dim (MonoArrayHandle arr, gint32 dim, MonoArrayBoun *bounds = MONO_HANDLE_GETVAL (arr, bounds [dim]); } -#define mono_span_length(span) (span._length) +#define mono_span_length(span) (span->_length) -#define mono_span_get(span,type,idx) (type)(!span._pointer ? NULL : span._pointer[idx]) +#define mono_span_get(span,type,idx) (type)(!span->_pointer ? NULL : span->_pointer[idx]) -#define mono_span_addr(span,type,idx) (type*)(span._pointer + idx) +#define mono_span_addr(span,type,idx) (type*)(span->_pointer + idx) #define mono_span_setref(span,index,value) \ do { \ @@ -1870,7 +1870,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, MonoObject **exc, MonoError *error); MonoObject* -mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects params, +mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects *params, MonoError *error); void* diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index aa6c90dcce6732..2d5b10917a4603 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -4529,7 +4529,7 @@ mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **ex * On failure sets @error and returns NULL. */ static gpointer -invoke_span_extract_argument (MonoSpanOfObjects params_span, int i, MonoType *t, MonoObject **pa_obj, gboolean* has_byref_nullables, MonoError *error) +invoke_span_extract_argument (MonoSpanOfObjects *params_span, int i, MonoType *t, MonoObject **pa_obj, gboolean* has_byref_nullables, MonoError *error) { MonoType *t_orig = t; gpointer result = NULL; @@ -4684,7 +4684,7 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params, } static MonoObject* -mono_runtime_try_invoke_span (MonoMethod *method, void *obj, MonoSpanOfObjects params_span, +mono_runtime_try_invoke_span (MonoMethod *method, void *obj, MonoSpanOfObjects *params_span, MonoObject **exc, MonoError *error) { error_init (error); @@ -4853,7 +4853,7 @@ mono_runtime_try_invoke_span (MonoMethod *method, void *obj, MonoSpanOfObjects p * reference. */ MonoObject* -mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects params, +mono_runtime_invoke_span_checked (MonoMethod *method, void *obj, MonoSpanOfObjects *params, MonoError *error) { error_init (error); @@ -4906,7 +4906,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, HANDLE_FUNCTION_ENTER (); MonoSpanOfObjects params_span = mono_span_create_from_object_array (params); - MonoObject *res = mono_runtime_try_invoke_span (method, obj, params_span, exc, error); + MonoObject *res = mono_runtime_try_invoke_span (method, obj, ¶ms_span, exc, error); HANDLE_FUNCTION_RETURN_VAL (res); } From 0658e94bc7a4b8f139d6382c5b2df57ab05914de Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 13 Oct 2021 18:33:49 -0700 Subject: [PATCH 15/16] Updates to mono/ - fix cast to int32_t. --- src/mono/mono/metadata/object-internals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index cc111c50c60a71..9d37d996b14088 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -299,7 +299,7 @@ static inline MonoSpanOfObjects mono_span_create_from_object_array (MonoArray *arr) { MonoSpanOfObjects span; if (arr != NULL) { - span._length = (int)mono_array_length_internal (arr); + span._length = (int32_t)mono_array_length_internal (arr); span._pointer = mono_array_addr_fast (arr, MonoObject*, 0); } else { span._length = 0; From 32143f096576cb25c15fb2144c3041469d1de0dd Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Thu, 14 Oct 2021 11:57:30 -0700 Subject: [PATCH 16/16] Rename various files to match partial class style. --- .../System.Private.CoreLib/System.Private.CoreLib.csproj | 4 ++-- ...meConstructorInfo.cs => RuntimeConstructorInfo.CoreCLR.cs} | 0 .../{RuntimeMethodInfo.cs => RuntimeMethodInfo.CoreCLR.cs} | 0 src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj | 2 +- .../{RuntimeMethodInfo.cs => RuntimeMethodInfo.Mono.cs} | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename src/coreclr/System.Private.CoreLib/src/System/Reflection/{RuntimeConstructorInfo.cs => RuntimeConstructorInfo.CoreCLR.cs} (100%) rename src/coreclr/System.Private.CoreLib/src/System/Reflection/{RuntimeMethodInfo.cs => RuntimeMethodInfo.CoreCLR.cs} (100%) rename src/mono/System.Private.CoreLib/src/System/Reflection/{RuntimeMethodInfo.cs => RuntimeMethodInfo.Mono.cs} (100%) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 5114c10ee714bd..cb9ca774e43b10 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -186,14 +186,14 @@ - + - + diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs rename to src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.CoreCLR.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs rename to src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 64ee4cbd6ac644..622b664f10b801 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -202,7 +202,7 @@ - + diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs similarity index 100% rename from src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs rename to src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.Mono.cs