From cf083b6c2f798bb3ffcec5de199a7dad56f88214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 16 Sep 2026 13:12:45 +0900 Subject: [PATCH 1/2] Share CoreCLR RuntimeParameterInfo with NativeAOT Replace the NativeAOT parameter-info hierarchy with a sealed implementation sharing the existing CoreCLR source in place. Add native metadata handling and update method, property, and synthetic parameter construction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b689a562-006b-4ec0-8607-f5a91479388e --- .../System/Reflection/RuntimeParameterInfo.cs | 62 +++++- .../src/System.Private.CoreLib.csproj | 10 +- .../Reflection/ModifiedType.NativeAot.cs | 12 ++ .../NativeFormatRuntimeEventInfo.cs | 1 - .../Runtime/EventInfos/RuntimeEventInfo.cs | 1 - .../General/Dispensers.NativeFormat.cs | 14 -- .../Reflection/Runtime/General/Dispensers.cs | 36 ---- .../Runtime/General/QSignatureTypeHandle.cs | 6 +- .../MethodInfos/IRuntimeMethodCommon.cs | 8 +- .../NativeFormat/NativeFormatMethodCommon.cs | 18 +- .../Runtime/MethodInfos/OpenMethodInvoker.cs | 1 - .../RuntimeConstructedGenericMethodInfo.cs | 10 +- .../MethodInfos/RuntimeConstructorInfo.cs | 1 - .../MethodInfos/RuntimeDummyMethodInfo.cs | 4 +- .../MethodInfos/RuntimeMethodHelpers.cs | 43 +---- .../MethodInfos/RuntimeNamedMethodInfo.cs | 10 +- .../RuntimePlainConstructorInfo.cs | 3 +- .../RuntimeSyntheticConstructorInfo.cs | 3 +- .../MethodInfos/RuntimeSyntheticMethodInfo.cs | 11 +- .../Runtime/MethodInfos/SyntheticMethodId.cs | 1 - .../VirtualRuntimeParameterInfoArray.cs | 47 ----- .../NativeFormatMethodParameterInfo.cs | 157 ---------------- .../RuntimeFatMethodParameterInfo.cs | 70 ------- .../RuntimeMethodParameterInfo.cs | 45 ----- .../ParameterInfos/RuntimeParameterInfo.cs | 123 ------------ .../RuntimePropertyIndexParameterInfo.cs | 98 ---------- .../RuntimeSyntheticParameterInfo.cs | 88 --------- .../RuntimeThinMethodParameterInfo.cs | 77 -------- .../NativeFormatRuntimePropertyInfo.cs | 12 +- .../PropertyInfos/RuntimePropertyInfo.cs | 9 +- .../System/Reflection/RuntimeMethodInfo.cs | 23 +-- .../RuntimeParameterInfo.NativeAot.cs | 176 ++++++++++++++++++ .../Reflection/RuntimeCustomAttributeData.cs | 1 - 33 files changed, 305 insertions(+), 876 deletions(-) delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs create mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index d46d596ecec63d..8f36cde4c3662e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -4,13 +4,19 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; +#if NATIVEAOT +using System.Reflection.Runtime.General; +using System.Reflection.Runtime.PropertyInfos; +#else using MdToken = System.Reflection.MetadataToken; +#endif namespace System.Reflection { - internal sealed class RuntimeParameterInfo : ParameterInfo + internal sealed partial class RuntimeParameterInfo : ParameterInfo { #region Static Members +#if !NATIVEAOT internal static ParameterInfo[] GetParameters(IRuntimeMethodInfo method, MemberInfo member, Signature sig) { Debug.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo); @@ -109,12 +115,15 @@ private static ParameterInfo[] GetParameters( return args; } +#endif #endregion #region Private Data Members +#if !NATIVEAOT private readonly int m_tkParamDef; private readonly MetadataImport m_scope; private readonly Signature? m_signature; +#endif private volatile bool m_nameIsCached; private readonly bool m_noMetadata; private bool m_noDefaultValue; @@ -150,7 +159,11 @@ internal void SetAttributes(ParameterAttributes attributes) internal RuntimeParameterInfo(RuntimeParameterInfo accessor, RuntimePropertyInfo property) : this(accessor, (MemberInfo)property) { +#if NATIVEAOT + m_signature = property.GetParameterTypeHandle(PositionImpl); +#else m_signature = property.Signature; +#endif } private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member) @@ -172,10 +185,16 @@ private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member) // Strictly speaking, properties don't contain parameter tokens // However we need this to make ca's work... oh well... +#if NATIVEAOT + m_parameterHandle = accessor.m_parameterHandle; + m_typeContext = accessor.m_typeContext; +#else m_tkParamDef = MdToken.IsNullToken(accessor.MetadataToken) ? (int)MetadataTokenType.ParamDef : accessor.MetadataToken; +#endif m_scope = accessor.m_scope; } +#if !NATIVEAOT private RuntimeParameterInfo( Signature signature, MetadataImport scope, int tkParamDef, int position, ParameterAttributes attributes, MemberInfo member) @@ -194,6 +213,7 @@ private RuntimeParameterInfo( ClassImpl = null; NameImpl = null; } +#endif // ctor for no metadata MethodInfo in the DynamicMethod and RuntimeMethodInfo cases internal RuntimeParameterInfo(MethodInfo owner, string? name, Type parameterType, int position) @@ -205,7 +225,9 @@ internal RuntimeParameterInfo(MethodInfo owner, string? name, Type parameterType ClassImpl = parameterType; PositionImpl = position; AttrsImpl = ParameterAttributes.None; +#if !NATIVEAOT m_tkParamDef = (int)MetadataTokenType.ParamDef; +#endif m_scope = default; } #endregion @@ -218,6 +240,9 @@ public override Type ParameterType // only instance of ParameterInfo has ClassImpl, all its subclasses don't if (ClassImpl == null) { +#if NATIVEAOT + ClassImpl = m_signature.Resolve(m_typeContext).ToType(); +#else Debug.Assert(m_signature != null); RuntimeType parameterType; @@ -229,6 +254,7 @@ public override Type ParameterType Debug.Assert(parameterType != null); // different thread could only write ClassImpl to the same value, so a race condition is not a problem here ClassImpl = parameterType; +#endif } return ClassImpl; @@ -241,12 +267,20 @@ public override string? Name { if (!m_nameIsCached) { +#if NATIVEAOT + if (!m_parameterHandle.IsNil) + { + Debug.Assert(m_scope is not null); + NameImpl = m_scope.GetParameter(m_parameterHandle).Name.GetStringOrNull(m_scope) ?? string.Empty; + } +#else if (!MdToken.IsNullToken(m_tkParamDef)) { string name = m_scope.GetName(m_tkParamDef).ToString(); GC.KeepAlive(this); NameImpl = name; } +#endif // other threads could only write it to true, so a race condition is OK // this field is volatile, so the write ordering is guaranteed @@ -334,7 +368,11 @@ private bool TryGetDefaultValueInternal(bool raw, out object? defaultValue) { Debug.Assert(!m_noMetadata); +#if NATIVEAOT + if (m_noDefaultValue || m_parameterHandle.IsNil) +#else if (m_noDefaultValue || MdToken.IsNullToken(m_tkParamDef)) +#endif { defaultValue = DBNull.Value; m_noDefaultValue = true; @@ -344,8 +382,12 @@ private bool TryGetDefaultValueInternal(bool raw, out object? defaultValue) // Prioritize metadata constant over custom attribute constant #region Look for a default value in metadata // This will return DBNull.Value if no constant value is defined on m_tkParamDef in the metadata. +#if NATIVEAOT + defaultValue = GetDefaultValueFromMetadata(raw); +#else defaultValue = MdConstant.GetValue(m_scope, m_tkParamDef, ParameterType.TypeHandle, raw); GC.KeepAlive(this); +#endif // If default value is not specified in metadata, look for it in custom attributes if (defaultValue == DBNull.Value) @@ -414,6 +456,7 @@ private static DateTime GetRawDateTimeConstant(CustomAttributeData attr) return DBNull.Value; } +#if !NATIVEAOT internal RuntimeModule? GetRuntimeModule() { RuntimeMethodInfo? method = Member as RuntimeMethodInfo; @@ -444,13 +487,18 @@ public override Type[] GetOptionalCustomModifiers() public override Type GetModifiedParameterType() => ModifiedType.Create(unmodifiedType: ParameterType, m_signature, parameterIndex: PositionImpl + 1); +#endif #endregion #region ICustomAttributeProvider public override object[] GetCustomAttributes(bool inherit) { +#if NATIVEAOT + if (m_parameterHandle.IsNil) +#else if (MdToken.IsNullToken(m_tkParamDef)) +#endif return []; return RuntimeCustomAttribute.GetCustomAttributes(this, (typeof(object) as RuntimeType)!); @@ -463,7 +511,11 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit) if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); +#if NATIVEAOT + if (m_parameterHandle.IsNil) +#else if (MdToken.IsNullToken(m_tkParamDef)) +#endif return RuntimeCustomAttribute.CreateAttributeArrayHelper(attributeRuntimeType, 0); return RuntimeCustomAttribute.GetCustomAttributes(this, attributeRuntimeType); @@ -473,7 +525,11 @@ public override bool IsDefined(Type attributeType, bool inherit) { ArgumentNullException.ThrowIfNull(attributeType); +#if NATIVEAOT + if (m_parameterHandle.IsNil) +#else if (MdToken.IsNullToken(m_tkParamDef)) +#endif return false; if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) @@ -484,7 +540,11 @@ public override bool IsDefined(Type attributeType, bool inherit) public override IList GetCustomAttributesData() { +#if NATIVEAOT + if (m_parameterHandle.IsNil) +#else if (MdToken.IsNullToken(m_tkParamDef)) +#endif return Array.Empty(); return RuntimeCustomAttributeData.GetCustomAttributesInternal(this); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index ab73db0b2ee0e1..02d8b53cf8a6ae 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -63,6 +63,7 @@ + @@ -164,6 +165,7 @@ + @@ -434,16 +436,8 @@ - - - - - - - - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ModifiedType.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ModifiedType.NativeAot.cs index ca568de056be54..9edc3dbbb5dc53 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ModifiedType.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/ModifiedType.NativeAot.cs @@ -23,6 +23,9 @@ public TypeSignature(MetadataReader reader, Handle handle) internal Type GetTypeParameter(Type unmodifiedType, int index) { MetadataReader reader = _typeSignature.Reader; + if (reader is null) + return Create(unmodifiedType); + Handle handle = _typeSignature.Handle; while (handle.HandleType == HandleType.ModifiedType) @@ -77,6 +80,9 @@ internal Type GetTypeParameter(Type unmodifiedType, int index) internal SignatureCallingConvention GetCallingConventionFromFunctionPointer() { MetadataReader reader = _typeSignature.Reader; + if (reader is null) + return default; + Handle fnPtrTypeSigHandle = reader.GetTypeSpecification( _typeSignature.Handle.ToTypeSpecificationHandle(reader)).Signature; MethodSignatureHandle methodSigHandle = reader.GetFunctionPointerSignature( @@ -93,6 +99,9 @@ private Type[] GetCustomModifiers(bool required) ArrayBuilder builder = default; MetadataReader reader = _typeSignature.Reader; + if (reader is null) + return []; + Handle handle = _typeSignature.Handle; while (handle.HandleType == HandleType.ModifiedType) @@ -117,6 +126,9 @@ private Type[] GetCustomModifiers(bool required) return result; } + internal static Type Create(Type unmodifiedType) + => Create(unmodifiedType, default(TypeSignature)); + public static Type Create(Type unmodifiedType, MetadataReader reader, Handle typeSignature) => ModifiedType.Create(unmodifiedType, new TypeSignature(reader, typeSignature)); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs index e3e1b73dcb9bda..72ecdda97327d2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs @@ -8,7 +8,6 @@ using System.Reflection.Runtime.General; using System.Reflection.Runtime.MethodInfos; using System.Reflection.Runtime.MethodInfos.NativeFormat; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Reflection.Runtime.TypeInfos.NativeFormat; using System.Runtime.CompilerServices; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs index effe854a8facd3..06a79fd1e3a461 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Runtime.CompilerServices; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs index 7e4e24ec1549d6..a634114381c422 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs @@ -153,17 +153,3 @@ internal static RuntimeModule GetRuntimeModule(NativeFormatRuntimeAssembly assem } } } - -namespace System.Reflection.Runtime.ParameterInfos.NativeFormat -{ - //----------------------------------------------------------------------------------------------------------- - // ParameterInfos for MethodBase objects with Parameter metadata. - //----------------------------------------------------------------------------------------------------------- - internal sealed partial class NativeFormatMethodParameterInfo - { - internal static NativeFormatMethodParameterInfo GetNativeFormatMethodParameterInfo(MethodBase member, int position, ParameterHandle parameterHandle, QSignatureTypeHandle qualifiedParameterType, TypeContext typeContext) - { - return new NativeFormatMethodParameterInfo(member, position, parameterHandle, qualifiedParameterType, typeContext); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs index bca23c27f7216d..314c613a609b4f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs @@ -158,39 +158,3 @@ internal static RuntimeMethodInfo GetRuntimeSyntheticMethodInfo(SyntheticMethodI } } } - -namespace System.Reflection.Runtime.ParameterInfos -{ - //----------------------------------------------------------------------------------------------------------- - // ParameterInfos for MethodBase objects with no Parameter metadata. - //----------------------------------------------------------------------------------------------------------- - internal sealed partial class RuntimeThinMethodParameterInfo : RuntimeMethodParameterInfo - { - internal static RuntimeThinMethodParameterInfo GetRuntimeThinMethodParameterInfo(MethodBase member, int position, QSignatureTypeHandle qualifiedParameterType, TypeContext typeContext) - { - return new RuntimeThinMethodParameterInfo(member, position, qualifiedParameterType, typeContext); - } - } - - //----------------------------------------------------------------------------------------------------------- - // ParameterInfos returned by PropertyInfo.GetIndexParameters() - //----------------------------------------------------------------------------------------------------------- - internal sealed partial class RuntimePropertyIndexParameterInfo : RuntimeParameterInfo - { - internal static RuntimePropertyIndexParameterInfo GetRuntimePropertyIndexParameterInfo(RuntimePropertyInfo member, RuntimeParameterInfo backingParameter) - { - return new RuntimePropertyIndexParameterInfo(member, backingParameter); - } - } - - //----------------------------------------------------------------------------------------------------------- - // ParameterInfos returned by Get/Set methods on array types. - //----------------------------------------------------------------------------------------------------------- - internal sealed partial class RuntimeSyntheticParameterInfo : RuntimeParameterInfo - { - internal static RuntimeSyntheticParameterInfo GetRuntimeSyntheticParameterInfo(MemberInfo member, int position, RuntimeTypeInfo parameterType) - { - return new RuntimeSyntheticParameterInfo(member, position, parameterType); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs index 9a597690dc8f09..c51b9732dd0791 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs @@ -61,9 +61,11 @@ internal Type[] GetCustomModifiers(TypeContext typeContext, bool optional) #endif } - internal Type GetModifiedType(TypeContext typeContext) + internal Type GetModifiedType(Type unmodifiedType) { - return ModifiedType.Create(Resolve(typeContext).ToType(), (global::Internal.Metadata.NativeFormat.MetadataReader)Reader, _handle); + return Reader is null + ? ModifiedType.Create(unmodifiedType) + : ModifiedType.Create(unmodifiedType, (global::Internal.Metadata.NativeFormat.MetadataReader)Reader, _handle); } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs index a560ef4a6c7c06..35db6d31e18cb0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Text; @@ -38,12 +37,7 @@ internal interface IRuntimeMethodCommon where TRuntimeMeth MetadataReader GetMetadataReader(); CustomAttributeHandleCollection GetCustomAttributeHandles(); - /// - /// Parse the metadata that describes parameters, and for each parameter for which there is specific metadata - /// construct a RuntimeParameterInfo and fill in the VirtualRuntimeParameterInfoArray. Do remember to use contextMethod - /// instead of using the one internal to the RuntimeMethodCommon, as the runtime may pass in a subtly different context. - /// - void FillInMetadataDescribedParameters(ref VirtualRuntimeParameterInfoArray result, QSignatureTypeHandle[] parameterTypes, MethodBase contextMethod, TypeContext typeContext); + ParameterHandleCollection ParameterHandles { get; } string Name { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs index 41637dd9a4cb4c..81b67d9d107c26 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; -using System.Reflection.Runtime.ParameterInfos.NativeFormat; using System.Reflection.Runtime.TypeInfos; using System.Reflection.Runtime.TypeInfos.NativeFormat; @@ -55,21 +53,7 @@ public NativeFormatMethodCommon RuntimeMethodCommonOfUninstantiatedMethod } } - public void FillInMetadataDescribedParameters(ref VirtualRuntimeParameterInfoArray result, QSignatureTypeHandle[] typeSignatures, MethodBase contextMethod, TypeContext typeContext) - { - foreach (ParameterHandle parameterHandle in _method.Parameters) - { - Parameter parameterRecord = parameterHandle.GetParameter(_reader); - int index = parameterRecord.Sequence; - result[index] = - NativeFormatMethodParameterInfo.GetNativeFormatMethodParameterInfo( - contextMethod, - index - 1, - parameterHandle, - typeSignatures[index], - typeContext); - } - } + public ParameterHandleCollection ParameterHandles => _method.Parameters; public int GenericParameterCount => MethodHandle.GetMethod(Reader).GenericParameters.Count; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs index e6e8f0b99d333b..58ffa1ec8f0793 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Reflection.Core.Execution; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs index 78c43c79531e5b..913192f9493a46 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs @@ -7,7 +7,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Metadata.NativeFormat; @@ -205,9 +204,14 @@ internal sealed override string RuntimeName } } - internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod, out RuntimeParameterInfo returnParameter) + internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod) { - return _genericMethodDefinition.GetRuntimeParameters(this, out returnParameter); + return _genericMethodDefinition.GetRuntimeParameters(this); + } + + internal sealed override RuntimeParameterInfo GetRuntimeReturnParameter(RuntimeMethodInfo contextMethod) + { + return _genericMethodDefinition.GetRuntimeReturnParameter(this); } internal sealed override RuntimeMethodInfo WithReflectedTypeSetToDeclaringType diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs index 205e5ad2841e94..ceb37e6a07b873 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs @@ -6,7 +6,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using Internal.Metadata.NativeFormat; using Internal.Reflection.Core.Execution; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs index 6f65ff44a6e81e..31a5eb1b56d8ff 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Reflection.Core.Execution; @@ -39,7 +38,8 @@ private RuntimeDummyMethodInfo() { } public sealed override int MetadataToken { get { throw NotImplemented.ByDesign; } } public sealed override RuntimeMethodHandle MethodHandle { get { throw NotImplemented.ByDesign; } } protected sealed override MethodBaseInvoker UncachedMethodInvoker { get { throw NotImplemented.ByDesign; } } - internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod, out RuntimeParameterInfo returnParameter) { throw NotImplemented.ByDesign; } + internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod) { throw NotImplemented.ByDesign; } + internal sealed override RuntimeParameterInfo GetRuntimeReturnParameter(RuntimeMethodInfo contextMethod) { throw NotImplemented.ByDesign; } internal sealed override RuntimeTypeInfo RuntimeDeclaringType { get { throw NotImplemented.ByDesign; } } internal sealed override string RuntimeName { get { throw NotImplemented.ByDesign; } } internal sealed override RuntimeTypeInfo[] RuntimeGenericArgumentsOrParameters { get { throw NotImplemented.ByDesign; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs index 21c07b740385da..92a21c63502a56 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Text; @@ -17,50 +16,12 @@ namespace System.Reflection.Runtime.MethodInfos { internal static class RuntimeMethodHelpers { - // - // Returns the ParameterInfo objects for the method parameters and return parameter. - // - // The ParameterInfo objects will report "contextMethod" as their Member property and use it to get type variable information from - // the contextMethod's declaring type. The actual metadata, however, comes from "this." - // - // The methodTypeArguments provides the fill-ins for any method type variable elements in the parameter type signatures. - // - // Does not array-copy. - // - internal static RuntimeParameterInfo[] GetRuntimeParameters(ref TRuntimeMethodCommon runtimeMethodCommon, MethodBase contextMethod, RuntimeTypeInfo[] methodTypeArguments, out RuntimeParameterInfo returnParameter) - where TRuntimeMethodCommon : IRuntimeMethodCommon, IEquatable - { - TypeContext typeContext = contextMethod.DeclaringType.ToRuntimeTypeInfo().TypeContext; - typeContext = new TypeContext(typeContext.GenericTypeArguments, methodTypeArguments); - QSignatureTypeHandle[] typeSignatures = runtimeMethodCommon.QualifiedMethodSignature; - int count = typeSignatures.Length; - - VirtualRuntimeParameterInfoArray result = new VirtualRuntimeParameterInfoArray(count); - runtimeMethodCommon.FillInMetadataDescribedParameters(ref result, typeSignatures, contextMethod, typeContext); - - for (int i = 0; i < count; i++) - { - if (result[i] == null) - { - result[i] = - RuntimeThinMethodParameterInfo.GetRuntimeThinMethodParameterInfo( - contextMethod, - i - 1, - typeSignatures[i], - typeContext); - } - } - - returnParameter = result.First; - return result.Remainder; - } - // Compute the ToString() value in a pay-to-play-safe way. internal static string ComputeToString(ref TRuntimeMethodCommon runtimeMethodCommon, MethodBase contextMethod, RuntimeTypeInfo[] methodTypeArguments) where TRuntimeMethodCommon : IRuntimeMethodCommon, IEquatable { - RuntimeParameterInfo returnParameter; - RuntimeParameterInfo[] parameters = GetRuntimeParameters(ref runtimeMethodCommon, contextMethod, methodTypeArguments, out returnParameter); + RuntimeParameterInfo returnParameter = RuntimeParameterInfo.GetReturnParameter(ref runtimeMethodCommon, contextMethod, methodTypeArguments); + RuntimeParameterInfo[] parameters = RuntimeParameterInfo.GetParameters(ref runtimeMethodCommon, contextMethod, methodTypeArguments); return ComputeToString(contextMethod, methodTypeArguments, parameters, returnParameter); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs index f4b5cceb8a6888..0741ba6ef10db9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs @@ -7,7 +7,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Runtime.InteropServices; @@ -229,9 +228,14 @@ internal sealed override RuntimeTypeInfo[] RuntimeGenericArgumentsOrParameters } } - internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod, out RuntimeParameterInfo returnParameter) + internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod) { - return RuntimeMethodHelpers.GetRuntimeParameters(ref _common, contextMethod, contextMethod.RuntimeGenericArgumentsOrParameters, out returnParameter); + return RuntimeParameterInfo.GetParameters(ref _common, contextMethod, contextMethod.RuntimeGenericArgumentsOrParameters); + } + + internal sealed override RuntimeParameterInfo GetRuntimeReturnParameter(RuntimeMethodInfo contextMethod) + { + return RuntimeParameterInfo.GetReturnParameter(ref _common, contextMethod, contextMethod.RuntimeGenericArgumentsOrParameters); } internal sealed override RuntimeTypeInfo RuntimeDeclaringType diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs index 470391d492cac4..7eadd2e1ff8394 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs @@ -7,7 +7,6 @@ using System.Globalization; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Metadata.NativeFormat; @@ -150,7 +149,7 @@ protected sealed override RuntimeParameterInfo[] RuntimeParameters { get { - return _lazyParameters ??= RuntimeMethodHelpers.GetRuntimeParameters(ref _common, this, Array.Empty(), out _); + return _lazyParameters ??= RuntimeParameterInfo.GetParameters(ref _common, this, Array.Empty()); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs index 0aa8bfb01e8b37..97743efbfc0aa9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs @@ -7,7 +7,6 @@ using System.Globalization; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Reflection.Core.Execution; @@ -142,7 +141,7 @@ protected sealed override RuntimeParameterInfo[] RuntimeParameters parameters = new RuntimeParameterInfo[runtimeParameterTypes.Length]; for (int i = 0; i < parameters.Length; i++) { - parameters[i] = RuntimeSyntheticParameterInfo.GetRuntimeSyntheticParameterInfo(this, i, runtimeParameterTypes[i]); + parameters[i] = new RuntimeParameterInfo(this, runtimeParameterTypes[i].ToType(), i); } _lazyParameters = parameters; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs index 22d5c586cc290d..48e73a7a43a979 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs @@ -7,7 +7,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Reflection.Core.Execution; @@ -189,18 +188,22 @@ internal sealed override string RuntimeName } } - internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod, out RuntimeParameterInfo returnParameter) + internal sealed override RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod) { RuntimeTypeInfo[] runtimeParameterTypes = _runtimeParameterTypes; RuntimeParameterInfo[] parameters = new RuntimeParameterInfo[runtimeParameterTypes.Length]; for (int i = 0; i < parameters.Length; i++) { - parameters[i] = RuntimeSyntheticParameterInfo.GetRuntimeSyntheticParameterInfo(this, i, runtimeParameterTypes[i]); + parameters[i] = new RuntimeParameterInfo(this, runtimeParameterTypes[i].ToType(), i); } - returnParameter = RuntimeSyntheticParameterInfo.GetRuntimeSyntheticParameterInfo(this, -1, _returnType); return parameters; } + internal sealed override RuntimeParameterInfo GetRuntimeReturnParameter(RuntimeMethodInfo contextMethod) + { + return new RuntimeParameterInfo(this, _returnType.ToType(), -1); + } + internal sealed override RuntimeMethodInfo WithReflectedTypeSetToDeclaringType { get diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs index d04ef633f91bbf..579814ab849b1c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using Internal.Reflection.Core; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs deleted file mode 100644 index db837130ec9212..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; -using System.Reflection.Runtime.TypeInfos; -using System.Text; - -using Internal.Reflection.Core; -using Internal.Reflection.Core.Execution; - -namespace System.Reflection.Runtime.MethodInfos -{ - // Helper for GetRuntimeParameters() - array mimic that supports an efficient "array.Skip(1).ToArray()" operation. - internal struct VirtualRuntimeParameterInfoArray - { - public VirtualRuntimeParameterInfoArray(int count) - : this() - { - Debug.Assert(count >= 1); - Remainder = (count == 1) ? Array.Empty() : new RuntimeParameterInfo[count - 1]; - } - - public RuntimeParameterInfo this[int index] - { - get - { - return index == 0 ? First : Remainder[index - 1]; - } - - set - { - if (index == 0) - First = value; - else - Remainder[index - 1] = value; - } - } - - public RuntimeParameterInfo First { get; private set; } - public RuntimeParameterInfo[] Remainder { get; } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs deleted file mode 100644 index 7ab03b09197a88..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; -using System.Reflection.Runtime.General.NativeFormat; -using System.Runtime.CompilerServices; - -using Internal.Metadata.NativeFormat; -using Internal.Reflection.Core; -using Internal.Reflection.Core.Execution; - -namespace System.Reflection.Runtime.ParameterInfos.NativeFormat -{ - // - // This implements ParameterInfo objects owned by MethodBase objects that have an associated Parameter metadata entity. - // - internal sealed partial class NativeFormatMethodParameterInfo : RuntimeFatMethodParameterInfo - { - private NativeFormatMethodParameterInfo(MethodBase member, int position, ParameterHandle parameterHandle, QSignatureTypeHandle qualifiedParameterTypeHandle, TypeContext typeContext) - : base(member, position, qualifiedParameterTypeHandle, typeContext) - { - _parameter = parameterHandle.GetParameter(Reader); - } - - private MetadataReader Reader - { - get - { - Debug.Assert(QualifiedParameterTypeHandle.Reader is MetadataReader); - return (MetadataReader)QualifiedParameterTypeHandle.Reader; - } - } - - public sealed override ParameterAttributes Attributes - { - get - { - return _parameter.Flags; - } - } - - public sealed override string Name - { - get - { - return _parameter.Name.GetStringOrNull(this.Reader); - } - } - - public sealed override int MetadataToken - { - get - { - throw new InvalidOperationException(SR.NoMetadataTokenAvailable); - } - } - - internal sealed override MetadataReader GetMetadataReader() => Reader; - - internal sealed override CustomAttributeHandleCollection GetCustomAttributeHandles() => _parameter.CustomAttributes; - - protected sealed override bool GetDefaultValueIfAvailable(bool raw, out object? defaultValue) - { - if (DefaultValueParser.GetDefaultValueFromConstantIfAny(Reader, _parameter.DefaultValue, ParameterType, raw, out defaultValue)) - return true; - - defaultValue = raw ? GetDefaultValueFromCustomAttributeData() : GetDefaultValueFromCustomAttributes(); - if (defaultValue != DBNull.Value) - return true; - - defaultValue = null; - return false; - } - - private object? GetDefaultValueFromCustomAttributeData() - { - foreach (CustomAttributeData attributeData in GetCustomAttributesData()) - { - Type attributeType = attributeData.AttributeType; - if (attributeType == typeof(DecimalConstantAttribute)) - { - return GetRawDecimalConstant(attributeData); - } - else if (attributeType.IsSubclassOf(typeof(CustomConstantAttribute))) - { - if (attributeType == typeof(DateTimeConstantAttribute)) - { - return GetRawDateTimeConstant(attributeData); - } - return GetRawConstant(attributeData); - } - } - return DBNull.Value; - } - - private object? GetDefaultValueFromCustomAttributes() - { - object[] customAttributes = GetCustomAttributes(typeof(CustomConstantAttribute), false); - if (customAttributes.Length != 0) - return ((CustomConstantAttribute)customAttributes[0]).Value; - - customAttributes = GetCustomAttributes(typeof(DecimalConstantAttribute), false); - if (customAttributes.Length != 0) - return ((DecimalConstantAttribute)customAttributes[0]).Value; - - return DBNull.Value; - } - - private static decimal GetRawDecimalConstant(CustomAttributeData attr) - { - Debug.Assert(attr.Constructor.DeclaringType == typeof(DecimalConstantAttribute)); - IList args = attr.ConstructorArguments; - Debug.Assert(args.Count == 5); - - return new decimal( - lo: GetConstructorArgument(args, 4), - mid: GetConstructorArgument(args, 3), - hi: GetConstructorArgument(args, 2), - isNegative: ((byte)args[1].Value!) != 0, - scale: (byte)args[0].Value!); - - static int GetConstructorArgument(IList args, int index) - { - // The constructor is overloaded to accept both signed and unsigned arguments - object obj = args[index].Value!; - return (obj is int value) ? value : (int)(uint)obj; - } - } - - private static DateTime GetRawDateTimeConstant(CustomAttributeData attr) - { - Debug.Assert(attr.Constructor.DeclaringType == typeof(DateTimeConstantAttribute)); - Debug.Assert(attr.ConstructorArguments.Count == 1); - - return new DateTime((long)attr.ConstructorArguments[0].Value!); - } - - private static object? GetRawConstant(CustomAttributeData attr) - { - Debug.Assert(attr.AttributeType.IsSubclassOf(typeof(CustomConstantAttribute))); - - // We are relying only on named arguments for historical reasons - foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments) - { - if (namedArgument.MemberInfo.Name.Equals("Value")) - return namedArgument.TypedValue.Value; - } - return DBNull.Value; - } - - private readonly Parameter _parameter; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs deleted file mode 100644 index 6f144f2ea3757b..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection.Runtime.General; -using System.Runtime.InteropServices; - -namespace System.Reflection.Runtime.ParameterInfos -{ - // - // This implements ParameterInfo objects owned by MethodBase objects that have associated Parameter metadata. (In practice, - // this means all non-return parameters since most such parameters have at least a name.) - // - internal abstract class RuntimeFatMethodParameterInfo : RuntimeMethodParameterInfo - { - protected RuntimeFatMethodParameterInfo(MethodBase member, int position, QSignatureTypeHandle qualifiedParameterTypeHandle, TypeContext typeContext) - : base(member, position, qualifiedParameterTypeHandle, typeContext) - { - } - - public sealed override bool HasDefaultValue => DefaultValueInfo.Item1; - public sealed override object DefaultValue => DefaultValueInfo.Item2; - - public sealed override object RawDefaultValue - { - get - { - Tuple rawDefaultValueInfo = _lazyRawDefaultValueInfo; - if (rawDefaultValueInfo == null) - { - object rawDefaultValue; - GetDefaultValueOrSentinel(raw: true, defaultValue: out rawDefaultValue); - rawDefaultValueInfo = _lazyRawDefaultValueInfo = Tuple.Create(rawDefaultValue); - } - return rawDefaultValueInfo.Item1; - } - } - - protected abstract bool GetDefaultValueIfAvailable(bool raw, out object defaultValue); - - private Tuple DefaultValueInfo - { - get - { - Tuple defaultValueInfo = _lazyDefaultValueInfo; - if (defaultValueInfo == null) - { - object defaultValue; - bool hasDefaultValue = GetDefaultValueOrSentinel(raw: false, defaultValue: out defaultValue); - defaultValueInfo = _lazyDefaultValueInfo = Tuple.Create(hasDefaultValue, defaultValue); - } - return defaultValueInfo; - } - } - - private bool GetDefaultValueOrSentinel(bool raw, out object defaultValue) - { - bool hasDefaultValue = GetDefaultValueIfAvailable(raw, out defaultValue); - if (!hasDefaultValue) - { - defaultValue = IsOptional ? (object)Missing.Value : (object)DBNull.Value; - } - return hasDefaultValue; - } - - private volatile Tuple _lazyDefaultValueInfo; - private volatile Tuple _lazyRawDefaultValueInfo; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs deleted file mode 100644 index 85e746270a6158..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; - -using Internal.Reflection.Core; - -namespace System.Reflection.Runtime.ParameterInfos -{ - // - // Abstract base for all ParameterInfo objects exposed by runtime MethodBase objects - // (including the ReturnParameter.) - // - internal abstract class RuntimeMethodParameterInfo : RuntimeParameterInfo - { - protected RuntimeMethodParameterInfo(MethodBase member, int position, QSignatureTypeHandle qualifiedParameterTypeHandle, TypeContext typeContext) - : base(member, position) - { - QualifiedParameterTypeHandle = qualifiedParameterTypeHandle; - _typeContext = typeContext; - } - - public sealed override Type[] GetOptionalCustomModifiers() => QualifiedParameterTypeHandle.GetCustomModifiers(_typeContext, optional: true); - - public sealed override Type[] GetRequiredCustomModifiers() => QualifiedParameterTypeHandle.GetCustomModifiers(_typeContext, optional: false); - - public sealed override Type ParameterType - { - get - { - return _lazyParameterType ??= QualifiedParameterTypeHandle.Resolve(_typeContext).ToType(); - } - } - - public sealed override Type GetModifiedParameterType() => QualifiedParameterTypeHandle.GetModifiedType(_typeContext); - - protected readonly QSignatureTypeHandle QualifiedParameterTypeHandle; - private readonly TypeContext _typeContext; - private volatile Type _lazyParameterType; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs deleted file mode 100644 index 193f8fb09412c7..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; - -using Internal.Metadata.NativeFormat; - -namespace System.Reflection.Runtime.ParameterInfos -{ - // - // Abstract base for all ParameterInfo objects created by the Runtime. - // - internal abstract partial class RuntimeParameterInfo : ParameterInfo - { - protected RuntimeParameterInfo(MemberInfo member, int position) - { - _member = member; - _position = position; - } - - public abstract override ParameterAttributes Attributes { get; } - public abstract override object DefaultValue { get; } - public abstract override object RawDefaultValue { get; } - - public sealed override object[] GetCustomAttributes(bool inherit) - { - if (GetMetadataReader() is null) - return []; - - return RuntimeCustomAttribute.GetCustomAttributes(this, (RuntimeType)typeof(object)); - } - - public sealed override object[] GetCustomAttributes(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - - if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) - throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); - - if (GetMetadataReader() is null) - return RuntimeCustomAttribute.CreateAttributeArrayHelper(attributeRuntimeType, 0); - - return RuntimeCustomAttribute.GetCustomAttributes(this, attributeRuntimeType); - } - - public sealed override IList GetCustomAttributesData() => RuntimeCustomAttributeData.GetCustomAttributesInternal(this); - - internal virtual MetadataReader? GetMetadataReader() => null; - - internal virtual CustomAttributeHandleCollection GetCustomAttributeHandles() => default; - - public sealed override bool IsDefined(Type attributeType, bool inherit) - { - ArgumentNullException.ThrowIfNull(attributeType); - - if (GetMetadataReader() is null) - return false; - - if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) - throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); - - return RuntimeCustomAttribute.IsDefined(this, attributeRuntimeType); - } - - public sealed override bool Equals(object obj) - { - if (!(obj is RuntimeParameterInfo other)) - return false; - if (_position != other._position) - return false; - if (!(_member.Equals(other._member))) - return false; - return true; - } - - public sealed override int GetHashCode() - { - return _member.GetHashCode(); - } - - public abstract override Type[] GetOptionalCustomModifiers(); - - public abstract override Type[] GetRequiredCustomModifiers(); - - public abstract override bool HasDefaultValue { get; } - - public abstract override int MetadataToken - { - get; - } - - public sealed override MemberInfo Member - { - get - { - return _member; - } - } - - public abstract override string Name { get; } - public abstract override Type ParameterType { get; } - - public sealed override int Position - { - get - { - return _position; - } - } - - public sealed override string ToString() - { - return this.ParameterType.FormatTypeName() + " " + this.Name; - } - - private readonly MemberInfo _member; - private readonly int _position; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs deleted file mode 100644 index 18d29e58e83df2..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.PropertyInfos; - -using Internal.Metadata.NativeFormat; - -namespace System.Reflection.Runtime.ParameterInfos -{ - // - // This implements ParameterInfo objects returned by PropertyInfo.GetIndexParameters(). Basically, they're identical to the underling accessor method's - // ParameterInfo's except that the Member property returns the PropertyInfo rather than a MethodBase. - // - internal sealed partial class RuntimePropertyIndexParameterInfo : RuntimeParameterInfo - { - private RuntimePropertyIndexParameterInfo(RuntimePropertyInfo member, RuntimeParameterInfo backingParameter) - : base(member, backingParameter.Position) - { - _backingParameter = backingParameter; - } - - public sealed override ParameterAttributes Attributes - { - get - { - return _backingParameter.Attributes; - } - } - - internal sealed override MetadataReader? GetMetadataReader() => _backingParameter.GetMetadataReader(); - - internal sealed override CustomAttributeHandleCollection GetCustomAttributeHandles() => _backingParameter.GetCustomAttributeHandles(); - - public sealed override object DefaultValue - { - get - { - return _backingParameter.DefaultValue; - } - } - - public sealed override object RawDefaultValue - { - get - { - return _backingParameter.RawDefaultValue; - } - } - - public sealed override Type[] GetOptionalCustomModifiers() - { - return _backingParameter.GetOptionalCustomModifiers(); - } - - public sealed override Type[] GetRequiredCustomModifiers() - { - return _backingParameter.GetRequiredCustomModifiers(); - } - - public sealed override bool HasDefaultValue - { - get - { - return _backingParameter.HasDefaultValue; - } - } - - public sealed override string Name - { - get - { - return _backingParameter.Name; - } - } - - public sealed override Type ParameterType - { - get - { - return _backingParameter.ParameterType; - } - } - - public sealed override int MetadataToken - { - get - { - return _backingParameter.MetadataToken; - } - } - - private readonly RuntimeParameterInfo _backingParameter; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs deleted file mode 100644 index ff5a0a7a2b0e5a..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; -using System.Reflection.Runtime.TypeInfos; - -using Internal.Reflection.Core; -using Internal.Reflection.Core.Execution; - -namespace System.Reflection.Runtime.ParameterInfos -{ - // This class is used for the "Get/Set" methods on array types. - internal sealed partial class RuntimeSyntheticParameterInfo : RuntimeParameterInfo - { - private RuntimeSyntheticParameterInfo(MemberInfo memberInfo, int position, RuntimeTypeInfo parameterType) - : base(memberInfo, position) - { - _parameterType = parameterType; - } - - public sealed override ParameterAttributes Attributes - { - get - { - return ParameterAttributes.None; - } - } - - public sealed override object DefaultValue - { - get - { - return null; // Legacy: This is what the desktop returns. - } - } - - public sealed override object RawDefaultValue - { - get - { - return null; // Legacy: This is what the desktop returns. - } - } - - public sealed override bool HasDefaultValue - { - get - { - // Compat: returning "true" makes no sense but this is how it's always been. - return true; - } - } - - public sealed override Type[] GetOptionalCustomModifiers() => Array.Empty(); - - public sealed override Type[] GetRequiredCustomModifiers() => Array.Empty(); - - public sealed override string Name - { - get - { - return null; // Legacy: This is what the dekstop returns. - } - } - - public sealed override Type ParameterType - { - get - { - return _parameterType.ToType(); - } - } - - public sealed override int MetadataToken - { - get - { - return 0x08000000; // nil ParamDef token - } - } - - private readonly RuntimeTypeInfo _parameterType; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs deleted file mode 100644 index 7b320992c6653a..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Reflection.Runtime.General; - -using Internal.Reflection.Core; - -namespace System.Reflection.Runtime.ParameterInfos -{ - // - // This implements ParameterInfo objects owned by MethodBase objects that have no associated Parameter metadata. (In practice, - // this means return type "Parameters" that don't have custom attributes. - // - internal sealed partial class RuntimeThinMethodParameterInfo : RuntimeMethodParameterInfo - { - private RuntimeThinMethodParameterInfo(MethodBase member, int position, QSignatureTypeHandle qualifiedParameterTypeHandle, TypeContext typeContext) - : base(member, position, qualifiedParameterTypeHandle, typeContext) - { - } - - public sealed override ParameterAttributes Attributes - { - get - { - return ParameterAttributes.None; - } - } - - public sealed override object DefaultValue - { - get - { - // Returning "null" matches the desktop behavior, though this is inconsistent with the DBNull/Missing values - // returned by non-return ParameterInfo's without default values. - return null; - } - } - - public sealed override object RawDefaultValue - { - get - { - // Returning "null" matches the desktop behavior, though this is inconsistent with the DBNull/Missing values - // returned by non-return ParameterInfo's without default values. - return null; - } - } - - public sealed override bool HasDefaultValue - { - get - { - return false; - } - } - - public sealed override string Name - { - get - { - return null; - } - } - - public sealed override int MetadataToken - { - get - { - return 0x08000000; // nil ParamDef token - } - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs index 33762f8d1984cb..0873ed61a7e488 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs @@ -10,7 +10,6 @@ using System.Reflection.Runtime.General.NativeFormat; using System.Reflection.Runtime.MethodInfos; using System.Reflection.Runtime.MethodInfos.NativeFormat; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Reflection.Runtime.TypeInfos.NativeFormat; using System.Runtime.CompilerServices; @@ -127,6 +126,17 @@ protected sealed override QSignatureTypeHandle PropertyTypeHandle } } + internal override QSignatureTypeHandle GetParameterTypeHandle(int position) + { + foreach (Handle parameterType in _property.Signature.GetPropertySignature(_reader).Parameters) + { + if (position-- == 0) + return new QSignatureTypeHandle(_reader, parameterType); + } + + throw new BadImageFormatException(SR.BadImageFormat_ParameterSignatureMismatch); + } + protected sealed override bool GetDefaultValueIfAny(bool raw, out object? defaultValue) { return DefaultValueParser.GetDefaultValueFromConstantIfAny(_reader, _property.DefaultValue, PropertyType, raw, out defaultValue); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs index dd79e1e34f2e59..208490eeb97888 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs @@ -8,7 +8,6 @@ using System.Reflection; using System.Reflection.Runtime.General; using System.Reflection.Runtime.MethodInfos; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Runtime.CompilerServices; using System.Text; @@ -80,9 +79,9 @@ public sealed override ParameterInfo[] GetIndexParameters() { bool useGetter = CanRead; RuntimeMethodInfo accessor = (useGetter ? Getter : Setter); - RuntimeParameterInfo[] runtimeMethodParameterInfos = accessor.RuntimeParameters; + RuntimeParameterInfo[] runtimeMethodParameterInfos = accessor?.RuntimeParameters ?? []; int count = runtimeMethodParameterInfos.Length; - if (!useGetter) + if (!useGetter && accessor is not null) count--; // If we're taking the parameters off the setter, subtract one for the "value" parameter. if (count == 0) { @@ -93,7 +92,7 @@ public sealed override ParameterInfo[] GetIndexParameters() indexParameters = new ParameterInfo[count]; for (int i = 0; i < count; i++) { - indexParameters[i] = RuntimePropertyIndexParameterInfo.GetRuntimePropertyIndexParameterInfo(this, runtimeMethodParameterInfos[i]); + indexParameters[i] = new RuntimeParameterInfo(runtimeMethodParameterInfos[i], this); } _lazyIndexParameters = indexParameters; } @@ -326,6 +325,8 @@ public sealed override bool IsDefined(Type attributeType, bool inherit) /// protected abstract QSignatureTypeHandle PropertyTypeHandle { get; } + internal abstract QSignatureTypeHandle GetParameterTypeHandle(int position); + protected enum PropertyMethodSemantics { Getter, diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index f596dbf74cb11f..53e7367be3a708 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -9,7 +9,6 @@ using System.Reflection; using System.Reflection.Runtime.BindingFlagSupport; using System.Reflection.Runtime.General; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.TypeInfos; using System.Runtime.CompilerServices; @@ -279,7 +278,9 @@ internal abstract string RuntimeName // internal abstract RuntimeTypeInfo[] RuntimeGenericArgumentsOrParameters { get; } - internal abstract RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod, out RuntimeParameterInfo returnParameter); + internal abstract RuntimeParameterInfo[] GetRuntimeParameters(RuntimeMethodInfo contextMethod); + + internal abstract RuntimeParameterInfo GetRuntimeReturnParameter(RuntimeMethodInfo contextMethod); // // The non-public version of MethodInfo.GetParameters() (does not array-copy.) @@ -288,14 +289,7 @@ internal RuntimeParameterInfo[] RuntimeParameters { get { - RuntimeParameterInfo[] parameters = _lazyParameters; - if (parameters == null) - { - RuntimeParameterInfo returnParameter; - parameters = _lazyParameters = GetRuntimeParameters(this, out returnParameter); - _lazyReturnParameter = returnParameter; // Opportunistically initialize the _lazyReturnParameter latch as well. - } - return parameters; + return _lazyParameters ??= GetRuntimeParameters(this); } } @@ -303,14 +297,7 @@ internal RuntimeParameterInfo RuntimeReturnParameter { get { - RuntimeParameterInfo returnParameter = _lazyReturnParameter; - if (returnParameter == null) - { - // Though the returnParameter is our primary objective, we can opportunistically initialize the _lazyParameters latch too. - _lazyParameters = GetRuntimeParameters(this, out returnParameter); - _lazyReturnParameter = returnParameter; - } - return returnParameter; + return _lazyReturnParameter ??= GetRuntimeReturnParameter(this); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs new file mode 100644 index 00000000000000..0910fe8bfe81a4 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs @@ -0,0 +1,176 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Reflection.Runtime.General; +using System.Reflection.Runtime.MethodInfos; +using System.Reflection.Runtime.TypeInfos; + +using Internal.Metadata.NativeFormat; + +namespace System.Reflection; + +internal sealed partial class RuntimeParameterInfo : ParameterInfo +{ + private readonly ParameterHandle m_parameterHandle; + private readonly MetadataReader? m_scope; + private readonly QSignatureTypeHandle m_signature; + private readonly TypeContext m_typeContext; + + internal static RuntimeParameterInfo[] GetParameters( + ref TRuntimeMethodCommon method, MethodBase member, RuntimeTypeInfo[] methodTypeArguments) + where TRuntimeMethodCommon : IRuntimeMethodCommon, IEquatable + { + return GetParameters(ref method, member, methodTypeArguments, out _, fetchReturnParameter: false); + } + + internal static RuntimeParameterInfo GetReturnParameter( + ref TRuntimeMethodCommon method, MethodBase member, RuntimeTypeInfo[] methodTypeArguments) + where TRuntimeMethodCommon : IRuntimeMethodCommon, IEquatable + { + GetParameters(ref method, member, methodTypeArguments, out RuntimeParameterInfo? returnParameter, fetchReturnParameter: true); + Debug.Assert(returnParameter is not null); + return returnParameter; + } + + private static RuntimeParameterInfo[] GetParameters( + ref TRuntimeMethodCommon method, MethodBase member, RuntimeTypeInfo[] methodTypeArguments, + out RuntimeParameterInfo? returnParameter, bool fetchReturnParameter) + where TRuntimeMethodCommon : IRuntimeMethodCommon, IEquatable + { + TypeContext typeContext = member.DeclaringType.ToRuntimeTypeInfo().TypeContext; + typeContext = new TypeContext(typeContext.GenericTypeArguments, methodTypeArguments); + QSignatureTypeHandle[] sig = method.QualifiedMethodSignature; + Debug.Assert(sig.Length > 0); + + returnParameter = null; + int sigArgCount = sig.Length - 1; + RuntimeParameterInfo[] args = + fetchReturnParameter ? null! : + sigArgCount == 0 ? [] : + new RuntimeParameterInfo[sigArgCount]; + + MetadataReader scope = method.GetMetadataReader(); + ParameterHandleCollection parameterHandles = method.ParameterHandles; + int cParamDefs = parameterHandles.Count; + if (cParamDefs > sigArgCount + 1) + throw new BadImageFormatException(SR.BadImageFormat_ParameterSignatureMismatch); + + foreach (ParameterHandle parameterHandle in parameterHandles) + { + Parameter parameter = scope.GetParameter(parameterHandle); + int position = parameter.Sequence - 1; + + if (fetchReturnParameter && position == -1) + { + if (returnParameter is not null) + throw new BadImageFormatException(SR.BadImageFormat_ParameterSignatureMismatch); + + returnParameter = new RuntimeParameterInfo(sig[0], typeContext, scope, parameterHandle, position, parameter.Flags, member); + } + else if (!fetchReturnParameter && position >= 0) + { + if (position >= sigArgCount) + throw new BadImageFormatException(SR.BadImageFormat_ParameterSignatureMismatch); + + args[position] = new RuntimeParameterInfo(sig[position + 1], typeContext, scope, parameterHandle, position, parameter.Flags, member); + } + } + + if (fetchReturnParameter) + { + returnParameter ??= new RuntimeParameterInfo(sig[0], typeContext, null, default, -1, ParameterAttributes.None, member); + } + else if (cParamDefs < args.Length + 1) + { + for (int i = 0; i < args.Length; i++) + { + args[i] ??= new RuntimeParameterInfo(sig[i + 1], typeContext, null, default, i, ParameterAttributes.None, member); + } + } + + return args; + } + + private RuntimeParameterInfo( + QSignatureTypeHandle signature, TypeContext typeContext, MetadataReader? scope, ParameterHandle parameterHandle, + int position, ParameterAttributes attributes, MemberInfo member) + { + Debug.Assert(parameterHandle.IsNil == (scope is null)); + + PositionImpl = position; + MemberImpl = member; + m_signature = signature; + m_typeContext = typeContext; + m_parameterHandle = parameterHandle; + m_scope = scope; + AttrsImpl = attributes; + } + + // Array members have no metadata signatures, but otherwise behave like ordinary tokenless parameters. + internal RuntimeParameterInfo(MemberInfo owner, Type parameterType, int position) + { + MemberImpl = owner; + ClassImpl = parameterType; + PositionImpl = position; + m_nameIsCached = true; + } + + private object? GetDefaultValueFromMetadata(bool raw) + { + Debug.Assert(m_scope is not null && !m_parameterHandle.IsNil); + Type parameterType = ParameterType; + Handle constantHandle = m_scope.GetParameter(m_parameterHandle).DefaultValue; + if (constantHandle.IsNil) + return DBNull.Value; + + object? value = constantHandle.ParseConstantValue(m_scope); + if (parameterType.IsEnum && !raw) + { + if (value is null) + return null; + + if (value is not (char or sbyte or byte or short or ushort or int or uint or long or ulong)) + throw new FormatException(SR.Arg_BadLiteralFormat); + + if (!parameterType.ContainsGenericParameters) + return Enum.ToObject(parameterType, value); + } + else if (parameterType == typeof(DateTime)) + { + return value switch + { + null => null, + long ticks => new DateTime(ticks), + ulong ticks => new DateTime(unchecked((long)ticks)), + _ => throw new FormatException(SR.Arg_BadLiteralFormat), + }; + } + + return value; + } + + internal MetadataReader? GetMetadataReader() => m_scope; + + internal CustomAttributeHandleCollection GetCustomAttributeHandles() + { + if (m_parameterHandle.IsNil) + return default; + + Debug.Assert(m_scope is not null); + return m_scope.GetParameter(m_parameterHandle).CustomAttributes; + } + + public override int MetadataToken => m_parameterHandle.IsNil + ? base.MetadataToken + : throw new InvalidOperationException(SR.NoMetadataTokenAvailable); + + public override Type[] GetRequiredCustomModifiers() => + m_signature.Reader is null ? [] : m_signature.GetCustomModifiers(m_typeContext, optional: false); + + public override Type[] GetOptionalCustomModifiers() => + m_signature.Reader is null ? [] : m_signature.GetCustomModifiers(m_typeContext, optional: true); + + public override Type GetModifiedParameterType() => + m_signature.GetModifiedType(ParameterType); +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index 6840604bdd2e5d..cc9f667f2c05cb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -15,7 +15,6 @@ using System.Reflection.Runtime.General; using System.Reflection.Runtime.MethodInfos; using System.Reflection.Runtime.Modules; -using System.Reflection.Runtime.ParameterInfos; using System.Reflection.Runtime.PropertyInfos; using Internal.Metadata.NativeFormat; From fd5fb22a0a42e9636425358ac60720dff2c88c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 16 Sep 2026 13:45:09 +0900 Subject: [PATCH 2/2] Reduce NativeAOT RuntimeParameterInfo conditionals Use file-local token and metadata-name adapters to share the original CoreCLR expressions without changing CoreCLR behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b689a562-006b-4ec0-8607-f5a91479388e --- .../System/Reflection/RuntimeParameterInfo.cs | 44 +++++++------------ .../RuntimeParameterInfo.NativeAot.cs | 14 +++--- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index 8f36cde4c3662e..d4779da37feae1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -7,6 +7,7 @@ #if NATIVEAOT using System.Reflection.Runtime.General; using System.Reflection.Runtime.PropertyInfos; +using Internal.Metadata.NativeFormat; #else using MdToken = System.Reflection.MetadataToken; #endif @@ -186,7 +187,7 @@ private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member) // Strictly speaking, properties don't contain parameter tokens // However we need this to make ca's work... oh well... #if NATIVEAOT - m_parameterHandle = accessor.m_parameterHandle; + m_tkParamDef = accessor.m_tkParamDef; m_typeContext = accessor.m_typeContext; #else m_tkParamDef = MdToken.IsNullToken(accessor.MetadataToken) ? (int)MetadataTokenType.ParamDef : accessor.MetadataToken; @@ -267,20 +268,12 @@ public override string? Name { if (!m_nameIsCached) { -#if NATIVEAOT - if (!m_parameterHandle.IsNil) - { - Debug.Assert(m_scope is not null); - NameImpl = m_scope.GetParameter(m_parameterHandle).Name.GetStringOrNull(m_scope) ?? string.Empty; - } -#else if (!MdToken.IsNullToken(m_tkParamDef)) { string name = m_scope.GetName(m_tkParamDef).ToString(); GC.KeepAlive(this); NameImpl = name; } -#endif // other threads could only write it to true, so a race condition is OK // this field is volatile, so the write ordering is guaranteed @@ -368,11 +361,7 @@ private bool TryGetDefaultValueInternal(bool raw, out object? defaultValue) { Debug.Assert(!m_noMetadata); -#if NATIVEAOT - if (m_noDefaultValue || m_parameterHandle.IsNil) -#else if (m_noDefaultValue || MdToken.IsNullToken(m_tkParamDef)) -#endif { defaultValue = DBNull.Value; m_noDefaultValue = true; @@ -494,11 +483,7 @@ public override Type GetModifiedParameterType() => #region ICustomAttributeProvider public override object[] GetCustomAttributes(bool inherit) { -#if NATIVEAOT - if (m_parameterHandle.IsNil) -#else if (MdToken.IsNullToken(m_tkParamDef)) -#endif return []; return RuntimeCustomAttribute.GetCustomAttributes(this, (typeof(object) as RuntimeType)!); @@ -511,11 +496,7 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit) if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType)); -#if NATIVEAOT - if (m_parameterHandle.IsNil) -#else if (MdToken.IsNullToken(m_tkParamDef)) -#endif return RuntimeCustomAttribute.CreateAttributeArrayHelper(attributeRuntimeType, 0); return RuntimeCustomAttribute.GetCustomAttributes(this, attributeRuntimeType); @@ -525,11 +506,7 @@ public override bool IsDefined(Type attributeType, bool inherit) { ArgumentNullException.ThrowIfNull(attributeType); -#if NATIVEAOT - if (m_parameterHandle.IsNil) -#else if (MdToken.IsNullToken(m_tkParamDef)) -#endif return false; if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType) @@ -540,15 +517,24 @@ public override bool IsDefined(Type attributeType, bool inherit) public override IList GetCustomAttributesData() { -#if NATIVEAOT - if (m_parameterHandle.IsNil) -#else if (MdToken.IsNullToken(m_tkParamDef)) -#endif return Array.Empty(); return RuntimeCustomAttributeData.GetCustomAttributesInternal(this); } #endregion } +#if NATIVEAOT + + file static class MdToken + { + public static bool IsNullToken(ParameterHandle token) => token.IsNil; + } + + file static class MetadataImportExtensions + { + public static string GetName(this MetadataReader? scope, ParameterHandle token) => + scope!.GetParameter(token).Name.GetStringOrNull(scope!) ?? string.Empty; + } +#endif } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs index 0910fe8bfe81a4..aae11ac53471aa 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.NativeAot.cs @@ -12,7 +12,7 @@ namespace System.Reflection; internal sealed partial class RuntimeParameterInfo : ParameterInfo { - private readonly ParameterHandle m_parameterHandle; + private readonly ParameterHandle m_tkParamDef; private readonly MetadataReader? m_scope; private readonly QSignatureTypeHandle m_signature; private readonly TypeContext m_typeContext; @@ -102,7 +102,7 @@ private RuntimeParameterInfo( MemberImpl = member; m_signature = signature; m_typeContext = typeContext; - m_parameterHandle = parameterHandle; + m_tkParamDef = parameterHandle; m_scope = scope; AttrsImpl = attributes; } @@ -118,9 +118,9 @@ internal RuntimeParameterInfo(MemberInfo owner, Type parameterType, int position private object? GetDefaultValueFromMetadata(bool raw) { - Debug.Assert(m_scope is not null && !m_parameterHandle.IsNil); + Debug.Assert(m_scope is not null && !m_tkParamDef.IsNil); Type parameterType = ParameterType; - Handle constantHandle = m_scope.GetParameter(m_parameterHandle).DefaultValue; + Handle constantHandle = m_scope.GetParameter(m_tkParamDef).DefaultValue; if (constantHandle.IsNil) return DBNull.Value; @@ -154,14 +154,14 @@ internal RuntimeParameterInfo(MemberInfo owner, Type parameterType, int position internal CustomAttributeHandleCollection GetCustomAttributeHandles() { - if (m_parameterHandle.IsNil) + if (m_tkParamDef.IsNil) return default; Debug.Assert(m_scope is not null); - return m_scope.GetParameter(m_parameterHandle).CustomAttributes; + return m_scope.GetParameter(m_tkParamDef).CustomAttributes; } - public override int MetadataToken => m_parameterHandle.IsNil + public override int MetadataToken => m_tkParamDef.IsNil ? base.MetadataToken : throw new InvalidOperationException(SR.NoMetadataTokenAvailable);