From f9bca292a6a493269d3fc83b230771238e7825cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 12 Aug 2025 06:42:36 +0200 Subject: [PATCH] Optimize away GVM resolution metadata Ever since GVM support was added to native AOT, we were generating the GVM resolution metadata for every type considered allocated. This included GVMs that were never even called (see `TypeGVMEntriesNode` that simply goes over everything on the type). This PR introduces tracking with method level granularity. I ran into this in a different PR where this was dragging `double`/`float` into compilation just because `int` implements generic math. --- .../ConstructedEETypeNode.cs | 10 +- .../Compiler/DependencyAnalysis/EETypeNode.cs | 2 - .../DependencyAnalysis/GVMDependenciesNode.cs | 15 ++- .../DependencyAnalysis/GVMMetadataNode.cs | 49 +++++++ .../GenericVirtualMethodTableNode.cs | 8 +- .../InterfaceGVMMetadataNode.cs | 65 ++++++++++ .../InterfaceGenericVirtualMethodTableNode.cs | 8 +- .../DependencyAnalysis/NodeFactory.cs | 49 ++++++- .../DependencyAnalysis/TypeGVMEntriesNode.cs | 122 ------------------ .../Compiler/MetadataManager.cs | 23 +++- .../ILCompiler.Compiler.csproj | 3 +- 11 files changed, 194 insertions(+), 160 deletions(-) create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMMetadataNode.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGVMMetadataNode.cs delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index 250b8964a31caa..20a0a0ebd5a3f7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -52,15 +52,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencyList.Add(factory.VTable(closestDefType), "VTable"); - if (_type.IsCanonicalSubtype(CanonicalFormKind.Any)) - { - // Track generic virtual methods that will get added to the GVM tables - if ((_virtualMethodAnalysisFlags & VirtualMethodAnalysisFlags.NeedsGvmEntries) != 0) - { - dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type.GetTypeDefinition()), "Type with generic virtual methods")); - } - } - else + if (!_type.IsCanonicalSubtype(CanonicalFormKind.Any)) { factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index c1e48b4901b1b6..d6ff866e7d0af5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -628,8 +628,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact // Generated type contains generic virtual methods that will get added to the GVM tables if ((_virtualMethodAnalysisFlags & VirtualMethodAnalysisFlags.NeedsGvmEntries) != 0) { - dependencies.Add(new DependencyListEntry(factory.TypeGVMEntries(_type.GetTypeDefinition()), "Type with generic virtual methods")); - TypeDesc canonicalType = _type.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonicalType != _type) dependencies.Add(factory.ConstructedTypeSymbol(canonicalType), "Type with generic virtual methods"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMDependenciesNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMDependenciesNode.cs index 66047d79f08228..09ff03cd1d7b07 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMDependenciesNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMDependenciesNode.cs @@ -41,7 +41,12 @@ public GVMDependenciesNode(MethodDesc method) public override IEnumerable GetStaticDependencies(NodeFactory factory) { if (!_method.IsAbstract) + { yield return new DependencyListEntry(factory.GenericVirtualMethodImpl(_method), "Implementation of the generic virtual method"); + + if (!_method.OwningType.IsInterface) + yield return new DependencyListEntry(factory.GVMMetadata(_method.GetTypicalMethodDefinition(), _method.GetTypicalMethodDefinition()), "Implementation of the generic virtual method"); + } } public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; @@ -124,11 +129,12 @@ public override IEnumerable SearchDynamicDependenci MethodDesc slotDecl = interfaceMethod.Signature.IsStatic ? potentialOverrideDefinition.InstantiateAsOpen().ResolveInterfaceMethodToStaticVirtualMethodOnType(interfaceMethod) : potentialOverrideDefinition.InstantiateAsOpen().ResolveInterfaceMethodTarget(interfaceMethod); + DefaultInterfaceMethodResolution defaultResolution = DefaultInterfaceMethodResolution.None; if (slotDecl == null) { // The method might be implemented through a default interface method - var result = potentialOverrideDefinition.InstantiateAsOpen().ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, out slotDecl); - if (result != DefaultInterfaceMethodResolution.DefaultImplementation) + defaultResolution = potentialOverrideDefinition.InstantiateAsOpen().ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, out slotDecl); + if (defaultResolution != DefaultInterfaceMethodResolution.DefaultImplementation) { slotDecl = null; } @@ -147,6 +153,8 @@ public override IEnumerable SearchDynamicDependenci else dynamicDependencies.Add(new CombinedDependencyListEntry(factory.GVMDependencies(implementingMethodInstantiation.GetCanonMethodTarget(CanonicalFormKind.Specific)), null, "ImplementingMethodInstantiation")); + dynamicDependencies.Add(new CombinedDependencyListEntry(factory.InterfaceGVMMetadata(interfaceMethod, slotDecl.GetTypicalMethodDefinition(), potentialOverrideDefinition, defaultResolution), null, "Metadata")); + TypeSystemEntity origin = (implementingMethodInstantiation.OwningType != potentialOverrideType) ? potentialOverrideType : null; factory.MetadataManager.NoteOverridingMethod(_method, implementingMethodInstantiation, origin); } @@ -200,6 +208,9 @@ public override IEnumerable SearchDynamicDependenci dynamicDependencies.Add(new CombinedDependencyListEntry( factory.GenericVirtualMethodImpl(instantiatedTargetMethod), null, "DerivedMethodInstantiation")); + dynamicDependencies.Add(new CombinedDependencyListEntry(factory.GVMMetadata( + methodToResolve.GetTypicalMethodDefinition(), instantiatedTargetMethod.GetTypicalMethodDefinition()), null, "Metadata")); + factory.MetadataManager.NoteOverridingMethod(_method, instantiatedTargetMethod); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMMetadataNode.cs new file mode 100644 index 00000000000000..09165b950a06c5 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMMetadataNode.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Collections.Generic; + +using ILCompiler.DependencyAnalysisFramework; +using Internal.TypeSystem; + +namespace ILCompiler.DependencyAnalysis +{ + internal sealed class GVMMetadataNode : SortableDependencyNode + { + public MethodDesc CallingMethod { get; } + public MethodDesc ImplementationMethod { get; } + public GVMMetadataNode(MethodDesc callingMethod, MethodDesc implementationMethod) + => (CallingMethod, ImplementationMethod) = (callingMethod, implementationMethod); + + protected override string GetName(NodeFactory context) => + $"GVM method: {CallingMethod}: {ImplementationMethod}"; + + public override IEnumerable GetStaticDependencies(NodeFactory factory) + { + var list = new DependencyList(); + GenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref list, factory, CallingMethod, ImplementationMethod); + return list; + } + + public override int ClassCode => 0x2898423; + + public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) + { + var otherNode = (GVMMetadataNode)other; + + int result = comparer.Compare(CallingMethod, otherNode.CallingMethod); + if (result != 0) + return result; + + return comparer.Compare(ImplementationMethod, otherNode.ImplementationMethod); + } + + 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 context) => null; + public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + } +} 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 3df07d1581bca5..5386c644f1187f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -80,13 +80,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (relocsOnly) return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); - // Build the GVM table entries from the list of interesting GVMTableEntryNodes - foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries()) + foreach (var typeGVMEntryInfo in factory.MetadataManager.GetGVMMetadatas()) { - foreach (var typeGVMEntryInfo in interestingEntry.ScanForGenericVirtualMethodEntries()) - { - AddGenericVirtualMethodImplementation(typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationMethod); - } + AddGenericVirtualMethodImplementation(typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationMethod); } // Ensure the native layout blob has been saved diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGVMMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGVMMetadataNode.cs new file mode 100644 index 00000000000000..7238efce24b9b1 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGVMMetadataNode.cs @@ -0,0 +1,65 @@ +// 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.Collections.Generic; + +using ILCompiler.DependencyAnalysisFramework; +using Internal.TypeSystem; + +namespace ILCompiler.DependencyAnalysis +{ + internal sealed class InterfaceGVMMetadataNode : SortableDependencyNode + { + public MethodDesc CallingMethod { get; } + public MethodDesc ImplementationMethod { get; } + public TypeDesc ImplementationType { get; } + public DefaultInterfaceMethodResolution DefaultResolution { get; } + + public InterfaceGVMMetadataNode(MethodDesc callingMethod, MethodDesc implementationMethod, + TypeDesc implementationType, DefaultInterfaceMethodResolution defaultResolution) + => (CallingMethod, ImplementationMethod, ImplementationType, DefaultResolution) + = (callingMethod, implementationMethod, implementationType, defaultResolution); + + protected override string GetName(NodeFactory context) => + $"GVM interface method: {CallingMethod} on {ImplementationType}: {ImplementationMethod}, {DefaultResolution}"; + + public override IEnumerable GetStaticDependencies(NodeFactory factory) + { + var list = new DependencyList(); + InterfaceGenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref list, factory, CallingMethod, ImplementationType, ImplementationMethod); + return list; + } + + public override int ClassCode => 0x48bcaa1; + + public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) + { + var otherNode = (InterfaceGVMMetadataNode)other; + + int result = comparer.Compare(ImplementationType, otherNode.ImplementationType); + if (result != 0) + return result; + + DefType[] interfaceList = ImplementationType.RuntimeInterfaces; + int thisIndex = Array.IndexOf(interfaceList, CallingMethod.OwningType); + int thatIndex = Array.IndexOf(interfaceList, otherNode.CallingMethod.OwningType); + + Debug.Assert(thisIndex >= 0 && thatIndex >= 0); + + result = Comparer.Default.Compare(thisIndex, thatIndex); + if (result != 0) + return result; + + return comparer.Compare(ImplementationMethod, otherNode.ImplementationMethod); + } + + 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 context) => null; + public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + } +} 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 e1f432af8ff3c6..e994224d38bea2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -125,13 +125,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (relocsOnly) return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); - // Build the GVM table entries from the list of interesting GVMTableEntryNodes - foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries()) + foreach (var typeGVMEntryInfo in factory.MetadataManager.GetInterfaceGVMMetadatas()) { - foreach (var typeGVMEntryInfo in interestingEntry.ScanForInterfaceGenericVirtualMethodEntries()) - { - AddGenericVirtualMethodImplementation(typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationType, typeGVMEntryInfo.ImplementationMethod, typeGVMEntryInfo.DefaultResolution); - } + AddGenericVirtualMethodImplementation(typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationType, typeGVMEntryInfo.ImplementationMethod, typeGVMEntryInfo.DefaultResolution); } // Ensure the native layout blob has been saved 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 ef6a4fed1c1949..9528f9dc29a810 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -339,9 +339,14 @@ private void CreateNodeCaches() return new ExactMethodInstantiationsEntryNode(method); }); - _gvmTableEntries = new NodeCache(type => + _gvmMetadatas = new NodeCache(key => { - return new TypeGVMEntriesNode(type); + return new GVMMetadataNode(key.CallingMethod, key.ImplementationMethod); + }); + + _interfaceGvmMetadatas = new NodeCache(key => + { + return new InterfaceGVMMetadataNode(key.CallingMethod, key.ImplementationMethod, key.ImplementationType, key.DefaultResolution); }); _addressTakenMethods = new NodeCache(method => @@ -1165,10 +1170,16 @@ public ExactMethodInstantiationsEntryNode ExactMethodInstantiationsHashtableEntr return _exactMethodEntries.GetOrAdd(method); } - private NodeCache _gvmTableEntries; - internal TypeGVMEntriesNode TypeGVMEntries(TypeDesc type) + private NodeCache _gvmMetadatas; + internal GVMMetadataNode GVMMetadata(MethodDesc callingMethod, MethodDesc implementationMethod) + { + return _gvmMetadatas.GetOrAdd(new GVMMetadataKey(callingMethod, implementationMethod)); + } + + private NodeCache _interfaceGvmMetadatas; + internal InterfaceGVMMetadataNode InterfaceGVMMetadata(MethodDesc callingMethod, MethodDesc implementationMethod, TypeDesc implementationType, DefaultInterfaceMethodResolution defaultResolution) { - return _gvmTableEntries.GetOrAdd(type); + return _interfaceGvmMetadatas.GetOrAdd(new InterfaceGVMMetadataKey(callingMethod, implementationMethod, implementationType, defaultResolution)); } private NodeCache _addressTakenMethods; @@ -1739,5 +1750,33 @@ private struct MethodILKey : IEquatable public override int GetHashCode() => MethodIL.OwningMethod.GetHashCode(); } + + private struct GVMMetadataKey : IEquatable + { + public readonly MethodDesc CallingMethod; + public readonly MethodDesc ImplementationMethod; + + public GVMMetadataKey(MethodDesc callingMethod, MethodDesc implementationMethod) + => (CallingMethod, ImplementationMethod) = (callingMethod, implementationMethod); + + public override bool Equals(object obj) => obj is GVMMetadataKey other && Equals(other); + public bool Equals(GVMMetadataKey other) => CallingMethod == other.CallingMethod && ImplementationMethod == other.ImplementationMethod; + public override int GetHashCode() => HashCode.Combine(CallingMethod, ImplementationMethod); + } + + private struct InterfaceGVMMetadataKey : IEquatable + { + public readonly MethodDesc CallingMethod; + public readonly MethodDesc ImplementationMethod; + public readonly TypeDesc ImplementationType; + public readonly DefaultInterfaceMethodResolution DefaultResolution; + + public InterfaceGVMMetadataKey(MethodDesc callingMethod, MethodDesc implementationMethod, TypeDesc implementationType, DefaultInterfaceMethodResolution resolution) + => (CallingMethod, ImplementationMethod, ImplementationType, DefaultResolution) = (callingMethod, implementationMethod, implementationType, resolution); + + public override bool Equals(object obj) => obj is InterfaceGVMMetadataKey other && Equals(other); + public bool Equals(InterfaceGVMMetadataKey other) => CallingMethod == other.CallingMethod && ImplementationType == other.ImplementationType; + public override int GetHashCode() => HashCode.Combine(CallingMethod, ImplementationType); + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs deleted file mode 100644 index e3a0b4d38ab17e..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Diagnostics; - -using Internal.TypeSystem; -using ILCompiler.DependencyAnalysisFramework; - -namespace ILCompiler.DependencyAnalysis -{ - /// - /// This node is used for GVM dependency analysis and GVM tables building. Given an input - /// type, this node can scan the type for a list of GVM table entries, and compute their dependencies. - /// - internal sealed class TypeGVMEntriesNode : DependencyNodeCore - { - internal class TypeGVMEntryInfo - { - public TypeGVMEntryInfo(MethodDesc callingMethod, MethodDesc implementationMethod) - { - CallingMethod = callingMethod; - ImplementationMethod = implementationMethod; - } - public MethodDesc CallingMethod { get; } - public MethodDesc ImplementationMethod { get; } - } - - internal sealed class InterfaceGVMEntryInfo : TypeGVMEntryInfo - { - public InterfaceGVMEntryInfo(MethodDesc callingMethod, MethodDesc implementationMethod, - TypeDesc implementationType, DefaultInterfaceMethodResolution defaultResolution) - : base(callingMethod, implementationMethod) - { - ImplementationType = implementationType; - DefaultResolution = defaultResolution; - } - - public TypeDesc ImplementationType { get; } - public DefaultInterfaceMethodResolution DefaultResolution { get; } - } - - private readonly TypeDesc _associatedType; - private DependencyList _staticDependencies; - - public TypeGVMEntriesNode(TypeDesc associatedType) - { - Debug.Assert(associatedType.IsTypeDefinition); - _associatedType = associatedType; - } - - public TypeDesc AssociatedType => _associatedType; - - public override bool HasConditionalStaticDependencies => false; - public override bool HasDynamicDependencies => false; - public override bool InterestingForDynamicDependencyAnalysis => false; - public override bool StaticDependenciesAreComputed => true; - protected override string GetName(NodeFactory factory) => "__TypeGVMEntriesNode_" + factory.NameMangler.GetMangledTypeName(_associatedType); - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; - - public override IEnumerable GetStaticDependencies(NodeFactory context) - { - if (_staticDependencies == null) - { - _staticDependencies = new DependencyList(); - - foreach (var entry in ScanForGenericVirtualMethodEntries()) - GenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref _staticDependencies, context, entry.CallingMethod, entry.ImplementationMethod); - - foreach (var entry in ScanForInterfaceGenericVirtualMethodEntries()) - InterfaceGenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref _staticDependencies, context, entry.CallingMethod, entry.ImplementationType, entry.ImplementationMethod); - } - - return _staticDependencies; - } - - public IEnumerable ScanForGenericVirtualMethodEntries() - { - foreach (MethodDesc decl in _associatedType.EnumAllVirtualSlots()) - { - // Non-Generic virtual methods are tracked by an orthogonal mechanism. - if (!decl.HasInstantiation) - continue; - - MethodDesc impl = _associatedType.FindVirtualFunctionTargetMethodOnObjectType(decl); - - if (impl.OwningType == _associatedType) - yield return new TypeGVMEntryInfo(decl, impl); - } - } - - public IEnumerable ScanForInterfaceGenericVirtualMethodEntries() - { - foreach (var iface in _associatedType.RuntimeInterfaces) - { - foreach (var method in iface.GetVirtualMethods()) - { - if (!method.HasInstantiation) - continue; - - DefaultInterfaceMethodResolution resolution = DefaultInterfaceMethodResolution.None; - MethodDesc slotDecl = method.Signature.IsStatic ? - _associatedType.ResolveInterfaceMethodToStaticVirtualMethodOnType(method) : _associatedType.ResolveInterfaceMethodTarget(method); - if (slotDecl == null) - { - resolution = _associatedType.ResolveInterfaceMethodToDefaultImplementationOnType(method, out slotDecl); - if (resolution != DefaultInterfaceMethodResolution.DefaultImplementation) - slotDecl = null; - } - - if (slotDecl != null - || resolution == DefaultInterfaceMethodResolution.Diamond - || resolution == DefaultInterfaceMethodResolution.Reabstraction) - { - yield return new InterfaceGVMEntryInfo(method, slotDecl, _associatedType, resolution); - } - } - } - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 93a2e79d9df627..49eedb3b20a4c5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -72,8 +72,8 @@ public abstract class MetadataManager : ICompilationRootProvider private readonly SortedSet _genericDictionariesGenerated = new SortedSet(CompilerComparer.Instance); private readonly SortedSet _methodBodiesGenerated = new SortedSet(CompilerComparer.Instance); private readonly SortedSet _frozenObjects = new SortedSet(CompilerComparer.Instance); - private readonly SortedSet _typeGVMEntries - = new SortedSet(Comparer.Create((a, b) => TypeSystemComparer.Instance.Compare(a.AssociatedType, b.AssociatedType))); + private readonly SortedSet _gvmMetadatas = new SortedSet(CompilerComparer.Instance); + private readonly SortedSet _interfaceGvmMetadatas = new SortedSet(CompilerComparer.Instance); private readonly SortedSet _typesWithDelegateMarshalling = new SortedSet(TypeSystemComparer.Instance); private readonly SortedSet _typesWithStructMarshalling = new SortedSet(TypeSystemComparer.Instance); private HashSet _templateMethodEntries = new HashSet(); @@ -286,10 +286,14 @@ protected virtual void Graph_NewMarkedNode(DependencyNodeCore obj) _typesWithThreadStaticsGenerated.Add(threadStaticsNode.Type); } - var gvmEntryNode = obj as TypeGVMEntriesNode; - if (gvmEntryNode != null) + if (obj is GVMMetadataNode gvmMetadataNode) { - _typeGVMEntries.Add(gvmEntryNode); + _gvmMetadatas.Add(gvmMetadataNode); + } + + if (obj is InterfaceGVMMetadataNode interfaceGvmMetadataNode) + { + _interfaceGvmMetadatas.Add(interfaceGvmMetadataNode); } var dictionaryNode = obj as GenericDictionaryNode; @@ -1024,9 +1028,14 @@ internal IEnumerable GetTypesWithStaticBases() internal bool HasThreadStaticBase(MetadataType type) => _typesWithThreadStaticsGenerated.Contains(type); internal bool HasConstructedEEType(TypeDesc type) => _typesWithConstructedEETypesGenerated.Contains(type); - internal IEnumerable GetTypeGVMEntries() + internal IEnumerable GetGVMMetadatas() + { + return _gvmMetadatas; + } + + internal IEnumerable GetInterfaceGVMMetadatas() { - return _typeGVMEntries; + return _interfaceGvmMetadatas; } internal IReadOnlyCollection GetCompiledGenericDictionaries() diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 3ac5cfb27289d4..82997a013ba6cc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -502,9 +502,10 @@ + - +