From bafbf8a8b57ff7114fdda84cdeb9ecd5d10682e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 12 Mar 2025 12:09:45 +0100 Subject: [PATCH 1/8] Delete native layout representation of fields --- .../src/CompatibilitySuppressions.xml | 4 - .../Runtime/Augments/TypeLoaderCallbacks.cs | 4 +- .../RuntimeFieldHandleInfo.cs | 15 --- .../src/System.Private.CoreLib.csproj | 1 - .../NativeFormatRuntimeFieldInfo.cs | 2 +- .../src/System/RuntimeFieldHandle.cs | 15 +-- ...EnvironmentImplementation.MappingTables.cs | 27 +---- .../TypeLoader/GenericDictionaryCell.cs | 14 ++- ...peLoaderEnvironment.LdTokenResultLookup.cs | 101 ++++-------------- .../TypeLoader/TypeLoaderEnvironment.cs | 25 +---- .../NativeFormat/NativeFormatWriter.cs | 53 --------- .../NativeLayoutVertexNode.cs | 42 ++------ .../NodeFactory.NativeLayout.cs | 11 -- .../RuntimeFieldHandleNode.cs | 8 +- .../Compiler/MetadataManager.cs | 11 ++ 15 files changed, 65 insertions(+), 268 deletions(-) delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 0abedd830a6b14..dd7b03022aab4a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -717,10 +717,6 @@ CP0001 T:Internal.Runtime.CompilerServices.OpenMethodResolver - - CP0001 - T:Internal.Runtime.CompilerServices.RuntimeFieldHandleInfo - CP0001 T:Internal.Runtime.CompilerServices.RuntimeMethodHandleInfo diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs index 7dc7641435e5e9..82b17ff7753764 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs @@ -24,8 +24,8 @@ public abstract class TypeLoaderCallbacks public abstract bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2); public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeMethodHandle declMethod); - public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName); - public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName); + public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle handle); + public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle); public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle, out RuntimeTypeHandle pointerTypeHandle); public abstract bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, bool isMdArray, int rank, out RuntimeTypeHandle arrayTypeHandle); /// diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs deleted file mode 100644 index 53f4d7e9ac2585..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeFieldHandleInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.InteropServices; - -namespace Internal.Runtime.CompilerServices -{ - [StructLayout(LayoutKind.Sequential)] - [CLSCompliant(false)] - public unsafe struct RuntimeFieldHandleInfo - { - public IntPtr NativeLayoutInfoSignature; - } -} 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 7bb3b0f58e70e5..5fb8b8fdabb1f0 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 @@ -119,7 +119,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs index 1674cc9b18cfe0..fde55471130bb6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs @@ -130,7 +130,7 @@ public sealed override RuntimeFieldHandle FieldHandle { return RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleForComponents( DeclaringType.TypeHandle, - Name); + _fieldHandle); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs index 01624ba5469dde..1e0cacbaf0aabc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using System.Runtime.Serialization; +using Internal.Metadata.NativeFormat; using Internal.Runtime.Augments; namespace System @@ -37,13 +38,13 @@ public bool Equals(RuntimeFieldHandle handle) if (_value == IntPtr.Zero || handle._value == IntPtr.Zero) return false; - string fieldName1, fieldName2; + FieldHandle fieldHandle1, fieldHandle2; RuntimeTypeHandle declaringType1, declaringType2; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType1, out fieldName1); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(handle, out declaringType2, out fieldName2); + RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType1, out fieldHandle1); + RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(handle, out declaringType2, out fieldHandle2); - return declaringType1.Equals(declaringType2) && fieldName1 == fieldName2; + return declaringType1.Equals(declaringType2) && fieldHandle1.Equals(fieldHandle2); } public override int GetHashCode() @@ -51,12 +52,12 @@ public override int GetHashCode() if (_value == IntPtr.Zero) return 0; - string fieldName; + FieldHandle fieldHandle; RuntimeTypeHandle declaringType; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType, out fieldName); + RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType, out fieldHandle); int hashcode = declaringType.GetHashCode(); - return (hashcode + int.RotateLeft(hashcode, 13)) ^ fieldName.GetHashCode(); + return (hashcode + int.RotateLeft(hashcode, 13)) ^ fieldHandle.GetHashCode(); } public static RuntimeFieldHandle FromIntPtr(IntPtr value) => new RuntimeFieldHandle(value); diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 10c1ac5bb45da7..6d7ff877d49d09 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -875,32 +875,7 @@ public sealed override bool TryGetMethodFromHandleAndType(RuntimeMethodHandle ru // public sealed override unsafe bool TryGetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle) { - fieldHandle = default(FieldHandle); - - string fieldName; - if (!TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName)) - return false; - - RuntimeTypeHandle metadataLookupTypeHandle = GetTypeDefinition(declaringTypeHandle); - - QTypeDefinition qTypeDefinition = GetMetadataForNamedType(metadataLookupTypeHandle); - - // TODO! Handle ecma style types - MetadataReader reader = qTypeDefinition.NativeFormatReader; - TypeDefinitionHandle typeDefinitionHandle = qTypeDefinition.NativeFormatHandle; - - TypeDefinition typeDefinition = typeDefinitionHandle.GetTypeDefinition(reader); - foreach (FieldHandle fh in typeDefinition.Fields) - { - Field field = fh.GetField(reader); - if (field.Name.StringEquals(fieldName, reader)) - { - fieldHandle = fh; - return true; - } - } - - return false; + return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldHandle); } // diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs index 215a0f51325215..0157ab96ed192a 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs @@ -253,7 +253,7 @@ internal override IntPtr Create(TypeBuilder builder) private class FieldLdTokenCell : GenericDictionaryCell { internal TypeDesc ContainingType; - internal IntPtr FieldName; + internal int FieldHandle; internal override unsafe void Prepare(TypeBuilder builder) { @@ -267,7 +267,7 @@ internal override unsafe IntPtr Create(TypeBuilder builder) { RuntimeFieldHandle handle = TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents( builder.GetRuntimeTypeHandle(ContainingType), - FieldName); + FieldHandle); return *(IntPtr*)&handle; } @@ -467,13 +467,11 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.FieldLdToken: { - NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); - - var type = nativeLayoutInfoLoadContext.GetType(ref ldtokenSigParser); - IntPtr fieldNameSig = ldtokenSigParser.Reader.OffsetToAddress(ldtokenSigParser.Offset); - TypeLoaderLogger.WriteLine("LdToken on: " + type.ToString() + "." + ldtokenSigParser.GetString()); + var type = nativeLayoutInfoLoadContext.GetType(ref parser); + int handle = (int)parser.GetUnsigned(); + TypeLoaderLogger.WriteLine("LdToken on: " + type.ToString() + "." + handle.LowLevelToString()); - cell = new FieldLdTokenCell() { FieldName = fieldNameSig, ContainingType = type }; + cell = new FieldLdTokenCell() { FieldHandle = handle, ContainingType = type }; } break; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index dd2bc75e3d61d4..91c0fe3de55a91 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -11,6 +11,7 @@ using System.Text; using System.Threading; +using Internal.Metadata.NativeFormat; using Internal.NativeFormat; using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; @@ -23,10 +24,10 @@ namespace Internal.Runtime.TypeLoader public sealed partial class TypeLoaderEnvironment { [StructLayout(LayoutKind.Sequential)] - private struct DynamicFieldHandleInfo + private struct FieldHandleInfo { - public IntPtr DeclaringType; - public IntPtr FieldName; + public RuntimeTypeHandle DeclaringType; + public FieldHandle Handle; } [StructLayout(LayoutKind.Sequential)] @@ -87,14 +88,12 @@ public unsafe IntPtr GetNativeFormatStringForString(string str) private struct RuntimeFieldHandleKey : IEquatable { private RuntimeTypeHandle _declaringType; - private string _fieldName; - private int _hashcode; + private FieldHandle _handle; - public RuntimeFieldHandleKey(RuntimeTypeHandle declaringType, string fieldName) + public RuntimeFieldHandleKey(RuntimeTypeHandle declaringType, FieldHandle fieldHandle) { _declaringType = declaringType; - _fieldName = fieldName; - _hashcode = declaringType.GetHashCode() ^ fieldName.GetHashCode(); + _handle = fieldHandle; } public override bool Equals(object obj) @@ -108,10 +107,10 @@ public override bool Equals(object obj) public bool Equals(RuntimeFieldHandleKey other) { - return other._declaringType.Equals(_declaringType) && other._fieldName == _fieldName; + return other._declaringType.Equals(_declaringType) && other._handle.Equals(_handle); } - public override int GetHashCode() { return _hashcode; } + public override int GetHashCode() => _declaringType.GetHashCode() ^ _handle.GetHashCode(); } private struct RuntimeMethodHandleKey : IEquatable @@ -180,30 +179,23 @@ public bool Equals(RuntimeMethodHandleKey other) #region Field Ldtoken Functions - public RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName) + public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, int handle) { - IntPtr nameAsIntPtr = GetNativeFormatStringForString(fieldName); - return GetRuntimeFieldHandleForComponents(declaringTypeHandle, nameAsIntPtr); + return GetRuntimeFieldHandleForComponents(declaringTypeHandle, handle.AsHandle().ToFieldHandle(null)); } - public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, IntPtr fieldName) + public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle) { - string fieldNameStr = GetStringFromMemoryInNativeFormat(fieldName); - - RuntimeFieldHandleKey key = new RuntimeFieldHandleKey(declaringTypeHandle, fieldNameStr); - RuntimeFieldHandle runtimeFieldHandle = default(RuntimeFieldHandle); + RuntimeFieldHandleKey key = new RuntimeFieldHandleKey(declaringTypeHandle, handle); lock (_runtimeFieldHandles) { - if (!_runtimeFieldHandles.TryGetValue(key, out runtimeFieldHandle)) + if (!_runtimeFieldHandles.TryGetValue(key, out RuntimeFieldHandle runtimeFieldHandle)) { - DynamicFieldHandleInfo* fieldData = (DynamicFieldHandleInfo*)MemoryHelpers.AllocateMemory(sizeof(DynamicFieldHandleInfo)); - fieldData->DeclaringType = *(IntPtr*)&declaringTypeHandle; - fieldData->FieldName = fieldName; - - // Special flag (lowest bit set) in the handle value to indicate it was dynamically allocated - IntPtr runtimeFieldHandleValue = (IntPtr)fieldData + 1; - runtimeFieldHandle = *(RuntimeFieldHandle*)&runtimeFieldHandleValue; + FieldHandleInfo* fieldData = (FieldHandleInfo*)MemoryHelpers.AllocateMemory(sizeof(FieldHandleInfo)); + fieldData->DeclaringType = declaringTypeHandle; + fieldData->Handle = handle; + runtimeFieldHandle = RuntimeFieldHandle.FromIntPtr((nint)fieldData); _runtimeFieldHandles.Add(key, runtimeFieldHandle); } @@ -212,60 +204,11 @@ public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeH } } - public bool TryGetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) + public unsafe bool TryGetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle) { - return runtimeFieldHandle.IsDynamic() ? - TryGetDynamicRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName) : - TryGetStaticRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName); - } - - private unsafe bool TryGetDynamicRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) - { - IntPtr runtimeFieldHandleValue = *(IntPtr*)&runtimeFieldHandle; - - // Special flag in the handle value to indicate it was dynamically allocated - Debug.Assert((runtimeFieldHandleValue & 0x1) == 0x1); - - DynamicFieldHandleInfo* fieldData = (DynamicFieldHandleInfo*)(runtimeFieldHandleValue - 1); - declaringTypeHandle = *(RuntimeTypeHandle*)&(fieldData->DeclaringType); - - // FieldName points to the field name in NativeLayout format, so we parse it using a NativeParser - IntPtr fieldNamePtr = fieldData->FieldName; - fieldName = GetStringFromMemoryInNativeFormat(fieldNamePtr); - - return true; - } - - private unsafe bool TryGetStaticRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) - { - fieldName = null; - declaringTypeHandle = default(RuntimeTypeHandle); - - // Make sure it's not a dynamically allocated RuntimeFieldHandle before we attempt to use it to parse native layout data - Debug.Assert(((*(IntPtr*)&runtimeFieldHandle).ToInt64() & 0x1) == 0); - - RuntimeFieldHandleInfo* fieldData = *(RuntimeFieldHandleInfo**)&runtimeFieldHandle; - RuntimeSignature signature; - - // The native layout info signature is a pair. - // The first is a pointer that points to the TypeManager indirection cell. - // The second is the offset into the native layout info blob in that TypeManager, where the native signature is encoded. - IntPtr* nativeLayoutInfoSignatureData = (IntPtr*)fieldData->NativeLayoutInfoSignature; - - signature = RuntimeSignature.CreateFromNativeLayoutSignature( - new TypeManagerHandle(*(IntPtr*)nativeLayoutInfoSignatureData[0]), - (uint)nativeLayoutInfoSignatureData[1].ToInt32()); - - RuntimeSignature remainingSignature; - if (!GetTypeFromSignatureAndContext(signature, null, null, out declaringTypeHandle, out remainingSignature)) - return false; - - // GetTypeFromSignatureAndContext parses the type from the signature and returns a pointer to the next - // part of the native layout signature to read which we get the field name from - var reader = GetNativeLayoutInfoReader(remainingSignature); - var parser = new NativeParser(reader, remainingSignature.NativeLayoutOffset); - fieldName = parser.GetString(); - + FieldHandleInfo* fieldData = (FieldHandleInfo*)runtimeFieldHandle.Value; + declaringTypeHandle = fieldData->DeclaringType; + fieldHandle = fieldData->Handle; return true; } #endregion diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index 22c07b2e837bc6..c9170e3e9000e4 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -73,14 +73,14 @@ public override IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targe return TypeLoaderEnvironment.Instance.ResolveGenericVirtualMethodTarget(targetTypeHandle, declMethod); } - public override bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName) + public override bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle handle) { - return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName); + return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out handle); } - public override RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName) + public override RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle) { - return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents(declaringTypeHandle, fieldName); + return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents(declaringTypeHandle, handle); } public override IntPtr ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(IntPtr unboxingFunctionPointer, RuntimeTypeHandle declaringType) @@ -210,23 +210,6 @@ private bool EnsureTypeHandleForType(TypeDesc type) return !type.RuntimeTypeHandle.IsNull(); } - // - // Parse a native layout signature pointed to by "signature" in the executable image, optionally using - // "typeArgs" and "methodArgs" for generic type parameter substitution. The first field in "signature" - // must be an encoded type but any data beyond that is user-defined and returned in "remainingSignature" - // - internal bool GetTypeFromSignatureAndContext(RuntimeSignature signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType, out RuntimeSignature remainingSignature) - { - NativeReader reader = GetNativeLayoutInfoReader(signature); - NativeParser parser = new NativeParser(reader, signature.NativeLayoutOffset); - - bool result = GetTypeFromSignatureAndContext(ref parser, new TypeManagerHandle(signature.ModuleHandle), typeArgs, methodArgs, out createdType); - - remainingSignature = RuntimeSignature.CreateFromNativeLayoutSignature(signature, parser.Offset); - - return result; - } - internal bool GetTypeFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType) { createdType = default(RuntimeTypeHandle); diff --git a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs index 0a347d7ab3c567..56e55feaef309c 100644 --- a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs +++ b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs @@ -466,12 +466,6 @@ public Vertex GetMethodSignature(uint flags, uint fptrReferenceId, Vertex contai return Unify(sig); } - public Vertex GetFieldSignature(Vertex containingType, string name) - { - FieldSignature sig = new FieldSignature(containingType, name); - return Unify(sig); - } - public Vertex GetFixupSignature(FixupSignatureKind kind, Vertex signature) { FixupSignature sig = new FixupSignature(kind, signature); @@ -1032,53 +1026,6 @@ public override bool Equals(object obj) } } -#if NATIVEFORMAT_PUBLICWRITER - public -#else - internal -#endif - class FieldSignature : Vertex - { - private Vertex _containingType; - private string _name; - - public FieldSignature(Vertex containingType, string name) - { - _containingType = containingType; - _name = name; - } - - internal override void Save(NativeWriter writer) - { - _containingType.Save(writer); - writer.WriteString(_name); - } - - public override int GetHashCode() - { - int hash = 113 + 97 * _containingType.GetHashCode(); - foreach (char c in _name) - hash += (hash << 5) + c * 19; - - return hash; - } - - public override bool Equals(object obj) - { - var other = obj as FieldSignature; - if (other == null) - return false; - - if (!Equals(other._containingType, _containingType)) - return false; - - if (!Equals(other._name, _name)) - return false; - - return true; - } - } - #if NATIVEFORMAT_PUBLICWRITER public #else diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs index f807b6b8e6c037..d31338d83e5914 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -274,39 +274,6 @@ public override Vertex WriteVertex(NodeFactory factory) } } - internal sealed class NativeLayoutFieldLdTokenVertexNode : NativeLayoutSavedVertexNode - { - private readonly FieldDesc _field; - private readonly NativeLayoutTypeSignatureVertexNode _containingTypeSig; - - public NativeLayoutFieldLdTokenVertexNode(NodeFactory factory, FieldDesc field) - { - _field = field; - _containingTypeSig = factory.NativeLayout.TypeSignatureVertex(field.OwningType); - } - - protected override string GetName(NodeFactory factory) => "NativeLayoutFieldLdTokenVertexNode_" + factory.NameMangler.GetMangledFieldName(_field); - - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - return new DependencyListEntry[] - { - new DependencyListEntry(_containingTypeSig, "NativeLayoutFieldLdTokenVertexNode containing type signature"), - }; - } - - public override Vertex WriteVertex(NodeFactory factory) - { - Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); - - Vertex containingType = _containingTypeSig.WriteVertex(factory); - - Vertex unplacedVertex = GetNativeWriter(factory).GetFieldSignature(containingType, _field.Name); - - return SetSavedVertex(factory.MetadataManager.NativeLayoutInfo.LdTokenInfoSection.Place(unplacedVertex)); - } - } - internal sealed class NativeLayoutMethodSignatureVertexNode : NativeLayoutVertexNode { private Internal.TypeSystem.MethodSignature _signature; @@ -1739,7 +1706,7 @@ public sealed override IEnumerable GetStaticDependencies(No { var result = new DependencyList { - { factory.NativeLayout.FieldLdTokenVertex(_field), "Field Signature" } + { factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Owning type of field" } }; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType)) @@ -1756,8 +1723,11 @@ public sealed override IEnumerable GetStaticDependencies(No protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) { - Vertex ldToken = factory.NativeLayout.FieldLdTokenVertex(_field).WriteVertex(factory); - return GetNativeWriter(factory).GetRelativeOffsetSignature(ldToken); + Vertex owningType = factory.NativeLayout.TypeSignatureVertex(_field.OwningType).WriteVertex(factory); + Vertex fieldMetadataHandle = writer.GetUnsignedConstant( + (uint)factory.MetadataManager.GetMetadataHandleForField(factory, _field.GetTypicalFieldDefinition())); + + return writer.GetTuple(owningType, fieldMetadataHandle); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs index e3eb154d8d0c3b..4ad5145d949e9f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs @@ -62,11 +62,6 @@ private void CreateNodeCaches() return new NativeLayoutMethodLdTokenVertexNode(_factory, method); }); - _fieldLdTokenSignatures = new NodeCache(field => - { - return new NativeLayoutFieldLdTokenVertexNode(_factory, field); - }); - _nativeLayoutSignatureNodes = new NodeCache(key => { return new NativeLayoutSignatureNode(key.SignatureVertex, key.Identity, key.IdentityPrefix); @@ -361,12 +356,6 @@ internal NativeLayoutMethodLdTokenVertexNode MethodLdTokenVertex(MethodDesc meth return _methodLdTokenSignatures.GetOrAdd(method); } - private NodeCache _fieldLdTokenSignatures; - internal NativeLayoutFieldLdTokenVertexNode FieldLdTokenVertex(FieldDesc field) - { - return _fieldLdTokenSignatures.GetOrAdd(field); - } - private struct NativeLayoutSignatureKey : IEquatable { public NativeLayoutSignatureKey(NativeLayoutSavedVertexNode signatureVertex, Utf8String identityPrefix, TypeSystemEntity identity) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs index ddb94c51c9df48..150d4d6a0e9a32 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs @@ -38,8 +38,6 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) return ObjectNodeSection.DataSection; } - private static readonly Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RFHSignature_"); - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { DependencyList result = null; @@ -54,8 +52,10 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); - NativeLayoutFieldLdTokenVertexNode ldtokenSigNode = factory.NativeLayout.FieldLdTokenVertex(_targetField); - objData.EmitPointerReloc(factory.NativeLayout.NativeLayoutSignature(ldtokenSigNode, s_NativeLayoutSignaturePrefix, _targetField)); + int handle = relocsOnly ? 0 : factory.MetadataManager.GetMetadataHandleForField(factory, _targetField.GetTypicalFieldDefinition()); + + objData.EmitPointerReloc(factory.MaximallyConstructableType(_targetField.OwningType)); + objData.EmitInt(handle); return objData.ToObjectData(); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 53a722cdb663f0..d69a3f32e07386 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -48,6 +48,7 @@ public abstract class MetadataManager : ICompilationRootProvider private byte[] _metadataBlob; private List> _typeMappings; private List> _fieldMappings; + private Dictionary _fieldHandleMap; private List> _methodMappings; private List _stackTraceMappings; protected readonly string _metadataLogFile; @@ -692,6 +693,10 @@ protected void EnsureMetadataGenerated(NodeFactory factory) return; ComputeMetadata(factory, out _metadataBlob, out _typeMappings, out _methodMappings, out _fieldMappings, out _stackTraceMappings); + + _fieldHandleMap = new Dictionary(); + foreach (var fieldMapEntry in _fieldMappings) + _fieldHandleMap[fieldMapEntry.Entity.GetTypicalFieldDefinition()] = fieldMapEntry.MetadataHandle; } void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) @@ -955,6 +960,12 @@ public IEnumerable> GetFieldMapping(NodeFactory facto return _fieldMappings; } + public int GetMetadataHandleForField(NodeFactory factory, FieldDesc field) + { + EnsureMetadataGenerated(factory); + return _fieldHandleMap[field]; + } + public IEnumerable GetStackTraceMapping(NodeFactory factory) { EnsureMetadataGenerated(factory); From 7751a65008f0e05756f921406d819577e6b07819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 12 Mar 2025 12:10:26 +0100 Subject: [PATCH 2/8] Delete native layout representation of methods --- .../src/CompatibilitySuppressions.xml | 8 - .../Runtime/Augments/TypeLoaderCallbacks.cs | 5 +- .../RuntimeMethodHandleInfo.cs | 35 +- .../CompilerServices/RuntimeSignature.cs | 127 ------ .../src/System.Private.CoreLib.csproj | 1 - .../NativeFormat/NativeFormatMethodCommon.cs | 5 +- .../src/System/RuntimeMethodHandle.cs | 7 +- ...EnvironmentImplementation.MappingTables.cs | 26 +- .../DelegateMethodInfoRetriever.cs | 2 +- .../TypeLoader/GenericDictionaryCell.cs | 21 +- .../Internal/Runtime/TypeLoader/ModuleList.cs | 18 - .../TypeLoader/NativeLayoutInfoLoadContext.cs | 11 +- .../Runtime/TypeLoader/TypeBuilder.cs | 2 +- ...ronment.ConstructedGenericMethodsLookup.cs | 20 +- .../TypeLoaderEnvironment.GVMResolution.cs | 27 +- ...peLoaderEnvironment.LdTokenResultLookup.cs | 238 +++-------- .../TypeLoaderEnvironment.Metadata.cs | 95 +---- ...derEnvironment.MetadataSignatureParsing.cs | 402 ------------------ .../TypeLoaderEnvironment.SignatureParsing.cs | 334 +-------------- .../TypeLoader/TypeLoaderEnvironment.cs | 86 +--- .../Internal/TypeSystem/RuntimeMethodDesc.cs | 4 +- .../TypeSystem/TypeSystemContext.Runtime.cs | 2 +- .../src/System.Private.TypeLoader.csproj | 1 - .../NativeFormat/NativeFormatWriter.cs | 63 +-- .../Compiler/AnalysisBasedMetadataManager.cs | 33 ++ .../ExactMethodInstantiationsNode.cs | 14 +- .../GenericMethodsHashtableNode.cs | 12 +- .../GenericVirtualMethodTableNode.cs | 15 +- .../InterfaceGenericVirtualMethodTableNode.cs | 15 +- .../DependencyAnalysis/MethodMetadataNode.cs | 22 +- .../MethodParameterMetadataNode.cs | 41 ++ .../NativeLayoutInfoNode.cs | 3 - .../NativeLayoutSignatureNode.cs | 128 ------ .../NativeLayoutVertexNode.cs | 132 +----- .../NodeFactory.NativeLayout.cs | 75 +--- .../DependencyAnalysis/NodeFactory.cs | 32 +- .../ReflectionInvokeMapNode.cs | 24 +- .../ReflectionVirtualInvokeMapNode.cs | 16 +- .../RuntimeMethodHandleNode.cs | 12 +- .../DependencyAnalysis/TypeGVMEntriesNode.cs | 2 - .../Compiler/MetadataManager.cs | 55 ++- .../Compiler/UsageBasedMetadataManager.cs | 26 +- .../ILCompiler.Compiler.csproj | 2 +- .../ILCompiler/Metadata/EntityMap.cs | 2 + .../ILCompiler/Metadata/IMetadataPolicy.cs | 6 + .../Metadata/MetadataTransformResult.cs | 7 + .../ILCompiler/Metadata/Transform.Method.cs | 3 + 47 files changed, 410 insertions(+), 1807 deletions(-) delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs delete mode 100644 src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.MetadataSignatureParsing.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index dd7b03022aab4a..f807a13680d788 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -717,14 +717,6 @@ CP0001 T:Internal.Runtime.CompilerServices.OpenMethodResolver - - CP0001 - T:Internal.Runtime.CompilerServices.RuntimeMethodHandleInfo - - - CP0001 - T:Internal.Runtime.CompilerServices.RuntimeSignature - CP0001 T:Internal.Runtime.TypeManagerHandle diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs index 82b17ff7753764..2bd2e7579d00ef 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs @@ -19,9 +19,8 @@ public abstract class TypeLoaderCallbacks public abstract bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr GetThreadStaticGCDescForDynamicType(TypeManagerHandle handle, int index); public abstract IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntPtr signature, out IntPtr auxResult); - public abstract bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs); - public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs); - public abstract bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2); + public abstract bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs); + public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs); public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeMethodHandle declMethod); public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle handle); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs index 41aa17cdcbfdae..a5910c31319a47 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs @@ -6,19 +6,27 @@ using System.Reflection; using System.Runtime.InteropServices; +using Internal.Metadata.NativeFormat; using Internal.Runtime.Augments; namespace Internal.Runtime.CompilerServices { + [CLSCompliant(false)] public class MethodNameAndSignature { - public string Name { get; } - public RuntimeSignature Signature { get; } + public MetadataReader Reader { get; } + public MethodHandle Handle { get; } - public MethodNameAndSignature(string name, RuntimeSignature signature) + public MethodNameAndSignature(MetadataReader reader, MethodHandle handle) { - Name = name; - Signature = signature; + Reader = reader; + Handle = handle; + } + + public string GetName() + { + Method method = Reader.GetMethod(Handle); + return Reader.GetString(method.Name); } public override bool Equals(object? compare) @@ -30,24 +38,17 @@ public override bool Equals(object? compare) if (other == null) return false; - if (Name != other.Name) + if (GetName() != other.GetName()) return false; - return Signature.Equals(other.Signature); + // Comparing handles is enough if there's only one metadata blob + Debug.Assert(Reader == other.Reader); + return Reader.GetMethod(Handle).Signature.Equals(other.Reader.GetMethod(other.Handle).Signature); } public override int GetHashCode() { - int hash = Name.GetHashCode(); - - return hash; + return Handle.GetHashCode(); } } - - [StructLayout(LayoutKind.Sequential)] - [CLSCompliant(false)] - public unsafe struct RuntimeMethodHandleInfo - { - public IntPtr NativeLayoutInfoSignature; - } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs deleted file mode 100644 index 28fc165de7df99..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeSignature.cs +++ /dev/null @@ -1,127 +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.Diagnostics; -using System.Runtime; - -using Internal.Runtime.Augments; - -namespace Internal.Runtime.CompilerServices -{ - public struct RuntimeSignature - { - private IntPtr _moduleHandle; - private int _tokenOrOffset; - private bool _isNativeLayoutSignature; - - [CLSCompliant(false)] - public static RuntimeSignature CreateFromNativeLayoutSignature(TypeManagerHandle moduleHandle, uint nativeLayoutOffset) - { - return new RuntimeSignature - { - _moduleHandle = moduleHandle.GetIntPtrUNSAFE(), - _tokenOrOffset = (int)nativeLayoutOffset, - _isNativeLayoutSignature = true, - }; - } - - [CLSCompliant(false)] - public static RuntimeSignature CreateFromNativeLayoutSignature(RuntimeSignature oldSignature, uint newNativeLayoutOffset) - { - return new RuntimeSignature - { - _moduleHandle = oldSignature._moduleHandle, - _tokenOrOffset = (int)newNativeLayoutOffset, - _isNativeLayoutSignature = true, - }; - } - - public static RuntimeSignature CreateFromMethodHandle(TypeManagerHandle moduleHandle, int token) - { - return new RuntimeSignature - { - _moduleHandle = moduleHandle.GetIntPtrUNSAFE(), - _tokenOrOffset = token, - _isNativeLayoutSignature = false, - }; - } - - public bool IsNativeLayoutSignature - { - get - { - return _isNativeLayoutSignature; - } - } - - public int Token - { - get - { - if (_isNativeLayoutSignature) - { - Debug.Assert(false); - return -1; - } - return _tokenOrOffset; - } - } - - [CLSCompliant(false)] - public uint NativeLayoutOffset - { - get - { - if (!_isNativeLayoutSignature) - { - Debug.Assert(false); - return unchecked((uint)-1); - } - return (uint)_tokenOrOffset; - } - } - - public IntPtr ModuleHandle - { - get - { - return _moduleHandle; - } - } - - public bool Equals(RuntimeSignature other) - { - if (IsNativeLayoutSignature && other.IsNativeLayoutSignature) - { - if ((ModuleHandle == other.ModuleHandle) && (NativeLayoutOffset == other.NativeLayoutOffset)) - return true; - } - else if (!IsNativeLayoutSignature && !other.IsNativeLayoutSignature) - { - if ((ModuleHandle == other.ModuleHandle) && (Token == other.Token)) - return true; - } - - // Walk both signatures to check for equality the slow way - return RuntimeAugments.TypeLoaderCallbacks.CompareMethodSignatures(this, other); - } - - /// - /// Fast equality check - /// - public bool StructuralEquals(RuntimeSignature other) - { - if (_moduleHandle != other._moduleHandle) - return false; - - if (_tokenOrOffset != other._tokenOrOffset) - return false; - - if (_isNativeLayoutSignature != other._isNativeLayoutSignature) - return false; - - return true; - } - } -} 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 5fb8b8fdabb1f0..c89b37a3d60252 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 @@ -120,7 +120,6 @@ - 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 e07f23d3fcc205..ad37847fc02cea 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 @@ -201,12 +201,9 @@ public RuntimeMethodHandle GetRuntimeMethodHandle(Type[] genericArgs) genericArgHandles = null; } - TypeManagerHandle typeManager = RuntimeAugments.TypeLoaderCallbacks.GetModuleForMetadataReader(Reader); - return RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleForComponents( DeclaringType.TypeHandle, - Name, - RuntimeSignature.CreateFromMethodHandle(typeManager, MethodHandle.AsInt()), + _methodHandle, genericArgHandles); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs index 3de517db8f37c1..f37af72848cd2a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using System.Runtime.Serialization; +using Internal.Metadata.NativeFormat; using Internal.Reflection.Augments; using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; @@ -40,7 +41,7 @@ public bool Equals(RuntimeMethodHandle handle) return false; RuntimeTypeHandle declaringType1, declaringType2; - MethodNameAndSignature nameAndSignature1, nameAndSignature2; + MethodHandle nameAndSignature1, nameAndSignature2; RuntimeTypeHandle[] genericArgs1, genericArgs2; RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType1, out nameAndSignature1, out genericArgs1); @@ -72,12 +73,12 @@ public override int GetHashCode() return 0; RuntimeTypeHandle declaringType; - MethodNameAndSignature nameAndSignature; + MethodHandle nameAndSignature; RuntimeTypeHandle[] genericArgs; RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType, out nameAndSignature, out genericArgs); int hashcode = declaringType.GetHashCode(); - hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ nameAndSignature.Name.GetHashCode(); + hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ nameAndSignature.GetHashCode(); if (genericArgs != null) { for (int i = 0; i < genericArgs.Length; i++) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 6d7ff877d49d09..81914a83bbeca7 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -227,8 +227,6 @@ public sealed override MethodBaseInvoker TryGetMethodInvokerNoConstraintCheck(Ru { MethodBase methodInfo = ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles); - MethodSignatureComparer methodSignatureComparer = new MethodSignatureComparer(methodHandle); - MethodInvokeInfo methodInvokeInfo; #if GENERICS_FORCE_USG // Stress mode to force the usage of universal canonical method targets for reflection invokes. @@ -244,12 +242,12 @@ public sealed override MethodBaseInvoker TryGetMethodInvokerNoConstraintCheck(Ru methodInfo, ref methodSignatureComparer, CanonicalFormKind.Universal); #else methodInvokeInfo = TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - methodInfo, ref methodSignatureComparer, CanonicalFormKind.Specific); + methodInfo, CanonicalFormKind.Specific); // If we failed to get a MethodInvokeInfo for an exact method, or a canonically equivalent method, check if there is a universal canonically // equivalent entry that could be used (it will be much slower, and require a calling convention converter) methodInvokeInfo ??= TryGetMethodInvokeInfo(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - methodInfo, ref methodSignatureComparer, CanonicalFormKind.Universal); + methodInfo, CanonicalFormKind.Universal); #endif if (methodInvokeInfo == null) @@ -280,12 +278,10 @@ private static RuntimeTypeHandle[] GetTypeSequence(ref ExternalReferencesTable e return result; } - private static IntPtr TryGetVirtualResolveData(NativeFormatModuleInfo module, - RuntimeTypeHandle methodHandleDeclaringType, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericArgs, - ref MethodSignatureComparer methodSignatureComparer) + private static IntPtr TryGetVirtualResolveData(RuntimeTypeHandle methodHandleDeclaringType, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericArgs) { TypeLoaderEnvironment.VirtualResolveDataResult lookupResult; - bool success = TypeLoaderEnvironment.TryGetVirtualResolveData(module, methodHandleDeclaringType, genericArgs, ref methodSignatureComparer, out lookupResult); + bool success = TypeLoaderEnvironment.TryGetVirtualResolveData(methodHandleDeclaringType, methodHandle, genericArgs, out lookupResult); if (!success) return IntPtr.Zero; else @@ -311,7 +307,6 @@ private static IntPtr TryGetVirtualResolveData(NativeFormatModuleInfo module, /// Handle of method to look up /// Runtime handles of generic method arguments /// MethodInfo of method to look up - /// Helper structure used for comparing signatures /// Requested canon form /// Constructed method invoke info, null on failure private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( @@ -319,7 +314,6 @@ private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles, MethodBase methodInfo, - ref MethodSignatureComparer methodSignatureComparer, CanonicalFormKind canonFormKind) { MethodInvokeMetadata methodInvokeMetadata; @@ -328,7 +322,6 @@ private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - ref methodSignatureComparer, canonFormKind, out methodInvokeMetadata)) { @@ -351,9 +344,7 @@ private static unsafe MethodInvokeInfo TryGetMethodInvokeInfo( IntPtr resolver = IntPtr.Zero; if ((methodInvokeMetadata.InvokeTableFlags & InvokeTableFlags.HasVirtualInvoke) != 0) { - resolver = TryGetVirtualResolveData(ModuleList.Instance.GetModuleInfoForMetadataReader(methodHandle.NativeFormatReader), - declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles, - ref methodSignatureComparer); + resolver = TryGetVirtualResolveData(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles); // Unable to find virtual resolution information, cannot return valid MethodInvokeInfo if (resolver == IntPtr.Zero) @@ -854,12 +845,7 @@ public sealed override FieldAccessor TryGetFieldAccessor( // public sealed override unsafe bool TryGetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { - MethodNameAndSignature nameAndSignature; - methodHandle = default(QMethodDefinition); - if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodTypeArgumentHandles)) - return false; - - return TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSignature, out methodHandle); + return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles); } // diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs index 5669203a6f39d1..9bb61c5cfb9073 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Extensions/NonPortable/DelegateMethodInfoRetriever.cs @@ -47,7 +47,7 @@ public static MethodInfo GetDelegateMethodInfo(Delegate del) callTryGetMethod = false; methodHandle = QMethodDefinition.FromObjectAndInt(resolver->Reader, resolver->Handle); - if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(resolver->GVMMethodHandle, out _, out _, out genericMethodTypeArgumentHandles)) + if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(resolver->GVMMethodHandle, out _, out QMethodDefinition dummy, out genericMethodTypeArgumentHandles)) throw new NotSupportedException(SR.DelegateGetMethodInfo_NoInstantiation); } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs index 0157ab96ed192a..8a2b4caecd5eac 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs @@ -276,8 +276,6 @@ internal override unsafe IntPtr Create(TypeBuilder builder) private class MethodLdTokenCell : GenericDictionaryCell { internal MethodDesc Method; - internal IntPtr MethodName; - internal RuntimeSignature MethodSignature; internal override unsafe void Prepare(TypeBuilder builder) { @@ -301,8 +299,7 @@ internal override unsafe IntPtr Create(TypeBuilder builder) RuntimeMethodHandle handle = TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents( builder.GetRuntimeTypeHandle(Method.OwningType), - MethodName, - MethodSignature, + Method.NameAndSignature.Handle, genericArgHandles); return *(IntPtr*)&handle; @@ -477,18 +474,12 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.MethodLdToken: { - NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); - - RuntimeSignature methodNameSig; - RuntimeSignature methodSig; - var method = nativeLayoutInfoLoadContext.GetMethod(ref ldtokenSigParser, out methodNameSig, out methodSig); - TypeLoaderLogger.WriteLine("LdToken on: " + method.OwningType.ToString() + "::" + method.NameAndSignature.Name); + var method = nativeLayoutInfoLoadContext.GetMethod(ref parser); + TypeLoaderLogger.WriteLine("LdToken on: " + method.OwningType.ToString() + "::" + method.NameAndSignature.GetName()); cell = new MethodLdTokenCell { Method = method, - MethodName = methodNameSig.NativeLayoutSignature(), - MethodSignature = methodSig }; } break; @@ -513,7 +504,7 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.Method: { - var method = nativeLayoutInfoLoadContext.GetMethod(ref parser, out _, out _); + var method = nativeLayoutInfoLoadContext.GetMethod(ref parser); TypeLoaderLogger.WriteLine("Method: " + method.ToString()); cell = new MethodCell @@ -542,9 +533,7 @@ internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadCon case FixupSignatureKind.GenericStaticConstrainedMethod: { TypeDesc constraintType = nativeLayoutInfoLoadContext.GetType(ref parser); - - NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); - MethodDesc constrainedMethod = nativeLayoutInfoLoadContext.GetMethod(ref ldtokenSigParser); + MethodDesc constrainedMethod = nativeLayoutInfoLoadContext.GetMethod(ref parser); TypeLoaderLogger.WriteLine("GenericStaticConstrainedMethod: " + constraintType.ToString() + " Method " + constrainedMethod.ToString()); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs index c484eb6e5afded..f4353f9db8f54b 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs @@ -395,22 +395,4 @@ public static NativeFormatModuleInfoEnumerable EnumerateModules(TypeManagerHandl return new NativeFormatModuleInfoEnumerable(Instance._loadedModuleMap, preferredModule); } } - - public static partial class RuntimeSignatureHelper - { - public static ModuleInfo GetModuleInfo(this Internal.Runtime.CompilerServices.RuntimeSignature methodSignature) - { - if (methodSignature.IsNativeLayoutSignature) - { - return ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(methodSignature.ModuleHandle)); - } - else - { - ModuleInfo moduleInfo; - bool success = ModuleList.Instance.TryGetModuleInfoByHandle(new TypeManagerHandle(methodSignature.ModuleHandle), out moduleInfo); - Debug.Assert(success); - return moduleInfo; - } - } - } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs index 90a2c9857c6dc1..e7e798a7e6728f 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutInfoLoadContext.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using System.Reflection.Runtime.General; using Internal.NativeFormat; using Internal.Runtime; @@ -175,7 +176,7 @@ internal TypeDesc GetType(ref NativeParser parser) } } - internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature methodNameSig, out RuntimeSignature methodSig) + internal MethodDesc GetMethod(ref NativeParser parser) { MethodFlags flags = (MethodFlags)parser.GetUnsigned(); @@ -184,7 +185,8 @@ internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature meth functionPointer = GetExternalReferencePointer(parser.GetUnsigned()); DefType containingType = (DefType)GetType(ref parser); - MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.GetMethodNameAndSignature(ref parser, _module.Handle, out methodNameSig, out methodSig); + int token = (int)parser.GetUnsigned(); + MethodNameAndSignature nameAndSignature = new MethodNameAndSignature(_module.MetadataReader, token.AsHandle().ToMethodHandle(_module.MetadataReader)); bool unboxingStub = (flags & MethodFlags.IsUnboxingStub) != 0; @@ -208,11 +210,6 @@ internal MethodDesc GetMethod(ref NativeParser parser, out RuntimeSignature meth return retVal; } - internal MethodDesc GetMethod(ref NativeParser parser) - { - return GetMethod(ref parser, out _, out _); - } - internal TypeDesc[] GetTypeSequence(ref NativeParser parser) { uint count = parser.GetSequenceCount(); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index 5d817bff72eda9..77adef43e27c9d 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -348,7 +348,7 @@ internal void ParseNativeLayoutInfo(InstantiatedMethod method) break; default: - Debug.Fail("Unexpected BagElementKind for generic method with name " + method.NameAndSignature.Name + "! Only BagElementKind.DictionaryLayout should appear."); + Debug.Fail("Unexpected BagElementKind for generic method with name " + method.NameAndSignature.GetName() + "! Only BagElementKind.DictionaryLayout should appear."); throw new BadImageFormatException(); } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs index 634770228e4da2..30fa2dcd32fed0 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; +using System.Reflection.Runtime.General; using System.Threading; using Internal.NativeFormat; @@ -27,7 +28,7 @@ public override int GetHashCode() { if (!_hashCode.HasValue) { - _hashCode = _declaringTypeHandle.GetHashCode() ^ TypeHashingAlgorithms.ComputeGenericInstanceHashCode(TypeHashingAlgorithms.ComputeNameHashCode(_methodNameAndSignature.Name), _genericMethodArgumentHandles); + _hashCode = _declaringTypeHandle.GetHashCode() ^ TypeHashingAlgorithms.ComputeGenericInstanceHashCode(TypeHashingAlgorithms.ComputeNameHashCode(_methodNameAndSignature.GetName()), _genericMethodArgumentHandles); } return _hashCode.Value; } @@ -147,7 +148,7 @@ internal override bool MatchParsedEntry(ref NativeParser entryParser, ref Extern RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); // Hash table names / sigs are indirected through to the native layout info - MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.Instance.GetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned()); + MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.GetMethodNameAndSignatureFromToken(moduleHandle, entryParser.GetUnsigned()); RuntimeTypeHandle[] parsedArgsHandles = GetTypeSequence(ref externalReferencesLookup, ref entryParser); @@ -186,10 +187,8 @@ public bool TryGetGenericMethodComponents(IntPtr methodDictionary, out RuntimeTy { if (!TryGetDynamicGenericMethodComponents(methodDictionary, out declaringType, out nameAndSignature, out genericMethodArgumentHandles)) { - if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out TypeManagerHandle typeManager, out uint nameAndSigOffset, out genericMethodArgumentHandles)) + if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out nameAndSignature, out genericMethodArgumentHandles)) return false; - - nameAndSignature = TypeLoaderEnvironment.Instance.GetMethodNameAndSignatureFromNativeLayoutOffset(typeManager, nameAndSigOffset); } return true; @@ -199,7 +198,7 @@ public static bool TryGetGenericMethodComponents(IntPtr methodDictionary, out Ru { TypeLoaderEnvironment instance = TypeLoaderEnvironment.InstanceOrNull; if (instance == null || !instance.TryGetDynamicGenericMethodComponents(methodDictionary, out declaringType, out _, out genericMethodArgumentHandles)) - if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out _, out _, out genericMethodArgumentHandles)) + if (!TryGetStaticGenericMethodComponents(methodDictionary, out declaringType, out _, out genericMethodArgumentHandles)) return false; return true; @@ -370,7 +369,7 @@ private bool TryGetDynamicGenericMethodComponents(IntPtr methodDictionary, out R return true; } } - private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDictionary, out RuntimeTypeHandle declaringType, out TypeManagerHandle typeManager, out uint nameAndSigOffset, out RuntimeTypeHandle[] genericMethodArgumentHandles) + private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDictionary, out RuntimeTypeHandle declaringType, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgumentHandles) { // Generic method dictionaries have a header that has the hash code in it. Locate the header IntPtr dictionaryHeader = IntPtr.Subtract(methodDictionary, IntPtr.Size); @@ -398,8 +397,8 @@ private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDict // We have a match - fill in the results declaringType = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); - typeManager = module.Handle; - nameAndSigOffset = entryParser.GetUnsigned(); + int token = (int)entryParser.GetUnsigned(); + nameAndSignature = new MethodNameAndSignature(module.MetadataReader, token.AsHandle().ToMethodHandle(module.MetadataReader)); uint arity = entryParser.GetSequenceCount(); genericMethodArgumentHandles = new RuntimeTypeHandle[arity]; @@ -414,8 +413,7 @@ private static unsafe bool TryGetStaticGenericMethodComponents(IntPtr methodDict } declaringType = default(RuntimeTypeHandle); - typeManager = default; - nameAndSigOffset = 0; + nameAndSignature = null; genericMethodArgumentHandles = null; return false; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs index c73df4af62b5d7..25de1746006d84 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Reflection.Runtime.General; using System.Runtime; using System.Runtime.InteropServices; using System.Threading; @@ -105,7 +106,7 @@ internal static InstantiatedMethod GVMLookupForSlotWorker(DefType targetType, In sb.AppendLine(); sb.AppendLine("Declaring type: " + GetTypeNameDebug(slotMethod.OwningType)); sb.AppendLine("Target type: " + GetTypeNameDebug(targetType)); - sb.AppendLine("Method name: " + slotMethod.NameAndSignature.Name); + sb.AppendLine("Method name: " + slotMethod.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < slotMethod.Instantiation.Length; i++) { @@ -133,7 +134,7 @@ internal unsafe IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle type, sb.AppendLine("Failed to create generic virtual method implementation"); sb.AppendLine(); sb.AppendLine("Declaring type: " + GetTypeNameDebug(result.OwningType)); - sb.AppendLine("Method name: " + result.NameAndSignature.Name); + sb.AppendLine("Method name: " + result.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < result.Instantiation.Length; i++) { @@ -146,19 +147,9 @@ internal unsafe IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle type, return FunctionPointerOps.GetGenericMethodFunctionPointer(methodPointer, dictionaryPointer); } - private static MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, TypeManagerHandle moduleHandle, uint nativeLayoutOffset) + public static MethodNameAndSignature GetMethodNameAndSignatureFromToken(TypeManagerHandle moduleHandle, uint token) { - NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset); - - string methodName = parser.GetString(); - - // Signatures are indirected to through a relative offset so that we don't have to parse them - // when not comparing signatures (parsing them requires resolving types and is tremendously - // expensive). - NativeParser sigParser = parser.GetParserFromRelativeOffset(); - RuntimeSignature methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, sigParser.Offset); - - return new MethodNameAndSignature(methodName, methodSig); + return new MethodNameAndSignature(ModuleList.Instance.GetMetadataReaderForModule(moduleHandle), token.AsHandle().ToMethodHandle(null)); } private static RuntimeTypeHandle GetTypeDefinition(RuntimeTypeHandle typeHandle) @@ -191,7 +182,7 @@ private static InstantiatedMethod FindMatchingInterfaceSlot(NativeFormatModuleIn if (nameAndSigToken != SpecialGVMInterfaceEntry.Diamond && nameAndSigToken != SpecialGVMInterfaceEntry.Reabstraction) { - targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); + targetMethodNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, nameAndSigToken); targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); isDefaultInterfaceMethodImplementation = RuntimeAugments.IsInterface(targetTypeHandle); #if GVM_RESOLUTION_TRACE @@ -357,7 +348,7 @@ private static InstantiatedMethod ResolveInterfaceGenericVirtualMethodSlot(DefTy continue; uint nameAndSigToken = entryParser.GetUnsigned(); - MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, nameAndSigToken); + MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, nameAndSigToken); if (!interfaceMethodNameAndSignature.Equals(slotMethod.NameAndSignature)) continue; @@ -489,13 +480,13 @@ private static InstantiatedMethod ResolveGenericVirtualMethodTarget(DefType targ continue; uint parsedCallingNameAndSigToken = entryParser.GetUnsigned(); - MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedCallingNameAndSigToken); + MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(slotMethod.NameAndSignature)) continue; uint parsedTargetMethodNameAndSigToken = entryParser.GetUnsigned(); - MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, module.Handle, parsedTargetMethodNameAndSigToken); + MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromToken(module.Handle, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index 91c0fe3de55a91..69b94757717973 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -31,59 +31,14 @@ private struct FieldHandleInfo } [StructLayout(LayoutKind.Sequential)] - internal struct DynamicMethodHandleInfo + internal struct MethodHandleInfo { - public IntPtr DeclaringType; - public IntPtr MethodName; - public RuntimeSignature MethodSignature; + public RuntimeTypeHandle DeclaringType; + public MethodHandle Handle; public int NumGenericArgs; - public IntPtr GenericArgsArray; - } - - - #region String conversions - private static unsafe string GetStringFromMemoryInNativeFormat(IntPtr pointerToDataStream) - { - byte* dataStream = (byte*)pointerToDataStream; - uint stringLen = NativePrimitiveDecoder.DecodeUnsigned(ref dataStream); - return Encoding.UTF8.GetString(dataStream, checked((int)stringLen)); + public RuntimeTypeHandle FirstArgument; } - /// - /// From a string, get a pointer to an allocated memory location that holds a NativeFormat encoded string. - /// This is used for the creation of RuntimeFieldHandles from metadata. - /// - /// - /// - public unsafe IntPtr GetNativeFormatStringForString(string str) - { - using (_typeLoaderLock.EnterScope()) - { - IntPtr result; - if (_nativeFormatStrings.TryGetValue(str, out result)) - return result; - - NativePrimitiveEncoder stringEncoder = default; - stringEncoder.Init(); - byte[] utf8Bytes = Encoding.UTF8.GetBytes(str); - stringEncoder.WriteUnsigned(checked((uint)utf8Bytes.Length)); - foreach (byte b in utf8Bytes) - stringEncoder.WriteByte(b); - - void* allocatedNativeFormatString = MemoryHelpers.AllocateMemory(stringEncoder.Size); - unsafe - { - stringEncoder.Save((byte*)allocatedNativeFormatString, stringEncoder.Size); - } - _nativeFormatStrings.Add(str, (IntPtr)allocatedNativeFormatString); - return (IntPtr)allocatedNativeFormatString; - } - } - - private LowLevelDictionary _nativeFormatStrings = new LowLevelDictionary(); - #endregion - - #region Ldtoken Hashtables private struct RuntimeFieldHandleKey : IEquatable { @@ -116,28 +71,18 @@ public bool Equals(RuntimeFieldHandleKey other) private struct RuntimeMethodHandleKey : IEquatable { private RuntimeTypeHandle _declaringType; - private string _methodName; - private RuntimeSignature _signature; + private MethodHandle _handle; private RuntimeTypeHandle[] _genericArgs; - private int _hashcode; - public RuntimeMethodHandleKey(RuntimeTypeHandle declaringType, string methodName, RuntimeSignature signature, RuntimeTypeHandle[] genericArgs) + public RuntimeMethodHandleKey(RuntimeTypeHandle declaringType, MethodHandle handle, RuntimeTypeHandle[] genericArgs) { // genericArgs will be null if this is a (typical or not) method definition // genericArgs are non-null only for instantiated generic methods. Debug.Assert(genericArgs == null || genericArgs.Length > 0); _declaringType = declaringType; - _methodName = methodName; - _signature = signature; + _handle = handle; _genericArgs = genericArgs; - int methodNameHashCode = methodName == null ? 0 : methodName.GetHashCode(); - _hashcode = methodNameHashCode ^ signature.GetHashCode(); - - if (genericArgs != null) - _hashcode ^= TypeHashingAlgorithms.ComputeGenericInstanceHashCode(declaringType.GetHashCode(), genericArgs); - else - _hashcode ^= declaringType.GetHashCode(); } public override bool Equals(object obj) @@ -151,7 +96,7 @@ public override bool Equals(object obj) public bool Equals(RuntimeMethodHandleKey other) { - if (!_declaringType.Equals(other._declaringType) || _methodName != other._methodName || !_signature.Equals(other._signature)) + if (!_declaringType.Equals(other._declaringType) || !_handle.Equals(other._handle)) return false; if ((_genericArgs == null) != (other._genericArgs == null)) @@ -170,7 +115,10 @@ public bool Equals(RuntimeMethodHandleKey other) return true; } - public override int GetHashCode() { return _hashcode; } + public override int GetHashCode() + => _handle.GetHashCode() ^ (_genericArgs == null + ? _declaringType.GetHashCode() + : TypeHashingAlgorithms.ComputeGenericInstanceHashCode(_declaringType.GetHashCode(), _genericArgs)); } private LowLevelDictionary _runtimeFieldHandles = new LowLevelDictionary(); @@ -215,42 +163,39 @@ public unsafe bool TryGetRuntimeFieldHandleComponents(RuntimeFieldHandle runtime #region Method Ldtoken Functions + public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, int handle, RuntimeTypeHandle[] genericMethodArgs) + => GetRuntimeMethodHandleForComponents(declaringTypeHandle, handle.AsHandle().ToMethodHandle(null), genericMethodArgs); + /// /// Create a runtime method handle from name, signature and generic arguments. If the methodSignature /// is constructed from a metadata token, the methodName should be IntPtr.Zero, as it already encodes the method /// name. /// - public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, IntPtr methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) + public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs) { - string methodNameStr = methodName == IntPtr.Zero ? null : GetStringFromMemoryInNativeFormat(methodName); - - RuntimeMethodHandleKey key = new RuntimeMethodHandleKey(declaringTypeHandle, methodNameStr, methodSignature, genericMethodArgs); - RuntimeMethodHandle runtimeMethodHandle = default(RuntimeMethodHandle); + RuntimeMethodHandleKey key = new RuntimeMethodHandleKey(declaringTypeHandle, handle, genericMethodArgs); lock (_runtimeMethodHandles) { - if (!_runtimeMethodHandles.TryGetValue(key, out runtimeMethodHandle)) + if (!_runtimeMethodHandles.TryGetValue(key, out RuntimeMethodHandle runtimeMethodHandle)) { - int sizeToAllocate = sizeof(DynamicMethodHandleInfo); + int sizeToAllocate = sizeof(MethodHandleInfo); int numGenericMethodArgs = genericMethodArgs == null ? 0 : genericMethodArgs.Length; // Use checked arithmetics to ensure there aren't any overflows/truncations sizeToAllocate = checked(sizeToAllocate + (numGenericMethodArgs > 0 ? sizeof(IntPtr) * (numGenericMethodArgs - 1) : 0)); - DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)MemoryHelpers.AllocateMemory(sizeToAllocate); - methodData->DeclaringType = *(IntPtr*)&declaringTypeHandle; - methodData->MethodName = methodName; - methodData->MethodSignature = methodSignature; + MethodHandleInfo* methodData = (MethodHandleInfo*)MemoryHelpers.AllocateMemory(sizeToAllocate); + methodData->DeclaringType = declaringTypeHandle; + methodData->Handle = handle; methodData->NumGenericArgs = numGenericMethodArgs; - IntPtr* genericArgPtr = &(methodData->GenericArgsArray); + RuntimeTypeHandle* genericArgPtr = &methodData->FirstArgument; for (int i = 0; i < numGenericMethodArgs; i++) { RuntimeTypeHandle currentArg = genericMethodArgs[i]; - genericArgPtr[i] = *(IntPtr*)¤tArg; + genericArgPtr[i] = currentArg; } - // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob - IntPtr runtimeMethodHandleValue = (IntPtr)methodData + 1; - runtimeMethodHandle = *(RuntimeMethodHandle*)&runtimeMethodHandleValue; + runtimeMethodHandle = RuntimeMethodHandle.FromIntPtr((nint)methodData); _runtimeMethodHandles.Add(key, runtimeMethodHandle); } @@ -258,74 +203,16 @@ public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTyp return runtimeMethodHandle; } } - public RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) - { - IntPtr nameAsIntPtr = GetNativeFormatStringForString(methodName); - return GetRuntimeMethodHandleForComponents(declaringTypeHandle, nameAsIntPtr, methodSignature, genericMethodArgs); - } public MethodDesc GetMethodDescForRuntimeMethodHandle(TypeSystemContext context, RuntimeMethodHandle runtimeMethodHandle) { - return runtimeMethodHandle.IsDynamic() ? - GetMethodDescForDynamicRuntimeMethodHandle(context, runtimeMethodHandle) : - GetMethodDescForStaticRuntimeMethodHandle(context, runtimeMethodHandle); - } - - public bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) - { - return runtimeMethodHandle.IsDynamic() ? - TryGetDynamicRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs) : - TryGetStaticRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs); - } - - private unsafe bool TryGetDynamicRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) - { - IntPtr runtimeMethodHandleValue = *(IntPtr*)&runtimeMethodHandle; - - // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob - Debug.Assert((runtimeMethodHandleValue & 0x1) == 0x1); - - DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)(runtimeMethodHandleValue - 1); - - declaringTypeHandle = *(RuntimeTypeHandle*)&(methodData->DeclaringType); - genericMethodArgs = null; - - if (methodData->NumGenericArgs > 0) - { - IntPtr* genericArgPtr = &(methodData->GenericArgsArray); - genericMethodArgs = new RuntimeTypeHandle[methodData->NumGenericArgs]; - for (int i = 0; i < methodData->NumGenericArgs; i++) - { - genericMethodArgs[i] = *(RuntimeTypeHandle*)&(genericArgPtr[i]); - } - } - - if (methodData->MethodSignature.IsNativeLayoutSignature) - { - // MethodName points to the method name in NativeLayout format, so we parse it using a NativeParser - IntPtr methodNamePtr = methodData->MethodName; - string name = GetStringFromMemoryInNativeFormat(methodNamePtr); - - nameAndSignature = new MethodNameAndSignature(name, methodData->MethodSignature); - } - else - { - ModuleInfo moduleInfo = methodData->MethodSignature.GetModuleInfo(); - var metadataReader = ((NativeFormatModuleInfo)moduleInfo).MetadataReader; - var methodHandle = methodData->MethodSignature.Token.AsHandle().ToMethodHandle(metadataReader); - var method = methodHandle.GetMethod(metadataReader); - var name = metadataReader.GetConstantStringValue(method.Name).Value; - nameAndSignature = new MethodNameAndSignature(name, methodData->MethodSignature); - } - - return true; - } - public MethodDesc GetMethodDescForDynamicRuntimeMethodHandle(TypeSystemContext context, RuntimeMethodHandle runtimeMethodHandle) - { - bool success = TryGetDynamicRuntimeMethodHandleComponents(runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, - out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs); + bool success = TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, + out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs); Debug.Assert(success); + MetadataReader reader = ModuleList.Instance.GetMetadataReaderForModule(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)); + MethodNameAndSignature nameAndSignature = new MethodNameAndSignature(reader, handle); + DefType type = (DefType)context.ResolveRuntimeTypeHandle(declaringTypeHandle); if (genericMethodArgs != null) @@ -337,57 +224,40 @@ public MethodDesc GetMethodDescForDynamicRuntimeMethodHandle(TypeSystemContext c return context.ResolveRuntimeMethod(unboxingStub: false, type, nameAndSignature); } - private unsafe bool TryGetStaticRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) + public unsafe bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition handle, out RuntimeTypeHandle[] genericMethodArgs) { - declaringTypeHandle = default(RuntimeTypeHandle); - nameAndSignature = null; - genericMethodArgs = null; - - TypeSystemContext context = TypeSystemContextFactory.Create(); + if (TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out MethodHandle methodHandle, out genericMethodArgs)) + { + MetadataReader reader = ModuleList.Instance.GetMetadataReaderForModule(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle)); + handle = new QMethodDefinition(reader, methodHandle); + return true; + } + handle = default; + return false; + } - MethodDesc parsedMethod = GetMethodDescForStaticRuntimeMethodHandle(context, runtimeMethodHandle); + public unsafe bool TryGetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs) + { + MethodHandleInfo* methodData = (MethodHandleInfo*)runtimeMethodHandle.Value; - if (!EnsureTypeHandleForType(parsedMethod.OwningType)) - return false; + declaringTypeHandle = methodData->DeclaringType; + handle = methodData->Handle; - declaringTypeHandle = parsedMethod.OwningType.RuntimeTypeHandle; - nameAndSignature = parsedMethod.NameAndSignature; - if (!parsedMethod.IsMethodDefinition && parsedMethod.Instantiation.Length > 0) + if (methodData->NumGenericArgs > 0) { - genericMethodArgs = new RuntimeTypeHandle[parsedMethod.Instantiation.Length]; - for (int i = 0; i < parsedMethod.Instantiation.Length; ++i) + RuntimeTypeHandle* genericArgPtr = (RuntimeTypeHandle*)&methodData->FirstArgument; + genericMethodArgs = new RuntimeTypeHandle[methodData->NumGenericArgs]; + for (int i = 0; i < methodData->NumGenericArgs; i++) { - if (!EnsureTypeHandleForType(parsedMethod.Instantiation[i])) - return false; - - genericMethodArgs[i] = parsedMethod.Instantiation[i].RuntimeTypeHandle; + genericMethodArgs[i] = genericArgPtr[i]; } } - - TypeSystemContextFactory.Recycle(context); + else + { + genericMethodArgs = null; + } return true; } - - public unsafe MethodDesc GetMethodDescForStaticRuntimeMethodHandle(TypeSystemContext context, RuntimeMethodHandle runtimeMethodHandle) - { - // Make sure it's not a dynamically allocated RuntimeMethodHandle before we attempt to use it to parse native layout data - Debug.Assert(((*(IntPtr*)&runtimeMethodHandle).ToInt64() & 0x1) == 0); - - RuntimeMethodHandleInfo* methodData = *(RuntimeMethodHandleInfo**)&runtimeMethodHandle; - RuntimeSignature signature; - - // The native layout info signature is a pair. - // The first is a pointer that points to the TypeManager indirection cell. - // The second is the offset into the native layout info blob in that TypeManager, where the native signature is encoded. - IntPtr* nativeLayoutInfoSignatureData = (IntPtr*)methodData->NativeLayoutInfoSignature; - - signature = RuntimeSignature.CreateFromNativeLayoutSignature( - new TypeManagerHandle(*(IntPtr*)nativeLayoutInfoSignatureData[0]), - (uint)nativeLayoutInfoSignatureData[1].ToInt32()); - - RuntimeSignature remainingSignature; - return GetMethodFromSignatureAndContext(context, signature, null, null, out remainingSignature); - } #endregion } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index 6c94d937a87382..ed03fddc56448d 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -495,11 +495,12 @@ public struct VirtualResolveDataResult public bool IsGVM; } - public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, - RuntimeTypeHandle methodHandleDeclaringType, RuntimeTypeHandle[] genericArgs, - ref MethodSignatureComparer methodSignatureComparer, + public static bool TryGetVirtualResolveData( + RuntimeTypeHandle methodHandleDeclaringType, QMethodDefinition method, RuntimeTypeHandle[] genericArgs, out VirtualResolveDataResult lookupResult) { + NativeFormatModuleInfo module = ModuleList.Instance.GetModuleInfoForMetadataReader(method.NativeFormatReader); + lookupResult = default(VirtualResolveDataResult); NativeReader invokeMapReader = GetNativeReaderForBlob(module, ReflectionMapBlob.VirtualInvokeMap); NativeParser invokeMapParser = new NativeParser(invokeMapReader, 0); @@ -531,19 +532,18 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, { // Grammar of an entry in the hash table: // Virtual Method uses a normal slot - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1) + slot + // TypeKey + Handle + (NumberOfStepsUpParentHierarchyToType << 1) + slot // OR // Generic Virtual Method - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1 + 1) + // TypeKey + Handle + (NumberOfStepsUpParentHierarchyToType << 1 + 1) RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!canonHelper.IsCanonicallyEquivalent(entryType)) continue; - uint nameAndSigPointerToken = entryParser.GetUnsigned(); + int token = (int)entryParser.GetUnsigned(); - MethodNameAndSignature nameAndSig = TypeLoaderEnvironment.Instance.GetMethodNameAndSignatureFromNativeLayoutOffset(module.Handle, nameAndSigPointerToken); - if (!methodSignatureComparer.IsMatchingNativeLayoutMethodNameAndSignature(nameAndSig.Name, nameAndSig.Signature)) + if (!token.AsHandle().ToMethodHandle(module.MetadataReader).Equals(method.NativeFormatHandle)) { continue; } @@ -567,16 +567,7 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, if (isGenericVirtualMethod) { - RuntimeSignature methodName; - RuntimeSignature methodSignature; - - if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignaturePointersFromNativeLayoutSignature(module.Handle, nameAndSigPointerToken, out methodName, out methodSignature)) - { - Debug.Assert(false); - return false; - } - - RuntimeMethodHandle gvmSlot = TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeOfVirtualInvoke, methodName.NativeLayoutSignature(), methodSignature, genericArgs); + RuntimeMethodHandle gvmSlot = TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeOfVirtualInvoke, token, genericArgs); lookupResult = new VirtualResolveDataResult { @@ -610,7 +601,6 @@ public static bool TryGetVirtualResolveData(NativeFormatModuleInfo module, /// Declaring type for the method /// Method handle /// Handles of generic argument types - /// Helper class used to compare method signatures /// Canonical form to use /// Output - metadata information for method invoker construction /// true when found, false otherwise @@ -618,7 +608,6 @@ public static bool TryGetMethodInvokeMetadata( RuntimeTypeHandle declaringTypeHandle, QMethodDefinition methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles, - ref MethodSignatureComparer methodSignatureComparer, CanonicalFormKind canonFormKind, out MethodInvokeMetadata methodInvokeMetadata) { @@ -629,7 +618,6 @@ public static bool TryGetMethodInvokeMetadata( declaringTypeHandle, methodHandle.NativeFormatHandle, genericMethodTypeArgumentHandles, - ref methodSignatureComparer, canonFormKind, out methodInvokeMetadata)) { @@ -648,7 +636,6 @@ public static bool TryGetMethodInvokeMetadata( /// Declaring type for the method /// Method handle /// Handles of generic argument types - /// Helper class used to compare method signatures /// Canonical form to use /// Output - metadata information for method invoker construction /// true when found, false otherwise @@ -657,7 +644,6 @@ private static bool TryGetMethodInvokeMetadataFromInvokeMap( RuntimeTypeHandle declaringTypeHandle, MethodHandle methodHandle, RuntimeTypeHandle[] genericMethodTypeArgumentHandles, - ref MethodSignatureComparer methodSignatureComparer, CanonicalFormKind canonFormKind, out MethodInvokeMetadata methodInvokeMetadata) { @@ -689,7 +675,7 @@ private static bool TryGetMethodInvokeMetadataFromInvokeMap( NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { - entryData.GetNext(ref entryParser, ref externalReferences, ref methodSignatureComparer, canonHelper); + entryData.GetNext(ref entryParser, ref externalReferences, canonHelper); if (!entryData.IsMatchingOrCompatibleEntry()) continue; @@ -793,7 +779,6 @@ private struct InvokeMapEntryDataEnumerator - /// Metadata reader corresponding to the method declaring type - /// - private readonly MetadataReader _metadataReader; - - /// - /// Method handle - /// - private readonly MethodHandle _methodHandle; - - /// - /// Method instance obtained from the method handle - /// - private readonly Method _method; - - /// - /// Method signature - /// - private readonly MethodSignature _methodSignature; - - /// - /// true = this is a static method - /// - private readonly bool _isStatic; - - /// - /// true = this is a generic method - /// - private readonly bool _isGeneric; - - public MethodSignatureComparer( - QMethodDefinition methodHandle) - { - if (methodHandle.IsNativeFormatMetadataBased) - { - _metadataReader = methodHandle.NativeFormatReader; - _methodHandle = methodHandle.NativeFormatHandle; - - _method = _methodHandle.GetMethod(_metadataReader); - - _methodSignature = _method.Signature.GetMethodSignature(_metadataReader); - _isGeneric = (_methodSignature.GenericParameterCount != 0); - - // Precalculate initial method attributes used in signature queries - _isStatic = (_method.Flags & MethodAttributes.Static) != 0; - } - else - { - _metadataReader = null; - _methodHandle = default(MethodHandle); - _method = default(Method); - _methodSignature = default(MethodSignature); - _isGeneric = false; - _isStatic = false; - } - } - - /// - /// Construct a comparer between NativeFormat metadata methods and native layouts - /// - /// Metadata reader for the method declaring type - /// Handle of method to compare - public MethodSignatureComparer( - MetadataReader metadataReader, - MethodHandle methodHandle) - { - _metadataReader = metadataReader; - _methodHandle = methodHandle; - - _method = methodHandle.GetMethod(metadataReader); - - _methodSignature = _method.Signature.GetMethodSignature(_metadataReader); - _isGeneric = (_methodSignature.GenericParameterCount != 0); - - // Precalculate initial method attributes used in signature queries - _isStatic = (_method.Flags & MethodAttributes.Static) != 0; - } - - public bool IsMatchingNativeLayoutMethodNameAndSignature(string name, RuntimeSignature signature) - { - return _method.Name.StringEquals(name, _metadataReader) && - IsMatchingNativeLayoutMethodSignature(signature); - } - - public bool IsMatchingNativeLayoutMethodSignature(RuntimeSignature signature) - { - NativeParser parser = GetNativeParserForSignature(signature); - - if (!CompareCallingConventions((MethodCallingConvention)parser.GetUnsigned())) - return false; - - if (_isGeneric) - { - uint genericParamCount1 = parser.GetUnsigned(); - int genericParamCount2 = _methodSignature.GenericParameterCount; - - if (genericParamCount1 != genericParamCount2) - return false; - } - - uint parameterCount = parser.GetUnsigned(); - - if (!CompareTypeSigWithType(ref parser, new TypeManagerHandle(signature.ModuleHandle), _methodSignature.ReturnType)) - { - return false; - } - - uint parameterIndexToMatch = 0; - foreach (Handle parameterSignature in _methodSignature.Parameters) - { - if (parameterIndexToMatch >= parameterCount) - { - // The metadata-defined _method has more parameters than the native layout - return false; - } - if (!CompareTypeSigWithType(ref parser, new TypeManagerHandle(signature.ModuleHandle), parameterSignature)) - return false; - parameterIndexToMatch++; - } - - // Make sure that all native layout parameters have been matched - return parameterIndexToMatch == parameterCount; - } - - /// - /// Look up module containing given nativesignature and return the appropriate native parser. - /// - /// Signature to look up - /// Native parser for the signature - internal static NativeParser GetNativeParserForSignature(RuntimeSignature signature) - { - Debug.Assert(signature.IsNativeLayoutSignature); - NativeFormatModuleInfo module = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature.ModuleHandle)); - - NativeReader reader = TypeLoaderEnvironment.GetNativeReaderForBlob(module, ReflectionMapBlob.NativeLayoutInfo); - return new NativeParser(reader, signature.NativeLayoutOffset); - } - - private bool CompareTypeSigWithType(ref NativeParser parser, TypeManagerHandle moduleHandle, Handle typeHandle) - { - while (typeHandle.HandleType == HandleType.TypeSpecification - || typeHandle.HandleType == HandleType.ModifiedType) - { - if (typeHandle.HandleType == HandleType.TypeSpecification) - { - typeHandle = typeHandle - .ToTypeSpecificationHandle(_metadataReader) - .GetTypeSpecification(_metadataReader) - .Signature; - } - else - { - typeHandle = typeHandle - .ToModifiedTypeHandle(_metadataReader) - .GetModifiedType(_metadataReader) - .Type; - } - } - - // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader - // expects to read it in. - uint startOffset = parser.Offset; - - uint data; - var typeSignatureKind = parser.GetTypeSignatureKind(out data); - - switch (typeSignatureKind) - { - case TypeSignatureKind.Lookback: - { - NativeParser lookbackParser = parser.GetLookbackParser(data); - return CompareTypeSigWithType(ref lookbackParser, moduleHandle, typeHandle); - } - - case TypeSignatureKind.Modifier: - { - // Ensure the modifier kind (vector, pointer, byref) is the same - TypeModifierKind modifierKind = (TypeModifierKind)data; - switch (modifierKind) - { - case TypeModifierKind.Array: - if (typeHandle.HandleType == HandleType.SZArraySignature) - { - return CompareTypeSigWithType(ref parser, moduleHandle, typeHandle - .ToSZArraySignatureHandle(_metadataReader) - .GetSZArraySignature(_metadataReader) - .ElementType); - } - return false; - - case TypeModifierKind.ByRef: - if (typeHandle.HandleType == HandleType.ByReferenceSignature) - { - return CompareTypeSigWithType(ref parser, moduleHandle, typeHandle - .ToByReferenceSignatureHandle(_metadataReader) - .GetByReferenceSignature(_metadataReader) - .Type); - } - return false; - - case TypeModifierKind.Pointer: - if (typeHandle.HandleType == HandleType.PointerSignature) - { - return CompareTypeSigWithType(ref parser, moduleHandle, typeHandle - .ToPointerSignatureHandle(_metadataReader) - .GetPointerSignature(_metadataReader) - .Type); - } - return false; - - default: - Debug.Assert(null == "invalid type modifier kind"); - return false; - } - } - - case TypeSignatureKind.Variable: - { - bool isMethodVar = (data & 0x1) == 1; - uint index = data >> 1; - - if (isMethodVar) - { - if (typeHandle.HandleType == HandleType.MethodTypeVariableSignature) - { - return index == typeHandle - .ToMethodTypeVariableSignatureHandle(_metadataReader) - .GetMethodTypeVariableSignature(_metadataReader) - .Number; - } - } - else - { - if (typeHandle.HandleType == HandleType.TypeVariableSignature) - { - return index == typeHandle - .ToTypeVariableSignatureHandle(_metadataReader) - .GetTypeVariableSignature(_metadataReader) - .Number; - } - } - - return false; - } - - case TypeSignatureKind.MultiDimArray: - { - if (typeHandle.HandleType != HandleType.ArraySignature) - { - return false; - } - - ArraySignature sig = typeHandle - .ToArraySignatureHandle(_metadataReader) - .GetArraySignature(_metadataReader); - - if (data != sig.Rank) - return false; - - if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.ElementType)) - return false; - - uint boundCount1 = parser.GetUnsigned(); - for (uint i = 0; i < boundCount1; i++) - { - parser.GetUnsigned(); - } - - uint lowerBoundCount1 = parser.GetUnsigned(); - - for (uint i = 0; i < lowerBoundCount1; i++) - { - parser.GetUnsigned(); - } - break; - } - - case TypeSignatureKind.FunctionPointer: - { - // callingConvention is in data - uint argCount1 = parser.GetUnsigned(); - - for (uint i = 0; i < argCount1; i++) - { - if (!CompareTypeSigWithType(ref parser, moduleHandle, typeHandle)) - return false; - } - return false; - } - - case TypeSignatureKind.Instantiation: - { - if (typeHandle.HandleType != HandleType.TypeInstantiationSignature) - { - return false; - } - - TypeInstantiationSignature sig = typeHandle - .ToTypeInstantiationSignatureHandle(_metadataReader) - .GetTypeInstantiationSignature(_metadataReader); - - if (!CompareTypeSigWithType(ref parser, moduleHandle, sig.GenericType)) - { - return false; - } - - uint genericArgIndex = 0; - foreach (Handle genericArgumentTypeHandle in sig.GenericTypeArguments) - { - if (genericArgIndex >= data) - { - // The metadata generic has more parameters than the native layour - return false; - } - if (!CompareTypeSigWithType(ref parser, moduleHandle, genericArgumentTypeHandle)) - { - return false; - } - genericArgIndex++; - } - // Make sure all generic parameters have been matched - return genericArgIndex == data; - } - - case TypeSignatureKind.BuiltIn: - case TypeSignatureKind.External: - { - RuntimeTypeHandle type2; - switch (typeHandle.HandleType) - { - case HandleType.TypeDefinition: - if (!TypeLoaderEnvironment.TryGetNamedTypeForMetadata( - new QTypeDefinition(_metadataReader, typeHandle.ToTypeDefinitionHandle(_metadataReader)), out type2)) - { - return false; - } - break; - - default: - return false; - } - - RuntimeTypeHandle type1; - if (typeSignatureKind == TypeSignatureKind.External) - { - type1 = SigParsing.GetTypeFromNativeLayoutSignature(ref parser, moduleHandle, startOffset); - } - else - { - type1 = ((Internal.TypeSystem.WellKnownType)data).GetRuntimeTypeHandle(); - } - - return type1.Equals(type2); - } - - default: - return false; - } - return true; - } - - private bool CompareCallingConventions(MethodCallingConvention callingConvention) - { - return (callingConvention.HasFlag(MethodCallingConvention.Static) == _isStatic) && - (callingConvention.HasFlag(MethodCallingConvention.Generic) == _isGeneric); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs index bc9c208f472f10..eef4c2e793f8cf 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs @@ -22,340 +22,18 @@ namespace Internal.Runtime.TypeLoader { public sealed partial class TypeLoaderEnvironment { - public bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2) - { - if (signature1.IsNativeLayoutSignature && signature2.IsNativeLayoutSignature) - { - if (signature1.StructuralEquals(signature2)) - return true; - - NativeFormatModuleInfo module1 = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature1.ModuleHandle)); - NativeReader reader1 = GetNativeLayoutInfoReader(signature1); - NativeParser parser1 = new NativeParser(reader1, signature1.NativeLayoutOffset); - - NativeFormatModuleInfo module2 = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature2.ModuleHandle)); - NativeReader reader2 = GetNativeLayoutInfoReader(signature2); - NativeParser parser2 = new NativeParser(reader2, signature2.NativeLayoutOffset); - - return CompareMethodSigs(parser1, module1, parser2, module2); - } - else if (signature1.IsNativeLayoutSignature) - { - int token = signature2.Token; - MetadataReader metadataReader = ModuleList.Instance.GetMetadataReaderForModule(new TypeManagerHandle(signature2.ModuleHandle)); - - MethodSignatureComparer comparer = new MethodSignatureComparer(metadataReader, token.AsHandle().ToMethodHandle(metadataReader)); - return comparer.IsMatchingNativeLayoutMethodSignature(signature1); - } - else if (signature2.IsNativeLayoutSignature) - { - int token = signature1.Token; - MetadataReader metadataReader = ModuleList.Instance.GetMetadataReaderForModule(new TypeManagerHandle(signature1.ModuleHandle)); - - MethodSignatureComparer comparer = new MethodSignatureComparer(metadataReader, token.AsHandle().ToMethodHandle(metadataReader)); - return comparer.IsMatchingNativeLayoutMethodSignature(signature2); - } - else - { - // For now, RuntimeSignatures are only used to compare for method signature equality (along with their Name) - // So we can implement this with the simple equals check - if (signature1.Token != signature2.Token) - return false; - - if (signature1.ModuleHandle != signature2.ModuleHandle) - return false; - - return true; - } - } - public static bool IsStaticMethodSignature(MethodNameAndSignature signature) { - Debug.Assert(signature.Signature.IsNativeLayoutSignature); - NativeReader reader = GetNativeLayoutInfoReader(signature.Signature); - NativeParser parser = new NativeParser(reader, signature.Signature.NativeLayoutOffset); - - MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); - return (callingConvention & MethodCallingConvention.Static) != 0; + var method = signature.Handle.GetMethod(signature.Reader); + return (method.Flags & MethodAttributes.Static) != 0; } public uint GetGenericArgumentCountFromMethodNameAndSignature(MethodNameAndSignature signature) { - if (signature.Signature.IsNativeLayoutSignature) - { - NativeReader reader = GetNativeLayoutInfoReader(signature.Signature); - NativeParser parser = new NativeParser(reader, signature.Signature.NativeLayoutOffset); - - return GetGenericArgCountFromSig(parser); - } - else - { - ModuleInfo module = signature.Signature.GetModuleInfo(); - NativeFormatModuleInfo nativeFormatModule = (NativeFormatModuleInfo)module; - var metadataReader = nativeFormatModule.MetadataReader; - var methodHandle = signature.Signature.Token.AsHandle().ToMethodHandle(metadataReader); - - var method = methodHandle.GetMethod(metadataReader); - var methodSignature = method.Signature.GetMethodSignature(metadataReader); - return checked((uint)methodSignature.GenericParameterCount); - } - } - - public bool TryGetMethodNameAndSignaturePointersFromNativeLayoutSignature(TypeManagerHandle module, uint methodNameAndSigToken, out RuntimeSignature methodNameSig, out RuntimeSignature methodSig) - { - methodNameSig = default(RuntimeSignature); - methodSig = default(RuntimeSignature); - - NativeReader reader = GetNativeLayoutInfoReader(module); - NativeParser parser = new NativeParser(reader, methodNameAndSigToken); - if (parser.IsNull) - return false; - - methodNameSig = RuntimeSignature.CreateFromNativeLayoutSignature(module, parser.Offset); - parser.SkipString(); // methodName - - // Signatures are indirected to through a relative offset so that we don't have to parse them - // when not comparing signatures (parsing them requires resolving types and is tremendously - // expensive). - NativeParser sigParser = parser.GetParserFromRelativeOffset(); - methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(module, sigParser.Offset); - - return true; - } - - public MethodNameAndSignature GetMethodNameAndSignatureFromNativeLayoutOffset(TypeManagerHandle moduleHandle, uint nativeLayoutOffset) - { - NativeReader reader = GetNativeLayoutInfoReader(moduleHandle); - NativeParser parser = new NativeParser(reader, nativeLayoutOffset); - return GetMethodNameAndSignature(ref parser, moduleHandle, out _, out _); - } - - internal static MethodNameAndSignature GetMethodNameAndSignature(ref NativeParser parser, TypeManagerHandle moduleHandle, out RuntimeSignature methodNameSig, out RuntimeSignature methodSig) - { - methodNameSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, parser.Offset); - string methodName = parser.GetString(); - - // Signatures are indirected to through a relative offset so that we don't have to parse them - // when not comparing signatures (parsing them requires resolving types and is tremendously - // expensive). - NativeParser sigParser = parser.GetParserFromRelativeOffset(); - methodSig = RuntimeSignature.CreateFromNativeLayoutSignature(moduleHandle, sigParser.Offset); - - return new MethodNameAndSignature(methodName, methodSig); - } - - #region Private Helpers - - private static RuntimeTypeHandle GetExternalTypeHandle(NativeFormatModuleInfo moduleHandle, uint typeIndex) - { - Debug.Assert(moduleHandle != null); - - RuntimeTypeHandle result; - - TypeSystemContext context = TypeSystemContextFactory.Create(); - { - NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); - nativeLayoutContext._module = moduleHandle; - nativeLayoutContext._typeSystemContext = context; - - TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex); - result = type.RuntimeTypeHandle; - } - TypeSystemContextFactory.Recycle(context); - - Debug.Assert(!result.IsNull()); - return result; - } - - private static uint GetGenericArgCountFromSig(NativeParser parser) - { - MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); - - if ((callingConvention & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) - { - return parser.GetUnsigned(); - } - else - { - return 0; - } - } - - private static bool CompareMethodSigs(NativeParser parser1, NativeFormatModuleInfo moduleHandle1, NativeParser parser2, NativeFormatModuleInfo moduleHandle2) - { - MethodCallingConvention callingConvention1 = (MethodCallingConvention)parser1.GetUnsigned(); - MethodCallingConvention callingConvention2 = (MethodCallingConvention)parser2.GetUnsigned(); - - if (callingConvention1 != callingConvention2) - return false; - - if ((callingConvention1 & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) - { - if (parser1.GetUnsigned() != parser2.GetUnsigned()) - return false; - } - - uint parameterCount1 = parser1.GetUnsigned(); - uint parameterCount2 = parser2.GetUnsigned(); - if (parameterCount1 != parameterCount2) - return false; - - // Compare one extra parameter to account for the return type - for (uint i = 0; i <= parameterCount1; i++) - { - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - } - - return true; - } - - private static bool CompareTypeSigs(ref NativeParser parser1, NativeFormatModuleInfo moduleHandle1, ref NativeParser parser2, NativeFormatModuleInfo moduleHandle2) - { - // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader - // expects to read it in. - uint data1; - uint startOffset1 = parser1.Offset; - var typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1); - - // If the parser is at a lookback type, get a new parser for it and recurse. - // Since we haven't read the element type of parser2 yet, we just pass it in unchanged - if (typeSignatureKind1 == TypeSignatureKind.Lookback) - { - NativeParser lookbackParser1 = parser1.GetLookbackParser(data1); - return CompareTypeSigs(ref lookbackParser1, moduleHandle1, ref parser2, moduleHandle2); - } - - uint data2; - var typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2); - - // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1 - // before recursing. - if (typeSignatureKind2 == TypeSignatureKind.Lookback) - { - NativeParser lookbackParser2 = parser2.GetLookbackParser(data2); - parser1 = new NativeParser(parser1.Reader, startOffset1); - return CompareTypeSigs(ref parser1, moduleHandle1, ref lookbackParser2, moduleHandle2); - } - - if (typeSignatureKind1 != typeSignatureKind2) - return false; - - switch (typeSignatureKind1) - { - case TypeSignatureKind.Lookback: - { - // Recursion above better have removed all lookbacks - Debug.Fail("Unexpected lookback type"); - return false; - } - - case TypeSignatureKind.Modifier: - { - // Ensure the modifier kind (vector, pointer, byref) is the same - if (data1 != data2) - return false; - return CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2); - } - - case TypeSignatureKind.Variable: - { - // variable index is in data - if (data1 != data2) - return false; - break; - } - - case TypeSignatureKind.MultiDimArray: - { - // rank is in data - if (data1 != data2) - return false; - - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - - uint boundCount1 = parser1.GetUnsigned(); - uint boundCount2 = parser2.GetUnsigned(); - if (boundCount1 != boundCount2) - return false; - - for (uint i = 0; i < boundCount1; i++) - { - if (parser1.GetUnsigned() != parser2.GetUnsigned()) - return false; - } - - uint lowerBoundCount1 = parser1.GetUnsigned(); - uint lowerBoundCount2 = parser2.GetUnsigned(); - if (lowerBoundCount1 != lowerBoundCount2) - return false; - - for (uint i = 0; i < lowerBoundCount1; i++) - { - if (parser1.GetUnsigned() != parser2.GetUnsigned()) - return false; - } - break; - } - - case TypeSignatureKind.FunctionPointer: - { - // callingConvention is in data - if (data1 != data2) - return false; - uint argCount1 = parser1.GetUnsigned(); - uint argCount2 = parser2.GetUnsigned(); - if (argCount1 != argCount2) - return false; - for (uint i = 0; i < argCount1; i++) - { - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - } - break; - } - - case TypeSignatureKind.Instantiation: - { - // Type parameter count is in data - if (data1 != data2) - return false; - - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - - for (uint i = 0; i < data1; i++) - { - if (!CompareTypeSigs(ref parser1, moduleHandle1, ref parser2, moduleHandle2)) - return false; - } - break; - } - - case TypeSignatureKind.BuiltIn: - RuntimeTypeHandle typeHandle3 = ((WellKnownType)data1).GetRuntimeTypeHandle(); - RuntimeTypeHandle typeHandle4 = ((WellKnownType)data2).GetRuntimeTypeHandle(); - if (!typeHandle3.Equals(typeHandle4)) - return false; - - break; - - case TypeSignatureKind.External: - { - RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(moduleHandle1, data1); - RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(moduleHandle2, data2); - if (!typeHandle1.Equals(typeHandle2)) - return false; - - break; - } - - default: - return false; - } - return true; + var metadataReader = signature.Reader; + var method = signature.Handle.GetMethod(metadataReader); + var methodSignature = method.Signature.GetMethodSignature(metadataReader); + return checked((uint)methodSignature.GenericParameterCount); } - #endregion } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index c9170e3e9000e4..51266c01c0b17a 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -48,19 +48,14 @@ public override IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntP return TypeLoaderEnvironment.Instance.GenericLookupFromContextAndSignature(context, signature, out auxResult); } - public override bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs) + public override bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs) { - return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs); + return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out handle, out genericMethodArgs); } - public override RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) + public override RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs) { - return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeHandle, methodName, methodSignature, genericMethodArgs); - } - - public override bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2) - { - return TypeLoaderEnvironment.Instance.CompareMethodSignatures(signature1, signature2); + return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeHandle, handle, genericMethodArgs); } public override IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle) @@ -99,18 +94,6 @@ public override bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementType } } - public static class RuntimeSignatureExtensions - { - public static IntPtr NativeLayoutSignature(this RuntimeSignature signature) - { - if (!signature.IsNativeLayoutSignature) - Environment.FailFast("Not a valid native layout signature"); - - NativeReader reader = TypeLoaderEnvironment.GetNativeLayoutInfoReader(signature); - return reader.OffsetToAddress(signature.NativeLayoutOffset); - } - } - public sealed partial class TypeLoaderEnvironment { [ThreadStatic] @@ -210,50 +193,6 @@ private bool EnsureTypeHandleForType(TypeDesc type) return !type.RuntimeTypeHandle.IsNull(); } - internal bool GetTypeFromSignatureAndContext(ref NativeParser parser, TypeManagerHandle moduleHandle, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeTypeHandle createdType) - { - createdType = default(RuntimeTypeHandle); - TypeSystemContext context = TypeSystemContextFactory.Create(); - - TypeDesc parsedType = TryParseNativeSignatureWorker(context, moduleHandle, ref parser, typeArgs, methodArgs, false) as TypeDesc; - if (parsedType == null) - return false; - - if (!EnsureTypeHandleForType(parsedType)) - return false; - - createdType = parsedType.RuntimeTypeHandle; - - TypeSystemContextFactory.Recycle(context); - return true; - } - - // - // Parse a native layout signature pointed to by "signature" in the executable image, optionally using - // "typeArgs" and "methodArgs" for generic type parameter substitution. The first field in "signature" - // must be an encoded method but any data beyond that is user-defined and returned in "remainingSignature" - // - public MethodDesc GetMethodFromSignatureAndContext(TypeSystemContext context, RuntimeSignature signature, RuntimeTypeHandle[] typeArgs, RuntimeTypeHandle[] methodArgs, out RuntimeSignature remainingSignature) - { - NativeReader reader = GetNativeLayoutInfoReader(signature); - NativeParser parser = new NativeParser(reader, signature.NativeLayoutOffset); - - MethodDesc result = TryParseNativeSignatureWorker(context, new TypeManagerHandle(signature.ModuleHandle), ref parser, typeArgs, methodArgs, true) as MethodDesc; - - remainingSignature = RuntimeSignature.CreateFromNativeLayoutSignature(signature, parser.Offset); - - return result; - } - - // - // Returns the native layout info reader - // - internal static unsafe NativeReader GetNativeLayoutInfoReader(RuntimeSignature signature) - { - Debug.Assert(signature.IsNativeLayoutSignature); - return GetNativeLayoutInfoReader(new TypeManagerHandle(signature.ModuleHandle)); - } - // // Returns the native layout info reader // @@ -446,23 +385,6 @@ public int GetCanonicalHashCode(RuntimeTypeHandle typeHandle, CanonicalFormKind return hashCode; } - private static object TryParseNativeSignatureWorker(TypeSystemContext typeSystemContext, TypeManagerHandle moduleHandle, ref NativeParser parser, RuntimeTypeHandle[] typeGenericArgumentHandles, RuntimeTypeHandle[] methodGenericArgumentHandles, bool isMethodSignature) - { - Instantiation typeGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(typeGenericArgumentHandles ?? Array.Empty()); - Instantiation methodGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(methodGenericArgumentHandles ?? Array.Empty()); - - NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); - nativeLayoutContext._module = ModuleList.Instance.GetModuleInfoByHandle(moduleHandle); - nativeLayoutContext._typeSystemContext = typeSystemContext; - nativeLayoutContext._typeArgumentHandles = typeGenericArguments; - nativeLayoutContext._methodArgumentHandles = methodGenericArguments; - - if (isMethodSignature) - return nativeLayoutContext.GetMethod(ref parser); - else - return nativeLayoutContext.GetType(ref parser); - } - public bool TryGetGenericMethodDictionaryForComponents(RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericMethodArgHandles, MethodNameAndSignature nameAndSignature, out IntPtr methodDictionary) { TypeSystemContext context = TypeSystemContextFactory.Create(); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs index 042b1957e22b65..9df61f9ad7f1bc 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs @@ -93,7 +93,7 @@ public override string Name { get { - return _nameAndSignature.Name; + return NameAndSignature.GetName(); } } @@ -163,7 +163,7 @@ public override bool HasCustomAttribute(string attributeNamespace, string attrib public override string ToString() { - string result = OwningType.ToString() + ".Method(" + NameAndSignature.Name + ")"; + string result = OwningType.ToString() + ".Method(" + Name + ")"; return result; } #endif diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs index 1e4b888552220a..f048c41ea5cd6c 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs @@ -335,7 +335,7 @@ public RuntimeMethodKey(bool unboxingStub, DefType owningType, MethodNameAndSign _owningType = owningType; _methodNameAndSignature = nameAndSignature; - _hashCode = TypeHashingAlgorithms.ComputeMethodHashCode(owningType.GetHashCode(), TypeHashingAlgorithms.ComputeNameHashCode(nameAndSignature.Name)); + _hashCode = TypeHashingAlgorithms.ComputeMethodHashCode(owningType.GetHashCode(), TypeHashingAlgorithms.ComputeNameHashCode(nameAndSignature.GetName())); } public class RuntimeMethodKeyHashtable : LockFreeReaderHashtable diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj index 09881516e2950c..daf61deea9e24c 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj @@ -241,7 +241,6 @@ - diff --git a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs index 56e55feaef309c..f2f0f33a8c6f25 100644 --- a/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs +++ b/src/coreclr/tools/Common/Internal/NativeFormat/NativeFormatWriter.cs @@ -428,14 +428,6 @@ public Vertex GetTuple(Vertex item1, Vertex item2, Vertex item3) return Unify(vertex); } - public Vertex GetMethodNameAndSigSignature(string name, Vertex signature) - { - MethodNameAndSigSignature sig = new MethodNameAndSigSignature( - GetStringConstant(name), - GetRelativeOffsetSignature(signature)); - return Unify(sig); - } - public Vertex GetStringConstant(string value) { StringConstant vertex = new StringConstant(value); @@ -460,9 +452,9 @@ public Vertex GetExternalTypeSignature(uint externalTypeId) return Unify(sig); } - public Vertex GetMethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, Vertex methodNameAndSig, Vertex[] args) + public Vertex GetMethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, int token, Vertex[] args) { - MethodSignature sig = new MethodSignature(flags, fptrReferenceId, containingType, methodNameAndSig, args); + MethodSignature sig = new MethodSignature(flags, fptrReferenceId, containingType, token, args); return Unify(sig); } @@ -759,43 +751,6 @@ public override int GetHashCode() } } -#if NATIVEFORMAT_PUBLICWRITER - public -#else - internal -#endif - class MethodNameAndSigSignature : Vertex - { - private Vertex _methodName; - private Vertex _signature; - - public MethodNameAndSigSignature(Vertex methodName, Vertex signature) - { - _methodName = methodName; - _signature = signature; - } - - internal override void Save(NativeWriter writer) - { - _methodName.Save(writer); - _signature.Save(writer); - } - - public override int GetHashCode() - { - return 509 * 197 + _methodName.GetHashCode() + 647 * _signature.GetHashCode(); - } - - public override bool Equals(object obj) - { - MethodNameAndSigSignature other = obj as MethodNameAndSigSignature; - if (other == null) - return false; - - return Equals(_methodName, other._methodName) && Equals(_signature, other._signature); - } - } - #if NATIVEFORMAT_PUBLICWRITER public #else @@ -952,15 +907,15 @@ class MethodSignature : Vertex private uint _flags; private uint _fptrReferenceId; private Vertex _containingType; - private Vertex _methodNameAndSig; + private int _token; private Vertex[] _args; - public MethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, Vertex methodNameAndSig, Vertex[] args) + public MethodSignature(uint flags, uint fptrReferenceId, Vertex containingType, int token, Vertex[] args) { _flags = flags; _fptrReferenceId = fptrReferenceId; _containingType = containingType; - _methodNameAndSig = methodNameAndSig; + _token = token; _args = args; if ((flags & (uint)MethodFlags.HasInstantiation) != 0) @@ -975,7 +930,7 @@ internal override void Save(NativeWriter writer) if ((_flags & (uint)MethodFlags.HasFunctionPointer) != 0) writer.WriteUnsigned(_fptrReferenceId); _containingType.Save(writer); - _methodNameAndSig.Save(writer); + writer.WriteUnsigned((uint)_token); if ((_flags & (uint)MethodFlags.HasInstantiation) != 0) { writer.WriteUnsigned((uint)_args.Length); @@ -992,7 +947,7 @@ public override int GetHashCode() hash += (hash << 5) + _containingType.GetHashCode(); for (uint iArg = 0; _args != null && iArg < _args.Length; iArg++) hash += (hash << 5) + _args[iArg].GetHashCode(); - hash += (hash << 5) + _methodNameAndSig.GetHashCode(); + hash += (hash << 5) + _token.GetHashCode(); return hash; } @@ -1005,8 +960,8 @@ public override bool Equals(object obj) if (!( _flags == other._flags && _fptrReferenceId == other._fptrReferenceId && - Equals(_containingType, other._containingType) && - Equals(_methodNameAndSig, other._methodNameAndSig))) + _token == other._token && + Equals(_containingType, other._containingType))) { return false; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs index 854f958b69f916..0e5a953736a5ac 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedMetadataManager.cs @@ -14,6 +14,7 @@ using CustomAttributeHandle = System.Reflection.Metadata.CustomAttributeHandle; using ExportedTypeHandle = System.Reflection.Metadata.ExportedTypeHandle; using FlowAnnotations = ILLink.Shared.TrimAnalysis.FlowAnnotations; +using ParameterHandle = System.Reflection.Metadata.ParameterHandle; namespace ILCompiler { @@ -29,6 +30,7 @@ public sealed class AnalysisBasedMetadataManager : MetadataManager, ICompilation private readonly Dictionary _reflectableMethods = new Dictionary(); private readonly Dictionary _reflectableFields = new Dictionary(); private readonly HashSet _reflectableAttributes = new HashSet(); + private readonly HashSet _reflectableParameters = new HashSet(); public AnalysisBasedMetadataManager(CompilerTypeSystemContext typeSystemContext) : this(typeSystemContext, new FullyBlockedMetadataBlockingPolicy(), @@ -36,6 +38,7 @@ public AnalysisBasedMetadataManager(CompilerTypeSystemContext typeSystemContext) new NoDynamicInvokeThunkGenerationPolicy(), null, Array.Empty(), Array.Empty(), Array.Empty>(), Array.Empty>(), Array.Empty>(), Array.Empty(), + Array.Empty(), default) { } @@ -54,6 +57,7 @@ public AnalysisBasedMetadataManager( IEnumerable> reflectableMethods, IEnumerable> reflectableFields, IEnumerable reflectableAttributes, + IEnumerable reflectableParameters, MetadataManagerOptions options) : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy, options, flowAnnotations) { @@ -92,6 +96,11 @@ public AnalysisBasedMetadataManager( _reflectableAttributes.Add(refAttribute); } + foreach (var refParameter in reflectableParameters) + { + _reflectableParameters.Add(refParameter); + } + #if DEBUG HashSet moduleHash = new HashSet(_modulesWithMetadata); foreach (var refType in reflectableTypes) @@ -135,14 +144,18 @@ protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping) { ComputeMetadata(new Policy(_blockingPolicy, this), factory, out metadataBlob, out typeMappings, out methodMappings, + out methodMetadataMappings, out fieldMappings, + out fieldMetadataMappings, out stackTraceMapping); } @@ -239,6 +252,11 @@ public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle) return _parent._reflectableAttributes.Contains(new ReflectableCustomAttribute(module, caHandle)); } + public bool GeneratesMetadata(EcmaModule module, ParameterHandle paramHandle) + { + return _parent._reflectableParameters.Contains(new ReflectableParameter(module, paramHandle)); + } + public bool GeneratesMetadata(EcmaModule module, ExportedTypeHandle exportedTypeHandle) { // We'll possibly need to do something else here if we ever use this MetadataManager @@ -299,4 +317,19 @@ public override bool Equals(object obj) => obj is ReflectableCustomAttribute other && Equals(other); public override int GetHashCode() => Module.GetHashCode() ^ CustomAttributeHandle.GetHashCode(); } + + public struct ReflectableParameter : IEquatable + { + public readonly EcmaModule Module; + public readonly ParameterHandle ParameterHandle; + + public ReflectableParameter(EcmaModule module, ParameterHandle paramHandle) + => (Module, ParameterHandle) = (module, paramHandle); + + public bool Equals(ReflectableParameter other) + => other.Module == Module && other.ParameterHandle == ParameterHandle; + public override bool Equals(object obj) + => obj is ReflectableParameter other && Equals(other); + public override int GetHashCode() => Module.GetHashCode() ^ ParameterHandle.GetHashCode(); + } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs index 9e1a274e30bc4e..9740188e3dc32d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs @@ -73,17 +73,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode))); } - // Get the name and sig of the method. - // Note: the method name and signature are stored in the NativeLayoutInfo blob, not in the hashtable we build here. - - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - Debug.Assert(placedNameAndSig.SavedVertex != null); - Vertex placedNameAndSigOffsetSig = nativeWriter.GetOffsetSignature(placedNameAndSig.SavedVertex); + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, method.GetTypicalMethodDefinition()); // Get the vertex for the completed method signature - Vertex methodSignature = nativeWriter.GetTuple(declaringType, placedNameAndSigOffsetSig, arguments); + Vertex methodSignature = nativeWriter.GetTuple(declaringType, nativeWriter.GetUnsignedConstant((uint)token), arguments); // Make the generic method entry vertex @@ -118,9 +112,7 @@ public static void GetExactMethodInstantiationDependenciesForMethod(ref Dependen foreach (var arg in method.Instantiation) dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(arg), "Exact method instantiation entry")); - // Get native layout dependencies for the method signature. - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(nameAndSig), "Exact method instantiation entry")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, method.GetTypicalMethodDefinition()); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs index 04d62dbad5541d..67da861f048d76 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs @@ -67,12 +67,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode))); } - // Method name and signature - NativeLayoutVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutSavedVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - Vertex placedNameAndSigVertexOffset = nativeWriter.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset); + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, method.GetTypicalMethodDefinition()); - fullMethodSignature = nativeWriter.GetTuple(containingType, placedNameAndSigVertexOffset, arguments); + fullMethodSignature = nativeWriter.GetTuple(containingType, nativeWriter.GetUnsignedConstant((uint)token), arguments); } // Method's dictionary pointer @@ -108,10 +105,7 @@ public static void GetGenericMethodsHashtableDependenciesForMethod(ref Dependenc dependencies.Add(new DependencyListEntry(argNode, "GenericMethodsHashtable entry instantiation argument")); } - // Method name and signature - NativeLayoutVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutSavedVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - dependencies.Add(new DependencyListEntry(placedNameAndSig, "GenericMethodsHashtable entry signature")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, method.GetTypicalMethodDefinition()); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs index 210293d9435834..6a3affe4b74d8c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -53,11 +53,8 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); - var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); - var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); - - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "gvm table calling method signature")); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "gvm table implementation method signature")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod); } private void AddGenericVirtualMethodImplementation(MethodDesc callingMethod, MethodDesc implementationMethod) @@ -116,11 +113,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) uint targetTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType)); vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(targetTypeId)); - var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); - vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + int callingMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, callingMethod); + vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)callingMethodToken)); - nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); - vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + int implementationMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, implementationMethod); + vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)implementationMethodToken)); int hashCode = callingMethod.OwningType.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ implementationType.GetHashCode(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs index 8815fea96e9b56..e1f432af8ff3c6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -55,16 +55,15 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); TypeDesc openImplementationType = implementationType.GetTypeDefinition(); - var openCallingMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openCallingMethod); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openCallingMethodNameAndSig), "interface gvm table calling method signature")); + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod); // Implementation could be null if this is a default interface method reabstraction or diamond. We need to record those. if (implementationMethod != null) { MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(openImplementationMethod.OwningType), "interface gvm table implementation method owning type")); - var openImplementationMethodNameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(openImplementationMethod); - dependencies.Add(new DependencyListEntry(factory.NativeLayout.PlacedSignatureVertex(openImplementationMethodNameAndSig), "interface gvm table implementation method signature")); + + factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod); } if (!openImplementationType.IsInterface) @@ -153,10 +152,10 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // Emit the method signature and containing type of the current interface method uint typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType)); - var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod)); + int callingMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, callingMethod); Vertex vertex = nativeFormatWriter.GetTuple( nativeFormatWriter.GetUnsignedConstant(typeId), - nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + nativeFormatWriter.GetUnsignedConstant((uint)callingMethodToken)); // Emit the method name / sig and containing type of each GVM target method for the current interface method entry vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)gvmEntry.Value.Count)); @@ -164,11 +163,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (impl is MethodDesc implementationMethod) { - nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod)); + int implementationMethodToken = factory.MetadataManager.GetMetadataHandleForMethod(factory, implementationMethod); typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationMethod.OwningType)); vertex = nativeFormatWriter.GetTuple( vertex, - nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset), + nativeFormatWriter.GetUnsignedConstant((uint)implementationMethodToken), nativeFormatWriter.GetUnsignedConstant(typeId)); } else diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs index 7f44064c450894..8eaade82cc95f3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs @@ -25,12 +25,14 @@ namespace ILCompiler.DependencyAnalysis /// internal sealed class MethodMetadataNode : DependencyNodeCore { - private readonly MethodDesc _method; + private readonly EcmaMethod _method; + private readonly bool _isMinimal; - public MethodMetadataNode(MethodDesc method) + public MethodMetadataNode(MethodDesc method, bool isMinimal) { Debug.Assert(method.IsTypicalMethodDefinition); - _method = method; + _method = (EcmaMethod)method; + _isMinimal = isMinimal; } public MethodDesc Method => _method; @@ -40,7 +42,15 @@ public override IEnumerable GetStaticDependencies(NodeFacto DependencyList dependencies = new DependencyList(); dependencies.Add(factory.TypeMetadata((MetadataType)_method.OwningType), "Owning type metadata"); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaMethod)_method)); + if (!_isMinimal) + { + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _method); + + foreach (var parameterHandle in _method.MetadataReader.GetMethodDefinition(_method.Handle).GetParameters()) + { + dependencies.Add(factory.MethodParameterMetadata(new ReflectableParameter(_method.Module, parameterHandle)), "Parameter is visible"); + } + } MethodSignature sig = _method.Signature; const string reason = "Method signature metadata"; @@ -57,9 +67,9 @@ public override IEnumerable GetStaticDependencies(NodeFacto TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, sigData.type, "Modifier in a method signature"); } - if (_method is EcmaMethod ecmaMethod) + if (!_isMinimal) { - DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaMethod); + DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, _method); // On a reflectable method, perform generic data flow for the return type and all the parameter types // This is a compensation for the DI issue described in https://github.com/dotnet/runtime/issues/81358 diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs new file mode 100644 index 00000000000000..ff0278c3f1d83b --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs @@ -0,0 +1,41 @@ +// 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 ILCompiler.DependencyAnalysisFramework; + +namespace ILCompiler.DependencyAnalysis +{ + /// + /// Represents a parameter that has metadata generated in the current compilation. + /// + /// + /// Only expected to be used during ILScanning when scanning for reflection. + /// + internal sealed class MethodParameterMetadataNode : DependencyNodeCore + { + private readonly ReflectableParameter _parameter; + + public MethodParameterMetadataNode(ReflectableParameter parameter) + { + _parameter = parameter; + } + + public ReflectableParameter Parameter => _parameter; + + public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + + protected override string GetName(NodeFactory factory) + { + return $"Reflectable parameter {_parameter.ParameterHandle} in {_parameter.Module}"; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasDynamicDependencies => false; + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => true; + public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; + public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs index 8e5b9c4734f4ba..3e2b17b3617ecb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs @@ -22,7 +22,6 @@ public sealed class NativeLayoutInfoNode : ObjectNode, ISymbolDefinitionNode, IN private byte[] _writerSavedBytes; private Section _signaturesSection; - private Section _ldTokenInfoSection; private Section _templatesSection; private List _vertexNodesToWrite; @@ -34,7 +33,6 @@ public NativeLayoutInfoNode(ExternalReferencesTableNode externalReferences, Exte _writer = new NativeWriter(); _signaturesSection = _writer.NewSection(); - _ldTokenInfoSection = _writer.NewSection(); _templatesSection = _writer.NewSection(); _vertexNodesToWrite = new List(); @@ -51,7 +49,6 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => true; protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - public Section LdTokenInfoSection => _ldTokenInfoSection; public Section SignaturesSection => _signaturesSection; public Section TemplatesSection => _templatesSection; public ExternalReferencesTableNode ExternalReferences => _externalReferences; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs deleted file mode 100644 index fe00421b74e60c..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs +++ /dev/null @@ -1,128 +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.Diagnostics; - -using Internal.Text; -using Internal.TypeSystem; - -namespace ILCompiler.DependencyAnalysis -{ - /// - /// Represents a native layout signature. A signature is a pair where the first item is a pointer - /// to the TypeManager that contains the native layout info blob of interest, and the second item - /// is an offset into that native layout info blob - /// - public class NativeLayoutSignatureNode : DehydratableObjectNode, ISymbolDefinitionNode - { - private TypeSystemEntity _identity; - private Utf8String _identityPrefix; - private NativeLayoutSavedVertexNode _nativeSignature; - - public TypeSystemEntity Identity => _identity; - - public NativeLayoutSignatureNode(NativeLayoutSavedVertexNode nativeSignature, TypeSystemEntity identity, Utf8String identityPrefix) - { - _nativeSignature = nativeSignature; - _identity = identity; - _identityPrefix = identityPrefix; - } - - public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - { - Utf8String identityString; - if (_identity is MethodDesc) - { - identityString = nameMangler.GetMangledMethodName((MethodDesc)_identity); - } - else if (_identity is TypeDesc) - { - identityString = nameMangler.GetMangledTypeName((TypeDesc)_identity); - } - else if (_identity is FieldDesc) - { - identityString = nameMangler.GetMangledFieldName((FieldDesc)_identity); - } - else - { - Debug.Assert(false); - identityString = new Utf8String("unknown"); - } - - sb.Append(nameMangler.CompilationUnitPrefix).Append(_identityPrefix).Append(identityString); - } - - public int Offset => 0; - protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) - { - if (factory.Target.IsWindows) - return ObjectNodeSection.ReadOnlyDataSection; - else - return ObjectNodeSection.DataSection; - } - public override bool IsShareable => false; - public override bool StaticDependenciesAreComputed => true; - - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) - { - DependencyList dependencies = new DependencyList(); - dependencies.Add(new DependencyListEntry(_nativeSignature, "NativeLayoutSignatureNode target vertex")); - return dependencies; - } - - protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) - { - // This node does not trigger generation of other nodes. - if (relocsOnly) - return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); - - // Ensure native layout is saved to get valid Vertex offsets - factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); - - ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); - - objData.RequireInitialPointerAlignment(); - objData.AddSymbol(this); - - objData.EmitPointerReloc(factory.TypeManagerIndirection); - objData.EmitNaturalInt(_nativeSignature.SavedVertex.VertexOffset); - - return objData.ToObjectData(); - } - - public override int ClassCode => 1887049331; - - public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) - { - NativeLayoutSignatureNode otherSignature = (NativeLayoutSignatureNode)other; - if (_identity is MethodDesc) - { - if (otherSignature._identity is TypeDesc || otherSignature._identity is FieldDesc) - return -1; - return comparer.Compare((MethodDesc)_identity, (MethodDesc)((NativeLayoutSignatureNode)other)._identity); - } - else if (_identity is TypeDesc) - { - if (otherSignature._identity is MethodDesc) - return 1; - - if (otherSignature._identity is FieldDesc) - return -1; - - return comparer.Compare((TypeDesc)_identity, (TypeDesc)((NativeLayoutSignatureNode)other)._identity); - } - else if (_identity is FieldDesc) - { - if (otherSignature._identity is MethodDesc || otherSignature._identity is TypeDesc) - return 1; - return comparer.Compare((FieldDesc)_identity, (FieldDesc)((NativeLayoutSignatureNode)other)._identity); - } - else - { - throw new NotSupportedException("New type system entity needs a comparison"); - } - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs index d31338d83e5914..875ddc23971b93 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -90,7 +90,7 @@ protected Vertex SetSavedVertex(Vertex value) } } - internal abstract class NativeLayoutMethodEntryVertexNode : NativeLayoutSavedVertexNode + internal class NativeLayoutMethodEntryVertexNode : NativeLayoutSavedVertexNode { [Flags] public enum MethodEntryFlags @@ -102,18 +102,18 @@ public enum MethodEntryFlags protected readonly MethodDesc _method; private MethodEntryFlags _flags; private NativeLayoutTypeSignatureVertexNode _containingTypeSig; - private NativeLayoutMethodSignatureVertexNode _methodSig; private NativeLayoutTypeSignatureVertexNode[] _instantiationArgsSig; public MethodDesc Method => _method; public virtual bool IsUnboxingStub => _method.OwningType.IsValueType && !_method.Signature.IsStatic; + protected override string GetName(NodeFactory factory) => "MethodEntryVertex_" + factory.NameMangler.GetMangledMethodName(_method); + public NativeLayoutMethodEntryVertexNode(NodeFactory factory, MethodDesc method, MethodEntryFlags flags) { _method = method; _flags = flags; - _methodSig = factory.NativeLayout.MethodSignatureVertex(method.GetTypicalMethodDefinition().Signature); if ((_flags & MethodEntryFlags.CreateInstantiatedSignature) == 0) { @@ -131,7 +131,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto { DependencyList dependencies = new DependencyList(); - dependencies.Add(new DependencyListEntry(_methodSig, "NativeLayoutMethodEntryVertexNode method signature")); if ((_flags & MethodEntryFlags.CreateInstantiatedSignature) != 0) { dependencies.Add(new DependencyListEntry(context.NecessaryTypeSymbol(_method.OwningType), "NativeLayoutMethodEntryVertexNode containing type")); @@ -154,6 +153,8 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(new DependencyListEntry(methodEntryPointNode, "NativeLayoutMethodEntryVertexNode entrypoint")); } + context.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, context, _method.GetTypicalMethodDefinition()); + return dependencies; } @@ -162,8 +163,6 @@ public override Vertex WriteVertex(NodeFactory factory) Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); Vertex containingType = GetContainingTypeVertex(factory); - Vertex methodSig = _methodSig.WriteVertex(factory); - Vertex methodNameAndSig = GetNativeWriter(factory).GetMethodNameAndSigSignature(_method.Name, methodSig); Vertex[] args = null; MethodFlags flags = 0; @@ -204,7 +203,8 @@ public override Vertex WriteVertex(NodeFactory factory) flags |= MethodFlags.FunctionPointerIsUSG; } - return GetNativeWriter(factory).GetMethodSignature((uint)flags, fptrReferenceId, containingType, methodNameAndSig, args); + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, _method.GetTypicalMethodDefinition()); + return GetNativeWriter(factory).GetMethodSignature((uint)flags, fptrReferenceId, containingType, token, args); } private Vertex GetContainingTypeVertex(NodeFactory factory) @@ -228,52 +228,6 @@ protected virtual IMethodNode GetMethodEntrypointNode(NodeFactory factory) } } - internal sealed class NativeLayoutMethodLdTokenVertexNode : NativeLayoutMethodEntryVertexNode - { - protected override string GetName(NodeFactory factory) => "NativeLayoutMethodLdTokenVertexNode_" + factory.NameMangler.GetMangledMethodName(_method); - - public NativeLayoutMethodLdTokenVertexNode(NodeFactory factory, MethodDesc method) - : base(factory, method, method.IsRuntimeDeterminedExactMethod || method.IsGenericMethodDefinition ? 0 : MethodEntryFlags.CreateInstantiatedSignature) - { - } - - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - if (_method.IsVirtual && _method.HasInstantiation && !_method.IsGenericMethodDefinition) - { - return GetGenericVirtualMethodDependencies(context); - } - else - { - return base.GetStaticDependencies(context); - } - } - - private DependencyList GetGenericVirtualMethodDependencies(NodeFactory factory) - { - var dependencies = (DependencyList)base.GetStaticDependencies(factory); - - MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific); - - dependencies.Add(factory.GVMDependencies(canonMethod), "Potential generic virtual method call"); - - foreach (TypeDesc instArg in canonMethod.Instantiation) - { - dependencies.Add(factory.MaximallyConstructableType(instArg), "Type we need to look up for GVM dispatch"); - } - - return dependencies; - } - - public override Vertex WriteVertex(NodeFactory factory) - { - Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); - - Vertex methodEntryVertex = base.WriteVertex(factory); - return SetSavedVertex(factory.MetadataManager.NativeLayoutInfo.LdTokenInfoSection.Place(methodEntryVertex)); - } - } - internal sealed class NativeLayoutMethodSignatureVertexNode : NativeLayoutVertexNode { private Internal.TypeSystem.MethodSignature _signature; @@ -327,31 +281,6 @@ public override Vertex WriteVertex(NodeFactory factory) } } - internal sealed class NativeLayoutMethodNameAndSignatureVertexNode : NativeLayoutVertexNode - { - private MethodDesc _method; - private NativeLayoutMethodSignatureVertexNode _methodSig; - - protected override string GetName(NodeFactory factory) => "NativeLayoutMethodNameAndSignatureVertexNode" + factory.NameMangler.GetMangledMethodName(_method); - - public NativeLayoutMethodNameAndSignatureVertexNode(NodeFactory factory, MethodDesc method) - { - _method = method; - _methodSig = factory.NativeLayout.MethodSignatureVertex(method.Signature); - } - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - return new DependencyListEntry[] { new DependencyListEntry(_methodSig, "NativeLayoutMethodNameAndSignatureVertexNode signature vertex") }; - } - public override Vertex WriteVertex(NodeFactory factory) - { - Debug.Assert(Marked, "WriteVertex should only happen for marked vertices"); - - Vertex methodSig = _methodSig.WriteVertex(factory); - return GetNativeWriter(factory).GetMethodNameAndSigSignature(_method.Name, methodSig); - } - } - internal abstract class NativeLayoutTypeSignatureVertexNode : NativeLayoutVertexNode { protected readonly TypeDesc _type; @@ -1633,29 +1562,11 @@ protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeF public sealed class NativeLayoutMethodDictionaryGenericDictionarySlotNode : NativeLayoutGenericDictionarySlotNode { private MethodDesc _method; - private WrappedMethodDictionaryVertexNode _wrappedNode; - - private sealed class WrappedMethodDictionaryVertexNode : NativeLayoutMethodEntryVertexNode - { - public WrappedMethodDictionaryVertexNode(NodeFactory factory, MethodDesc method) : - base(factory, method, default(MethodEntryFlags)) - { - } - - protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory) - { - throw new NotSupportedException(); - } - - protected sealed override string GetName(NodeFactory factory) => "WrappedMethodEntryVertexNodeForDictionarySlot_" + factory.NameMangler.GetMangledMethodName(_method); - } - public NativeLayoutMethodDictionaryGenericDictionarySlotNode(NodeFactory factory, MethodDesc method) { Debug.Assert(method.HasInstantiation); _method = method; - _wrappedNode = new WrappedMethodDictionaryVertexNode(factory, method); } protected sealed override string GetName(NodeFactory factory) => "NativeLayoutMethodDictionaryGenericDictionarySlotNode_" + factory.NameMangler.GetMangledMethodName(_method); @@ -1677,14 +1588,14 @@ public sealed override IEnumerable GetStaticDependencies(No GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); - dependencies.Add(_wrappedNode, "wrappednode"); + dependencies.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); return dependencies; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) { - return _wrappedNode.WriteVertex(factory); + return factory.NativeLayout.MethodEntry(_method).WriteVertex(factory); } } @@ -1735,7 +1646,7 @@ public sealed class NativeLayoutMethodLdTokenGenericDictionarySlotNode : NativeL { private MethodDesc _method; - public NativeLayoutMethodLdTokenGenericDictionarySlotNode(MethodDesc method) + public NativeLayoutMethodLdTokenGenericDictionarySlotNode(NodeFactory factory, MethodDesc method) { _method = method; } @@ -1746,10 +1657,7 @@ public NativeLayoutMethodLdTokenGenericDictionarySlotNode(MethodDesc method) public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) { - var result = new DependencyList - { - { factory.NativeLayout.MethodLdTokenVertex(_method), "Method Signature" } - }; + var result = new DependencyList(); foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { @@ -1764,13 +1672,14 @@ public sealed override IEnumerable GetStaticDependencies(No factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + result.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); + return result; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) { - Vertex ldToken = factory.NativeLayout.MethodLdTokenVertex(_method).WriteVertex(factory); - return GetNativeWriter(factory).GetRelativeOffsetSignature(ldToken); + return factory.NativeLayout.MethodEntry(_method).WriteVertex(factory); } } @@ -1813,7 +1722,7 @@ public sealed override IEnumerable GetStaticDependencies(No DependencyNodeCore constrainedMethodDescriptorNode; if (_constrainedMethod.HasInstantiation) { - constrainedMethodDescriptorNode = factory.NativeLayout.MethodLdTokenVertex(_constrainedMethod); + constrainedMethodDescriptorNode = factory.NativeLayout.MethodEntry(_constrainedMethod); } else { @@ -1837,6 +1746,12 @@ public sealed override IEnumerable GetStaticDependencies(No foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constraintType)) yield return new DependencyListEntry(dependency, "template construction dependency constraintType"); + + if (_constrainedMethod.IsVirtual && _constrainedMethod.HasInstantiation) + { + MethodDesc canonMethod = _constrainedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); + yield return new DependencyListEntry(factory.GVMDependencies(canonMethod), "Generic virtual method call"); + } } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1845,9 +1760,8 @@ protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeF if (_constrainedMethod.HasInstantiation) { Debug.Assert(SignatureKind is FixupSignatureKind.GenericStaticConstrainedMethod); - Vertex constrainedMethodVertex = factory.NativeLayout.MethodLdTokenVertex(_constrainedMethod).WriteVertex(factory); - Vertex relativeOffsetVertex = GetNativeWriter(factory).GetRelativeOffsetSignature(constrainedMethodVertex); - return writer.GetTuple(constraintType, relativeOffsetVertex); + Vertex constrainedMethodVertex = factory.NativeLayout.MethodEntry(_constrainedMethod).WriteVertex(factory); + return writer.GetTuple(constraintType, constrainedMethodVertex); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs index 4ad5145d949e9f..763e7adef476e7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs @@ -37,11 +37,6 @@ private void CreateNodeCaches() return new NativeLayoutMethodSignatureVertexNode(_factory, signature); }); - _methodNameAndSignatures = new NodeCache(method => - { - return new NativeLayoutMethodNameAndSignatureVertexNode(_factory, method); - }); - _placedSignatures = new NodeCache(vertexNode => { return new NativeLayoutPlacedSignatureVertexNode(vertexNode); @@ -57,14 +52,9 @@ private void CreateNodeCaches() return new NativeLayoutPlacedVertexSequenceOfUIntVertexNode(uints); }, new UIntSequenceComparer()); - _methodLdTokenSignatures = new NodeCache(method => - { - return new NativeLayoutMethodLdTokenVertexNode(_factory, method); - }); - - _nativeLayoutSignatureNodes = new NodeCache(key => + _methodEntries = new NodeCache(method => { - return new NativeLayoutSignatureNode(key.SignatureVertex, key.Identity, key.IdentityPrefix); + return new NativeLayoutMethodEntryVertexNode(_factory, method, default); }); _templateMethodEntries = new NodeCache(method => @@ -139,7 +129,7 @@ private void CreateNodeCaches() _methodLdToken_GenericDictionarySlots = new NodeCache(method => { - return new NativeLayoutMethodLdTokenGenericDictionarySlotNode(method); + return new NativeLayoutMethodLdTokenGenericDictionarySlotNode(_factory, method); }); _dictionarySignatures = new NodeCache(owningMethodOrType => @@ -255,12 +245,6 @@ internal NativeLayoutMethodSignatureVertexNode MethodSignatureVertex(MethodSigna return _methodSignatures.GetOrAdd(signature); } - private NodeCache _methodNameAndSignatures; - internal NativeLayoutMethodNameAndSignatureVertexNode MethodNameAndSignatureVertex(MethodDesc method) - { - return _methodNameAndSignatures.GetOrAdd(method); - } - private NodeCache _placedSignatures; internal NativeLayoutPlacedSignatureVertexNode PlacedSignatureVertex(NativeLayoutVertexNode vertexNode) { @@ -350,57 +334,10 @@ internal NativeLayoutPlacedVertexSequenceOfUIntVertexNode PlacedUIntVertexSequen return _placedUIntVertexSequence.GetOrAdd(uints); } - private NodeCache _methodLdTokenSignatures; - internal NativeLayoutMethodLdTokenVertexNode MethodLdTokenVertex(MethodDesc method) - { - return _methodLdTokenSignatures.GetOrAdd(method); - } - - private struct NativeLayoutSignatureKey : IEquatable - { - public NativeLayoutSignatureKey(NativeLayoutSavedVertexNode signatureVertex, Utf8String identityPrefix, TypeSystemEntity identity) - { - SignatureVertex = signatureVertex; - IdentityPrefix = identityPrefix; - Identity = identity; - } - - public NativeLayoutSavedVertexNode SignatureVertex { get; } - public Utf8String IdentityPrefix { get; } - public TypeSystemEntity Identity { get; } - - public override bool Equals(object obj) - { - if (!(obj is NativeLayoutSignatureKey)) - return false; - - return Equals((NativeLayoutSignatureKey)obj); - } - - public override int GetHashCode() - { - return SignatureVertex.GetHashCode(); - } - - public bool Equals(NativeLayoutSignatureKey other) - { - if (SignatureVertex != other.SignatureVertex) - return false; - - if (!IdentityPrefix.Equals(other.IdentityPrefix)) - return false; - - if (Identity != other.Identity) - return false; - - return true; - } - } - - private NodeCache _nativeLayoutSignatureNodes; - public NativeLayoutSignatureNode NativeLayoutSignature(NativeLayoutSavedVertexNode signature, Utf8String identityPrefix, TypeSystemEntity identity) + private NodeCache _methodEntries; + internal NativeLayoutMethodEntryVertexNode MethodEntry(MethodDesc method) { - return _nativeLayoutSignatureNodes.GetOrAdd(new NativeLayoutSignatureKey(signature, identityPrefix, identity)); + return _methodEntries.GetOrAdd(method); } private NodeCache _templateMethodEntries; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index f7ef925ea3f6f9..9b73ea95894a3a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -541,7 +541,12 @@ private void CreateNodeCaches() _methodsWithMetadata = new NodeCache(method => { - return new MethodMetadataNode(method); + return new MethodMetadataNode(method, isMinimal: false); + }); + + _methodsWithLimitedMetadata = new NodeCache(method => + { + return new MethodMetadataNode(method, isMinimal: true); }); _fieldsWithMetadata = new NodeCache(field => @@ -564,6 +569,11 @@ private void CreateNodeCaches() return new CustomAttributeMetadataNode(ca); }); + _parametersWithMetadata = new NodeCache(p => + { + return new MethodParameterMetadataNode(p); + }); + _genericDictionaryLayouts = new NodeCache(_dictionaryLayoutProvider.GetLayout); _stringAllocators = new NodeCache(constructor => @@ -1331,6 +1341,16 @@ internal MethodMetadataNode MethodMetadata(MethodDesc method) return _methodsWithMetadata.GetOrAdd(method); } + private NodeCache _methodsWithLimitedMetadata; + + internal MethodMetadataNode LimitedMethodMetadata(MethodDesc method) + { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); + return _methodsWithLimitedMetadata.GetOrAdd(method); + } + private NodeCache _fieldsWithMetadata; internal FieldMetadataNode FieldMetadata(FieldDesc field) @@ -1367,6 +1387,16 @@ internal CustomAttributeMetadataNode CustomAttributeMetadata(ReflectableCustomAt return _customAttributesWithMetadata.GetOrAdd(ca); } + private NodeCache _parametersWithMetadata; + + internal MethodParameterMetadataNode MethodParameterMetadata(ReflectableParameter ca) + { + // These are only meaningful for UsageBasedMetadataManager. We should not have them + // in the dependency graph otherwise. + Debug.Assert(MetadataManager is UsageBasedMetadataManager); + return _parametersWithMetadata.GetOrAdd(ca); + } + private NodeCache _frozenStringNodes; public FrozenStringNode SerializedStringObject(string data) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs index f0786d96ac9f71..5cf6fcdb404bdc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -68,22 +68,8 @@ public static void AddDependenciesDueToReflectability(ref DependencyList depende dependencies.Add(factory.AddressTakenMethodEntrypoint(method), "Body of a reflectable method"); } - // If the method is defined in a different module than this one, a metadata token isn't known for performing the reference - // Use a name/sig reference instead. - if (!factory.MetadataManager.WillUseMetadataTokenToReferenceMethod(method)) - { - dependencies.Add(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())), - "Non metadata-local method reference"); - } - if (method.HasInstantiation) { - if (method.IsCanonicalMethod(CanonicalFormKind.Any)) - { - dependencies.Add(factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())), - "Signature of canonical method"); - } - if (!method.IsCanonicalMethod(CanonicalFormKind.Universal)) { foreach (var instArg in method.Instantiation) @@ -206,8 +192,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) } else { - var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset)); + // Dead code + throw new NotImplementedException(); } // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted. @@ -232,12 +218,6 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if ((flags & InvokeTableFlags.IsGenericMethod) != 0) { - if ((flags & InvokeTableFlags.RequiresInstArg) != 0) - { - var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition())); - vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSigGenericMethod.SavedVertex.VertexOffset)); - } - if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) == 0) { VertexSequence args = new VertexSequence(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs index fa6bd51940aacc..cdce445f8264fd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs @@ -88,10 +88,6 @@ public static void GetVirtualInvokeMapDependencies(ref DependencyList dependenci factory.NecessaryTypeSymbol(method.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific)), "Reflection virtual invoke owning type"); - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - dependencies.Add(placedNameAndSig, "Reflection virtual invoke method signature"); - if (!method.HasInstantiation) { MethodDesc slotDefiningMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method); @@ -162,24 +158,22 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // Grammar of an entry in the hash table: // Virtual Method uses a normal slot - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1) + slot + // TypeKey + MethodHandle + (NumberOfStepsUpParentHierarchyToType << 1) + slot // OR // Generic Virtual Method - // TypeKey + NameAndSig metadata offset into the native layout metadata + (NumberOfStepsUpParentHierarchyToType << 1 + 1) + // TypeKey + MethodHandle + (NumberOfStepsUpParentHierarchyToType << 1 + 1) int parentHierarchyDistance; MethodDesc declaringMethodForSlot = GetDeclaringVirtualMethodAndHierarchyDistance(method, out parentHierarchyDistance); ISymbolNode containingTypeKeyNode = factory.NecessaryTypeSymbol(containingTypeKey); - NativeLayoutMethodNameAndSignatureVertexNode nameAndSig = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()); - NativeLayoutPlacedSignatureVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig); - + int token = factory.MetadataManager.GetMetadataHandleForMethod(factory, method.GetTypicalMethodDefinition()); Vertex vertex; if (method.HasInstantiation) { vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeKeyNode)), - writer.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset), + writer.GetUnsignedConstant((uint)token), writer.GetUnsignedConstant(((uint)parentHierarchyDistance << 1) + VirtualInvokeTableEntry.GenericVirtualMethod)); } else @@ -190,7 +184,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeKeyNode)), - writer.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset)); + writer.GetUnsignedConstant((uint)token)); vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)parentHierarchyDistance << 1), diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs index 6e20a964a64fcb..141a85126d2f97 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -66,8 +66,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact return dependencies; } - private static readonly Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RMHSignature_"); - protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); @@ -75,8 +73,14 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); - NativeLayoutMethodLdTokenVertexNode ldtokenSigNode = factory.NativeLayout.MethodLdTokenVertex(_targetMethod); - objData.EmitPointerReloc(factory.NativeLayout.NativeLayoutSignature(ldtokenSigNode, s_NativeLayoutSignaturePrefix, _targetMethod)); + int handle = relocsOnly ? 0 : factory.MetadataManager.GetMetadataHandleForMethod(factory, _targetMethod.GetTypicalMethodDefinition()); + + objData.EmitPointerReloc(factory.MaximallyConstructableType(_targetMethod.OwningType)); + objData.EmitInt(handle); + objData.EmitInt(_targetMethod.Instantiation.Length); + foreach (TypeDesc instParam in _targetMethod.Instantiation) + objData.EmitPointerReloc(factory.NecessaryTypeSymbol(instParam)); + return objData.ToObjectData(); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs index b5bb5760b5e29f..e3a0b4d38ab17e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs @@ -70,8 +70,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto foreach (var entry in ScanForInterfaceGenericVirtualMethodEntries()) InterfaceGenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref _staticDependencies, context, entry.CallingMethod, entry.ImplementationType, entry.ImplementationMethod); - - Debug.Assert(_staticDependencies.Count > 0); } return _staticDependencies; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index d69a3f32e07386..d28813e812ed5a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -50,6 +50,7 @@ public abstract class MetadataManager : ICompilationRootProvider private List> _fieldMappings; private Dictionary _fieldHandleMap; private List> _methodMappings; + private Dictionary _methodHandleMap; private List _stackTraceMappings; protected readonly string _metadataLogFile; protected readonly StackTraceEmissionPolicy _stackTraceEmissionPolicy; @@ -443,16 +444,6 @@ public bool ShouldMethodBeInInvokeMap(MethodDesc method) public void GetDependenciesDueToGenericDictionary(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { - MetadataCategory category = GetMetadataCategory(method.GetCanonMethodTarget(CanonicalFormKind.Specific)); - - if ((category & MetadataCategory.RuntimeMapping) != 0) - { - // If the method is visible from reflection, we need to keep track of this statically generated - // dictionary to make sure MakeGenericMethod works even without a type loader template - dependencies ??= new DependencyList(); - dependencies.Add(factory.GenericMethodsHashtableEntry(method), "Reflection visible dictionary"); - } - if (method.Signature.IsStatic && method.IsSynchronized) { dependencies ??= new DependencyList(); @@ -537,6 +528,11 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency // and property setters) } + public virtual void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + { + // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata + } + protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) { // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata @@ -692,11 +688,7 @@ protected void EnsureMetadataGenerated(NodeFactory factory) if (_metadataBlob != null) return; - ComputeMetadata(factory, out _metadataBlob, out _typeMappings, out _methodMappings, out _fieldMappings, out _stackTraceMappings); - - _fieldHandleMap = new Dictionary(); - foreach (var fieldMapEntry in _fieldMappings) - _fieldHandleMap[fieldMapEntry.Entity.GetTypicalFieldDefinition()] = fieldMapEntry.MetadataHandle; + ComputeMetadata(factory, out _metadataBlob, out _typeMappings, out _methodMappings, out _methodHandleMap, out _fieldMappings, out _fieldHandleMap, out _stackTraceMappings); } void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) @@ -709,7 +701,9 @@ protected abstract void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping); protected void ComputeMetadata( @@ -718,7 +712,9 @@ protected void ComputeMetadata( out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping) where TPolicy : struct, IMetadataPolicy { var transformed = MetadataTransform.Run(policy, GetCompilationModulesWithMetadata()); @@ -790,7 +786,9 @@ protected void ComputeMetadata( typeMappings = new List>(); methodMappings = new List>(); + methodMetadataMappings = new Dictionary(); fieldMappings = new List>(); + fieldMetadataMappings = new Dictionary(); stackTraceMapping = new List(); // Generate type definition mappings @@ -810,8 +808,15 @@ record ??= transformed.GetTransformedTypeReference(definition); typeMappings.Add(new MetadataMapping(definition, writer.GetRecordHandle(record))); } + foreach (var methodMapping in transformed.GetTransformedMethodDefinitions()) + methodMetadataMappings[methodMapping.Key] = writer.GetRecordHandle(methodMapping.Value); + foreach (var method in GetReflectableMethods()) { + MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); + if (record == null) + continue; + if (method.IsGenericMethodDefinition || method.OwningType.IsGenericDefinition) { // Generic definitions don't have runtime artifacts we would need to map to. @@ -830,15 +835,17 @@ record ??= transformed.GetTransformedTypeReference(definition); if ((GetMetadataCategory(method) & MetadataCategory.RuntimeMapping) == 0) continue; - MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); - - if (record != null) - methodMappings.Add(new MetadataMapping(method, writer.GetRecordHandle(record))); + methodMappings.Add(new MetadataMapping(method, writer.GetRecordHandle(record))); } HashSet canonicalFields = new HashSet(); foreach (var field in GetFieldsWithRuntimeMapping()) { + Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); + Debug.Assert(record != null); + + fieldMetadataMappings[field.GetTypicalFieldDefinition()] = writer.GetRecordHandle(record); + FieldDesc fieldToAdd = field; TypeDesc canonOwningType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonOwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) @@ -852,9 +859,7 @@ record ??= transformed.GetTransformedTypeReference(definition); fieldToAdd = canonField; } - Field record = transformed.GetTransformedFieldDefinition(fieldToAdd.GetTypicalFieldDefinition()); - if (record != null) - fieldMappings.Add(new MetadataMapping(fieldToAdd, writer.GetRecordHandle(record))); + fieldMappings.Add(new MetadataMapping(fieldToAdd, writer.GetRecordHandle(record))); } // Generate stack trace metadata mapping @@ -954,6 +959,12 @@ public IEnumerable> GetMethodMapping(NodeFactory fac return _methodMappings; } + public int GetMetadataHandleForMethod(NodeFactory factory, MethodDesc method) + { + EnsureMetadataGenerated(factory); + return _methodHandleMap[method]; + } + public IEnumerable> GetFieldMapping(NodeFactory factory) { EnsureMetadataGenerated(factory); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index fd0c4e025d65e1..e2f4c456641c0f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -56,6 +56,7 @@ private static (string AttributeName, DiagnosticId Id)[] _requiresAttributeMisma private readonly List _typesWithMetadata = new List(); private readonly List _fieldsWithRuntimeMapping = new List(); private readonly List _customAttributesWithMetadata = new List(); + private readonly List _parametersWithMetadata = new List(); internal IReadOnlyDictionary FeatureSwitches { get; } @@ -147,6 +148,12 @@ protected override void Graph_NewMarkedNode(DependencyNodeCore obj) _customAttributesWithMetadata.Add(customAttributeMetadataNode.CustomAttribute); } + var parameterMetadataNode = obj as MethodParameterMetadataNode; + if (parameterMetadataNode != null) + { + _parametersWithMetadata.Add(parameterMetadataNode.Parameter); + } + var reflectedFieldNode = obj as ReflectedFieldNode; if (reflectedFieldNode != null) { @@ -221,11 +228,13 @@ protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List> typeMappings, out List> methodMappings, + out Dictionary methodMetadataMappings, out List> fieldMappings, + out Dictionary fieldMetadataMappings, out List stackTraceMapping) { ComputeMetadata(new GeneratedTypesAndCodeMetadataPolicy(_blockingPolicy, factory), - factory, out metadataBlob, out typeMappings, out methodMappings, out fieldMappings, out stackTraceMapping); + factory, out metadataBlob, out typeMappings, out methodMappings, out methodMetadataMappings, out fieldMappings, out fieldMetadataMappings, out stackTraceMapping); } protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) @@ -234,6 +243,12 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method"); } + public override void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + { + dependencies ??= new DependencyList(); + dependencies.Add(factory.LimitedMethodMetadata(method.GetTypicalMethodDefinition()), "Method referenced from native layout"); + } + protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) { dependencies ??= new DependencyList(); @@ -918,7 +933,7 @@ public MetadataManager ToAnalysisBasedMetadataManager() return new AnalysisBasedMetadataManager( _typeSystemContext, _blockingPolicy, _resourceBlockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, _dynamicInvokeThunkGenerationPolicy, FlowAnnotations, _modulesWithMetadata, _typesWithForcedEEType, reflectableTypes.ToEnumerable(), reflectableMethods.ToEnumerable(), - reflectableFields.ToEnumerable(), _customAttributesWithMetadata, _options); + reflectableFields.ToEnumerable(), _customAttributesWithMetadata, _parametersWithMetadata, _options); } private void AddDataflowDependency(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, string reason) @@ -1018,7 +1033,7 @@ public bool GeneratesMetadata(FieldDesc fieldDef) public bool GeneratesMetadata(MethodDesc methodDef) { - return _factory.MethodMetadata(methodDef).Marked; + return _factory.MethodMetadata(methodDef).Marked || _factory.LimitedMethodMetadata(methodDef).Marked; } public bool GeneratesMetadata(MetadataType typeDef) @@ -1031,6 +1046,11 @@ public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle) return _factory.CustomAttributeMetadata(new ReflectableCustomAttribute(module, caHandle)).Marked; } + public bool GeneratesMetadata(EcmaModule module, ParameterHandle paramHandle) + { + return _factory.MethodParameterMetadata(new ReflectableParameter(module, paramHandle)).Marked; + } + public bool GeneratesMetadata(EcmaModule module, ExportedTypeHandle exportedTypeHandle) { // Generate the forwarder only if we generated the target type. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 954ae4124058ac..fecf22e9363035 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -426,6 +426,7 @@ + @@ -502,7 +503,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs index 02d48c7a810cfd..492bcb1f82db2c 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/EntityMap.cs @@ -15,6 +15,8 @@ public IReadOnlyCollection Records get { return _map.Values; } } + public IEnumerable> Entries => _map; + public EntityMap(IEqualityComparer comparer) { _map = new Dictionary(comparer); diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs index 408a3be6ded51f..c79bc3fe477aec 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/IMetadataPolicy.cs @@ -43,6 +43,12 @@ public interface IMetadataPolicy /// bool GeneratesMetadata(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandle customAttribute); + /// + /// Returns true if the parameter should generate metadata. + /// If false, the parameter is not generated. + /// + bool GeneratesMetadata(Cts.Ecma.EcmaModule module, Ecma.ParameterHandle parameter); + /// /// Returns true if an exported type entry should generate metadata. /// diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs index d64c6fd67dadb3..04e95b91beab91 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/MetadataTransformResult.cs @@ -97,6 +97,13 @@ public Method GetTransformedMethodDefinition(Cts.MethodDesc method) return rec as Method; } + public IEnumerable> GetTransformedMethodDefinitions() + { + foreach (KeyValuePair entry in _transform._methods.Entries) + if (entry.Value is Method m) + yield return new KeyValuePair(entry.Key, m); + } + /// /// Attempts to retrieve a record corresponding to the specified /// . Returns null if not found. diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs index 02c35466167aad..98845f5b6b2d43 100644 --- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs +++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Method.cs @@ -84,6 +84,9 @@ private void InitializeMethodDefinition(Cts.MethodDesc entity, Method record) record.Parameters.Capacity = paramHandles.Count; foreach (var paramHandle in paramHandles) { + if (!_policy.GeneratesMetadata(ecmaEntity.Module, paramHandle)) + continue; + Ecma.Parameter param = reader.GetParameter(paramHandle); Parameter paramRecord = new Parameter { From 1dd7315f40520ff816295c492c53e7ece07fd653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 12 Mar 2025 23:30:39 +0100 Subject: [PATCH 3/8] Fix uninstantiated generic methods --- .../DependencyAnalysis/RuntimeMethodHandleNode.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs index 141a85126d2f97..7f5f3035ccbc70 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -77,10 +77,17 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo objData.EmitPointerReloc(factory.MaximallyConstructableType(_targetMethod.OwningType)); objData.EmitInt(handle); - objData.EmitInt(_targetMethod.Instantiation.Length); - foreach (TypeDesc instParam in _targetMethod.Instantiation) - objData.EmitPointerReloc(factory.NecessaryTypeSymbol(instParam)); + if (_targetMethod != _targetMethod.GetMethodDefinition()) + { + objData.EmitInt(_targetMethod.Instantiation.Length); + foreach (TypeDesc instParam in _targetMethod.Instantiation) + objData.EmitPointerReloc(factory.NecessaryTypeSymbol(instParam)); + } + else + { + objData.EmitInt(0); + } return objData.ToObjectData(); } From ccedaa8bb01e478ed532396f9c49e3a3fee0f0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 13 Mar 2025 06:48:41 +0100 Subject: [PATCH 4/8] Fix multifile --- .../Compiler/MetadataManager.cs | 19 ++++++++++++++++++- .../Compiler/UsageBasedMetadataManager.cs | 13 +++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index d28813e812ed5a..1476d46cbd10e0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -842,7 +842,8 @@ record ??= transformed.GetTransformedTypeReference(definition); foreach (var field in GetFieldsWithRuntimeMapping()) { Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); - Debug.Assert(record != null); + if (record == null) + continue; fieldMetadataMappings[field.GetTypicalFieldDefinition()] = writer.GetRecordHandle(record); @@ -961,6 +962,14 @@ public IEnumerable> GetMethodMapping(NodeFactory fac public int GetMetadataHandleForMethod(NodeFactory factory, MethodDesc method) { + if (!CanGenerateMetadata(method)) + { + // We can end up here with reflection disabled or multifile compilation. + // If we ever productize either, we'll need to do something different. + // Scenarios that currently need this won't work in these modes. + return 0; + } + EnsureMetadataGenerated(factory); return _methodHandleMap[method]; } @@ -973,6 +982,14 @@ public IEnumerable> GetFieldMapping(NodeFactory facto public int GetMetadataHandleForField(NodeFactory factory, FieldDesc field) { + if (!CanGenerateMetadata(field)) + { + // We can end up here with reflection disabled or multifile compilation. + // If we ever productize either, we'll need to do something different. + // Scenarios that currently need this won't work in these modes. + return 0; + } + EnsureMetadataGenerated(factory); return _fieldHandleMap[field]; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index e2f4c456641c0f..799792ea28abf0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -245,8 +245,17 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc public override void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { - dependencies ??= new DependencyList(); - dependencies.Add(factory.LimitedMethodMetadata(method.GetTypicalMethodDefinition()), "Method referenced from native layout"); + if (CanGenerateMetadata(method)) + { + dependencies ??= new DependencyList(); + dependencies.Add(factory.LimitedMethodMetadata(method.GetTypicalMethodDefinition()), "Method referenced from native layout"); + } + else + { + // We can end up here with reflection disabled or multifile compilation. + // If we ever productize either, we'll need to do something different. + // Scenarios that currently need this won't work in these modes. + } } protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) From ba5ba5114f199aa6ee44cbae7ad5920001951c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 13 Mar 2025 14:35:34 +0100 Subject: [PATCH 5/8] Fix trimming tests --- .../DataFlow/GenericParameterDataFlowMarking.cs | 4 ++-- .../DynamicDependencies/DynamicDependencyMethod.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs index cf2c018b098752..2d6bc8afc221e5 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs @@ -58,7 +58,7 @@ class GenericMethodNoReference [Kept] static void GenericMethod () { } - [Kept] + [Kept (By = Tool.Trimmer)] class TargetTypeForNothing { public int PublicField; @@ -89,7 +89,7 @@ class GenericMethodCallReference [Kept] static void GenericMethod (T value) where T : IUse { value.Use (); } - [Kept] + [Kept (By = Tool.Trimmer)] [KeptInterfaceAttribute (typeof (IUse), By = Tool.Trimmer)] class TargetTypeForNothing : IUse { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs index 790db571d13705..7ccf4928e9a378 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DynamicDependencies/DynamicDependencyMethod.cs @@ -107,11 +107,11 @@ static Nested () class Complex { - [Kept] + [Kept (By = Tool.Trimmer)] public struct S { } - [Kept] + [Kept (By = Tool.Trimmer)] public class A { } - [Kept] + [Kept (By = Tool.Trimmer)] public class G { } [Kept] From d66b5fb69c711e66f9f5300f88fca4fbe26934ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 13 Mar 2025 14:50:11 +0100 Subject: [PATCH 6/8] Regression test --- .../SmokeTests/Reflection/Reflection.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index a0c6dc36b9e254..2288844cf79b84 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -93,6 +93,7 @@ private static int Main() TestBaseOnlyUsedFromCode.Run(); TestEntryPoint.Run(); TestGenericAttributesOnEnum.Run(); + TestLdtokenWithSignaturesDifferingInModifiers.Run(); return 100; } @@ -2781,6 +2782,26 @@ public static void Run() } } + unsafe class TestLdtokenWithSignaturesDifferingInModifiers + { + delegate string StdcallDelegate(delegate* unmanaged[Stdcall][] p); + delegate string CdeclDelegate(delegate* unmanaged[Cdecl][] p); + + static string Method(delegate* unmanaged[Stdcall][] p) => "Stdcall"; + static string Method(delegate* unmanaged[Cdecl][] p) => "Cdecl"; + + public static void Run() + { + Expression stdcall = x => Method(x); + if (stdcall.Compile()(null) != "Stdcall") + throw new Exception(); + + Expression cdecl = x => Method(x); + if (cdecl.Compile()(null) != "Cdecl") + throw new Exception(); + } + } + #region Helpers private static Type SecretGetType(string testName, string typeName) From ddd59b5993a0efd652b32ef0cbb546ff17ffd6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 14 Mar 2025 08:41:21 +0100 Subject: [PATCH 7/8] Review feedback --- .../src/CompatibilitySuppressions.xml | 8 ++ .../Runtime/Augments/TypeLoaderCallbacks.cs | 2 - ...andleInfo.cs => MethodNameAndSignature.cs} | 19 +++-- .../src/System.Private.CoreLib.csproj | 2 +- .../src/System/RuntimeFieldHandle.cs | 36 +++++---- .../src/System/RuntimeMethodHandle.cs | 74 ++++++++++--------- ...peLoaderEnvironment.LdTokenResultLookup.cs | 16 ---- .../TypeLoader/TypeLoaderEnvironment.cs | 10 --- .../SmokeTests/Reflection/Reflection.cs | 56 ++++++++++++++ 9 files changed, 139 insertions(+), 84 deletions(-) rename src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/{RuntimeMethodHandleInfo.cs => MethodNameAndSignature.cs} (70%) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index f807a13680d788..876c1bcbd60790 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -741,6 +741,14 @@ CP0001 T:System.MDArray + + CP0001 + T:System.FieldHandleInfo + + + CP0001 + T:System.MethodHandleInfo + CP0001 T:System.Reflection.BinderBundle diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs index 2bd2e7579d00ef..c7b5203ffebd4f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs @@ -19,11 +19,9 @@ public abstract class TypeLoaderCallbacks public abstract bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr GetThreadStaticGCDescForDynamicType(TypeManagerHandle handle, int index); public abstract IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntPtr signature, out IntPtr auxResult); - public abstract bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs); public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs); public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle); public abstract IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeMethodHandle declMethod); - public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle handle); public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle); public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle, out RuntimeTypeHandle pointerTypeHandle); public abstract bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, bool isMdArray, int rank, out RuntimeTypeHandle arrayTypeHandle); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/MethodNameAndSignature.cs similarity index 70% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs rename to src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/MethodNameAndSignature.cs index a5910c31319a47..04884e5ac54506 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RuntimeMethodHandleInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/MethodNameAndSignature.cs @@ -3,11 +3,8 @@ using System; using System.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; using Internal.Metadata.NativeFormat; -using Internal.Runtime.Augments; namespace Internal.Runtime.CompilerServices { @@ -38,17 +35,23 @@ public override bool Equals(object? compare) if (other == null) return false; - if (GetName() != other.GetName()) - return false; - // Comparing handles is enough if there's only one metadata blob + // (Same assumption in GetHashCode below!) Debug.Assert(Reader == other.Reader); - return Reader.GetMethod(Handle).Signature.Equals(other.Reader.GetMethod(other.Handle).Signature); + + Method thisMethod = Reader.GetMethod(Handle); + Method otherMethod = other.Reader.GetMethod(other.Handle); + + return thisMethod.Signature.Equals(otherMethod.Signature) + && thisMethod.Name.Equals(otherMethod.Name); } public override int GetHashCode() { - return Handle.GetHashCode(); + Method method = Reader.GetMethod(Handle); + + // Assumes we only have one metadata blob + return method.Signature.GetHashCode() ^ method.Name.GetHashCode(); } } } 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 c89b37a3d60252..d3106f38f9d6dc 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 @@ -119,7 +119,7 @@ - + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs index 1e0cacbaf0aabc..766d7b4bf7949c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; @@ -30,7 +31,7 @@ public override bool Equals(object? obj) return Equals((RuntimeFieldHandle)obj); } - public bool Equals(RuntimeFieldHandle handle) + public unsafe bool Equals(RuntimeFieldHandle handle) { if (_value == handle._value) return true; @@ -38,26 +39,21 @@ public bool Equals(RuntimeFieldHandle handle) if (_value == IntPtr.Zero || handle._value == IntPtr.Zero) return false; - FieldHandle fieldHandle1, fieldHandle2; - RuntimeTypeHandle declaringType1, declaringType2; + FieldHandleInfo* thisInfo = ToFieldHandleInfo(); + FieldHandleInfo* thatInfo = handle.ToFieldHandleInfo(); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType1, out fieldHandle1); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(handle, out declaringType2, out fieldHandle2); - - return declaringType1.Equals(declaringType2) && fieldHandle1.Equals(fieldHandle2); + return thisInfo->DeclaringType.Equals(thatInfo->DeclaringType) && thisInfo->Handle.Equals(thatInfo->Handle); } - public override int GetHashCode() + public override unsafe int GetHashCode() { if (_value == IntPtr.Zero) return 0; - FieldHandle fieldHandle; - RuntimeTypeHandle declaringType; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleComponents(this, out declaringType, out fieldHandle); + FieldHandleInfo* info = ToFieldHandleInfo(); - int hashcode = declaringType.GetHashCode(); - return (hashcode + int.RotateLeft(hashcode, 13)) ^ fieldHandle.GetHashCode(); + int hashcode = info->DeclaringType.GetHashCode(); + return (hashcode + int.RotateLeft(hashcode, 13)) ^ info->Handle.GetHashCode(); } public static RuntimeFieldHandle FromIntPtr(IntPtr value) => new RuntimeFieldHandle(value); @@ -80,5 +76,19 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) { throw new PlatformNotSupportedException(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal readonly unsafe FieldHandleInfo* ToFieldHandleInfo() + { + return (FieldHandleInfo*)_value; + } + } + + [CLSCompliant(false)] + [StructLayout(LayoutKind.Sequential)] + public struct FieldHandleInfo + { + public RuntimeTypeHandle DeclaringType; + public FieldHandle Handle; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs index f37af72848cd2a..13b10d64e93cc5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using Internal.Metadata.NativeFormat; using Internal.Reflection.Augments; +using Internal.Runtime; using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; @@ -32,7 +34,7 @@ public override bool Equals(object? obj) return Equals((RuntimeMethodHandle)obj); } - public bool Equals(RuntimeMethodHandle handle) + public unsafe bool Equals(RuntimeMethodHandle handle) { if (_value == handle._value) return true; @@ -40,52 +42,40 @@ public bool Equals(RuntimeMethodHandle handle) if (_value == IntPtr.Zero || handle._value == IntPtr.Zero) return false; - RuntimeTypeHandle declaringType1, declaringType2; - MethodHandle nameAndSignature1, nameAndSignature2; - RuntimeTypeHandle[] genericArgs1, genericArgs2; + MethodHandleInfo* thisInfo = ToMethodHandleInfo(); + MethodHandleInfo* thatInfo = handle.ToMethodHandleInfo(); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType1, out nameAndSignature1, out genericArgs1); - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(handle, out declaringType2, out nameAndSignature2, out genericArgs2); - - if (!declaringType1.Equals(declaringType2)) + if (!thisInfo->DeclaringType.Equals(thatInfo->DeclaringType)) return false; - if (!nameAndSignature1.Equals(nameAndSignature2)) + if (!thisInfo->Handle.Equals(thatInfo->Handle)) return false; - if ((genericArgs1 == null && genericArgs2 != null) || (genericArgs1 != null && genericArgs2 == null)) + if (thisInfo->NumGenericArgs != thatInfo->NumGenericArgs) return false; - if (genericArgs1 != null) + + RuntimeTypeHandle* thisFirstArg = &thisInfo->FirstArgument; + RuntimeTypeHandle* thatFirstArg = &thatInfo->FirstArgument; + for (int i = 0; i < thisInfo->NumGenericArgs; i++) { - if (genericArgs1.Length != genericArgs2!.Length) + if (!thisFirstArg[i].Equals(thatFirstArg[i])) return false; - for (int i = 0; i < genericArgs1.Length; i++) - { - if (!genericArgs1[i].Equals(genericArgs2![i])) - return false; - } } return true; } - public override int GetHashCode() + public override unsafe int GetHashCode() { if (_value == IntPtr.Zero) return 0; - RuntimeTypeHandle declaringType; - MethodHandle nameAndSignature; - RuntimeTypeHandle[] genericArgs; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType, out nameAndSignature, out genericArgs); + MethodHandleInfo* info = ToMethodHandleInfo(); - int hashcode = declaringType.GetHashCode(); - hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ nameAndSignature.GetHashCode(); - if (genericArgs != null) + int hashcode = info->DeclaringType.GetHashCode(); + hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ info->Handle.GetHashCode(); + for (int i = 0; i < info->NumGenericArgs; i++) { - for (int i = 0; i < genericArgs.Length; i++) - { - int argumentHashCode = genericArgs[i].GetHashCode(); - hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ argumentHashCode; - } + int argumentHashCode = (&info->FirstArgument)[i].GetHashCode(); + hashcode = (hashcode + int.RotateLeft(hashcode, 13)) ^ argumentHashCode; } return hashcode; @@ -105,12 +95,12 @@ public override int GetHashCode() return !left.Equals(right); } - public IntPtr GetFunctionPointer() + public unsafe IntPtr GetFunctionPointer() { - RuntimeTypeHandle declaringType; - RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleComponents(this, out declaringType, out _, out _); + if (_value == IntPtr.Zero) + throw new ArgumentNullException(null, SR.Arg_InvalidHandle); - return ReflectionAugments.GetFunctionPointer(this, declaringType); + return ReflectionAugments.GetFunctionPointer(this, ToMethodHandleInfo()->DeclaringType); } [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] @@ -119,5 +109,21 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) { throw new PlatformNotSupportedException(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal readonly unsafe MethodHandleInfo* ToMethodHandleInfo() + { + return (MethodHandleInfo*)_value; + } + } + + [CLSCompliant(false)] + [StructLayout(LayoutKind.Sequential)] + public struct MethodHandleInfo + { + public RuntimeTypeHandle DeclaringType; + public MethodHandle Handle; + public int NumGenericArgs; + public RuntimeTypeHandle FirstArgument; } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index 69b94757717973..f28b55e5b0d6dc 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -23,22 +23,6 @@ namespace Internal.Runtime.TypeLoader { public sealed partial class TypeLoaderEnvironment { - [StructLayout(LayoutKind.Sequential)] - private struct FieldHandleInfo - { - public RuntimeTypeHandle DeclaringType; - public FieldHandle Handle; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MethodHandleInfo - { - public RuntimeTypeHandle DeclaringType; - public MethodHandle Handle; - public int NumGenericArgs; - public RuntimeTypeHandle FirstArgument; - } - #region Ldtoken Hashtables private struct RuntimeFieldHandleKey : IEquatable { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index 51266c01c0b17a..cb1b6462ab3fe6 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -48,11 +48,6 @@ public override IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntP return TypeLoaderEnvironment.Instance.GenericLookupFromContextAndSignature(context, signature, out auxResult); } - public override bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodHandle handle, out RuntimeTypeHandle[] genericMethodArgs) - { - return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out handle, out genericMethodArgs); - } - public override RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, MethodHandle handle, RuntimeTypeHandle[] genericMethodArgs) { return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeHandle, handle, genericMethodArgs); @@ -68,11 +63,6 @@ public override IntPtr ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targe return TypeLoaderEnvironment.Instance.ResolveGenericVirtualMethodTarget(targetTypeHandle, declMethod); } - public override bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle handle) - { - return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out handle); - } - public override RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, FieldHandle handle) { return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents(declaringTypeHandle, handle); diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 2288844cf79b84..03f1b046d748ba 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -73,6 +73,7 @@ private static int Main() TestTypeHandlesVisibleFromIDynamicInterfaceCastable.Run(); TestCompilerGeneratedCode.Run(); Test105034Regression.Run(); + TestMethodsNeededFromNativeLayout.Run(); // @@ -756,6 +757,61 @@ static void Wrap() } } + class TestMethodsNeededFromNativeLayout + { + class MyAttribute : Attribute; + + class GenericClass where T : class + { + [MethodImpl(MethodImplOptions.NoInlining)] + [My] + public static void GenericMethod([My] string namedParameter = "Hello") { } + + public GenericClass() => GenericMethod(null); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Type GetObjectType() => typeof(object); + + public static void Run() + { + // This tests that limited reflection metadata (that was only needed for native layout) + // works within the reflection stack. + Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(GetObjectType())); + + // This should succeed because of the Activator + Type testType = GetTestType(nameof(TestMethodsNeededFromNativeLayout), "GenericClass`1"); + + // This should succeed because native layout forces the metadata. + // If this ever starts breaking, replace this pattern with something else that forces limited method metadata. + MethodInfo mi = testType.GetMethod(nameof(GenericClass.GenericMethod)); + + // We got a MethodInfo that is limited, check the reflection APIs work fine with it + if (mi.Name != nameof(GenericClass.GenericMethod)) + throw new Exception("Name"); + +#if !REFLECTION_FROM_USAGE + if (mi.GetCustomAttributes(inherit: true).Length != 0) + throw new Exception("Attributes"); +#endif + + var parameters = mi.GetParameters(); + if (parameters.Length != 1) + throw new Exception("ParamCount"); + +#if !REFLECTION_FROM_USAGE + if (parameters[0].Name != null) + throw new Exception("ParamName"); + + if (parameters[0].HasDefaultValue) + throw new Exception("DefaultValue"); + + if (parameters[0].GetCustomAttributes(inherit: true).Length != 0) + throw new Exception("Attributes"); +#endif + } + } + class TestCreateDelegate { internal class Greeter From 9d93d3f6ba2d0e7165d96e3c1266fd85da9e8e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Mon, 17 Mar 2025 13:04:23 +0100 Subject: [PATCH 8/8] FB --- ...EnvironmentImplementation.MappingTables.cs | 33 +++---------------- .../TypeLoaderEnvironment.FieldAccess.cs | 13 ++------ .../TypeLoaderEnvironment.Metadata.cs | 20 ++++------- .../Internal/Runtime/MappingTableFlags.cs | 4 +-- .../ReflectionFieldMapNode.cs | 18 ++-------- .../ReflectionInvokeMapNode.cs | 17 ++-------- .../SmokeTests/Reflection/Reflection.cs | 21 ++++++++++++ 7 files changed, 43 insertions(+), 83 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 81914a83bbeca7..9d5fa69582d5ed 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -704,36 +704,13 @@ private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFor declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle); } - if ((entryFlags & InvokeTableFlags.HasMetadataHandle) != 0) - { - RuntimeTypeHandle declaringTypeHandleDefinition = GetTypeDefinition(declaringTypeHandle); - QTypeDefinition qTypeDefinition = GetMetadataForNamedType(declaringTypeHandleDefinition); - - MethodHandle nativeFormatMethodHandle = - (((int)HandleType.Method << 25) | (int)entryMethodHandleOrNameAndSigRaw).AsMethodHandle(); + RuntimeTypeHandle declaringTypeHandleDefinition = GetTypeDefinition(declaringTypeHandle); + QTypeDefinition qTypeDefinition = GetMetadataForNamedType(declaringTypeHandleDefinition); - methodHandle = new QMethodDefinition(qTypeDefinition.NativeFormatReader, nativeFormatMethodHandle); - } - else - { -#if FEATURE_SHARED_LIBRARY - uint nameAndSigOffset = entryMethodHandleOrNameAndSigRaw; - MethodNameAndSignature nameAndSig; - if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(mappingTableModule.Handle, nameAndSigOffset, out nameAndSig)) - { - Debug.Assert(false); - return false; - } + MethodHandle nativeFormatMethodHandle = + (((int)HandleType.Method << 25) | (int)entryMethodHandleOrNameAndSigRaw).AsMethodHandle(); - if (!TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSig, out methodHandle)) - { - Debug.Assert(false); - return false; - } -#else - throw NotImplemented.ByDesign; -#endif - } + methodHandle = new QMethodDefinition(qTypeDefinition.NativeFormatReader, nativeFormatMethodHandle); return true; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs index efe5e92830c6c1..8e643c73d40596 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs @@ -127,16 +127,9 @@ private static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap( && !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle)) continue; - if ((entryFlags & FieldTableFlags.HasMetadataHandle) != 0) - { - Handle entryFieldHandle = (((int)HandleType.Field << 25) | (int)entryParser.GetUnsigned()).AsHandle(); - if (!fieldHandle.Equals(entryFieldHandle)) - continue; - } - else - { - Debug.Fail("Multifile path"); - } + Handle entryFieldHandle = (((int)HandleType.Field << 25) | (int)entryParser.GetUnsigned()).AsHandle(); + if (!fieldHandle.Equals(entryFieldHandle)) + continue; int fieldOffset; IntPtr fieldAddressCookie = IntPtr.Zero; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index ed03fddc56448d..8b9cd3887fba41 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -820,21 +820,13 @@ public void GetNext( if (((_flags & InvokeTableFlags.IsUniversalCanonicalEntry) != 0) != (_canonFormKind == CanonicalFormKind.Universal)) return; - if ((_flags & InvokeTableFlags.HasMetadataHandle) != 0) - { - // Metadata handles are not known cross module, and cannot be compared across modules. - if (_moduleHandle != _moduleForMethodHandle) - return; + // Metadata handles are not known cross module, and cannot be compared across modules. + if (_moduleHandle != _moduleForMethodHandle) + return; - Handle entryMethodHandle = (((uint)HandleType.Method << 25) | entryParser.GetUnsigned()).AsHandle(); - if (!_methodHandle.Equals(entryMethodHandle)) - return; - } - else - { - // unreached - Debug.Assert(false); - } + Handle entryMethodHandle = (((uint)HandleType.Method << 25) | entryParser.GetUnsigned()).AsHandle(); + if (!_methodHandle.Equals(entryMethodHandle)) + return; _entryType = extRefTable.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!canonHelper.IsCanonicallyEquivalent(_entryType)) diff --git a/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs b/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs index 189be63698bcd1..0263f8d298e035 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/MappingTableFlags.cs @@ -22,7 +22,7 @@ public enum InvokeTableFlags : uint { HasVirtualInvoke = 0x00000001, IsGenericMethod = 0x00000002, - HasMetadataHandle = 0x00000004, + // = 0x00000004, IsDefaultConstructor = 0x00000008, RequiresInstArg = 0x00000010, HasEntrypoint = 0x00000020, @@ -48,7 +48,7 @@ public enum FieldTableFlags : uint StorageClass = 0x03, IsUniversalCanonicalEntry = 0x04, - HasMetadataHandle = 0x08, + // = 0x08, FieldOffsetEncodedDirectly = 0x20, IsAnyCanonicalEntry = 0x40, IsInitOnly = 0x80 diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs index 09835d6ba6077f..3a9530b2c0de18 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs @@ -77,9 +77,6 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) flags = FieldTableFlags.Instance | FieldTableFlags.FieldOffsetEncodedDirectly; } - if (fieldMapping.MetadataHandle != 0) - flags |= FieldTableFlags.HasMetadataHandle; - if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) flags |= FieldTableFlags.IsAnyCanonicalEntry; @@ -98,18 +95,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(declaringTypeId)); - if ((flags & FieldTableFlags.HasMetadataHandle) != 0) - { - // Only store the offset portion of the metadata handle to get better integer compression - vertex = writer.GetTuple(vertex, - writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask))); - } - else - { - // No metadata handle means we need to store name - vertex = writer.GetTuple(vertex, - writer.GetStringConstant(field.Name)); - } + // Only store the offset portion of the metadata handle to get better integer compression + vertex = writer.GetTuple(vertex, + writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask))); if ((flags & FieldTableFlags.IsUniversalCanonicalEntry) != 0) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs index 5cf6fcdb404bdc..3c32eef0bb4a81 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -166,9 +166,6 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (!method.IsAbstract) flags |= InvokeTableFlags.HasEntrypoint; - if (mappingEntry.MetadataHandle != 0) - flags |= InvokeTableFlags.HasMetadataHandle; - if (!factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method)) flags |= InvokeTableFlags.NeedsParameterInterpretation; @@ -184,17 +181,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) Vertex vertex = writer.GetUnsignedConstant((uint)flags); - if ((flags & InvokeTableFlags.HasMetadataHandle) != 0) - { - // Only store the offset portion of the metadata handle to get better integer compression - vertex = writer.GetTuple(vertex, - writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask))); - } - else - { - // Dead code - throw new NotImplementedException(); - } + // Only store the offset portion of the metadata handle to get better integer compression + vertex = writer.GetTuple(vertex, + writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask))); // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted. IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType); diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 03f1b046d748ba..6c78e478e35b89 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -790,15 +790,36 @@ public static void Run() if (mi.Name != nameof(GenericClass.GenericMethod)) throw new Exception("Name"); + // Unless we're doing REFLECTION_FROM_USAGE, we don't expect to see attributes #if !REFLECTION_FROM_USAGE if (mi.GetCustomAttributes(inherit: true).Length != 0) throw new Exception("Attributes"); #endif + // Unless we're doing REFLECTION_FROM_USAGE, we don't expect to be able to reflection-invoke + var mi2 = (MethodInfo)typeof(GenericClass).GetMemberWithSameMetadataDefinitionAs(mi); +#if !REFLECTION_FROM_USAGE + try +#endif + { + + mi2.MakeGenericMethod(typeof(string)).Invoke(null, [ null ]); +#if !REFLECTION_FROM_USAGE + throw new Exception("Invoke"); +#endif + } +#if !REFLECTION_FROM_USAGE + catch (NotSupportedException) + { + } +#endif + + // Parameter count should match no matter what var parameters = mi.GetParameters(); if (parameters.Length != 1) throw new Exception("ParamCount"); + // But parameter names, default values, attributes should only work in REFLECTION_FROM_USAGE #if !REFLECTION_FROM_USAGE if (parameters[0].Name != null) throw new Exception("ParamName");