diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs index 8c576421f74d90..d14e2c29fb6610 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs @@ -40,9 +40,9 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool HasConditionalStaticDependencies => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } #if !SUPPORT_JIT public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/GVMDependenciesNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/GVMDependenciesNode.cs index a6e0ad77cfcee5..d7723a443f0151 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/GVMDependenciesNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/GVMDependenciesNode.cs @@ -42,24 +42,24 @@ public GVMDependenciesNode(MethodDesc method) public override bool StaticDependenciesAreComputed => true; protected override string GetName(NodeFactory factory) => "__GVMDependenciesNode_" + factory.NameMangler.GetMangledMethodName(_method); - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { if (!_method.IsAbstract) { DependencyNodeCore node = GetVirtualMethodImplNode(factory, _method); if (node != null) - yield return new DependencyListEntry(node, "Implementation of the generic virtual method"); + sink.Add(node, "Implementation of the generic virtual method"); } #if !READYTORUN if (!_method.OwningType.IsInterface) { - yield return new DependencyListEntry(factory.TypeGVMEntries(_method.OwningType.GetTypeDefinition()), "Resolution metadata"); + sink.Add(factory.TypeGVMEntries(_method.OwningType.GetTypeDefinition()), "Resolution metadata"); } - yield return new DependencyListEntry(factory.AnalysisCharacteristic("GenericVirtualMethodsPresent"), "Runtime GVM resolution needed"); + sink.Add(factory.AnalysisCharacteristic("GenericVirtualMethodsPresent"), "Runtime GVM resolution needed"); #endif } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } public override bool HasDynamicDependencies { @@ -76,9 +76,9 @@ public override bool HasDynamicDependencies } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { - List dynamicDependencies = new List(); + DependencySink dynamicDependencies = sink; TypeDesc methodOwningType = _method.OwningType; bool methodIsShared = _method.IsSharedByGenericInstantiations; @@ -174,7 +174,7 @@ public override IEnumerable SearchDynamicDependenci { DependencyNodeCore node = GetVirtualMethodImplNode(factory, canonImpl); if (node != null) - dynamicDependencies.Add(new CombinedDependencyListEntry(node, null, "ImplementingMethodInstantiation")); + dynamicDependencies.Add(node, "ImplementingMethodInstantiation"); } else { @@ -182,14 +182,14 @@ public override IEnumerable SearchDynamicDependenci if (!factory.CanBeInGenericCycle(canonImpl)) #endif { - dynamicDependencies.Add(new CombinedDependencyListEntry(factory.GVMDependencies(canonImpl), null, "ImplementingMethodInstantiation")); + dynamicDependencies.Add(factory.GVMDependencies(canonImpl), "ImplementingMethodInstantiation"); } } #if !READYTORUN TypeSystemEntity origin = (implementingMethodInstantiation.OwningType != potentialOverrideType) ? potentialOverrideType : null; factory.MetadataManager.NoteOverridingMethod(_method, implementingMethodInstantiation, origin); - factory.MetadataManager.GetDependenciesForOverridingMethod(ref dynamicDependencies, factory, _method, implementingMethodInstantiation); + factory.MetadataManager.GetDependenciesForOverridingMethod(dynamicDependencies, factory, _method, implementingMethodInstantiation); #endif } @@ -245,10 +245,10 @@ public override IEnumerable SearchDynamicDependenci { DependencyNodeCore node = GetVirtualMethodImplNode(factory, instantiatedTargetMethod); if (node != null) - dynamicDependencies.Add(new CombinedDependencyListEntry(node, null, "DerivedMethodInstantiation")); + dynamicDependencies.Add(node, "DerivedMethodInstantiation"); #if !READYTORUN factory.MetadataManager.NoteOverridingMethod(_method, instantiatedTargetMethod); - factory.MetadataManager.GetDependenciesForOverridingMethod(ref dynamicDependencies, factory, _method, instantiatedTargetMethod); + factory.MetadataManager.GetDependenciesForOverridingMethod(dynamicDependencies, factory, _method, instantiatedTargetMethod); foundImpl = true; #endif @@ -261,15 +261,13 @@ public override IEnumerable SearchDynamicDependenci TypeDesc currentType = potentialOverrideType; do { - dynamicDependencies.Add(new CombinedDependencyListEntry(factory.TypeGVMEntries(currentType.GetTypeDefinition()), null, "Resolution metadata")); + dynamicDependencies.Add(factory.TypeGVMEntries(currentType.GetTypeDefinition()), "Resolution metadata"); currentType = currentType.BaseType; } while (currentType != null); } #endif } - - return dynamicDependencies; } private static DependencyNodeCore GetVirtualMethodImplNode(NodeFactory factory, MethodDesc method) diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs index 6a17de9af54eed..f8ac4253f1429f 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/IMethodBodyNode.cs @@ -1,12 +1,27 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using ILCompiler.DependencyAnalysisFramework; + +using Internal.TypeSystem; + namespace ILCompiler.DependencyAnalysis { /// - /// Marker interface that identifies the node representing a compiled method body. + /// Represents a compiled method body whose dependencies can vary by generic instantiation. /// public interface IMethodBodyNode : IMethodNode, IPCodeSymbolNode { + /// + /// Specializes this canonical body's runtime-determined dependencies for + /// and streams the resulting static dependencies to . + /// + void AddRuntimeDeterminedStaticDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod); + + /// + /// Specializes this canonical body's runtime-determined conditional dependencies for + /// and streams them to , preserving their conditions. + /// + void AddRuntimeDeterminedConditionalDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod); } } diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs index d6e5f5445c37a2..7780eed20a744c 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithRuntimeDeterminedDependencies.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; +#nullable enable using Internal.TypeSystem; -using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -15,8 +15,16 @@ namespace ILCompiler.DependencyAnalysis public interface INodeWithRuntimeDeterminedDependencies { /// - /// Instantiates runtime determined dependencies of this node using the supplied generic context. + /// Instantiates runtime determined dependencies of this node using the + /// supplied generic context. If is + /// not null, the dependencies are considered conditional. /// - IEnumerable InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, bool isConcreteInstantiation); + void AddDependencies( + DependencySink sink, + NodeFactory factory, + Instantiation typeInstantiation, + Instantiation methodInstantiation, + bool isConcreteInstantiation, + DependencyNodeCore? otherReasonNode); } } diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNode.cs index 151fa1e8f587bf..f13e26d2df28fc 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNode.cs @@ -53,41 +53,31 @@ public virtual bool ShouldSkipEmittingObjectNode(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool InterestingForDynamicDependencyAnalysis => false; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = ComputeNonRelocationBasedDependencies(factory); + ComputeNonRelocationBasedDependencies(sink, factory); Relocation[] relocs = GetData(factory, true).Relocs; if (relocs != null) { - dependencies ??= new DependencyList(); - foreach (Relocation reloc in relocs) { - dependencies.Add(reloc.Target, "reloc"); + sink.Add(reloc.Target, "reloc"); } } if (factory.Target.IsWasm && this is IMethodCodeNodeWithTypeSignature wasmMethodCodeNode) { - dependencies ??= new DependencyList(); - WasmTypeNode wasmTypeNode = factory.WasmTypeNode(wasmMethodCodeNode.Method); - dependencies.Add(wasmTypeNode, "Wasm Method Code Nodes Require Signature"); + sink.Add(wasmTypeNode, "Wasm Method Code Nodes Require Signature"); } - - if (dependencies == null) - return Array.Empty(); - else - return dependencies; } - protected virtual DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected virtual void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - return null; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs index 1ce5973c387d38..0ef17ce0ccf9c2 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs @@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis /// public class ShadowConcreteMethodNode : ShadowMethodNode, IMethodNode, ISymbolNodeWithLinkage { - public ShadowConcreteMethodNode(MethodDesc method, IMethodNode canonicalMethod) + public ShadowConcreteMethodNode(MethodDesc method, IMethodBodyNode canonicalMethod) : base(method, canonicalMethod) { Debug.Assert(!method.IsSharedByGenericInstantiations); diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowMethodNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowMethodNode.cs index ba0b8280fb0b30..9a3365f229a9a1 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowMethodNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowMethodNode.cs @@ -24,7 +24,7 @@ public abstract class ShadowMethodNode : DependencyNodeCore, IMetho /// /// Gets the canonical method body that defines the dependencies of this node. /// - public IMethodNode CanonicalMethodNode { get; } + public IMethodBodyNode CanonicalMethodNode { get; } /// /// Gets the generic method represented by this node. @@ -42,7 +42,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => CanonicalMethodNode.StaticDependenciesAreComputed; - public ShadowMethodNode(MethodDesc method, IMethodNode canonicalMethod) + public ShadowMethodNode(MethodDesc method, IMethodBodyNode canonicalMethod) { Debug.Assert(!method.IsRuntimeDeterminedExactMethod); Debug.Assert(canonicalMethod.Method == method.GetCanonMethodTarget(CanonicalFormKind.Specific)); @@ -56,56 +56,17 @@ public ISymbolNode NodeForLinkage(NodeFactory factory) return CanonicalMethodNode; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); - // Make sure the canonical body gets generated - dependencies.Add(new DependencyListEntry(CanonicalMethodNode, "Canonical body")); - - // Instantiate the runtime determined dependencies of the canonical method body - // with the concrete instantiation of the method to get concrete dependencies. - Instantiation typeInst = Method.OwningType.Instantiation; - Instantiation methodInst = Method.Instantiation; - IEnumerable staticDependencies = CanonicalMethodNode.GetStaticDependencies(factory); - - if (staticDependencies != null) - { - foreach (DependencyListEntry canonDep in staticDependencies) - { - var runtimeDep = canonDep.Node as INodeWithRuntimeDeterminedDependencies; - if (runtimeDep != null) - { - dependencies.AddRange(runtimeDep.InstantiateDependencies(factory, typeInst, methodInst, isConcreteInstantiation: !Method.IsSharedByGenericInstantiations)); - } - } - } - - return dependencies; + sink.Add(new DependencyListEntry(CanonicalMethodNode, "Canonical body")); + + CanonicalMethodNode.AddRuntimeDeterminedStaticDependencies(sink, factory, Method); } - public sealed override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public sealed override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - // Instantiate the runtime determined dependencies of the canonical method body - // with the concrete instantiation of the method to get concrete dependencies. - Instantiation typeInst = Method.OwningType.Instantiation; - Instantiation methodInst = Method.Instantiation; - IEnumerable staticDependencies = CanonicalMethodNode.GetConditionalStaticDependencies(factory); - - if (staticDependencies != null) - { - foreach (CombinedDependencyListEntry canonDep in staticDependencies) - { - Debug.Assert(canonDep.OtherReasonNode is not INodeWithRuntimeDeterminedDependencies); - - var node = canonDep.Node; - if (node is INodeWithRuntimeDeterminedDependencies runtimeDeterminedNode) - { - foreach (var nodeInner in runtimeDeterminedNode.InstantiateDependencies(factory, typeInst, methodInst, isConcreteInstantiation: !Method.IsSharedByGenericInstantiations)) - yield return new CombinedDependencyListEntry(nodeInner.Node, canonDep.OtherReasonNode, nodeInner.Reason); - } - } - } + CanonicalMethodNode.AddRuntimeDeterminedConditionalDependencies(sink, factory, Method); } @@ -115,7 +76,7 @@ public sealed override IEnumerable GetConditionalSt public sealed override bool HasDynamicDependencies => false; public sealed override bool InterestingForDynamicDependencyAnalysis => false; - public sealed override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public sealed override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } int ISortableNode.ClassCode => ClassCode; diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowNonConcreteMethodNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowNonConcreteMethodNode.cs index 2163f0093eff7b..8a52c1b51e361c 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowNonConcreteMethodNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowNonConcreteMethodNode.cs @@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis /// public class ShadowNonConcreteMethodNode : ShadowMethodNode, IMethodNode, ISymbolNodeWithLinkage { - public ShadowNonConcreteMethodNode(MethodDesc method, IMethodNode canonicalMethod) + public ShadowNonConcreteMethodNode(MethodDesc method, IMethodBodyNode canonicalMethod) : base(method, canonicalMethod) { Debug.Assert(method.IsSharedByGenericInstantiations); diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs index 48825d0e82c059..bb5c4383305028 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs @@ -60,9 +60,9 @@ protected override void OnMarked(NodeFactory factory) public override bool StaticDependenciesAreComputed => true; #if !READYTORUN - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; MethodDesc canonDecl = _decl.GetCanonMethodTarget(CanonicalFormKind.Specific); if (canonDecl != _decl) @@ -72,18 +72,16 @@ public override IEnumerable GetStaticDependencies(NodeFacto // Do not report things like Foo.Frob(). if (!_decl.IsCanonicalMethod(CanonicalFormKind.Any) || canonDecl == _decl) - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref dependencies, factory, _decl); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(dependencies, factory, _decl); if (VariantInterfaceMethodUseNode.IsVariantMethodCall(factory, _decl)) dependencies.Add(factory.VariantInterfaceMethodUse(_decl.GetTypicalMethodDefinition()), "Variant interface call"); - - return dependencies; } #else - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } #endif - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 6463dc16006975..3cc11fb4e8f891 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -37,6 +37,9 @@ #endif using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; +using DependencyNode = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore; +using IDependencySink = ILCompiler.DependencyAnalysisFramework.IDependencySink; #pragma warning disable IDE0060 @@ -592,11 +595,11 @@ private void PublishCode() if (_synthesizedPgoDependencies != null) { Debug.Assert(_compilation.NodeFactory.InstrumentationDataTable != null, "Expected InstrumentationDataTable to be non-null with synthesized PGO data to embed"); - _compilation.NodeFactory.InstrumentationDataTable.EmbedSynthesizedPgoDataForMethods(ref _additionalDependencies, _synthesizedPgoDependencies); + _compilation.NodeFactory.InstrumentationDataTable.EmbedSynthesizedPgoDataForMethods(_additionalDependencies, _synthesizedPgoDependencies); } #else var methodIL = (MethodIL)HandleToObject((void*)_methodScope); - CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(ref _additionalDependencies, _compilation.NodeFactory, MethodBeingCompiled, methodIL); + CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(_additionalDependencies, _compilation.NodeFactory, MethodBeingCompiled, methodIL); _methodCodeNode.InitializeDebugInfo(_debugInfo); LocalVariableDefinition[] locals = methodIL.GetLocals(); @@ -607,7 +610,7 @@ private void PublishCode() _methodCodeNode.InitializeLocalTypes(localTypes); #endif - _methodCodeNode.InitializeNonRelocationDependencies(_additionalDependencies); + _methodCodeNode.InitializeNonRelocationDependencies(_additionalDependencies.TakeDependencies()); } private void PublishROData() @@ -719,7 +722,7 @@ private void CompileMethodCleanup() _gcInfo = null; _ehClauses = null; - _additionalDependencies = null; + _additionalDependencies.Clear(); #if !READYTORUN _debugInfo = null; @@ -2033,7 +2036,7 @@ private void resolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) ValidateSafetyOfUsingTypeEquivalenceInSignature(method.Signature); } #else - _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _additionalDependencies, _compilation.NodeFactory, (MethodIL)methodIL, method); + _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(_additionalDependencies, _compilation.NodeFactory, (MethodIL)methodIL, method); #endif if (pResolvedToken.tokenType is CorInfoTokenKind.CORINFO_TOKENKIND_Await) @@ -2074,7 +2077,7 @@ private void resolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) #endif #if !READYTORUN - _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _additionalDependencies, _compilation.NodeFactory, (MethodIL)methodIL, field); + _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(_additionalDependencies, _compilation.NodeFactory, (MethodIL)methodIL, field); #else ValidateSafetyOfUsingTypeEquivalenceOfType(field.FieldType); #endif @@ -4259,7 +4262,47 @@ private bool getTailCallHelpers(ref CORINFO_RESOLVED_TOKEN callToken, CORINFO_SI private byte[] _gcInfo; private CORINFO_EH_CLAUSE[] _ehClauses; - private DependencyList _additionalDependencies; + private sealed class AdditionalDependencyList : IDependencySink + { + private DependencyList _dependencies; + + public void Add(DependencyNode node, string reason) + { + (_dependencies ??= new DependencyList()).Add(node, reason); + } + + public void Add(object node, string reason) + { + (_dependencies ??= new DependencyList()).Add(node, reason); + } + + public void Add(DependencyListEntry dependency) + { + (_dependencies ??= new DependencyList()).Add(dependency); + } + + public void AddRange(params ReadOnlySpan dependencies) + { + foreach (DependencyListEntry dependency in dependencies) + { + Add(dependency); + } + } + + public DependencyList TakeDependencies() + { + DependencyList dependencies = _dependencies; + _dependencies = null; + return dependencies; + } + + public void Clear() + { + _dependencies = null; + } + } + + private readonly AdditionalDependencyList _additionalDependencies = new AdditionalDependencyList(); private void allocMem(ref AllocMemArgs args) { diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/AssemblyRootNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/AssemblyRootNode.cs index 27e67f37fa7af9..9144d28c636a2b 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/AssemblyRootNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/AssemblyRootNode.cs @@ -22,7 +22,7 @@ internal class AssemblyRootNode : DependencyNodeCore public AssemblyRootNode(string assemblyName, AssemblyRootMode mode) => (_assemblyName, _mode) = (assemblyName, mode); - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { // TODO: what is the failure mode of illink here? var module = (EcmaModule)factory.TypeSystemContext.ResolveAssembly(AssemblyNameInfo.Parse(_assemblyName)); @@ -35,7 +35,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto case AssemblyRootMode.EntryPoint: // TODO: what is the failure mode of illink here? MethodDefinitionHandle entrypointToken = (MethodDefinitionHandle)MetadataTokens.Handle(module.PEReader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); - yield return new DependencyListEntry(factory.MethodDefinition(module, entrypointToken), "Entrypoint"); + sink.Add(factory.MethodDefinition(module, entrypointToken), "Entrypoint"); break; case AssemblyRootMode.VisibleMembers: // TODO @@ -50,8 +50,8 @@ public override IEnumerable GetStaticDependencies(NodeFacto 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Assembly root: {_assemblyName} ({_mode})"; } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/ConstructedTypeNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/ConstructedTypeNode.cs index 8e118fe7b8e64d..249f19418a36ad 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/ConstructedTypeNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/ConstructedTypeNode.cs @@ -207,19 +207,22 @@ void INodeWithDeferredDependencies.ComputeDependencies(NodeFactory factory) _conditionalDependencies = result ?? (IReadOnlyCollection)Array.Empty(); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { System.Diagnostics.Debug.Assert(_conditionalDependencies != null); - return _conditionalDependencies; + foreach (CombinedDependencyListEntry dependency in _conditionalDependencies) + { + sink.Add(dependency); + } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { // Call GetTypeDefinition in case the base is an instantiated generic type. TypeDesc baseType = _type.BaseType?.GetTypeDefinition(); if (baseType != null) { - yield return new(factory.ConstructedType((EcmaType)baseType), "Base type"); + sink.Add(new DependencyListEntry(factory.ConstructedType((EcmaType)baseType), "Base type")); } } @@ -231,7 +234,7 @@ protected override string GetName(NodeFactory factory) public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool StaticDependenciesAreComputed => _conditionalDependencies != null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } private static MethodImplementationHandle TryGetMethodImplementationHandle(EcmaType implementingType, EcmaMethod declMethod) { diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/EcmaSignatureAnalyzer.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/EcmaSignatureAnalyzer.cs index c9c579937ccda4..47b17a22b57bbe 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/EcmaSignatureAnalyzer.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/EcmaSignatureAnalyzer.cs @@ -8,7 +8,7 @@ using Internal.TypeSystem.Ecma; using Internal.TypeSystem; -using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -17,27 +17,19 @@ public struct EcmaSignatureAnalyzer private readonly EcmaModule _module; private BlobReader _blobReader; private readonly NodeFactory _factory; - private DependencyList _dependenciesOrNull; + private readonly DependencySink _dependencies; - private DependencyList Dependencies - { - get - { - return _dependenciesOrNull ??= new DependencyList(); - } - } - - private EcmaSignatureAnalyzer(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies) + private EcmaSignatureAnalyzer(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { _module = module; _blobReader = blobReader; _factory = factory; - _dependenciesOrNull = dependencies; + _dependencies = dependencies; } private void AnalyzeCustomModifier(SignatureTypeCode typeCode) { - Dependencies.Add(_factory.GetNodeForTypeToken(_module, _blobReader.ReadTypeHandle()), "Custom modifier"); + _dependencies.Add(_factory.GetNodeForTypeToken(_module, _blobReader.ReadTypeHandle()), "Custom modifier"); } private void AnalyzeType() @@ -74,7 +66,7 @@ private void AnalyzeType(SignatureTypeCode typeCode) _blobReader.ReadCompressedInteger(); break; case SignatureTypeCode.TypeHandle: - Dependencies.Add(_factory.GetNodeForTypeToken(_module, _blobReader.ReadTypeHandle()), "Signature reference"); + _dependencies.Add(_factory.GetNodeForTypeToken(_module, _blobReader.ReadTypeHandle()), "Signature reference"); break; case SignatureTypeCode.SZArray: case SignatureTypeCode.Pointer: @@ -91,8 +83,8 @@ private void AnalyzeType(SignatureTypeCode typeCode) goto again; case SignatureTypeCode.GenericTypeInstance: _blobReader.ReadCompressedInteger(); - Dependencies.Add(_factory.GetNodeForTypeToken(_module, _blobReader.ReadTypeHandle()), "Signature reference"); - int numGenericArgs= _blobReader.ReadCompressedInteger(); + _dependencies.Add(_factory.GetNodeForTypeToken(_module, _blobReader.ReadTypeHandle()), "Signature reference"); + int numGenericArgs = _blobReader.ReadCompressedInteger(); for (int i = 0; i < numGenericArgs; i++) { AnalyzeType(); @@ -106,12 +98,13 @@ private void AnalyzeType(SignatureTypeCode typeCode) } } - public static DependencyList AnalyzeStandaloneSignatureBlob(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies = null) + public static void AnalyzeStandaloneSignatureBlob(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzeStandaloneSignatureBlob(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzeStandaloneSignatureBlob(); } - private DependencyList AnalyzeStandaloneSignatureBlob() + private void AnalyzeStandaloneSignatureBlob() { SignatureHeader header = _blobReader.ReadSignatureHeader(); switch (header.Kind) @@ -126,10 +119,9 @@ private DependencyList AnalyzeStandaloneSignatureBlob() throw new BadImageFormatException(); } - return _dependenciesOrNull; } - private DependencyList AnalyzeLocalVariablesBlob(SignatureHeader header) + private void AnalyzeLocalVariablesBlob(SignatureHeader header) { int varCount = _blobReader.ReadCompressedInteger(); for (int i = 0; i < varCount; i++) @@ -152,21 +144,21 @@ private DependencyList AnalyzeLocalVariablesBlob(SignatureHeader header) AnalyzeType(typeCode); } - return _dependenciesOrNull; } - public static DependencyList AnalyzeMethodSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies = null) + public static void AnalyzeMethodSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzeMethodSignature(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzeMethodSignature(); } - private DependencyList AnalyzeMethodSignature() + private void AnalyzeMethodSignature() { SignatureHeader header = _blobReader.ReadSignatureHeader(); - return AnalyzeMethodSignature(header); + AnalyzeMethodSignature(header); } - private DependencyList AnalyzeMethodSignature(SignatureHeader header) + private void AnalyzeMethodSignature(SignatureHeader header) { int arity = header.IsGeneric ? _blobReader.ReadCompressedInteger() : 0; int paramCount = _blobReader.ReadCompressedInteger(); @@ -179,64 +171,65 @@ private DependencyList AnalyzeMethodSignature(SignatureHeader header) AnalyzeType(); } - return _dependenciesOrNull; } - public static DependencyList AnalyzeFieldSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies = null) + public static void AnalyzeFieldSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzeFieldSignature(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzeFieldSignature(); } - private DependencyList AnalyzeFieldSignature() + private void AnalyzeFieldSignature() { SignatureHeader header = _blobReader.ReadSignatureHeader(); - return AnalyzeFieldSignature(header); + AnalyzeFieldSignature(header); } - private DependencyList AnalyzeFieldSignature(SignatureHeader header) + private void AnalyzeFieldSignature(SignatureHeader header) { // Return type AnalyzeType(); - return _dependenciesOrNull; } - public static DependencyList AnalyzeMemberReferenceSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies = null) + public static void AnalyzeMemberReferenceSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzeMemberReferenceSignature(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzeMemberReferenceSignature(); } - private DependencyList AnalyzeMemberReferenceSignature() + private void AnalyzeMemberReferenceSignature() { SignatureHeader header = _blobReader.ReadSignatureHeader(); if (header.Kind == SignatureKind.Method) { - return AnalyzeMethodSignature(header); + AnalyzeMethodSignature(header); } else { System.Diagnostics.Debug.Assert(header.Kind == SignatureKind.Field); - return AnalyzeFieldSignature(header); + AnalyzeFieldSignature(header); } } - public static DependencyList AnalyzeTypeSpecSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies) + public static void AnalyzeTypeSpecSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzeTypeSpecSignature(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzeTypeSpecSignature(); } - private DependencyList AnalyzeTypeSpecSignature() + private void AnalyzeTypeSpecSignature() { AnalyzeType(); - return _dependenciesOrNull; } - public static DependencyList AnalyzeMethodSpecSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies) + public static void AnalyzeMethodSpecSignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzeMethodSpecSignature(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzeMethodSpecSignature(); } - private DependencyList AnalyzeMethodSpecSignature() + private void AnalyzeMethodSpecSignature() { //II.23.2.15 MethodSpec GENRICINST GenArgCount Type Type* @@ -254,19 +247,19 @@ private DependencyList AnalyzeMethodSpecSignature() AnalyzeType(); } - return _dependenciesOrNull; } - public static DependencyList AnalyzePropertySignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencyList dependencies = null) + public static void AnalyzePropertySignature(EcmaModule module, BlobReader blobReader, NodeFactory factory, DependencySink dependencies) { - return new EcmaSignatureAnalyzer(module, blobReader, factory, dependencies).AnalyzePropertySignature(); + EcmaSignatureAnalyzer analyzer = new(module, blobReader, factory, dependencies); + analyzer.AnalyzePropertySignature(); } - private DependencyList AnalyzePropertySignature() + private void AnalyzePropertySignature() { SignatureHeader header = _blobReader.ReadSignatureHeader(); System.Diagnostics.Debug.Assert(header.Kind == SignatureKind.Property); - return AnalyzeMethodSignature(header); + AnalyzeMethodSignature(header); } } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/InterfaceUseNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/InterfaceUseNode.cs index b87e9575ccab99..b68d25035545f4 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/InterfaceUseNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/InterfaceUseNode.cs @@ -31,12 +31,12 @@ protected override string GetName(NodeFactory factory) return $"{_type} interface used"; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } public override bool HasConditionalStaticDependencies => false; public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/MethodBodyNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/MethodBodyNode.cs index bb0cd5ad8853d3..8b246aa238eff1 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/MethodBodyNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/MethodBodyNode.cs @@ -36,7 +36,13 @@ public MethodBodyNode(EcmaModule module, MethodDefinitionHandle methodHandle) public override bool StaticDependenciesAreComputed => _dependencies != null; - public override IEnumerable GetStaticDependencies(NodeFactory context) => _dependencies; + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) + { + foreach (DependencyListEntry dependency in _dependencies) + { + sink.Add(dependency); + } + } void INodeWithDeferredDependencies.ComputeDependencies(NodeFactory factory) { @@ -345,7 +351,7 @@ protected override string GetName(NodeFactory factory) public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/NodeFactory.cs index 08d44a6d05da07..7ef528f2f21e55 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/NodeFactory.cs @@ -345,9 +345,9 @@ public class NullDependencyNode : DependencyNodeCore public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory context) => Array.Empty(); - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null!; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Null dependency"; } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyDefinitionNode.cs index 15afa878645f89..eed8889a334c5a 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyDefinitionNode.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata.Ecma335; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -19,14 +20,13 @@ public AssemblyDefinitionNode(EcmaModule module) { } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; + DependencySink dependencies = sink; AssemblyDefinition asmDef = _module.MetadataReader.GetAssemblyDefinition(); - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, asmDef.GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, asmDef.GetCustomAttributes()); - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyReferenceNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyReferenceNode.cs index 45a3a1ab5d7e2d..6015a282fd363f 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyReferenceNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/AssemblyReferenceNode.cs @@ -52,9 +52,8 @@ public AssemblyReferenceNode(EcmaModule module, EcmaAssembly reference) _reference = reference; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - yield break; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ConstantNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ConstantNode.cs index 9dbe1aa9091d01..0c6766c5b14307 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ConstantNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ConstantNode.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -21,7 +22,7 @@ public ConstantNode(EcmaModule module, ConstantHandle handle) private ConstantHandle Handle => (ConstantHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) { diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/CustomAttributeNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/CustomAttributeNode.cs index 67507a567bae8d..6cdd61b56a2dae 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/CustomAttributeNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/CustomAttributeNode.cs @@ -15,6 +15,7 @@ using Internal.TypeSystem.Ecma; using DependencyNode = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -34,14 +35,13 @@ public CustomAttributeNode(EcmaModule module, CustomAttributeHandle handle) private CustomAttributeHandle Handle => (CustomAttributeHandle)_handle; - public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaModule module, CustomAttributeHandleCollection handles) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, EcmaModule module, CustomAttributeHandleCollection handles) { foreach (CustomAttributeHandle customAttribute in handles) { if (factory.Settings.StripSecurity && IsCustomAttributeForSecurity(module, customAttribute)) continue; - dependencies ??= new DependencyList(); dependencies.Add(factory.CustomAttribute(module, customAttribute), "Custom attribute"); } } @@ -66,9 +66,9 @@ public static bool IsCustomAttributeForSecurity(EcmaModule module, CustomAttribu return false; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; CustomAttribute customAttribute = _module.MetadataReader.GetCustomAttribute(Handle); @@ -86,7 +86,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto { // Metadata decode failed. _isCorrupted = true; - return dependencies; + return; } foreach (CustomAttributeTypedArgument fixedArg in decodedValue.FixedArguments) @@ -97,9 +97,9 @@ public override IEnumerable GetStaticDependencies(NodeFacto // Resolve the constructor once for the generic argument data flow and the named arguments MethodDesc constructor = _module.TryGetMethod(customAttribute.Constructor); if (constructor is null) - return dependencies; + return; - AddGenericArgumentDataFlowDependencies(ref dependencies, factory, customAttribute.Parent, constructor.OwningType); + AddGenericArgumentDataFlowDependencies(dependencies, factory, customAttribute.Parent, constructor.OwningType); foreach (CustomAttributeNamedArgument namedArg in decodedValue.NamedArguments) { @@ -110,11 +110,9 @@ public override IEnumerable GetStaticDependencies(NodeFacto GetDependenciesFromCustomAttributeArgument(dependencies, factory, namedArg.Type, namedArg.Value); } - - return dependencies; } - private void AddGenericArgumentDataFlowDependencies(ref DependencyList dependencies, NodeFactory factory, EntityHandle attributeTarget, TypeDesc attributeType) + private void AddGenericArgumentDataFlowDependencies(DependencySink dependencies, NodeFactory factory, EntityHandle attributeTarget, TypeDesc attributeType) { if (!GenericArgumentDataFlow.RequiresGenericArgumentDataFlow(factory.FlowAnnotations, attributeType)) return; @@ -148,7 +146,7 @@ private void AddGenericArgumentDataFlowDependencies(ref DependencyList dependenc break; } - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, origin, attributeType, typeContext, methodContext); + GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(dependencies, factory, origin, attributeType, typeContext, methodContext); } /// @@ -179,7 +177,7 @@ private TypeSystemEntity GetAttributeTargetGenericContext(EntityHandle attribute } } - private static void GetDependenciesFromCustomAttributeArgument(DependencyList dependencies, NodeFactory factory, TypeDesc type, object value) + private static void GetDependenciesFromCustomAttributeArgument(DependencySink dependencies, NodeFactory factory, TypeDesc type, object value) { // Report the type itself (e.g. enum types that need to be kept for boxing) dependencies.Add(factory.ReflectedType(type), "Custom attribute blob"); @@ -207,7 +205,7 @@ private static void GetDependenciesFromCustomAttributeArgument(DependencyList de } } - private static void GetDependenciesFromPropertySetter(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName) + private static void GetDependenciesFromPropertySetter(DependencySink dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName) { if (attributeType.GetTypeDefinition() is not EcmaType ecmaType) return; @@ -236,7 +234,7 @@ private static void GetDependenciesFromPropertySetter(DependencyList dependencie GetDependenciesFromPropertySetter(dependencies, factory, baseType, propertyName); } - private static void GetDependenciesFromField(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string fieldName) + private static void GetDependenciesFromField(DependencySink dependencies, NodeFactory factory, TypeDesc attributeType, string fieldName) { FieldDesc field = attributeType.GetField(Encoding.UTF8.GetBytes(fieldName)); if (field is not null) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/EventDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/EventDefinitionNode.cs index 3c8d8297f33e9f..e9aa88a3b3f081 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/EventDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/EventDefinitionNode.cs @@ -8,6 +8,7 @@ using System.Reflection.Metadata.Ecma335; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -23,7 +24,7 @@ public EventDefinitionNode(EcmaModule module, EventDefinitionHandle handle) private EventDefinitionHandle Handle => (EventDefinitionHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { MetadataReader reader = _module.MetadataReader; @@ -31,14 +32,14 @@ public override IEnumerable GetStaticDependencies(NodeFacto TypeDefinitionHandle declaringTypeHandle = eventDef.GetDeclaringType(); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(factory.TypeDefinition(_module, declaringTypeHandle), "Event owning type"); if (!eventDef.Type.IsNil) dependencies.Add(factory.GetNodeForTypeToken(_module, eventDef.Type), "Event type"); - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, eventDef.GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, eventDef.GetCustomAttributes()); // Unlike properties, we root ALL accessor methods when an event is kept. // If you can subscribe to an event, you must be able to unsubscribe — keeping @@ -51,8 +52,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (!accessors.Raiser.IsNil) dependencies.Add(factory.MethodDefinition(_module, accessors.Raiser), "Event raiser"); Debug.Assert(accessors.Others.Length == 0); - - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/FieldDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/FieldDefinitionNode.cs index 09dac50e890082..13b1fc7fcd5bf8 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/FieldDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/FieldDefinitionNode.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -21,12 +22,12 @@ public FieldDefinitionNode(EcmaModule module, FieldDefinitionHandle handle) private FieldDefinitionHandle Handle => (FieldDefinitionHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { FieldDefinition fieldDef = _module.MetadataReader.GetFieldDefinition(Handle); TypeDefinitionHandle declaringType = fieldDef.GetDeclaringType(); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; EcmaSignatureAnalyzer.AnalyzeFieldSignature( _module, @@ -41,9 +42,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(factory.Constant(_module, fieldDef.GetDefaultValue()), "Constant in field definition"); } - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, fieldDef.GetCustomAttributes()); - - return dependencies; + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, fieldDef.GetCustomAttributes()); } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterConstraintNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterConstraintNode.cs index b5722f70a252d8..adf62c74c0b5bd 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterConstraintNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterConstraintNode.cs @@ -8,6 +8,7 @@ using Internal.TypeSystem.Ecma; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -26,16 +27,14 @@ public GenericParameterConstraintNode(EcmaModule module, GenericParameterConstra private int _ownerCodedIndex = -1; private int _index = -1; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { GenericParameterConstraint genericParamConstraint = _module.MetadataReader.GetGenericParameterConstraint(Handle); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(factory.GetNodeForTypeToken(_module, genericParamConstraint.Type), "Parameter constrained to type"); - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, genericParamConstraint.GetCustomAttributes()); - - return dependencies; + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, genericParamConstraint.GetCustomAttributes()); } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterNode.cs index 74dcb9d7c262f8..7b9eabf8182a4d 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/GenericParameterNode.cs @@ -7,6 +7,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -25,21 +26,20 @@ public GenericParameterNode(EcmaModule module, GenericParameterHandle handle) private int _ownerCodedIndex = -1; private int _index = -1; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { GenericParameter genericParam = _module.MetadataReader.GetGenericParameter(Handle); - DependencyList dependencies = null; + DependencySink dependencies = sink; foreach (var genericParamConstrain in genericParam.GetConstraints()) { - dependencies ??= new DependencyList(); + dependencies.Add(factory.GenericParameterConstraint(_module, genericParamConstrain), "Generic Parameter Constraint of Generic Parameter"); } - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, genericParam.GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, genericParam.GetCustomAttributes()); - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ManifestResourceNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ManifestResourceNode.cs index 3f55462eea6f3c..5a07fcf3c13225 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ManifestResourceNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ManifestResourceNode.cs @@ -14,6 +14,7 @@ using Internal.TypeSystem.Ecma; using CodeOptimizations = Mono.Linker.CodeOptimizations; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -26,13 +27,13 @@ public class ManifestResourceNode : TokenBasedNode public ManifestResourceNode(EcmaModule module, ManifestResourceHandle handle) : base(module, handle) { } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { ManifestResource resource = _module.MetadataReader.GetManifestResource(Handle); _skipWritingResource = false; - DependencyList dependencies = null; + DependencySink dependencies = sink; if (resource.Implementation.IsNil) { @@ -54,13 +55,15 @@ public override IEnumerable GetStaticDependencies(NodeFacto ms = new UnmanagedMemoryStream(reader.CurrentPointer, length); } - dependencies = DescriptorMarker.GetDependencies(factory.Logger, factory, ms, resource, _module, "resource " + resourceName + " in " + _module.ToString(), factory.Settings.FeatureSettings); + foreach (DependencyListEntry dependency in DescriptorMarker.GetDependencies(factory.Logger, factory, ms, resource, _module, "resource " + resourceName + " in " + _module.ToString(), factory.Settings.FeatureSettings)) + { + dependencies.Add(dependency); + } } } } else { - dependencies = new(); switch (resource.Implementation.Kind) { case HandleKind.AssemblyReference: @@ -73,20 +76,19 @@ public override IEnumerable GetStaticDependencies(NodeFacto } } - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, resource.GetCustomAttributes()); - return dependencies; + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, resource.GetCustomAttributes()); } public override void BuildTokens(TokenMap.Builder builder) { - Debug.Assert(_skipWritingResource.HasValue, "Should have called GetStaticDependencies before writing"); + Debug.Assert(_skipWritingResource.HasValue, "Should have called AddStaticDependencies before writing"); if (!_skipWritingResource.Value) base.BuildTokens(builder); } public override void Write(ModuleWritingContext writeContext) { - Debug.Assert(_skipWritingResource.HasValue, "Should have called GetStaticDependencies before writing"); + Debug.Assert(_skipWritingResource.HasValue, "Should have called AddStaticDependencies before writing"); if (!_skipWritingResource.Value) base.Write(writeContext); } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MemberReferenceNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MemberReferenceNode.cs index 17f71f7166ea62..d895b0b0ff9c3c 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MemberReferenceNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MemberReferenceNode.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -21,12 +22,12 @@ public MemberReferenceNode(EcmaModule module, MemberReferenceHandle handle) private MemberReferenceHandle Handle => (MemberReferenceHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { var methodOrFieldDef = _module.GetObject(Handle); MemberReference memberRef = _module.MetadataReader.GetMemberReference(Handle); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; switch (methodOrFieldDef) { @@ -72,8 +73,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto signatureBlob, factory, dependencies); - - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodDefinitionNode.cs index 4e2c7bf0f43f81..ca70f7367aa50b 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodDefinitionNode.cs @@ -12,6 +12,7 @@ using Internal.TypeSystem.Ecma; using Mono.Linker; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -39,13 +40,13 @@ public bool IsInstanceMethodOnReferenceType } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { MetadataReader reader = _module.MetadataReader; MethodDefinition methodDef = reader.GetMethodDefinition(Handle); TypeDefinitionHandle declaringType = methodDef.GetDeclaringType(); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; EcmaSignatureAnalyzer.AnalyzeMethodSignature( _module, @@ -61,7 +62,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(factory.MethodBody(_module, Handle), "Method body"); } - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, methodDef.GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, methodDef.GetCustomAttributes()); foreach (ParameterHandle parameter in methodDef.GetParameters()) { @@ -87,7 +88,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto AddInteropAllocatedType(factory, dependencies, ecmaByRefParam); } - static void AddInteropAllocatedType(NodeFactory factory, DependencyList dependencies, EcmaType type) + static void AddInteropAllocatedType(NodeFactory factory, DependencySink dependencies, EcmaType type) { dependencies.Add(factory.ConstructedType(type), "Interop-allocated instance"); if (type.GetParameterlessConstructor() is EcmaMethod ctorMethod && factory.IsModuleTrimmed(ctorMethod.Module)) @@ -144,24 +145,22 @@ static void AddInteropAllocatedType(NodeFactory factory, DependencyList dependen dependencies.Add(factory.MethodDefinition(_module, pairMethod.Handle), "Delegate BeginInvoke/EndInvoke pair"); } } - - return dependencies; } // Instance methods on reference types conditionally depend on their bodies. public override bool HasConditionalStaticDependencies => IsInstanceMethodOnReferenceType; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { MethodDefinition methodDef = _module.MetadataReader.GetMethodDefinition(Handle); TypeDefinitionHandle declaringType = methodDef.GetDeclaringType(); var ecmaType = (EcmaType)_module.GetObject(declaringType); // Conditionally depend on the method body if the declaring type was constructed. - yield return new( + sink.Add(new CombinedDependencyListEntry( factory.MethodBody(_module, Handle), factory.ConstructedType(ecmaType), - "Method body on constructed type"); + "Method body on constructed type")); } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodImplementationNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodImplementationNode.cs index de63b510a1bd5c..14ee60f7138f91 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodImplementationNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodImplementationNode.cs @@ -5,6 +5,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -20,12 +21,12 @@ public MethodImplementationNode(EcmaModule module, MethodImplementationHandle ha private MethodImplementationHandle Handle => (MethodImplementationHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { var methodImpl = _module.MetadataReader.GetMethodImplementation(Handle); - yield return new(factory.GetNodeForMethodToken(_module, methodImpl.MethodBody), "MethodImpl body"); - yield return new(factory.GetNodeForMethodToken(_module, methodImpl.MethodDeclaration), "MethodImpl decl"); - yield return new(factory.GetNodeForTypeToken(_module, methodImpl.Type), "MethodImpl type"); + sink.Add(new DependencyListEntry(factory.GetNodeForMethodToken(_module, methodImpl.MethodBody), "MethodImpl body")); + sink.Add(new DependencyListEntry(factory.GetNodeForMethodToken(_module, methodImpl.MethodDeclaration), "MethodImpl decl")); + sink.Add(new DependencyListEntry(factory.GetNodeForTypeToken(_module, methodImpl.Type), "MethodImpl type")); } public override string ToString() diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodSpecificationNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodSpecificationNode.cs index 220609286fa211..75908f26699ca6 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodSpecificationNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/MethodSpecificationNode.cs @@ -5,6 +5,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -20,21 +21,19 @@ public MethodSpecificationNode(EcmaModule module, MethodSpecificationHandle hand private MethodSpecificationHandle Handle => (MethodSpecificationHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { MethodSpecification methodSpec = _module.MetadataReader.GetMethodSpecification(Handle); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; EcmaSignatureAnalyzer.AnalyzeMethodSpecSignature( _module, _module.MetadataReader.GetBlobReader(methodSpec.Signature), factory, dependencies); - + dependencies.Add(factory.GetNodeForMethodToken(_module, methodSpec.Method), "Instantiated method"); - - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleDefinitionNode.cs index ef0987eb366b7a..619ec414430c31 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleDefinitionNode.cs @@ -7,6 +7,7 @@ using Internal.TypeSystem.Ecma; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -24,23 +25,21 @@ public ModuleDefinitionNode(EcmaModule module) { } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; if (_module.MetadataReader.IsAssembly) dependencies.Add(factory.AssemblyDefinition(_module), "Assembly definition of the module"); dependencies.Add(factory.TypeDefinition(_module, GlobalModuleTypeHandle), "Global module type"); - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, _module.MetadataReader.GetModuleDefinition().GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, _module.MetadataReader.GetModuleDefinition().GetCustomAttributes()); foreach (var resourceHandle in _module.MetadataReader.ManifestResources) { dependencies.Add(factory.ManifestResource(_module, resourceHandle), "Manifest resource of a module"); } - - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleReferenceNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleReferenceNode.cs index e6e72dfb150c8f..46523e14d4e013 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleReferenceNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ModuleReferenceNode.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -21,9 +22,8 @@ public ModuleReferenceNode(EcmaModule module, ModuleReferenceHandle handle) private ModuleReferenceHandle Handle => (ModuleReferenceHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - return null; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ParameterNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ParameterNode.cs index 915e88954a167c..046a9616209173 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ParameterNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/ParameterNode.cs @@ -5,6 +5,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -20,14 +21,13 @@ public ParameterNode(EcmaModule module, ParameterHandle handle) private ParameterHandle Handle => (ParameterHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyList dependencies = null; + DependencySink dependencies = sink; Parameter parameter = _module.MetadataReader.GetParameter(Handle); - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, context, _module, parameter.GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, context, _module, parameter.GetCustomAttributes()); - return dependencies; } public override string ToString() diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/PropertyDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/PropertyDefinitionNode.cs index 25facbd59d63f6..9fcb3fa0dfd1a9 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/PropertyDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/PropertyDefinitionNode.cs @@ -7,6 +7,7 @@ using System.Reflection.Metadata.Ecma335; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -22,7 +23,7 @@ public PropertyDefinitionNode(EcmaModule module, PropertyDefinitionHandle handle private PropertyDefinitionHandle Handle => (PropertyDefinitionHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { MetadataReader reader = _module.MetadataReader; @@ -30,7 +31,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto TypeDefinitionHandle declaringTypeHandle = property.GetDeclaringType(); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; // We intentionally do NOT root accessor methods here. The accessor methods are kept // independently when they are called. The property definition is pulled in by the @@ -43,10 +44,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies); dependencies.Add(factory.TypeDefinition(_module, declaringTypeHandle), "Property owning type"); - - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, property.GetCustomAttributes()); - - return dependencies; + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, property.GetCustomAttributes()); } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/StandaloneSignatureNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/StandaloneSignatureNode.cs index 325bc3eb871a7a..77584bb79589fc 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/StandaloneSignatureNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/StandaloneSignatureNode.cs @@ -5,6 +5,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -20,7 +21,7 @@ public StandaloneSignatureNode(EcmaModule module, StandaloneSignatureHandle hand private StandaloneSignatureHandle Handle => (StandaloneSignatureHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { MetadataReader reader = _module.MetadataReader; @@ -28,11 +29,11 @@ public override IEnumerable GetStaticDependencies(NodeFacto BlobReader signatureReader = reader.GetBlobReader(standaloneSig.Signature); - return EcmaSignatureAnalyzer.AnalyzeStandaloneSignatureBlob( + EcmaSignatureAnalyzer.AnalyzeStandaloneSignatureBlob( _module, signatureReader, - factory - ); + factory, + sink); } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeDefinitionNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeDefinitionNode.cs index 081d10ba87bd76..222b7ee805b60f 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeDefinitionNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeDefinitionNode.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -21,9 +22,9 @@ public TypeDefinitionNode(EcmaModule module, TypeDefinitionHandle handle) private TypeDefinitionHandle Handle => (TypeDefinitionHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(factory.ModuleDefinition(_module), "Owning module"); @@ -38,7 +39,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(factory.GenericParameter(_module, parameter), "Generic parameter of type"); } - CustomAttributeNode.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _module, typeDef.GetCustomAttributes()); + CustomAttributeNode.AddDependenciesDueToCustomAttributes(dependencies, factory, _module, typeDef.GetCustomAttributes()); if (typeDef.IsNested) { @@ -90,8 +91,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto // for now (it's on par with IL Linker). dependencies.Add(factory.ConstructedType(ecmaType), "Implicitly constructed valuetype"); } - - return dependencies; } public override bool HasConditionalStaticDependencies @@ -102,7 +101,7 @@ public override bool HasConditionalStaticDependencies } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { MetadataReader reader = _module.MetadataReader; TypeDefinition typeDef = reader.GetTypeDefinition(Handle); @@ -113,10 +112,10 @@ public override IEnumerable GetConditionalStaticDep EcmaType interfaceType = _module.TryGetType(intfImpl.Interface)?.GetTypeDefinition() as EcmaType; if (interfaceType != null) { - yield return new( + sink.Add(new CombinedDependencyListEntry( factory.GetNodeForTypeToken(_module, intfImpl.Interface), factory.InterfaceUse(interfaceType), - "Implemented interface"); + "Implemented interface")); } } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeReferenceNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeReferenceNode.cs index 1f217b9989205f..f7912388bda2c9 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeReferenceNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeReferenceNode.cs @@ -9,6 +9,7 @@ using Internal.TypeSystem.Ecma; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -46,14 +47,14 @@ TokenWriterNode GetResolutionScopeNode(NodeFactory factory) } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - yield return new(GetResolutionScopeNode(factory), "Resolution Scope of a type reference"); + sink.Add(new DependencyListEntry(GetResolutionScopeNode(factory), "Resolution Scope of a type reference")); var typeDescObject = _module.GetObject(Handle); if (typeDescObject is EcmaType typeDef && factory.IsModuleTrimmed(typeDef.Module)) { - yield return new(factory.TypeDefinition(typeDef.Module, typeDef.Handle), "Target of a type reference"); + sink.Add(new DependencyListEntry(factory.TypeDefinition(typeDef.Module, typeDef.Handle), "Target of a type reference")); } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeSpecificationNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeSpecificationNode.cs index 97df8d8cff1bf2..03c5181d538fa1 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeSpecificationNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenBased/TypeSpecificationNode.cs @@ -5,6 +5,7 @@ using System.Reflection.Metadata; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -20,19 +21,17 @@ public TypeSpecificationNode(EcmaModule module, TypeSpecificationHandle handle) private TypeSpecificationHandle Handle => (TypeSpecificationHandle)_handle; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { TypeSpecification typeSpec = _module.MetadataReader.GetTypeSpecification(Handle); - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; EcmaSignatureAnalyzer.AnalyzeTypeSpecSignature( _module, _module.MetadataReader.GetBlobReader(typeSpec.Signature), factory, dependencies); - - return dependencies; } protected override EntityHandle WriteInternal(ModuleWritingContext writeContext) diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenWriterNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenWriterNode.cs index a665d9fdeb1ac3..b74396ac7fc247 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenWriterNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/TokenWriterNode.cs @@ -64,7 +64,7 @@ protected int CompareToHelper(TokenWriterNode other) public sealed override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; public sealed override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; - public sealed override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public sealed override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/VirtualMethodUseNode.cs b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/VirtualMethodUseNode.cs index 80b1c7af95febe..8427ab896b94e7 100644 --- a/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/VirtualMethodUseNode.cs +++ b/src/coreclr/tools/ILTrim.Core/DependencyAnalysis/VirtualMethodUseNode.cs @@ -36,18 +36,18 @@ protected override string GetName(NodeFactory factory) return $"VirtualMethodUse: {_decl}"; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { TypeDesc owningType = _decl.OwningType; if (owningType.IsInterface) - yield return new (factory.InterfaceUse((EcmaType)owningType), "Interface used in a call"); + sink.Add(new DependencyListEntry(factory.InterfaceUse((EcmaType)owningType), "Interface used in a call")); } 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/ILTrim.Core/RootingHelpers.cs b/src/coreclr/tools/ILTrim.Core/RootingHelpers.cs index 9fab6a48879822..205295dd79ceb4 100644 --- a/src/coreclr/tools/ILTrim.Core/RootingHelpers.cs +++ b/src/coreclr/tools/ILTrim.Core/RootingHelpers.cs @@ -5,6 +5,7 @@ using Internal.TypeSystem; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; #nullable enable @@ -14,26 +15,51 @@ namespace ILCompiler // that a type/method/field was accessed via reflection. public static class RootingHelpers { - public static bool TryGetDependenciesForReflectedType( - ref DependencyList dependencies, NodeFactory factory, TypeDesc type, string reason) + public static bool TryAddDependenciesForReflectedType( + IDependencySink dependencies, + NodeFactory factory, + TypeDesc type, + string reason) { - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedType(type), reason); return true; } - public static bool TryGetDependenciesForReflectedMethod( - ref DependencyList dependencies, NodeFactory factory, MethodDesc method, string reason) + public static bool TryAddDependenciesForReflectedType( + DependencySink dependencies, + NodeFactory factory, + TypeDesc type, + string reason, + DependencyNodeCore otherReasonNode) + { + dependencies.AddConditional(factory.ReflectedType(type), otherReasonNode, reason); + return true; + } + + public static bool TryAddDependenciesForReflectedMethod( + IDependencySink dependencies, + NodeFactory factory, + MethodDesc method, + string reason) { - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedMethod(method), reason); return true; } - public static bool TryGetDependenciesForReflectedField( - ref DependencyList dependencies, NodeFactory factory, FieldDesc field, string reason) + public static bool TryAddDependenciesForReflectedMethod( + DependencySink dependencies, + NodeFactory factory, + MethodDesc method, + string reason, + DependencyNodeCore otherReasonNode) + { + dependencies.AddConditional(factory.ReflectedMethod(method), otherReasonNode, reason); + return true; + } + + public static bool TryAddDependenciesForReflectedField( + IDependencySink dependencies, NodeFactory factory, FieldDesc field, string reason) { - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedField(field), reason); return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/DependencyGraphTests.cs b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/DependencyGraphTests.cs index 6295e9341f6bf3..5059b051d7f06a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/DependencyGraphTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/DependencyGraphTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text; using ILCompiler.Dataflow; +using ILCompiler.DependencyAnalysisFramework; using Internal.IL; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; @@ -126,6 +127,80 @@ public void TestDependencyGraphInvariants(EcmaMethod method) Assert.True(foundSomethingToCheck, "No invariants to check?"); } + [Fact] + public void DependencyAnalyzerComputesDeferredStaticDependenciesBeforeDynamicDependencies() + { + var deferredNode = new DeferredTestDependencyNode(); + var rootNode = new TestDependencyNode(deferredNode); + var analyzer = new DependencyAnalyzer, string>( + "context", + Comparer>.Create((left, right) => string.CompareOrdinal(left.ToString(), right.ToString()))); + analyzer.ComputeDependencyRoutine += nodes => + { + Assert.Same(deferredNode, Assert.Single(nodes)); + deferredNode.SetDependenciesComputed(); + }; + + analyzer.AddRoot(rootNode, "root"); + analyzer.ComputeMarkedNodes(); + + Assert.True(deferredNode.DynamicDependenciesQueried); + } + + private sealed class TestDependencyNode : DependencyNodeCore + { + private readonly DependencyNodeCore _dependency; + + public TestDependencyNode(DependencyNodeCore dependency) + { + _dependency = dependency; + } + + public override bool InterestingForDynamicDependencyAnalysis => false; + public override bool HasDynamicDependencies => false; + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => true; + + public override void AddStaticDependencies(DependencySink sink, string context) + { + sink.Add(_dependency, "static"); + } + + protected override string GetName(string context) => nameof(TestDependencyNode); + } + + private sealed class DeferredTestDependencyNode : DependencyNodeCore + { + private bool _dependenciesComputed; + + public bool DynamicDependenciesQueried { get; private set; } + public override bool InterestingForDynamicDependencyAnalysis => false; + + public override bool HasDynamicDependencies + { + get + { + Assert.True(_dependenciesComputed); + DynamicDependenciesQueried = true; + return false; + } + } + + public override bool HasConditionalStaticDependencies => false; + public override bool StaticDependenciesAreComputed => _dependenciesComputed; + + public void SetDependenciesComputed() + { + _dependenciesComputed = true; + } + + public override void AddStaticDependencies(DependencySink sink, string context) + { + } + + protected override string GetName(string context) => nameof(DeferredTestDependencyNode); + } + private static MethodDesc GetMethodFromAttribute(CustomAttributeValue attr) { if (attr.NamedArguments.Length > 0) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedInteropStubManager.cs index 0d293259be8e90..b1f94ba20705e7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/AnalysisBasedInteropStubManager.cs @@ -9,6 +9,7 @@ using ILCompiler.DependencyAnalysis; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler { @@ -40,15 +41,15 @@ public override void AddCompilationRoots(IRootingServiceProvider rootProvider) } } - public override void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddDependenciesDueToMethodCodePresence(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { } - public override void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public override void AddInterestingInteropConstructedTypeDependencies(DependencySink dependencies, NodeFactory factory, TypeDesc type) { } - public override void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddMarshalAPIsGenericDependencies(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs index 762f264deb5f07..7e37a0010fe939 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs @@ -12,7 +12,9 @@ using Internal.TypeSystem; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; using MultiValue = ILLink.Shared.DataFlow.ValueSet; +using ILCompiler.DependencyAnalysisFramework; #nullable enable @@ -21,7 +23,7 @@ namespace ILCompiler.Dataflow internal static class GenericArgumentDataFlow { public static void ProcessGenericArgumentDataFlow( - ref DependencyList dependencies, + IDependencySink dependencies, NodeFactory factory, in MessageOrigin origin, TypeDesc type, @@ -30,7 +32,7 @@ public static void ProcessGenericArgumentDataFlow( bool suppressAotAnalysisWarnings = false) { ProcessGenericArgumentDataFlow( - ref dependencies, + dependencies, factory, origin, type, @@ -40,13 +42,13 @@ public static void ProcessGenericArgumentDataFlow( suppressAotAnalysisWarnings); } - public static void ProcessGenericArgumentDataFlow(ref DependencyList dependencies, NodeFactory factory, in MessageOrigin origin, TypeDesc type, MethodDesc contextMethod) + public static void ProcessGenericArgumentDataFlow(IDependencySink dependencies, NodeFactory factory, in MessageOrigin origin, TypeDesc type, MethodDesc contextMethod) { - ProcessGenericArgumentDataFlow(ref dependencies, factory, origin, type, contextMethod.OwningType.Instantiation, contextMethod.Instantiation); + ProcessGenericArgumentDataFlow(dependencies, factory, origin, type, contextMethod.OwningType.Instantiation, contextMethod.Instantiation); } public static void ProcessGenericArgumentDataFlow( - ref DependencyList dependencies, + IDependencySink dependencies, NodeFactory factory, in MessageOrigin origin, TypeDesc type, @@ -88,10 +90,10 @@ public static void ProcessGenericArgumentDataFlow( if (reflectionMarker.Dependencies.Count > 0) { - if (dependencies == null) - dependencies = reflectionMarker.Dependencies; - else - dependencies.AddRange(reflectionMarker.Dependencies); + foreach (DependencyListEntry dependency in reflectionMarker.Dependencies) + { + dependencies.Add(dependency); + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs index 0082f24bd39db0..355956bc7f7a5d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs @@ -818,13 +818,26 @@ private sealed class MakeGenericMethodSite : INodeWithRuntimeDeterminedDependenc public MakeGenericMethodSite(MethodDesc method) => _method = method; - public IEnumerable.DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, bool isConcreteInstantiation) + public void AddDependencies( + DependencySink sink, + NodeFactory factory, + Instantiation typeInstantiation, + Instantiation methodInstantiation, + bool isConcreteInstantiation, + DependencyNodeCore? otherReasonNode) { - var list = new DependencyList(); MethodDesc instantiatedMethod = _method.InstantiateSignature(typeInstantiation, methodInstantiation); if (instantiatedMethod.CheckConstraints(new InstantiationContext(typeInstantiation, methodInstantiation))) - RootingHelpers.TryGetDependenciesForReflectedMethod(ref list, factory, instantiatedMethod, "MakeGenericMethod"); - return list; + { + if (otherReasonNode is null) + { + RootingHelpers.TryAddDependenciesForReflectedMethod(sink, factory, instantiatedMethod, "MakeGenericMethod"); + } + else + { + RootingHelpers.TryAddDependenciesForReflectedMethod(sink, factory, instantiatedMethod, "MakeGenericMethod", otherReasonNode); + } + } } } @@ -834,17 +847,30 @@ private sealed class MakeGenericTypeSite : INodeWithRuntimeDeterminedDependencie public MakeGenericTypeSite(TypeDesc type) => _type = type; - public IEnumerable.DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, bool isConcreteInstantiation) + public void AddDependencies( + DependencySink sink, + NodeFactory factory, + Instantiation typeInstantiation, + Instantiation methodInstantiation, + bool isConcreteInstantiation, + DependencyNodeCore? otherReasonNode) { - var list = new DependencyList(); TypeDesc instantiatedType = _type.InstantiateSignature(typeInstantiation, methodInstantiation); // InstantiateSignature could end up with a denormalized shape (Foo) so normalize. instantiatedType = instantiatedType.NormalizeInstantiation(); if (instantiatedType.CheckConstraints(new InstantiationContext(typeInstantiation, methodInstantiation))) - RootingHelpers.TryGetDependenciesForReflectedType(ref list, factory, instantiatedType, "MakeGenericType"); - return list; + { + if (otherReasonNode is null) + { + RootingHelpers.TryAddDependenciesForReflectedType(sink, factory, instantiatedType, "MakeGenericType"); + } + else + { + RootingHelpers.TryAddDependenciesForReflectedType(sink, factory, instantiatedType, "MakeGenericType", otherReasonNode); + } + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs index bad6655f6747a1..78b982a0500f25 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs @@ -14,6 +14,7 @@ using Internal.TypeSystem; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; #nullable enable #pragma warning disable IDE0060 @@ -22,7 +23,8 @@ namespace ILCompiler.Dataflow { public class ReflectionMarker { - private DependencyList _dependencies = new DependencyList(); + private readonly IDependencySink _dependencies; + private readonly DependencyList? _dependencyList; private readonly Logger _logger; private readonly MetadataType? _typeHierarchyDataFlowOrigin; private readonly bool _enabled; @@ -31,7 +33,14 @@ public class ReflectionMarker public NodeFactory Factory { get; } public FlowAnnotations Annotations { get; } - public DependencyList Dependencies { get => _dependencies; } + public DependencyList Dependencies + { + get + { + Debug.Assert(_dependencyList is not null); + return _dependencyList; + } + } public List<(MethodDesc OwningMethod, INodeWithRuntimeDeterminedDependencies Dependency)> RuntimeDeterminedDependencies { get; } = new List<(MethodDesc, INodeWithRuntimeDeterminedDependencies)>(); internal enum AccessKind @@ -48,7 +57,8 @@ public ReflectionMarker( MetadataType? typeHierarchyDataFlowOrigin, bool enabled, bool suppressTrimAnalysisWarnings = false, - bool suppressAotAnalysisWarnings = false) + bool suppressAotAnalysisWarnings = false, + IDependencySink? dependencySink = null) { _logger = logger; Factory = factory; @@ -57,6 +67,15 @@ public ReflectionMarker( _enabled = enabled; _suppressTrimAnalysisWarnings = suppressTrimAnalysisWarnings; _suppressAotAnalysisWarnings = suppressAotAnalysisWarnings; + if (dependencySink is null) + { + _dependencyList = new DependencyList(); + _dependencies = _dependencyList; + } + else + { + _dependencies = dependencySink; + } } internal void MarkTypeForDynamicallyAccessedMembers(in MessageOrigin origin, TypeDesc typeDefinition, DynamicallyAccessedMemberTypes requiredMemberTypes, TypeSystemEntity reason, bool declaredOnly = false) @@ -175,7 +194,7 @@ internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason, Ac if (!_enabled) return; - RootingHelpers.TryGetDependenciesForReflectedType(ref _dependencies, Factory, type, reason); + RootingHelpers.TryAddDependenciesForReflectedType(_dependencies, Factory, type, reason); } internal void MarkMethod(in MessageOrigin origin, MethodDesc method, TypeSystemEntity reason, AccessKind accessKind = AccessKind.Unspecified) @@ -193,7 +212,7 @@ internal void MarkMethod(in MessageOrigin origin, MethodDesc method, string reas CheckAndWarnOnReflectionAccess(origin, method, accessKind); - RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, Factory, method, reason); + RootingHelpers.TryAddDependenciesForReflectedMethod(_dependencies, Factory, method, reason); } internal void MarkField(in MessageOrigin origin, FieldDesc field, string reason, AccessKind accessKind = AccessKind.Unspecified) @@ -203,7 +222,7 @@ internal void MarkField(in MessageOrigin origin, FieldDesc field, string reason, CheckAndWarnOnReflectionAccess(origin, field, accessKind); - RootingHelpers.TryGetDependenciesForReflectedField(ref _dependencies, Factory, field, reason); + RootingHelpers.TryAddDependenciesForReflectedField(_dependencies, Factory, field, reason); } internal void MarkProperty(in MessageOrigin origin, PropertyPseudoDesc property, TypeSystemEntity reason, AccessKind accessKind = AccessKind.Unspecified) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index c9a3cd14f19770..e91ec5b5323ca8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -138,7 +138,7 @@ public static DependencyList ScanAndProcessReturnValue(NodeFactory factory, Flow return scanner._reflectionMarker.Dependencies; } - public static DependencyList ProcessTypeGetTypeDataflow(NodeFactory factory, FlowAnnotations flowAnnotations, Logger logger, MetadataType type) + public static void AddTypeGetTypeDataflowDependencies(DependencySink dependencies, NodeFactory factory, FlowAnnotations flowAnnotations, Logger logger, MetadataType type) { DynamicallyAccessedMemberTypes annotation = flowAnnotations.GetTypeAnnotation(type); Debug.Assert(annotation != DynamicallyAccessedMemberTypes.None); @@ -157,11 +157,11 @@ public static DependencyList ProcessTypeGetTypeDataflow(NodeFactory factory, Flo // If we're left with nothing, we're done if (annotation == DynamicallyAccessedMemberTypes.None) - return new DependencyList(); + return; } } - var reflectionMarker = new ReflectionMarker(logger, factory, flowAnnotations, typeHierarchyDataFlowOrigin: type, enabled: true); + var reflectionMarker = new ReflectionMarker(logger, factory, flowAnnotations, typeHierarchyDataFlowOrigin: type, enabled: true, dependencySink: dependencies); // We need to apply annotations to this type, and its base/interface types (recursively) // But the annotations on base/interfaces may already be applied so we don't need to apply those @@ -198,7 +198,6 @@ public static DependencyList ProcessTypeGetTypeDataflow(NodeFactory factory, Flo // warnings on the respective base/interface members, since those are already covered by applying // the annotations to those types. So we only need to handle the members directly declared on this type. reflectionMarker.MarkTypeForDynamicallyAccessedMembers(new MessageOrigin(type), type, annotation, type, declaredOnly: true); - return reflectionMarker.Dependencies; } protected override void WarnAboutInvalidILInMethod(MethodIL method, int ilOffset) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AddressTakenMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AddressTakenMethodNode.cs index a67a3a95bb24e3..abdc90f65382f5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AddressTakenMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AddressTakenMethodNode.cs @@ -43,8 +43,8 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return factory.ObjectInterner.GetDeduplicatedSymbol(factory, RealBody) == RealBody; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalysisCharacteristicNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalysisCharacteristicNode.cs index 1d667fd833d72c..c9ad400b93c0fb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalysisCharacteristicNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalysisCharacteristicNode.cs @@ -18,9 +18,9 @@ public AnalysisCharacteristicNode(string characteristic) 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 GetStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Analysis characteristic: {Characteristic}"; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedExternalTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedExternalTypeMapNode.cs index 531d6a9713d893..c0d29032b0cd35 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedExternalTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedExternalTypeMapNode.cs @@ -32,15 +32,15 @@ public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section se return section.Place(tuple); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { foreach (TypeDesc targetType in entries.Values) { - yield return new DependencyListEntry(context.MetadataTypeSymbol(targetType), "Analyzed external type map entry target type"); + sink.Add(context.MetadataTypeSymbol(targetType), "Analyzed external type map entry target type"); } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Analyzed External Type Map: {TypeMapGroup}"; public IExternalTypeMapNode ToAnalysisBasedNode(NodeFactory factory) => this; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedProxyTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedProxyTypeMapNode.cs index 77d4c629d0b032..5b27fe51187ec6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedProxyTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedProxyTypeMapNode.cs @@ -32,16 +32,16 @@ public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section se return section.Place(tuple); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { foreach (var (sourceType, proxyType) in entries) { - yield return new DependencyListEntry(context.MaximallyConstructableType(sourceType), "Analyzed proxy type map entry source type"); - yield return new DependencyListEntry(context.MetadataTypeSymbol(proxyType), "Analyzed proxy type map entry proxy type"); + sink.Add(context.MaximallyConstructableType(sourceType), "Analyzed proxy type map entry source type"); + sink.Add(context.MetadataTypeSymbol(proxyType), "Analyzed proxy type map entry proxy type"); } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Analyzed Proxy Type Map: {typeMapGroup}"; public IProxyTypeMapNode ToAnalysisBasedNode(NodeFactory factory) => this; public override bool InterestingForDynamicDependencyAnalysis => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs index e8f08aa357f2b5..6669f5f71d62c0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Internal.Text; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -85,13 +86,11 @@ protected override void OnMarked(NodeFactory factory) _parentNode.AddEmbeddedObject(this); } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - return new[] - { + sink.AddRange( new DependencyListEntry(Target, "reloc"), - new DependencyListEntry(_parentNode, "Pointer region") - }; + new DependencyListEntry(_parentNode, "Pointer region")); } public override int ClassCode => -66002498; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs index 65b1da0cf31df1..e9d4cb7d214d90 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs @@ -5,6 +5,7 @@ using Internal.TypeSystem; using Internal.Runtime; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -18,7 +19,7 @@ public CanonicalDefinitionEETypeNode(NodeFactory factory, TypeDesc type) : base( public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => false; public override bool StaticDependenciesAreComputed => true; public override bool IsShareable => true; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) => null; + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { } protected override int GCDescSize => 0; // Canonical definition types will have their base size set to the minimum diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs index ea42f9e654c3e1..2f47e8ab8ecb54 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CodeBasedDependencyAlgorithm.cs @@ -7,21 +7,22 @@ using Internal.TypeSystem; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { public static class CodeBasedDependencyAlgorithm { - public static void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) + public static void AddDependenciesDueToMethodCodePresence(IDependencySink dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) { - factory.MetadataManager.GetDependenciesDueToMethodCodePresence(ref dependencies, factory, method, methodIL); + factory.MetadataManager.GetDependenciesDueToMethodCodePresence(dependencies, factory, method, methodIL); - factory.InteropStubManager.AddDependenciesDueToMethodCodePresence(ref dependencies, factory, method); + factory.InteropStubManager.AddDependenciesDueToMethodCodePresence(dependencies, factory, method); if (method.OwningType is MetadataType mdType) - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module); + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(dependencies, factory, mdType.Module); if (method.IsIntrinsic) { @@ -53,7 +54,6 @@ public static void AddDependenciesDueToMethodCodePresence(ref DependencyList dep if (templateDependencies != null) { - dependencies ??= new DependencyList(); foreach (TypeDesc templateType in templateDependencies) { dependencies.Add(factory.NativeLayout.TemplateTypeLayout(templateType), "Generic comparer"); @@ -72,9 +72,9 @@ public static bool HasConditionalDependenciesDueToMethodCodePresence(MethodDesc return method.HasInstantiation || method.OwningType.HasInstantiation; } - public static void AddConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void AddConditionalDependenciesDueToMethodCodePresence(IConditionalDependencySink dependencies, NodeFactory factory, MethodDesc method) { - factory.MetadataManager.GetConditionalDependenciesDueToMethodCodePresence(ref dependencies, factory, method); + factory.MetadataManager.GetConditionalDependenciesDueToMethodCodePresence(dependencies, factory, method); } } } 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 a73ef4a1fbefc9..32e550dd5b5dd5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -5,6 +5,7 @@ using Internal.Runtime; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -24,9 +25,10 @@ public ConstructedEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, protected override bool IsReflectionVisible => true; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory); + DependencySink dependencyList = sink; + base.ComputeNonRelocationBasedDependencies(sink, factory); if (_type.IsIDynamicInterfaceCastable) { @@ -59,10 +61,8 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact if (!_type.IsCanonicalSubtype(CanonicalFormKind.Any)) { - factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type); + factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(dependencyList, factory, _type); } - - return dependencyList; } protected override ISymbolNode GetBaseTypeNode(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs index 7fd15f692c993a..755bb05309b5f6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs @@ -11,8 +11,9 @@ using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; using CombinedDependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyListEntry; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -28,21 +29,21 @@ private static IMethodNode GetMetadataApiDependency(NodeFactory factory, ReadOnl private static IMethodNode GetMetadataApiDependency(NodeFactory factory, ReadOnlySpan entityName) => GetMetadataApiDependency(factory, entityName, "get_CustomAttributes"u8); - public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EcmaMethod method) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, EcmaMethod method) { MetadataReader reader = method.MetadataReader; MethodDefinitionHandle methodHandle = method.Handle; MethodDefinition methodDef = reader.GetMethodDefinition(methodHandle); // Handle custom attributes on the method - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Method"u8), factory, method.Module, methodDef.GetCustomAttributes(), method); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "Method"u8), factory, method.Module, methodDef.GetCustomAttributes(), method); // Handle custom attributes on method parameters object parameterCondition = GetMetadataApiDependency(factory, "Parameter"u8); foreach (ParameterHandle parameterHandle in methodDef.GetParameters()) { Parameter parameter = reader.GetParameter(parameterHandle); - AddDependenciesDueToCustomAttributes(ref dependencies, parameterCondition, factory, method.Module, parameter.GetCustomAttributes(), method); + AddDependenciesDueToCustomAttributes(dependencies, parameterCondition, factory, method.Module, parameter.GetCustomAttributes(), method); } // Handle custom attributes on generic method parameters @@ -50,53 +51,53 @@ public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyLi foreach (GenericParameterHandle genericParameterHandle in methodDef.GetGenericParameters()) { GenericParameter parameter = reader.GetGenericParameter(genericParameterHandle); - AddDependenciesDueToCustomAttributes(ref dependencies, genericParameterCondition, factory, method.Module, parameter.GetCustomAttributes(), method); + AddDependenciesDueToCustomAttributes(dependencies, genericParameterCondition, factory, method.Module, parameter.GetCustomAttributes(), method); } } - public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EcmaType type) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, EcmaType type) { MetadataReader reader = type.MetadataReader; TypeDefinition typeDef = reader.GetTypeDefinition(type.Handle); - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "TypeDefinition"u8), factory, type.Module, typeDef.GetCustomAttributes(), type); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "TypeDefinition"u8), factory, type.Module, typeDef.GetCustomAttributes(), type); // Handle custom attributes on generic type parameters object genericParameterCondition = GetMetadataApiDependency(factory, "GenericParameter"u8); foreach (GenericParameterHandle genericParameterHandle in typeDef.GetGenericParameters()) { GenericParameter parameter = reader.GetGenericParameter(genericParameterHandle); - AddDependenciesDueToCustomAttributes(ref dependencies, genericParameterCondition, factory, type.Module, parameter.GetCustomAttributes(), type); + AddDependenciesDueToCustomAttributes(dependencies, genericParameterCondition, factory, type.Module, parameter.GetCustomAttributes(), type); } } - public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EcmaField field) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, EcmaField field) { FieldDefinition fieldDef = field.MetadataReader.GetFieldDefinition(field.Handle); - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Field"u8), factory, field.Module, fieldDef.GetCustomAttributes(), field); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "Field"u8), factory, field.Module, fieldDef.GetCustomAttributes(), field); } - public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, PropertyPseudoDesc property) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, PropertyPseudoDesc property) { - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Property"u8), factory, property.OwningType.Module, property.GetCustomAttributes, property); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "Property"u8), factory, property.OwningType.Module, property.GetCustomAttributes, property); } - public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EventPseudoDesc @event) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, EventPseudoDesc @event) { - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "Event"u8), factory, @event.OwningType.Module, @event.GetCustomAttributes, @event); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "Event"u8), factory, @event.OwningType.Module, @event.GetCustomAttributes, @event); } - public static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, NodeFactory factory, EcmaAssembly assembly) + public static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, NodeFactory factory, EcmaAssembly assembly) { AssemblyDefinition asmDef = assembly.MetadataReader.GetAssemblyDefinition(); - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "ScopeDefinition"u8), factory, assembly, asmDef.GetCustomAttributes(), assembly); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "ScopeDefinition"u8), factory, assembly, asmDef.GetCustomAttributes(), assembly); ModuleDefinition moduleDef = assembly.MetadataReader.GetModuleDefinition(); - AddDependenciesDueToCustomAttributes(ref dependencies, GetMetadataApiDependency(factory, "ScopeDefinition"u8, "get_ModuleCustomAttributes"u8), factory, assembly, moduleDef.GetCustomAttributes(), assembly); + AddDependenciesDueToCustomAttributes(dependencies, GetMetadataApiDependency(factory, "ScopeDefinition"u8, "get_ModuleCustomAttributes"u8), factory, assembly, moduleDef.GetCustomAttributes(), assembly); } - private static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyList dependencies, object condition, NodeFactory factory, EcmaModule module, CustomAttributeHandleCollection attributeHandles, TypeSystemEntity parent) + private static void AddDependenciesDueToCustomAttributes(DependencySink dependencies, object condition, NodeFactory factory, EcmaModule module, CustomAttributeHandleCollection attributeHandles, TypeSystemEntity parent) { MetadataReader reader = module.MetadataReader; var mdManager = (UsageBasedMetadataManager)factory.MetadataManager; @@ -127,7 +128,6 @@ private static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyL if (AddDependenciesFromCustomAttributeBlob(caDependencies, factory, constructor.OwningType, decodedValue)) { - dependencies ??= new CombinedDependencyList(); foreach (DependencyListEntry caDependency in caDependencies) { @@ -159,7 +159,7 @@ private static void AddDependenciesDueToCustomAttributes(ref CombinedDependencyL } } - private static bool AddDependenciesFromCustomAttributeBlob(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, CustomAttributeValue value) + private static bool AddDependenciesFromCustomAttributeBlob(IDependencySink dependencies, NodeFactory factory, TypeDesc attributeType, CustomAttributeValue value) { foreach (CustomAttributeTypedArgument decodedArgument in value.FixedArguments) { @@ -190,7 +190,7 @@ private static bool AddDependenciesFromCustomAttributeBlob(DependencyList depend return true; } - private static bool AddDependenciesFromField(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string fieldName) + private static bool AddDependenciesFromField(IDependencySink dependencies, NodeFactory factory, TypeDesc attributeType, string fieldName) { FieldDesc field = attributeType.GetField(System.Text.Encoding.UTF8.GetBytes(fieldName)); if (field is not null) @@ -213,7 +213,7 @@ private static bool AddDependenciesFromField(DependencyList dependencies, NodeFa return true; } - private static bool AddDependenciesFromPropertySetter(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName) + private static bool AddDependenciesFromPropertySetter(IDependencySink dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName) { EcmaType attributeTypeDefinition = (EcmaType)attributeType.GetTypeDefinition(); @@ -256,7 +256,7 @@ private static bool AddDependenciesFromPropertySetter(DependencyList dependencie return true; } - private static bool AddDependenciesFromCustomAttributeArgument(DependencyList dependencies, NodeFactory factory, TypeDesc type, object value) + private static bool AddDependenciesFromCustomAttributeArgument(IDependencySink dependencies, NodeFactory factory, TypeDesc type, object value) { // If this is an initializer that refers to e.g. a blocked enum, we can't encode this attribute. if (factory.MetadataManager.IsReflectionBlocked(type)) @@ -294,7 +294,7 @@ private static bool AddDependenciesFromCustomAttributeArgument(DependencyList de return false; // Grab the metadata nodes that will be necessary to represent the typeof in the metadata blob - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, typeofType, "Custom attribute blob"); + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, typeofType, "Custom attribute blob"); return true; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeMetadataNode.cs index 7b4706cde57bae..64e6f2c7186eff 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeMetadataNode.cs @@ -30,7 +30,7 @@ public CustomAttributeMetadataNode(ReflectableCustomAttribute customAttribute) // // We need to walk the dependencies before placing the node into the graph to find out whether // the attribute even can be generated (does it refer to blocked types or something like that?). - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } protected override string GetName(NodeFactory factory) { @@ -41,7 +41,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs index 07533b6b600921..f3e1e6f695544e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs @@ -28,23 +28,26 @@ public DataflowAnalyzedMethodNode(MethodIL methodIL) _methodIL = methodIL; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { var mdManager = (UsageBasedMetadataManager)factory.MetadataManager; try { - return Dataflow.ReflectionMethodBodyScanner.ScanAndProcessReturnValue(factory, mdManager.FlowAnnotations, mdManager.Logger, _methodIL, out _runtimeDependencies); + foreach (DependencyListEntry dependency in Dataflow.ReflectionMethodBodyScanner.ScanAndProcessReturnValue(factory, mdManager.FlowAnnotations, mdManager.Logger, _methodIL, out _runtimeDependencies)) + { + sink.Add(dependency); + } } catch (TypeSystemException) { // Something wrong with the input - missing references, etc. // The method body likely won't compile either, so we don't care. _runtimeDependencies = new List<(MethodDesc, INodeWithRuntimeDeterminedDependencies)>(); - return Array.Empty(); + return; } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { // Look for any generic specialization of this method or its compiler-generated callees (local methods, lambdas). // If any are found, specialize the dataflow dependencies that originated from that method. @@ -62,10 +65,13 @@ public override IEnumerable SearchDynamicDependenci if (n.OwningMethod != typicalMethod) continue; - foreach (var d in n.Dependency.InstantiateDependencies(factory, method.OwningType.Instantiation, method.Instantiation, isConcreteInstantiation: !method.IsSharedByGenericInstantiations)) - { - yield return new CombinedDependencyListEntry(d.Node, null, d.Reason); - } + n.Dependency.AddDependencies( + sink, + factory, + method.OwningType.Instantiation, + method.Instantiation, + isConcreteInstantiation: !method.IsSharedByGenericInstantiations, + otherReasonNode: null); } } } @@ -79,6 +85,6 @@ protected override string GetName(NodeFactory factory) public override bool HasDynamicDependencies => _runtimeDependencies.Count > 0; public override bool HasConditionalStaticDependencies => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs index 3a67003163c781..9800c6ef226266 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs @@ -25,7 +25,7 @@ public DataflowAnalyzedTypeDefinitionNode(TypeDesc typeDefinition) _typeDefinition = typeDefinition; } - public static void GetDependencies(ref DependencyList dependencies, NodeFactory factory, FlowAnnotations flowAnnotations, TypeDesc type) + public static void AddDependencies(DependencySink dependencies, NodeFactory factory, FlowAnnotations flowAnnotations, TypeDesc type) { bool needsDataflowAnalysis = false; @@ -58,14 +58,13 @@ public static void GetDependencies(ref DependencyList dependencies, NodeFactory if (needsDataflowAnalysis) { - dependencies ??= new DependencyList(); dependencies.Add(factory.DataflowAnalyzedTypeDefinition(type), "Dataflow for type definition"); } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; + DependencySink dependencies = sink; if (_typeDefinition is MetadataType metadataType) { @@ -79,7 +78,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto foreach (var interfaceType in metadataType.ExplicitlyImplementedInterfaces) { GenericArgumentDataFlow.ProcessGenericArgumentDataFlow( - ref dependencies, + dependencies, factory, new MessageOrigin(_typeDefinition), interfaceType, @@ -89,7 +88,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto } } - return dependencies; } protected override string GetName(NodeFactory factory) @@ -101,7 +99,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingDataNode.cs index 39c2670db18804..ee22ab2846a2a3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingDataNode.cs @@ -26,17 +26,15 @@ public DelegateMarshallingDataNode(DefType type) _type = type; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { InteropStateManager stateManager = ((CompilerGeneratedInteropStubManager)factory.InteropStubManager)._interopStateManager; - return new DependencyListEntry[] - { + sink.AddRange( new DependencyListEntry(factory.NecessaryTypeSymbol(_type), "Delegate Marshalling Stub"), new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetOpenStaticDelegateMarshallingThunk(_type)), "Delegate Marshalling Stub"), new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetClosedDelegateMarshallingThunk(_type)), "Delegate Marshalling Stub"), - new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetForwardDelegateCreationThunk(_type)), "Delegate Marshalling Stub"), - }; + new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetForwardDelegateCreationThunk(_type)), "Delegate Marshalling Stub")); } protected override string GetName(NodeFactory context) @@ -48,7 +46,7 @@ protected override string GetName(NodeFactory context) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateTargetVirtualMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateTargetVirtualMethodNode.cs index 62e4fb8d348058..ca92e5eb66f196 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateTargetVirtualMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateTargetVirtualMethodNode.cs @@ -30,13 +30,13 @@ protected override string GetName(NodeFactory factory) return (_reflected ? "Reflected delegate target method:" : "Delegate target method: ") + _method.ToString(); } - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } public sealed class ReflectableVirtualMethodImplNode : DependencyNodeCore @@ -58,20 +58,20 @@ protected override string GetName(NodeFactory factory) return $"Reflectable virtual method implementation: {_implementation} for {_declaration}"; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - yield return new CombinedDependencyListEntry( + sink.Add(new CombinedDependencyListEntry( factory.ReflectedMethod(_implementation), factory.ReflectedDelegateTargetVirtualMethod(_declaration), - "Virtual method declaration is reflectable"); + "Virtual method declaration is reflectable")); } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs index cc3a9d6f120add..5e5e6eec3a7fd5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs @@ -137,7 +137,7 @@ public virtual void EmitDictionaryData(ref ObjectDataBuilder builder, NodeFactor } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { if (HasFixedSlots) { @@ -145,13 +145,13 @@ public override IEnumerable GetStaticDependencies(NodeFacto { foreach (DependencyNodeCore dependency in lookupResult.NonRelocDependenciesFromUsage(factory)) { - yield return new DependencyListEntry(dependency, "GenericLookupResultDependency"); + sink.Add(dependency, "GenericLookupResultDependency"); } } } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { Debug.Assert(HasFixedSlots); @@ -165,7 +165,7 @@ public override IEnumerable GetConditionalStaticDep templateLayout = factory.NativeLayout.TemplateTypeLayout((TypeDesc)_owningMethodOrType); } - List conditionalDependencies = new List(); + DependencySink conditionalDependencies = sink; foreach (var lookupSignature in FixedEntries) { @@ -173,8 +173,6 @@ public override IEnumerable GetConditionalStaticDep templateLayout, "Type loader template")); } - - return conditionalDependencies; } protected override string GetName(NodeFactory factory) => $"Dictionary layout for {_owningMethodOrType}"; @@ -184,7 +182,7 @@ public override IEnumerable GetConditionalStaticDep public override bool InterestingForDynamicDependencyAnalysis => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } public class PrecomputedDictionaryLayoutNode : DictionaryLayoutNode diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DispatchCellNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DispatchCellNode.cs index 0ef47b833f5a12..caa753dc24dac8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DispatchCellNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DispatchCellNode.cs @@ -78,15 +78,17 @@ public void InitializeOffset(int offset) public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { if (_targetMethod.HasInstantiation) { - return GvmDispatchCellInfoSectionNode.GetCellDependencies(factory, _targetMethod); + GvmDispatchCellInfoSectionNode.AddCellDependencies(sink, factory, _targetMethod); + return; } else { - return InterfaceDispatchCellInfoSectionNode.GetCellDependencies(factory, _targetMethod); + InterfaceDispatchCellInfoSectionNode.AddCellDependencies(sink, factory, _targetMethod); + return; } } @@ -105,8 +107,8 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } internal sealed class DispatchCellInfoComparer : IComparer diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs index 3e46d482b5f6ad..1a97e9b4207939 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DynamicDependencyAttributesOnEntityNode.cs @@ -34,27 +34,25 @@ public DynamicDependencyAttributesOnEntityNode(TypeSystemEntity entity) _entity = entity; } - public static void AddDependenciesDueToDynamicDependencyAttribute(ref DependencyList dependencies, NodeFactory factory, EcmaMethod method) + public static void AddDependenciesDueToDynamicDependencyAttribute(IDependencySink dependencies, NodeFactory factory, EcmaMethod method) { if (method.HasCustomAttribute("System.Diagnostics.CodeAnalysis", "DynamicDependencyAttribute")) { - dependencies ??= new DependencyList(); dependencies.Add(factory.DynamicDependencyAttributesOnEntity(method), "DynamicDependencyAttribute present"); } } - public static void AddDependenciesDueToDynamicDependencyAttribute(ref DependencyList dependencies, NodeFactory factory, EcmaField field) + public static void AddDependenciesDueToDynamicDependencyAttribute(IDependencySink dependencies, NodeFactory factory, EcmaField field) { if (field.HasCustomAttribute("System.Diagnostics.CodeAnalysis", "DynamicDependencyAttribute")) { - dependencies ??= new DependencyList(); dependencies.Add(factory.DynamicDependencyAttributesOnEntity(field), "DynamicDependencyAttribute present"); } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; + DependencySink dependencies = sink; try { (TypeDesc owningType, IEnumerable> attributes) = _entity switch @@ -65,7 +63,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto foreach (CustomAttributeValue attribute in attributes) { - AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, _entity, owningType, attribute); + AddDependenciesDueToDynamicDependencyAttribute(dependencies, factory, _entity, owningType, attribute); } } catch (TypeSystemException) @@ -73,11 +71,10 @@ public override IEnumerable GetStaticDependencies(NodeFacto // Ignore entities with custom attributes that don't work. } - return dependencies; } private static void AddDependenciesDueToDynamicDependencyAttribute( - ref DependencyList dependencies, + IDependencySink dependencies, NodeFactory factory, TypeSystemEntity entity, TypeDesc owningType, @@ -231,8 +228,10 @@ static MetadataType Linkerify(TypeDesc type) reflectionMarker.MarkTypeSystemEntity(new MessageOrigin(entity), member, reason); } - dependencies ??= new DependencyList(); - dependencies.AddRange(reflectionMarker.Dependencies); + foreach (DependencyListEntry dependency in reflectionMarker.Dependencies) + { + dependencies.Add(dependency); + } } protected override string GetName(NodeFactory factory) @@ -244,7 +243,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } 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 4a41c8e78f7804..92e7ef433da36b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -12,6 +12,7 @@ using Debug = System.Diagnostics.Debug; using GenericVariance = Internal.Runtime.GenericVariance; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -312,13 +313,13 @@ public override bool HasConditionalStaticDependencies } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - List result = new List(); + DependencySink result = sink; if (IsReflectionVisible) { - factory.MetadataManager.GetConditionalDependenciesDueToEETypePresence(ref result, factory, _type, allocated: EmitVirtualSlots); + factory.MetadataManager.GetConditionalDependenciesDueToEETypePresence(result, factory, _type, allocated: EmitVirtualSlots); if (!_type.IsCanonicalSubtype(CanonicalFormKind.Any)) { @@ -344,7 +345,7 @@ public override IEnumerable GetConditionalStaticDep { result.Add(new CombinedDependencyListEntry(maximallyConstructableType, factory.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Trigger full type generation if canonical form exists")); } - return result; + return; } TypeDesc canonOwningType = _type.ConvertToCanonForm(CanonicalFormKind.Specific); @@ -357,7 +358,7 @@ public override IEnumerable GetConditionalStaticDep } if (!EmitVirtualSlots) - return result; + return; DefType defType = _type.GetClosestDefType(); @@ -415,7 +416,7 @@ public override IEnumerable GetConditionalStaticDep factory.MetadataManager.NoteOverridingMethod(decl, impl); } - factory.MetadataManager.GetDependenciesForOverridingMethod(ref result, factory, decl, impl); + factory.MetadataManager.GetDependenciesForOverridingMethod(result, factory, decl, impl); } } @@ -516,7 +517,7 @@ public override IEnumerable GetConditionalStaticDep TypeSystemEntity origin = (implMethod.OwningType != defType) ? defType : null; factory.MetadataManager.NoteOverridingMethod(interfaceMethod, implMethod, origin); - factory.MetadataManager.GetDependenciesForOverridingMethod(ref result, factory, interfaceMethod, implMethod); + factory.MetadataManager.GetDependenciesForOverridingMethod(result, factory, interfaceMethod, implMethod); } else { @@ -552,14 +553,12 @@ public override IEnumerable GetConditionalStaticDep factory.MetadataManager.NoteOverridingMethod(interfaceMethod, implMethod); - factory.MetadataManager.GetDependenciesForOverridingMethod(ref result, factory, interfaceMethod, implMethod); + factory.MetadataManager.GetDependenciesForOverridingMethod(result, factory, interfaceMethod, implMethod); } } } } } - - return result; } public static bool IsTypeNodeShareable(TypeDesc type) @@ -589,9 +588,9 @@ internal static bool MethodHasNonGenericILMethodBody(MethodDesc method) return true; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; if (_type.IsInterface) dependencies.Add(factory.InterfaceUse(_type.GetTypeDefinition()), "Interface is used"); @@ -662,17 +661,16 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact { // If necessary MethodTable is the highest load level for this type, ask the metadata manager // if we have any dependencies due to presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type); + factory.MetadataManager.GetDependenciesDueToEETypePresence(dependencies, factory, _type); // If necessary MethodTable is the highest load level, consider this a module use if (_type is MetadataType mdType) - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module); + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(dependencies, factory, mdType.Module); } if (_type.IsFunctionPointer) - FunctionPointerMapNode.GetHashtableDependencies(ref dependencies, factory, (FunctionPointerType)_type); + FunctionPointerMapNode.AddHashtableDependencies(dependencies, factory, (FunctionPointerType)_type); - return dependencies; } protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs index 33b7594383c49a..d7595c85b62ded 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs @@ -59,8 +59,8 @@ public void InitializeIndexFromBeginningOfArray(int index) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } public abstract void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs index e707e28af611a9..84e787eeecce93 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using Internal.Text; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -43,7 +44,7 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f } // At minimum, Target needs to be reported as a static dependency by inheritors. - public abstract override IEnumerable GetStaticDependencies(NodeFactory factory); + public abstract override void AddStaticDependencies(DependencySink sink, NodeFactory factory); int ISymbolNode.Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedTrimmingDescriptorNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedTrimmingDescriptorNode.cs index d63e3571a7629b..671d8664b61696 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedTrimmingDescriptorNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedTrimmingDescriptorNode.cs @@ -25,7 +25,7 @@ public EmbeddedTrimmingDescriptorNode(EcmaModule module) _module = module; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { PEMemoryBlock resourceDirectory = _module.PEReader.GetSectionData(_module.PEReader.PEHeaders.CorHeader.ResourcesDirectory.RelativeVirtualAddress); @@ -52,10 +52,13 @@ public override IEnumerable GetStaticDependencies(NodeFacto } var metadataManager = (UsageBasedMetadataManager)factory.MetadataManager; - return DescriptorMarker.GetDependencies(metadataManager.Logger, factory, ms, resource, _module, "resource " + resourceName + " in " + _module.ToString(), metadataManager.FeatureSwitches); + foreach (DependencyListEntry dependency in DescriptorMarker.GetDependencies(metadataManager.Logger, factory, ms, resource, _module, "resource " + resourceName + " in " + _module.ToString(), metadataManager.FeatureSwitches)) + { + sink.Add(dependency); + } + return; } } - return Array.Empty(); } protected override string GetName(NodeFactory factory) @@ -67,7 +70,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EventMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EventMetadataNode.cs index 349b43d253ded7..e81850033c9f7d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EventMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EventMetadataNode.cs @@ -27,13 +27,12 @@ public EventMetadataNode(EventPseudoDesc @event) public EventPseudoDesc Event => _event; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new List(); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _event); - return dependencies; + DependencySink dependencies = sink; + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(dependencies, factory, _event); } protected override string GetName(NodeFactory factory) @@ -45,6 +44,6 @@ protected override string GetName(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsEntryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsEntryNode.cs index 121e6209f9c17b..7965c07370945b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsEntryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsEntryNode.cs @@ -25,12 +25,11 @@ public ExactMethodInstantiationsEntryNode(MethodDesc method) public MethodDesc Method => _method; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; - ExactMethodInstantiationsNode.GetExactMethodInstantiationDependenciesForMethod(ref dependencies, factory, _method); + DependencySink dependencies = sink; + ExactMethodInstantiationsNode.GetExactMethodInstantiationDependenciesForMethod(dependencies, factory, _method); Debug.Assert(dependencies != null); - return dependencies; } protected override string GetName(NodeFactory factory) { @@ -41,7 +40,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } 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 dc4e3dbf557b81..91f574e286d85a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs @@ -8,6 +8,7 @@ using Internal.TypeSystem; using Internal.NativeFormat; using Internal.Runtime; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -100,9 +101,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } - public static void GetExactMethodInstantiationDependenciesForMethod(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void GetExactMethodInstantiationDependenciesForMethod(DependencySink dependencies, NodeFactory factory, MethodDesc method) { - dependencies ??= new DependencyList(); // Method entry point dependency bool getUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic; @@ -117,7 +117,7 @@ public static void GetExactMethodInstantiationDependenciesForMethod(ref Dependen foreach (var arg in method.Instantiation) dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(arg), "Exact method instantiation entry")); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, GetMethodForMetadata(method, out _, out _)); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, factory, GetMethodForMetadata(method, out _, out _)); } private static MethodDesc GetMethodForMetadata(MethodDesc method, out bool isAsyncVariant, out bool isReturnDroppingAsyncThunk) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapNode.cs index 3f2e82302b3bdd..65b1796856b07e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapNode.cs @@ -31,9 +31,9 @@ public ExternalTypeMapNode(TypeDesc typeMapGroup, IEnumerable GetConditionalStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { - List dependencies = []; + DependencySink dependencies = sink; foreach (var entry in _mapEntries) { @@ -51,24 +51,23 @@ public override IEnumerable GetConditionalStaticDep } } - return dependencies; } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { foreach (var entry in _mapEntries) { var (targetType, trimmingTargetType) = entry.Value; if (trimmingTargetType is null) { - yield return new DependencyListEntry( + sink.Add( context.MetadataTypeSymbol(targetType), "External type map entry target type"); } } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"External type map: {TypeMapGroup}"; public override int ClassCode => -785190502; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapRequestNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapRequestNode.cs index 46bec73bd78a52..e1ae79ec058e90 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapRequestNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapRequestNode.cs @@ -20,9 +20,9 @@ public sealed class ExternalTypeMapRequestNode(TypeDesc typeMapGroup) : Dependen public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) => []; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"External type map request: {TypeMapGroup}"; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs index 7c9aa3f5b278d5..c3d49aca7af3f4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs @@ -35,37 +35,34 @@ public FieldMetadataNode(FieldDesc field) public FieldDesc Field => _field; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(factory.TypeMetadata(_field.OwningType), "Owning type metadata"); if (_field is EcmaField ecmaField) { - DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaField); + DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(dependencies, factory, ecmaField); // On a reflectable field, perform generic data flow for the field's type // This is a compensation for the DI issue described in https://github.com/dotnet/runtime/issues/81358 - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_field), ecmaField.FieldType, ecmaField.OwningType); + GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(dependencies, factory, new MessageOrigin(_field), ecmaField.FieldType, ecmaField.OwningType); } if (_field.HasEmbeddedSignatureData) { foreach (var sigData in _field.GetEmbeddedSignatureData()) if (sigData.type != null) - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, sigData.type, "Modifier in a field signature"); + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, sigData.type, "Modifier in a field signature"); } - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, _field.FieldType, "Type of the field"); - - return dependencies; + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, _field.FieldType, "Type of the field"); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new List(); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, (EcmaField)_field); - return dependencies; + DependencySink dependencies = sink; + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(dependencies, factory, (EcmaField)_field); } protected override string GetName(NodeFactory factory) @@ -83,6 +80,6 @@ protected override void OnMarked(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index 2d1bcefd4fd56f..b5f2e520e44a55 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -7,6 +7,7 @@ using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -43,24 +44,19 @@ public sealed override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFa Debug.Assert(dataBuilder.CountBytes == sizeBefore + ContentSize); } - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { var builder = new ObjectDataBuilder(factory, relocsOnly: true); EncodeData(ref builder, factory, relocsOnly: true); Relocation[] relocs = builder.ToObjectData().Relocs; - DependencyList dependencies = null; - if (relocs != null) { - dependencies = new DependencyList(); foreach (Relocation reloc in relocs) { - dependencies.Add(reloc.Target, "reloc"); + sink.Add(reloc.Target, "reloc"); } } - - return dependencies; } public abstract void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs index 391e031d04fd57..18938b13046c31 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs @@ -6,6 +6,7 @@ using Internal.NativeFormat; using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -34,9 +35,8 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - public static void GetHashtableDependencies(ref DependencyList dependencies, NodeFactory factory, FunctionPointerType type) + public static void AddHashtableDependencies(DependencySink dependencies, NodeFactory factory, FunctionPointerType type) { - dependencies ??= new DependencyList(); dependencies.Add(factory.NecessaryTypeSymbol(type.Signature.ReturnType), "Function pointer type composition"); foreach (TypeDesc paramType in type.Signature) dependencies.Add(factory.NecessaryTypeSymbol(paramType), "Function pointer type composition"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs index 6eae730a964fb3..122f01b338e6d1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs @@ -8,6 +8,7 @@ using Debug = System.Diagnostics.Debug; using GCStaticRegionConstants = Internal.Runtime.GCStaticRegionConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -51,36 +52,31 @@ private ISymbolNode GetGCStaticEETypeNode(NodeFactory factory) return factory.GCStaticEEType(map, requiresAlign8); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencyList = new DependencyList(); + DependencySink dependencyList = sink; if (factory.PreinitializationManager.HasEagerStaticConstructor(_type)) { dependencyList.Add(factory.EagerCctorIndirection(_type.GetStaticConstructor()), "Eager .cctor"); } - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencyList, factory, _type.Module); + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(dependencyList, factory, _type.Module); dependencyList.Add(factory.GCStaticsRegion, "GCStatics Region"); - dependencyList.Add(factory.GCStaticIndirection(_type), "GC statics indirection"); - - return dependencyList; } public override bool HasConditionalStaticDependencies => _type.ConvertToCanonForm(CanonicalFormKind.Specific) != _type; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { // If we have a type loader template for this type, we need to keep track of the generated // bases in the type info hashtable. The type symbol node does such accounting. - return new CombinedDependencyListEntry[] - { + sink.Add( new CombinedDependencyListEntry(factory.NecessaryTypeSymbol(_type), factory.NativeLayout.TemplateTypeLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), - "Keeping track of template-constructable type static bases"), - }; + "Keeping track of template-constructable type static bases")); } public override bool StaticDependenciesAreComputed => true; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs index 70e3c714c7f028..57a0d2bdcf9dc1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs @@ -7,6 +7,7 @@ using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -19,7 +20,7 @@ public GenericDefinitionEETypeNode(NodeFactory factory, TypeDesc type) : base(fa public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } public override ISymbolNode NodeForLinkage(NodeFactory factory) { @@ -72,9 +73,8 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return factory.MetadataTypeSymbol(_type).Marked; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - return new DependencyList(); } public override int ClassCode => -287423988; @@ -98,9 +98,9 @@ protected override FrozenRuntimeTypeNode GetFrozenRuntimeTypeNode(NodeFactory fa protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler) + " reflection visible"; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - var dependencyList = new DependencyList(); + DependencySink dependencyList = sink; if (_type.IsInterface) dependencyList.Add(factory.InterfaceUse(_type.GetTypeDefinition()), "Interface is used"); @@ -108,9 +108,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencyList.Add(factory.NecessaryTypeSymbol(_type), "Reflection invisible type for a visible type"); // Ask the metadata manager if we have any dependencies due to the presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type); - - return dependencyList; + factory.MetadataManager.GetDependenciesDueToEETypePresence(dependencyList, factory, _type); } public override int ClassCode => 983279111; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs index be8571870a5c53..35b859b90b670c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs @@ -6,6 +6,7 @@ using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -117,9 +118,9 @@ public override DictionaryLayoutNode GetDictionaryLayout(NodeFactory factory) public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => GetDictionaryLayout(factory).IsEmpty; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList result = new DependencyList(); + DependencySink result = sink; // Include the layout as a dependency if the canonical type isn't imported TypeDesc canonicalOwningType = _owningType.ConvertToCanonForm(CanonicalFormKind.Specific); @@ -141,10 +142,10 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact } } - return result; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) +#nullable enable + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { // The generic dictionary layout is shared between all the canonically equivalent // instantiations. We need to track the dependencies of all canonical method bodies @@ -156,12 +157,13 @@ public override IEnumerable GetConditionalStaticDep // If a canonical method body was compiled, we need to track the dictionary // dependencies in the context of the concrete type that owns this dictionary. - yield return new CombinedDependencyListEntry( + sink.AddConditional( factory.ShadowConcreteMethod(method), factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Generic dictionary dependency"); } } +#nullable restore public TypeGenericDictionaryNode(TypeDesc owningType, NodeFactory factory) : base(factory) @@ -198,22 +200,22 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde public MethodDesc OwningMethod => _owningMethod; public override bool HasConditionalStaticDependencies => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - return factory.MetadataManager.GetConditionalDependenciesDueToGenericDictionary(factory, _owningMethod); + factory.MetadataManager.AddConditionalDependenciesDueToGenericDictionary(sink, factory, _owningMethod); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; MethodDesc canonicalTarget = _owningMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); if (factory.CompilationModuleGroup.ContainsMethodBody(canonicalTarget, false)) dependencies.Add(GetDictionaryLayout(factory), "Layout"); - factory.MetadataManager.GetDependenciesDueToGenericDictionary(ref dependencies, factory, _owningMethod); + factory.MetadataManager.GetDependenciesDueToGenericDictionary(dependencies, factory, _owningMethod); - factory.InteropStubManager.AddMarshalAPIsGenericDependencies(ref dependencies, factory, _owningMethod); + factory.InteropStubManager.AddMarshalAPIsGenericDependencies(dependencies, factory, _owningMethod); // Lazy generic use of the Activator.CreateInstance heuristic requires tracking type parameters that are used in lazy generics. if (factory.LazyGenericsPolicy.UsesLazyGenerics(_owningMethod)) @@ -242,8 +244,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact // Make sure the dictionary can also be populated dependencies.Add(factory.ShadowConcreteMethod(_owningMethod), "Dictionary contents"); - - return dependencies; } public override DictionaryLayoutNode GetDictionaryLayout(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableEntryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableEntryNode.cs index adab54ef0093a4..93ae269bdfb746 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableEntryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableEntryNode.cs @@ -22,12 +22,11 @@ public GenericMethodsHashtableEntryNode(MethodDesc method) public MethodDesc Method => _method; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; - GenericMethodsHashtableNode.GetGenericMethodsHashtableDependenciesForMethod(ref dependencies, factory, _method); + DependencySink dependencies = sink; + GenericMethodsHashtableNode.GetGenericMethodsHashtableDependenciesForMethod(dependencies, factory, _method); Debug.Assert(dependencies != null); - return dependencies; } protected override string GetName(NodeFactory factory) { @@ -38,7 +37,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } 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 bfe71bfbb7a7f4..efb941b718a5f5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs @@ -8,6 +8,7 @@ using Internal.TypeSystem; using Internal.NativeFormat; using Internal.Runtime; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -93,9 +94,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } - public static void GetGenericMethodsHashtableDependenciesForMethod(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void GetGenericMethodsHashtableDependenciesForMethod(DependencySink dependencies, NodeFactory factory, MethodDesc method) { - dependencies ??= new DependencyList(); Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any)); @@ -110,7 +110,7 @@ public static void GetGenericMethodsHashtableDependenciesForMethod(ref Dependenc dependencies.Add(new DependencyListEntry(argNode, "GenericMethodsHashtable entry instantiation argument")); } - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, GetMethodForMetadata(method, out _, out _)); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, factory, GetMethodForMetadata(method, out _, out _)); } private static MethodDesc GetMethodForMetadata(MethodDesc method, out bool isAsyncVariant, out bool isReturnDroppingAsyncThunk) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs index 214f8e04ffcde8..b2fc4a672391a7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.NativeFormat; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -72,12 +73,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } - public static void GetTemplateMethodDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void AddTemplateMethodDependencies(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { if (!IsEligibleToBeATemplate(method)) return; - dependencies ??= new DependencyList(); dependencies.Add(new DependencyListEntry(factory.NativeLayout.TemplateMethodEntry(method), "Template Method Entry")); dependencies.Add(new DependencyListEntry(factory.NativeLayout.TemplateMethodLayout(method), "Template Method Layout")); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericStaticBaseInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericStaticBaseInfoNode.cs index 9820371f273d4f..955c95368878f8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericStaticBaseInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericStaticBaseInfoNode.cs @@ -24,11 +24,10 @@ public GenericStaticBaseInfoNode(MetadataType type) Type = type; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new DependencyList(); - StaticsInfoHashtableNode.AddStaticsInfoDependencies(ref dependencies, factory, Type); - return dependencies; + DependencySink dependencies = sink; + StaticsInfoHashtableNode.AddStaticsInfoDependencies(dependencies, factory, Type); } protected override string GetName(NodeFactory factory) @@ -40,7 +39,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs index e3c016025bf6fc..dd6ce13f2e2e95 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.NativeFormat; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -68,14 +69,13 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } - public static void GetTemplateTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public static void AddTemplateTypeDependencies(IDependencySink dependencies, NodeFactory factory, TypeDesc type) { TypeDesc templateType = ConvertArrayOfTToRegularArray(factory, type); if (!IsEligibleToHaveATemplate(templateType)) return; - dependencies ??= new DependencyList(); dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(templateType), "Template type")); dependencies.Add(new DependencyListEntry(factory.NativeLayout.TemplateTypeLayout(templateType), "Template Type Layout")); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs index cc756532159ac7..4421af3d94b7c3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodImplNode.cs @@ -34,11 +34,11 @@ public GenericVirtualMethodImplNode(MethodDesc method) public override bool StaticDependenciesAreComputed => true; protected override string GetName(NodeFactory factory) => "__GVMImplNode_" + factory.NameMangler.GetMangledMethodName(_method); - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; + DependencySink dependencies = sink; - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref dependencies, factory, _method); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(dependencies, factory, _method); bool validInstantiation = _method.IsSharedByGenericInstantiations || ( // Non-exact methods are always valid instantiations (always pass constraints check) @@ -49,7 +49,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (validInstantiation) { bool getUnboxingStub = _method.OwningType.IsValueType && !_method.Signature.IsStatic; - dependencies ??= new DependencyList(); + dependencies.Add(factory.MethodEntrypoint(_method, getUnboxingStub), "GVM Dependency - Canon method"); if (_method.IsSharedByGenericInstantiations) @@ -64,13 +64,12 @@ public override IEnumerable GetStaticDependencies(NodeFacto } } - return dependencies; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } public override bool HasDynamicDependencies => false; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } 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 2b4ab88f6580a4..63e1e3f60b87f2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -8,6 +8,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.NativeFormat; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -43,7 +44,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) /// The dependencies returned from this function will be reported as static dependencies of the TypeGVMEntriesNode, /// which we create for each type that has generic virtual methods. /// - public static void GetGenericVirtualMethodImplementationDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc callingMethod, MethodDesc implementationMethod) + public static void AddGenericVirtualMethodImplementationDependencies(DependencySink dependencies, NodeFactory factory, MethodDesc callingMethod, MethodDesc implementationMethod) { Debug.Assert(!callingMethod.OwningType.IsInterface); @@ -51,9 +52,9 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, factory, openCallingMethod); dependencies.Add(factory.NecessaryTypeSymbol(openCallingMethod.OwningType), "Owning type of GVM declaration"); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, factory, openImplementationMethod); dependencies.Add(factory.NecessaryTypeSymbol(openImplementationMethod.OwningType), "Owning type of GVM implementation"); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GvmDispatchCellInfoSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GvmDispatchCellInfoSectionNode.cs index c31bafcac03a74..ecf0954da30a5b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GvmDispatchCellInfoSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GvmDispatchCellInfoSectionNode.cs @@ -9,6 +9,7 @@ using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; @@ -96,26 +97,22 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => true; - public static IEnumerable GetCellDependencies(NodeFactory factory, MethodDesc targetMethod) + public static void AddCellDependencies(DependencySink dependencies, NodeFactory factory, MethodDesc targetMethod) { - DependencyList result = new DependencyList(); - MethodDesc canonMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); - result.Add(factory.GVMDependencies(canonMethod), "GVM dependencies"); + dependencies.Add(factory.GVMDependencies(canonMethod), "GVM dependencies"); // GVM analysis happens on canonical forms, but this is potentially injecting new genericness // into the system. Ensure reflection analysis can still see this. if (targetMethod.IsAbstract) - factory.MetadataManager.GetDependenciesDueToMethodCodePresence(ref result, factory, canonMethod, methodIL: null); - - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref result, factory, targetMethod); + factory.MetadataManager.GetDependenciesDueToMethodCodePresence(dependencies, factory, canonMethod, methodIL: null); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref result, factory, GetMethodForMetadata(targetMethod, out _)); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(dependencies, factory, targetMethod); - result.Add(factory.MaximallyConstructableType(targetMethod.OwningType), "Owning type of GVM decl"); - result.Add(factory.MetadataEnabledGenericComposition(targetMethod.Instantiation), "GVM instantiation info"); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, factory, GetMethodForMetadata(targetMethod, out _)); - return result; + dependencies.Add(factory.MaximallyConstructableType(targetMethod.OwningType), "Owning type of GVM decl"); + dependencies.Add(factory.MetadataEnabledGenericComposition(targetMethod.Instantiation), "GVM instantiation info"); } public static MethodDesc GetMethodForMetadata(MethodDesc method, out bool isAsyncVariant) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InlineableStringsResourceNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InlineableStringsResourceNode.cs index 26d4100aed666c..11327d1862a2c2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InlineableStringsResourceNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InlineableStringsResourceNode.cs @@ -58,19 +58,18 @@ public static bool IsInlineableStringsResource(EcmaModule module, string resourc return srType.GetMethod(ResourceAccessorGetStringMethodName, null) != null; } - public static void AddDependenciesDueToResourceStringUse(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void AddDependenciesDueToResourceStringUse(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { if (method.Name == ResourceAccessorGetStringMethodName && method.OwningType is MetadataType mdType && mdType.Name == ResourceAccessorTypeName && mdType.Namespace == ResourceAccessorTypeNamespace) { - dependencies ??= new DependencyList(); dependencies.Add(factory.InlineableStringResource((EcmaModule)mdType.Module), "Using the System.SR class"); } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; - public override IEnumerable GetStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"String resources for {_module.Assembly.GetName().Name}"; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellInfoSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellInfoSectionNode.cs index 189e0422cdd98d..c59ebee2d8034a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellInfoSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellInfoSectionNode.cs @@ -9,6 +9,7 @@ using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; @@ -89,20 +90,16 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => true; - public static IEnumerable GetCellDependencies(NodeFactory factory, MethodDesc targetMethod) + public static void AddCellDependencies(DependencySink dependencies, NodeFactory factory, MethodDesc targetMethod) { - DependencyList result = new DependencyList(); - if (!factory.VTable(targetMethod.OwningType).HasKnownVirtualMethodUse) { - result.Add(factory.VirtualMethodUse(targetMethod), "Interface method use"); + dependencies.Add(factory.VirtualMethodUse(targetMethod), "Interface method use"); } - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref result, factory, targetMethod); - - result.Add(GetInterfaceTypeNode(factory, targetMethod), "Interface type"); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(dependencies, factory, targetMethod); - return result; + dependencies.Add(GetInterfaceTypeNode(factory, targetMethod), "Interface type"); } private static IEETypeNode GetInterfaceTypeNode(NodeFactory factory, MethodDesc targetMethod) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs index 9706010a9ae017..ad1fcea393799a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs @@ -8,6 +8,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.Runtime; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -47,9 +48,9 @@ public override ObjectNodeSection GetSection(NodeFactory factory) return ObjectNodeSection.DataSection; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - var result = new DependencyList(); + DependencySink result = sink; // VTable slots of implemented interfaces are consulted during emission foreach (TypeDesc runtimeInterface in _type.RuntimeInterfaces) @@ -57,7 +58,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact result.Add(factory.VTable(runtimeInterface), "Interface for a dispatch map"); } - return result; } /// 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 1c1049b2d47ce7..e3b52d053f5239 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -9,6 +9,7 @@ using Internal.TypeSystem; using Internal.NativeFormat; using Internal.Runtime; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -45,7 +46,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) /// The dependencies returned from this function will be reported as static dependencies of the TypeGVMEntriesNode, /// which we create for each type that has generic virtual methods. /// - public static void GetGenericVirtualMethodImplementationDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc callingMethod, TypeDesc implementationType, MethodDesc implementationMethod) + public static void AddGenericVirtualMethodImplementationDependencies(DependencySink dependencies, NodeFactory factory, MethodDesc callingMethod, TypeDesc implementationType, MethodDesc implementationMethod) { Debug.Assert(callingMethod.OwningType.IsInterface); @@ -53,7 +54,7 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openCallingMethod = callingMethod.GetTypicalMethodDefinition(); TypeDesc openImplementationType = implementationType.GetTypeDefinition(); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(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) @@ -61,7 +62,7 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition(); dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(openImplementationMethod.OwningType), "interface gvm table implementation method owning type")); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, factory, openImplementationMethod); } if (!openImplementationType.IsInterface) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceUseNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceUseNode.cs index 9ef45bb711844c..dd5b89377fa5e8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceUseNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceUseNode.cs @@ -29,12 +29,12 @@ public InterfaceUseNode(TypeDesc type) protected override string GetName(NodeFactory factory) => $"Interface use: {Type}"; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } 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 context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidExternalTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidExternalTypeMapNode.cs index fa527fdfae76c5..2a0118d31dddf3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidExternalTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidExternalTypeMapNode.cs @@ -20,15 +20,13 @@ internal sealed class InvalidExternalTypeMapNode(TypeDesc typeMapGroup, MethodDe public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => Array.Empty(); - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return [ - new DependencyListEntry(context.MethodEntrypoint(ThrowingMethodStub), "Throwing method stub for invalid type map"), - ]; + sink.Add(context.MethodEntrypoint(ThrowingMethodStub), "Throwing method stub for invalid type map"); } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Invalid external type map: {TypeMapGroup}"; public TypeDesc TypeMapGroup { get; } = typeMapGroup; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidProxyTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidProxyTypeMapNode.cs index f0035a2beb3e08..64106f9a7f7e2b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidProxyTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidProxyTypeMapNode.cs @@ -23,15 +23,13 @@ internal sealed class InvalidProxyTypeMapNode(TypeDesc typeMapGroup, MethodDesc public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => Array.Empty(); - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return [ - new DependencyListEntry(context.MethodEntrypoint(ThrowingMethodStub), "Throwing method stub for invalid type map"), - ]; + sink.Add(context.MethodEntrypoint(ThrowingMethodStub), "Throwing method stub for invalid type map"); } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Invalid proxy type map: {TypeMapGroup}"; public override int ClassCode => 36910224; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataEETypeNode.cs index 0cfd7e55a1b33c..eb9420237d84ec 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataEETypeNode.cs @@ -5,6 +5,7 @@ using Internal.Runtime; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -28,9 +29,10 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return false; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory); + DependencySink dependencyList = sink; + base.ComputeNonRelocationBasedDependencies(sink, factory); // Ensure that we track the necessary type symbol if we are working with a metadata type symbol. // The emitter will ensure we don't emit both, but this allows us assert that we only generate @@ -38,10 +40,10 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencyList.Add(factory.NecessaryTypeSymbol(_type), "NecessaryType for metadata type"); if (_type is MetadataType mdType) - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencyList, factory, mdType.Module); + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(dependencyList, factory, mdType.Module); // Ask the metadata manager if we have any dependencies due to the presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type); + factory.MetadataManager.GetDependenciesDueToEETypePresence(dependencyList, factory, _type); // Reflection-visible valuetypes are considered constructed due to APIs like RuntimeHelpers.Box, // or Enum.ToObject. @@ -73,8 +75,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact } if (hasStaticVirtuals) dependencyList.Add(factory.MaximallyConstructableType(_type), "Has static virtual methods"); - - return dependencyList; } protected override ISymbolNode GetBaseTypeNode(NodeFactory factory) 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 ab49aca5b7c407..004f43e14f1c84 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs @@ -40,9 +40,9 @@ public MethodMetadataNode(MethodDesc method, bool isMinimal) public MethodDesc Method => _method; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; var owningType = (MetadataType)_method.OwningType; dependencies.Add(factory.TypeMetadata(owningType), "Owning type metadata"); @@ -57,30 +57,30 @@ public override IEnumerable GetStaticDependencies(NodeFacto MethodSignature sig = _method.Signature; const string reason = "Method signature metadata"; - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, sig.ReturnType, reason); + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, sig.ReturnType, reason); foreach (TypeDesc paramType in sig) { - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, paramType, reason); + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, paramType, reason); } if (sig.HasEmbeddedSignatureData) { foreach (var sigData in sig.GetEmbeddedSignatureData()) if (sigData.type != null) - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, sigData.type, "Modifier in a method signature"); + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, sigData.type, "Modifier in a method signature"); } if (!_isMinimal) { - DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, _method); + DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(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 - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_method), _method.Signature.ReturnType, _method); + GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(dependencies, factory, new MessageOrigin(_method), _method.Signature.ReturnType, _method); foreach (TypeDesc parameterType in _method.Signature) { - GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(ref dependencies, factory, new MessageOrigin(_method), parameterType, _method); + GenericArgumentDataFlow.ProcessGenericArgumentDataFlow(dependencies, factory, new MessageOrigin(_method), parameterType, _method); } if (_method.HasCustomAttribute("System.Diagnostics", "StackTraceHiddenAttribute") @@ -121,15 +121,12 @@ public override IEnumerable GetStaticDependencies(NodeFacto } } } - - return dependencies; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new List(); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _method); - return dependencies; + DependencySink dependencies = sink; + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(dependencies, factory, _method); } protected override string GetName(NodeFactory factory) @@ -147,6 +144,6 @@ protected override void OnMarked(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => !_isMinimal; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs index ff0278c3f1d83b..cf833bca8c98b9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodParameterMetadataNode.cs @@ -24,7 +24,7 @@ public MethodParameterMetadataNode(ReflectableParameter parameter) public ReflectableParameter Parameter => _parameter; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } protected override string GetName(NodeFactory factory) { @@ -35,7 +35,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleMetadataNode.cs index 9e7aa3edba4db2..5b16265e2a3a84 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleMetadataNode.cs @@ -30,9 +30,9 @@ public ModuleMetadataNode(ModuleDesc module) public ModuleDesc Module => _module; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; // Global module type always generates metadata because it's really convenient to // have something in an assembly that always generates metadata. @@ -50,15 +50,12 @@ public override IEnumerable GetStaticDependencies(NodeFacto { dependencies.Add(factory.ModuleMetadata(satelliteModule), "Satellite assembly"); } - - return dependencies; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new List(); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, (EcmaAssembly)_module); - return dependencies; + DependencySink dependencies = sink; + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(dependencies, factory, (EcmaAssembly)_module); } protected override string GetName(NodeFactory factory) @@ -70,6 +67,6 @@ protected override string GetName(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleUseBasedDependencyAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleUseBasedDependencyAlgorithm.cs index c5409e8d882cec..d7e503459165e6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleUseBasedDependencyAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleUseBasedDependencyAlgorithm.cs @@ -3,20 +3,19 @@ using Internal.TypeSystem; -using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { internal static class ModuleUseBasedDependencyAlgorithm { - internal static void AddDependenciesDueToModuleUse(ref DependencyList dependencyList, NodeFactory factory, ModuleDesc module) + internal static void AddDependenciesDueToModuleUse(IDependencySink dependencyList, NodeFactory factory, ModuleDesc module) { - dependencyList ??= new DependencyList(); if (module.GetGlobalModuleType().GetStaticConstructor() is MethodDesc moduleCctor) { dependencyList.Add(factory.MethodEntrypoint(moduleCctor), "Module with a static constructor"); } - factory.MetadataManager.GetDependenciesDueToModuleUse(ref dependencyList, factory, module); + factory.MetadataManager.GetDependenciesDueToModuleUse(dependencyList, factory, module); } } } 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 e93b8c6a73f6a2..01861976fcad22 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -20,7 +20,7 @@ namespace ILCompiler.DependencyAnalysis /// NativeLayoutVertexNode nodes, and track it as a dependency of itself. /// Example: MethodCodeNodes that are saved to the table in the ExactMethodInstantiationsNode reference /// signatures stored in the native layout blob, so a NativeLayoutPlacedSignatureVertexNode node is created - /// and returned as a static dependency of the associated MethodCodeNode (in the GetStaticDependencies API). + /// and added as a static dependency of the associated MethodCodeNode (in the AddStaticDependencies API). /// /// Each NativeLayoutVertexNode that gets marked in the graph will register itself with the NativeLayoutInfoNode, /// so that the NativeLayoutInfoNode can write it later to the native layout blob during the call to its GetData API. @@ -39,14 +39,12 @@ public virtual void CheckIfMarkedEnoughToWrite() Debug.Assert(Marked); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { - return Array.Empty(); } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { - return Array.Empty(); } protected override void OnMarked(NodeFactory context) @@ -127,9 +125,9 @@ public NativeLayoutMethodEntryVertexNode(NodeFactory factory, MethodDesc method, } } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; if ((_flags & MethodEntryFlags.CreateInstantiatedSignature) != 0) { @@ -152,10 +150,8 @@ public override IEnumerable GetStaticDependencies(NodeFacto IMethodNode methodEntryPointNode = GetMethodEntrypointNode(context); dependencies.Add(new DependencyListEntry(methodEntryPointNode, "NativeLayoutMethodEntryVertexNode entrypoint")); } + context.MetadataManager.AddNativeLayoutMetadataDependencies(dependencies, context, GetMethodForMetadata(_method, out _, out _)); - context.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, context, GetMethodForMetadata(_method, out _, out _)); - - return dependencies; } public override Vertex WriteVertex(NodeFactory factory) @@ -268,15 +264,14 @@ public NativeLayoutMethodSignatureVertexNode(NodeFactory factory, Internal.TypeS _parametersSig[i] = factory.NativeLayout.TypeSignatureVertex(signature[i]); } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(new DependencyListEntry(_returnTypeSig, "NativeLayoutMethodSignatureVertexNode return type signature")); foreach (var arg in _parametersSig) dependencies.Add(new DependencyListEntry(arg, "NativeLayoutMethodSignatureVertexNode parameter signature")); - return dependencies; } public override Vertex WriteVertex(NodeFactory factory) @@ -352,9 +347,9 @@ public NativeLayoutParameterizedTypeSignatureVertexNode(NodeFactory factory, Typ { _parameterTypeSig = factory.NativeLayout.TypeSignatureVertex(((ParameterizedType)type).ParameterType); } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return new DependencyListEntry[] { new DependencyListEntry(_parameterTypeSig, "NativeLayoutParameterizedTypeSignatureVertexNode parameter type signature") }; + sink.Add(_parameterTypeSig, "NativeLayoutParameterizedTypeSignatureVertexNode parameter type signature"); } public override Vertex WriteVertex(NodeFactory factory) { @@ -396,9 +391,9 @@ public NativeLayoutFunctionPointerTypeSignatureVertexNode(NodeFactory factory, T { _sig = factory.NativeLayout.MethodSignatureVertex(((FunctionPointerType)type).Signature); } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return new DependencyListEntry[] { new DependencyListEntry(_sig, "Method signature") }; + sink.Add(_sig, "Method signature"); } public override Vertex WriteVertex(NodeFactory factory) { @@ -413,9 +408,8 @@ private sealed class NativeLayoutGenericVarSignatureVertexNode : NativeLayoutTyp public NativeLayoutGenericVarSignatureVertexNode(TypeDesc type) : base(type) { } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return Array.Empty(); } public override Vertex WriteVertex(NodeFactory factory) { @@ -450,15 +444,14 @@ public NativeLayoutInstantiatedTypeSignatureVertexNode(NodeFactory factory, Type _instantiationArgs[i] = factory.NativeLayout.TypeSignatureVertex(type.Instantiation[i]); } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(new DependencyListEntry(_genericTypeDefSig, "NativeLayoutInstantiatedTypeSignatureVertexNode generic definition signature")); foreach (var arg in _instantiationArgs) dependencies.Add(new DependencyListEntry(arg, "NativeLayoutInstantiatedTypeSignatureVertexNode instantiation argument signature")); - return dependencies; } public override Vertex WriteVertex(NodeFactory factory) { @@ -480,17 +473,15 @@ public NativeLayoutEETypeSignatureVertexNode(TypeDesc type) : base(type) Debug.Assert(!type.IsRuntimeDeterminedSubtype); Debug.Assert(!type.HasInstantiation || type.IsGenericDefinition); } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return new DependencyListEntry[] - { - // TODO-SIZE: this might be overly generous because we don't track what this type is used for. - // A necessary EEType might be enough for some cases. - // But we definitely need constructed if this is e.g. layout for a typehandle. - // Measurements show this doesn't amount to much (0.004% - 0.3% size cost vs Necessary). - new DependencyListEntry(_type.IsGenericDefinition ? context.NecessaryTypeSymbol(_type) : context.MaximallyConstructableType(_type), - "NativeLayoutEETypeVertexNode containing type signature") - }; + // TODO-SIZE: this might be overly generous because we don't track what this type is used for. + // A necessary EEType might be enough for some cases. + // But we definitely need constructed if this is e.g. layout for a typehandle. + // Measurements show this doesn't amount to much (0.004% - 0.3% size cost vs Necessary). + sink.Add( + _type.IsGenericDefinition ? context.NecessaryTypeSymbol(_type) : context.MaximallyConstructableType(_type), + "NativeLayoutEETypeVertexNode containing type signature"); } public override Vertex WriteVertex(NodeFactory factory) { @@ -514,12 +505,9 @@ public NativeLayoutExternalReferenceVertexNode(NodeFactory factory, ISymbolNode protected override string GetName(NodeFactory factory) => "NativeLayoutISymbolNodeReferenceVertexNode " + _symbol.GetMangledName(factory.NameMangler); - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return new DependencyListEntry[] - { - new DependencyListEntry(_symbol, "NativeLayoutISymbolNodeReferenceVertexNode containing symbol") - }; + sink.Add(_symbol, "NativeLayoutISymbolNodeReferenceVertexNode containing symbol"); } public override Vertex WriteVertex(NodeFactory factory) @@ -541,9 +529,9 @@ public NativeLayoutPlacedSignatureVertexNode(NativeLayoutVertexNode signatureToB { _signatureToBePlaced = signatureToBePlaced; } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return new DependencyListEntry[] { new DependencyListEntry(_signatureToBePlaced, "NativeLayoutPlacedSignatureVertexNode placed signature") }; + sink.Add(_signatureToBePlaced, "NativeLayoutPlacedSignatureVertexNode placed signature"); } public override Vertex WriteVertex(NodeFactory factory) { @@ -570,10 +558,9 @@ public NativeLayoutPlacedVertexSequenceOfUIntVertexNode(List uints) _uints = uints; } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { // There are no interesting dependencies - return null; } public override Vertex WriteVertex(NodeFactory factory) @@ -606,15 +593,12 @@ public NativeLayoutPlacedVertexSequenceVertexNode(List v _vertices = vertices; } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyListEntry[] dependencies = new DependencyListEntry[_vertices.Count]; for (int i = 0; i < _vertices.Count; i++) { - dependencies[i] = new DependencyListEntry(_vertices[i], "NativeLayoutPlacedVertexSequenceVertexNode element"); + sink.Add(_vertices[i], "NativeLayoutPlacedVertexSequenceVertexNode element"); } - - return dependencies; } public override Vertex WriteVertex(NodeFactory factory) @@ -677,9 +661,10 @@ protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory) return methodEntryPointNode; } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyList dependencies = (DependencyList)base.GetStaticDependencies(context); + DependencySink dependencies = sink; + base.AddStaticDependencies(sink, context); foreach (var arg in _method.Instantiation) { @@ -695,7 +680,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable OwningType")); } - return dependencies; } } @@ -741,22 +725,17 @@ private GenericContextKind ContextKind(NodeFactory factory) } } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { if ((ContextKind(context) & GenericContextKind.HasDeclaringType) != 0) { - return new DependencyListEntry[] - { + sink.AddRange( new DependencyListEntry(context.NativeLayout.TypeSignatureVertex((TypeDesc)_owningMethodOrType), "DeclaringType signature"), - new DependencyListEntry(context.GenericDictionaryLayout(_owningMethodOrType), "Dictionary Layout") - }; + new DependencyListEntry(context.GenericDictionaryLayout(_owningMethodOrType), "Dictionary Layout")); } else { - return new DependencyListEntry[] - { - new DependencyListEntry(context.GenericDictionaryLayout(_owningMethodOrType), "Dictionary Layout") - }; + sink.Add(context.GenericDictionaryLayout(_owningMethodOrType), "Dictionary Layout"); } } @@ -812,18 +791,18 @@ public NativeLayoutTemplateMethodLayoutVertexNode(NodeFactory factory, MethodDes Debug.Assert(method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method, "Assert that the canonical method passed in is in standard canonical form"); } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { - yield return new DependencyListEntry(dependency, "method OwningType itself must be template loadable"); + sink.Add(dependency, "method OwningType itself must be template loadable"); } foreach (var type in _method.Instantiation) { foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(type)) { - yield return new DependencyListEntry(dependency, "method's instantiation arguments must be template loadable"); + sink.Add(dependency, "method's instantiation arguments must be template loadable"); } } @@ -832,11 +811,11 @@ public override IEnumerable GetStaticDependencies(NodeFacto foreach (TypeDesc typeConstraint in genericParam.TypeConstraints) { if (typeConstraint.IsInterface) - yield return new DependencyListEntry(context.InterfaceUse(typeConstraint.GetTypeDefinition()), "Used as constraint"); + sink.Add(context.InterfaceUse(typeConstraint.GetTypeDefinition()), "Used as constraint"); } } - yield return new DependencyListEntry(context.GenericDictionaryLayout(_method), "Dictionary layout"); + sink.Add(context.GenericDictionaryLayout(_method), "Dictionary layout"); } private static int CompareDictionaryEntries(KeyValuePair left, KeyValuePair right) @@ -925,32 +904,32 @@ private ISymbolNode GetThreadStaticsNode(NodeFactory context, out BagElementKind return symbol; } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { ISymbolNode typeNode = context.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Specific)); - yield return new DependencyListEntry(typeNode, "Template MethodTable"); + sink.Add(typeNode, "Template MethodTable"); foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_type)) { - yield return new DependencyListEntry(dependency, "type itslef must be template loadable"); + sink.Add(dependency, "type itslef must be template loadable"); } - yield return new DependencyListEntry(context.GenericDictionaryLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific).GetClosestDefType()), "Dictionary layout"); + sink.Add(context.GenericDictionaryLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific).GetClosestDefType()), "Dictionary layout"); foreach (TypeDesc iface in _type.RuntimeInterfaces) { - yield return new DependencyListEntry(context.NativeLayout.TypeSignatureVertex(iface), "template interface list"); + sink.Add(context.NativeLayout.TypeSignatureVertex(iface), "template interface list"); foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(iface)) { - yield return new DependencyListEntry(dependency, "interface type dependency must be template loadable"); + sink.Add(dependency, "interface type dependency must be template loadable"); } } if (context.PreinitializationManager.HasLazyStaticConstructor(_type.ConvertToCanonForm(CanonicalFormKind.Specific))) { - yield return new DependencyListEntry(context.MethodEntrypoint(_type.GetStaticConstructor().GetCanonMethodTarget(CanonicalFormKind.Specific)), "cctor for template"); + sink.Add(context.MethodEntrypoint(_type.GetStaticConstructor().GetCanonMethodTarget(CanonicalFormKind.Specific)), "cctor for template"); } foreach (GenericParameterDesc genericParam in _type.GetTypeDefinition().Instantiation) @@ -958,19 +937,19 @@ public override IEnumerable GetStaticDependencies(NodeFacto foreach (TypeDesc typeConstraint in genericParam.TypeConstraints) { if (typeConstraint.IsInterface) - yield return new DependencyListEntry(context.InterfaceUse(typeConstraint.GetTypeDefinition()), "Used as constraint"); + sink.Add(context.InterfaceUse(typeConstraint.GetTypeDefinition()), "Used as constraint"); } } DefType closestCanonDefType = (DefType)_type.GetClosestDefType().ConvertToCanonForm(CanonicalFormKind.Specific); if (closestCanonDefType.GCStaticFieldSize.AsInt > 0) { - yield return new DependencyListEntry(GetStaticsNode(context, out _), "type gc static info"); + sink.Add(GetStaticsNode(context, out _), "type gc static info"); } if (closestCanonDefType.ThreadGcStaticFieldSize.AsInt > 0) { - yield return new DependencyListEntry(GetThreadStaticsNode(context, out _), "type thread static info"); + sink.Add(GetThreadStaticsNode(context, out _), "type thread static info"); } if (_type.BaseType != null && !_type.BaseType.IsRuntimeDeterminedSubtype) @@ -978,24 +957,24 @@ public override IEnumerable GetStaticDependencies(NodeFacto TypeDesc baseType = _type.BaseType; do { - yield return new DependencyListEntry(context.MaximallyConstructableType(baseType), "base types of canonical types must have their full vtables"); + sink.Add(context.MaximallyConstructableType(baseType), "base types of canonical types must have their full vtables"); baseType = baseType.BaseType; } while (baseType != null); } if (_type.BaseType != null && _type.BaseType.IsRuntimeDeterminedSubtype) { - yield return new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(_type.BaseType)), "template base type"); + sink.Add(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(_type.BaseType)), "template base type"); foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_type.BaseType)) { - yield return new DependencyListEntry(dependency, "base type must be template loadable"); + sink.Add(dependency, "base type must be template loadable"); } } } public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } private static int CompareDictionaryEntries(KeyValuePair left, KeyValuePair right) { @@ -1085,7 +1064,7 @@ public override Vertex WriteVertex(NodeFactory factory) public abstract class NativeLayoutGenericDictionarySlotNode : NativeLayoutVertexNode { - public abstract override IEnumerable GetStaticDependencies(NodeFactory context); + public abstract override void AddStaticDependencies(DependencySink sink, NodeFactory context); protected abstract Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory); protected abstract FixupSignatureKind SignatureKind { get; } @@ -1112,13 +1091,13 @@ public NativeLayoutTypeSignatureBasedGenericDictionarySlotNode(NodeFactory facto protected abstract string NodeTypeName { get; } protected sealed override string GetName(NodeFactory factory) => NodeTypeName + factory.NameMangler.GetMangledTypeName(_type); - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - yield return new DependencyListEntry(_signature, "TypeSignature"); + sink.Add(_signature, "TypeSignature"); foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_type)) { - yield return new DependencyListEntry(dependency, "template construction dependency"); + sink.Add(dependency, "template construction dependency"); } } @@ -1200,13 +1179,13 @@ public NativeLayoutStaticsGenericDictionarySlotNode(NodeFactory factory, TypeDes protected sealed override string GetName(NodeFactory factory) => NodeTypeName + factory.NameMangler.GetMangledTypeName(_type); protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.StaticData; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - yield return new DependencyListEntry(_signature, "TypeSignature"); + sink.Add(_signature, "TypeSignature"); foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_type)) { - yield return new DependencyListEntry(dependency, "template construction dependency"); + sink.Add(dependency, "template construction dependency"); } } @@ -1248,9 +1227,9 @@ public NativeLayoutInterfaceDispatchGenericDictionarySlotNode(NodeFactory factor protected sealed override string GetName(NodeFactory factory) => "NativeLayoutInterfaceDispatchGenericDictionarySlotNode_" + factory.NameMangler.GetMangledMethodName(_method); protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.InterfaceCall; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - yield return new DependencyListEntry(_signature, "TypeSignature"); + sink.Add(_signature, "TypeSignature"); MethodDesc method = _method; if (method.IsRuntimeDeterminedExactMethod) @@ -1258,12 +1237,12 @@ public sealed override IEnumerable GetStaticDependencies(No if (!factory.VTable(method.OwningType).HasKnownVirtualMethodUse) { - yield return new DependencyListEntry(factory.VirtualMethodUse(method), "Slot number"); + sink.Add(factory.VirtualMethodUse(method), "Slot number"); } foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(method.OwningType)) { - yield return new DependencyListEntry(dependency, "template construction dependency"); + sink.Add(dependency, "template construction dependency"); } } @@ -1293,9 +1272,9 @@ public NativeLayoutGvmDispatchGenericDictionarySlotNode(NodeFactory factory, Met protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.GvmDispatchCell; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - var result = new DependencyList(); + DependencySink result = sink; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { @@ -1310,10 +1289,9 @@ public sealed override IEnumerable GetStaticDependencies(No MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific); result.Add(factory.GVMDependencies(canonMethod), "GVM dependencies"); - factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref result, factory, GvmDispatchCellInfoSectionNode.GetMethodForMetadata(_method, out _)); + factory.MetadataManager.AddNativeLayoutMetadataDependencies(result, factory, GvmDispatchCellInfoSectionNode.GetMethodForMetadata(_method, out _)); result.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); - return result; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1334,9 +1312,9 @@ public NativeLayoutMethodDictionaryGenericDictionarySlotNode(NodeFactory factory protected sealed override string GetName(NodeFactory factory) => "NativeLayoutMethodDictionaryGenericDictionarySlotNode_" + factory.NameMangler.GetMangledMethodName(_method); protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.MethodDictionary; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new DependencyList(); + DependencySink dependencies = sink; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { @@ -1349,11 +1327,10 @@ public sealed override IEnumerable GetStaticDependencies(No dependencies.Add(dependency, "template construction dependency for method Instantiation types"); } - GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + GenericMethodsTemplateMap.AddTemplateMethodDependencies(dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); dependencies.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); - return dependencies; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1376,23 +1353,18 @@ public NativeLayoutFieldLdTokenGenericDictionarySlotNode(FieldDesc field) protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.FieldLdToken; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - var result = new DependencyList - { - { factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Owning type of field" } - }; + sink.Add(factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Owning type of field"); foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType)) { - result.Add(dependency, "template construction dependency"); + sink.Add(dependency, "template construction dependency"); } var canonOwningType = (InstantiatedType)_field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); FieldDesc canonField = factory.TypeSystemContext.GetFieldForInstantiatedType(_field.GetTypicalFieldDefinition(), canonOwningType); - factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, canonField); - - return result; + factory.MetadataManager.GetDependenciesDueToLdToken(sink, factory, canonField); } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1418,9 +1390,9 @@ public NativeLayoutMethodLdTokenGenericDictionarySlotNode(NodeFactory factory, M protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.MethodLdToken; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - var result = new DependencyList(); + DependencySink result = sink; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { @@ -1433,7 +1405,7 @@ public sealed override IEnumerable GetStaticDependencies(No result.Add(dependency, "template construction dependency for method Instantiation types"); } - factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + factory.MetadataManager.GetDependenciesDueToLdToken(result, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); if (_method.IsVirtual && _method.HasInstantiation && !_method.IsGenericMethodDefinition && !_method.OwningType.IsGenericDefinition) { @@ -1442,7 +1414,6 @@ public sealed override IEnumerable GetStaticDependencies(No result.Add(factory.NativeLayout.MethodEntry(_method), "wrappednode"); - return result; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1486,7 +1457,7 @@ protected sealed override FixupSignatureKind SignatureKind } } - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { DependencyNodeCore constrainedMethodDescriptorNode; if (_constrainedMethod.HasInstantiation) @@ -1498,28 +1469,28 @@ public sealed override IEnumerable GetStaticDependencies(No constrainedMethodDescriptorNode = factory.NativeLayout.TypeSignatureVertex(_constrainedMethod.OwningType); } - yield return new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_constraintType), "ConstraintType"); + sink.Add(factory.NativeLayout.TypeSignatureVertex(_constraintType), "ConstraintType"); - yield return new DependencyListEntry(constrainedMethodDescriptorNode, "ConstrainedMethodType"); + sink.Add(constrainedMethodDescriptorNode, "ConstrainedMethodType"); foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constrainedMethod.OwningType)) { - yield return new DependencyListEntry(dependency, "template construction dependency constrainedMethod OwningType"); + sink.Add(dependency, "template construction dependency constrainedMethod OwningType"); } foreach (var type in _constrainedMethod.Instantiation) { foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type)) - yield return new DependencyListEntry(dependency, "template construction dependency constrainedMethod Instantiation type"); + sink.Add(dependency, "template construction dependency constrainedMethod Instantiation type"); } foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constraintType)) - yield return new DependencyListEntry(dependency, "template construction dependency constraintType"); + sink.Add(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"); + sink.Add(factory.GVMDependencies(canonMethod), "Generic virtual method call"); } } @@ -1580,9 +1551,9 @@ public NativeLayoutMethodEntrypointGenericDictionarySlotNode(NodeFactory factory protected sealed override string GetName(NodeFactory factory) => "NativeLayoutMethodEntrypointGenericDictionarySlotNode_" + (_wrappedNode._unboxingStub ? "Unboxing_" : "") + factory.NameMangler.GetMangledMethodName(_method); protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.Method; - public sealed override IEnumerable GetStaticDependencies(NodeFactory factory) + public sealed override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType)) { @@ -1595,11 +1566,9 @@ public sealed override IEnumerable GetStaticDependencies(No dependencies.Add(dependency, "template construction dependency for method Instantiation types"); } - GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); - + GenericMethodsTemplateMap.AddTemplateMethodDependencies(dependencies, factory, _method.GetCanonMethodTarget(CanonicalFormKind.Specific)); dependencies.Add(_wrappedNode, "wrappednode"); - return dependencies; } protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory) @@ -1611,10 +1580,8 @@ protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeF public sealed class NativeLayoutNotSupportedDictionarySlotNode : NativeLayoutGenericDictionarySlotNode { protected override FixupSignatureKind SignatureKind => FixupSignatureKind.NotYetSupported; - - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - return null; } protected override string GetName(NodeFactory context) => "NativeLayoutNotSupportedDictionarySlotNode"; 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 2b04541d7d741b..636fc68edec7f4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -1306,7 +1306,7 @@ private sealed class ShadowConcreteMethodHashtable : LockFreeReaderHashtable key == value.Method; protected override bool CompareValueToValue(ShadowConcreteMethodNode value1, ShadowConcreteMethodNode value2) => value1.Method == value2.Method; protected override ShadowConcreteMethodNode CreateValueFromKey(MethodDesc key) => - new ShadowConcreteMethodNode(key, _factory.MethodEntrypoint(key.GetCanonMethodTarget(CanonicalFormKind.Specific))); + new ShadowConcreteMethodNode(key, (IMethodBodyNode)_factory.MethodEntrypoint(key.GetCanonMethodTarget(CanonicalFormKind.Specific))); protected override int GetKeyHashCode(MethodDesc key) => key.GetHashCode(); protected override int GetValueHashCode(ShadowConcreteMethodNode value) => value.Method.GetHashCode(); } @@ -1324,7 +1324,7 @@ private sealed class ShadowNonConcreteMethodHashtable : LockFreeReaderHashtable< protected override bool CompareKeyToValue(MethodDesc key, ShadowNonConcreteMethodNode value) => key == value.Method; protected override bool CompareValueToValue(ShadowNonConcreteMethodNode value1, ShadowNonConcreteMethodNode value2) => value1.Method == value2.Method; protected override ShadowNonConcreteMethodNode CreateValueFromKey(MethodDesc key) => - new ShadowNonConcreteMethodNode(key, _factory.MethodEntrypoint(key.GetCanonMethodTarget(CanonicalFormKind.Specific))); + new ShadowNonConcreteMethodNode(key, (IMethodBodyNode)_factory.MethodEntrypoint(key.GetCanonMethodTarget(CanonicalFormKind.Specific))); protected override int GetKeyHashCode(MethodDesc key) => key.GetHashCode(); protected override int GetValueHashCode(ShadowNonConcreteMethodNode value) => value.Method.GetHashCode(); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs index f2499a5859f7a6..e4104c748c5627 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs @@ -8,6 +8,7 @@ using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -155,32 +156,27 @@ public int GetAlignment(NodeFactory factory) public override bool HasConditionalStaticDependencies => _type.ConvertToCanonForm(CanonicalFormKind.Specific) != _type; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { // If we have a type loader template for this type, we need to keep track of the generated // bases in the type info hashtable. The type symbol node does such accounting. - return new CombinedDependencyListEntry[] - { + sink.Add( new CombinedDependencyListEntry(factory.NecessaryTypeSymbol(_type), factory.NativeLayout.TemplateTypeLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), - "Keeping track of template-constructable type static bases"), - }; + "Keeping track of template-constructable type static bases")); } public override bool StaticDependenciesAreComputed => true; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencyList = new DependencyList(); + DependencySink dependencyList = sink; if (factory.PreinitializationManager.HasEagerStaticConstructor(_type)) { dependencyList.Add(factory.EagerCctorIndirection(_type.GetStaticConstructor()), "Eager .cctor"); } - - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencyList, factory, _type.Module); - - return dependencyList; + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(dependencyList, factory, _type.Module); } private static bool IsNonGcStaticField(FieldDesc field) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NotReadOnlyFieldNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NotReadOnlyFieldNode.cs index c6fc397741aac4..091f1615a85964 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NotReadOnlyFieldNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NotReadOnlyFieldNode.cs @@ -36,8 +36,8 @@ protected override string GetName(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeCalledNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeCalledNode.cs index 10721729863182..77dec95a4dcf6e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeCalledNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeCalledNode.cs @@ -28,13 +28,13 @@ protected override string GetName(NodeFactory factory) return $"Object.GetType called on {_type}"; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeFlowDependenciesNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeFlowDependenciesNode.cs index 65cfe16246e14f..483de694a8916e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeFlowDependenciesNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectGetTypeFlowDependenciesNode.cs @@ -30,7 +30,7 @@ protected override string GetName(NodeFactory factory) return $"Object.GetType dependencies for {_type}"; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { #if ILTRIM FlowAnnotations flowAnnotations = factory.FlowAnnotations; @@ -41,31 +41,29 @@ public override IEnumerable GetStaticDependencies(NodeFacto Logger logger = mdManager.Logger; #endif - DependencyList result = Dataflow.ReflectionMethodBodyScanner.ProcessTypeGetTypeDataflow(factory, flowAnnotations, logger, _type); + Dataflow.ReflectionMethodBodyScanner.AddTypeGetTypeDataflowDependencies(sink, factory, flowAnnotations, logger, _type); MetadataType baseType = _type.BaseType; if (baseType != null && flowAnnotations.GetTypeAnnotation(baseType) != default) { - result.Add(factory.ObjectGetTypeFlowDependencies(baseType), "Apply annotations to bases"); + sink.Add(factory.ObjectGetTypeFlowDependencies(baseType), "Apply annotations to bases"); } foreach (DefType interfaceType in _type.RuntimeInterfaces) { if (flowAnnotations.GetTypeAnnotation(interfaceType) != default) { - result.Add(factory.ObjectGetTypeFlowDependencies((MetadataType)interfaceType), "Apply annotations to interfaces"); + sink.Add(factory.ObjectGetTypeFlowDependencies((MetadataType)interfaceType), "Apply annotations to interfaces"); } } - - return result; } 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PropertyMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PropertyMetadataNode.cs index 6a8fedbec05ee4..c19f03ec8b4b95 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PropertyMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PropertyMetadataNode.cs @@ -27,13 +27,12 @@ public PropertyMetadataNode(PropertyPseudoDesc property) public PropertyPseudoDesc Property => _property; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new List(); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, _property); - return dependencies; + DependencySink dependencies = sink; + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(dependencies, factory, _property); } protected override string GetName(NodeFactory factory) @@ -45,6 +44,6 @@ protected override string GetName(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapNode.cs index e82bb502c2cbe6..4f46e99d56a233 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapNode.cs @@ -38,30 +38,30 @@ public ProxyTypeMapNode(TypeDesc typeMapGroup, IEnumerable comparer.Compare(TypeMapGroup, ((ProxyTypeMapNode)other).TypeMapGroup); - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { foreach (var (key, value) in _mapEntries) { - yield return new CombinedDependencyListEntry( + sink.Add(new CombinedDependencyListEntry( context.MetadataTypeSymbol(value), context.MaximallyConstructableType(key), - "Proxy type map entry"); + "Proxy type map entry")); // If the key type has a canonical form, it could be created at runtime by the type loader. // If there is a type loader template for it, create the generic type instantiation eagerly. TypeDesc canonKey = key.ConvertToCanonForm(CanonicalFormKind.Specific); if (canonKey != key && GenericTypesTemplateMap.IsEligibleToHaveATemplate(canonKey)) { - yield return new CombinedDependencyListEntry( + sink.Add(new CombinedDependencyListEntry( context.MaximallyConstructableType(key), context.NativeLayout.TemplateTypeLayout(canonKey), - "Proxy map entry that could be loaded at runtime"); + "Proxy map entry that could be loaded at runtime")); } } } - public override IEnumerable GetStaticDependencies(NodeFactory context) => Array.Empty(); - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Proxy type map: {TypeMapGroup}"; private IEnumerable<(IEETypeNode key, IEETypeNode value)> GetMarkedEntries(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapRequestNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapRequestNode.cs index ebfb9a412c7a24..803eb17912e740 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapRequestNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapRequestNode.cs @@ -20,9 +20,9 @@ public sealed class ProxyTypeMapRequestNode(TypeDesc typeMapGroup) : DependencyN public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) => []; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Proxy type map request: {TypeMapGroup}"; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs index ec6fa5d049cd3f..266611e42dd31c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs @@ -126,9 +126,15 @@ private bool TriggersLazyStaticConstructor(NodeFactory factory) return factory.PreinitializationManager.HasLazyStaticConstructor(type.ConvertToCanonForm(CanonicalFormKind.Specific)); } - public IEnumerable InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, bool isConcreteInstantiation) +#nullable enable + public void AddDependencies( + DependencySink sink, + NodeFactory factory, + Instantiation typeInstantiation, + Instantiation methodInstantiation, + bool isConcreteInstantiation, + DependencyNodeCore? otherReasonNode) { - DependencyList result = new DependencyList(); var lookupContext = new GenericLookupResultContext(_dictionaryOwner, typeInstantiation, methodInstantiation); switch (_id) @@ -143,7 +149,7 @@ public IEnumerable InstantiateDependencies(NodeFactory fact var lookupTarget = factory.GenericLookup.TypeNonGCStaticBase((TypeDesc)_target).GetTarget(factory, lookupContext, isConcreteInstantiation); if (lookupTarget != null) { - result.Add(new DependencyListEntry(lookupTarget, "Dictionary dependency")); + AddDependency(sink, lookupTarget, "Dictionary dependency", otherReasonNode); } } } @@ -157,13 +163,14 @@ public IEnumerable InstantiateDependencies(NodeFactory fact MethodDesc instantiatedTargetMethod = createInfo.TargetMethod.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation); if (!factory.VTable(instantiatedTargetMethod.OwningType).HasKnownVirtualMethodUse) { - result.Add( - new DependencyListEntry( - factory.VirtualMethodUse(instantiatedTargetMethod), - "Dictionary dependency")); + AddDependency( + sink, + factory.VirtualMethodUse(instantiatedTargetMethod), + "Dictionary dependency", + otherReasonNode); } - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref result, factory, instantiatedTargetMethod); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(sink, factory, instantiatedTargetMethod, otherReasonNode); } } break; @@ -175,7 +182,7 @@ public IEnumerable InstantiateDependencies(NodeFactory fact if (lookupTarget != null) { // All generic lookups depend on the thing they point to - result.Add(new DependencyListEntry(lookupTarget, "Dictionary dependency")); + AddDependency(sink, lookupTarget, "Dictionary dependency", otherReasonNode); } } catch (TypeSystemException) @@ -184,11 +191,26 @@ public IEnumerable InstantiateDependencies(NodeFactory fact // dictionary. The helper needs to be able to handle a null slot and tailcall // and exception throwing helper instead of returning a result. _hasInvalidEntries = true; - result.Add(GetBadSlotHelper(factory), "Failure to build dictionary slot"); + AddDependency(sink, GetBadSlotHelper(factory), "Failure to build dictionary slot", otherReasonNode); } + } - return result.ToArray(); + private static void AddDependency( + DependencySink sink, + object dependency, + string reason, + DependencyNodeCore? otherReasonNode) + { + if (otherReasonNode is null) + { + sink.Add(dependency, reason); + } + else + { + sink.AddConditional(dependency, otherReasonNode, reason); + } } +#nullable restore private static IMethodNode GetBadSlotHelper(NodeFactory factory) { @@ -207,9 +229,9 @@ protected void AppendLookupSignatureMangledName(NameMangler nameMangler, Utf8Str } } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; if (_dictionaryOwner is TypeDesc type) { @@ -229,16 +251,14 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact { var delegateCreationInfo = (DelegateCreationInfo)_target; MethodDesc targetMethod = delegateCreationInfo.PossiblyUnresolvedTargetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); - factory.MetadataManager.GetDependenciesDueToDelegateCreation(ref dependencies, factory, delegateCreationInfo.DelegateType, targetMethod); + factory.MetadataManager.GetDependenciesDueToDelegateCreation(dependencies, factory, delegateCreationInfo.DelegateType, targetMethod); } - - return dependencies; } public override bool HasConditionalStaticDependencies => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - List conditionalDependencies = new List(); + DependencySink conditionalDependencies = sink; NativeLayoutSavedVertexNode templateLayout; if (_dictionaryOwner is MethodDesc) { @@ -274,10 +294,9 @@ public override IEnumerable GetConditionalStaticDep { var delegateCreationInfo = (DelegateCreationInfo)_target; MethodDesc targetMethod = delegateCreationInfo.PossiblyUnresolvedTargetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); - factory.MetadataManager.GetDependenciesDueToDelegateCreation(ref conditionalDependencies, factory, delegateCreationInfo.DelegateType, targetMethod); + factory.MetadataManager.GetConditionalDependenciesDueToDelegateCreation(conditionalDependencies, factory, delegateCreationInfo.DelegateType, targetMethod); } - return conditionalDependencies; } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs index 0109f977ea27ad..cad33a19373e48 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs @@ -8,6 +8,7 @@ using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -119,16 +120,16 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde public override bool IsShareable => true; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { if (_id == ReadyToRunHelperId.ResolveVirtualFunction) { var targetMethod = (MethodDesc)_target; - DependencyList dependencyList = new DependencyList(); + DependencySink dependencyList = sink; #if !SUPPORT_JIT - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref dependencyList, factory, targetMethod); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(dependencyList, factory, targetMethod); if (!factory.VTable(targetMethod.OwningType).HasKnownVirtualMethodUse) @@ -137,11 +138,11 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact } #endif - return dependencyList; + return; } else if (_id == ReadyToRunHelperId.DelegateCtor) { - DependencyList dependencyList = null; + DependencySink dependencyList = sink; var info = (DelegateCreationInfo)_target; if (info.NeedsVirtualMethodUseTracking) @@ -149,33 +150,30 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact MethodDesc targetMethod = info.TargetMethod; #if !SUPPORT_JIT - factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref dependencyList, factory, targetMethod); + factory.MetadataManager.AddDependenciesDueToVirtualMethodReflectability(dependencyList, factory, targetMethod); if (!factory.VTable(info.TargetMethod.OwningType).HasKnownVirtualMethodUse) { - dependencyList ??= new DependencyList(); + dependencyList.Add(factory.VirtualMethodUse(info.TargetMethod), "ReadyToRun Delegate to virtual method"); } #endif } - factory.MetadataManager.GetDependenciesDueToDelegateCreation(ref dependencyList, factory, info.DelegateType, + factory.MetadataManager.GetDependenciesDueToDelegateCreation(dependencyList, factory, info.DelegateType, info.PossiblyUnresolvedTargetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)); - return dependencyList; + return; } - - return null; } public override bool HasConditionalStaticDependencies => _id == ReadyToRunHelperId.DelegateCtor; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - List dependencyList = new List(); + DependencySink dependencyList = sink; var info = (DelegateCreationInfo)_target; - factory.MetadataManager.GetDependenciesDueToDelegateCreation(ref dependencyList, factory, info.DelegateType, info.PossiblyUnresolvedTargetMethod); - return dependencyList; + factory.MetadataManager.GetConditionalDependenciesDueToDelegateCreation(dependencyList, factory, info.DelegateType, info.PossiblyUnresolvedTargetMethod); } #if !SUPPORT_JIT diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedDelegateNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedDelegateNode.cs index 925642cd943846..06bb3a16c4471a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedDelegateNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedDelegateNode.cs @@ -38,12 +38,12 @@ protected override string GetName(NodeFactory factory) return "Reflectable delegate type: " + _delegateType?.ToString() ?? "All delegates"; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedFieldNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedFieldNode.cs index 60213cdfb8c634..ce2fae199858d4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedFieldNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedFieldNode.cs @@ -30,17 +30,17 @@ public ReflectedFieldNode(FieldDesc field) public FieldDesc Field => _field; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { Debug.Assert(!factory.MetadataManager.IsReflectionBlocked(_field.GetTypicalFieldDefinition())); - DependencyList dependencies = new DependencyList(); - factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencies, factory, _field); + DependencySink dependencies = sink; + factory.MetadataManager.GetDependenciesDueToReflectability(dependencies, factory, _field); // No runtime artifacts needed if this is a generic definition or literal field if (_field.OwningType.IsGenericDefinition || _field.IsLiteral) { - return dependencies; + return; } // readonly static fields are not reflection settable, the rest are @@ -97,10 +97,9 @@ public override IEnumerable GetStaticDependencies(NodeFacto } TypeDesc fieldType = _field.FieldType.NormalizeInstantiation(); - ReflectionInvokeMapNode.AddSignatureDependency(ref dependencies, factory, _field, fieldType, "Type of the field", isOut: true); - - return dependencies; + ReflectionInvokeMapNode.AddSignatureDependency(dependencies, factory, _field, fieldType, "Type of the field", isOut: true); } + protected override string GetName(NodeFactory factory) { return "Reflectable field: " + _field.ToString(); @@ -110,7 +109,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs index a12a6cf85d2969..d6ef12b2adad40 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedMethodNode.cs @@ -30,12 +30,12 @@ public ReflectedMethodNode(MethodDesc method) public MethodDesc Method => _method; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { Debug.Assert(!factory.MetadataManager.IsReflectionBlocked(_method.GetTypicalMethodDefinition())); - DependencyList dependencies = new DependencyList(); - factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencies, factory, _method); + DependencySink dependencies = sink; + factory.MetadataManager.GetDependenciesDueToReflectability(dependencies, factory, _method); // Ensure we consistently apply reflectability to all methods sharing the same definition. // Different instantiations of the method have a conditional dependency on the definition node that @@ -45,8 +45,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto { dependencies.Add(factory.ReflectedMethod(typicalMethod), "Definition of the reflectable method"); } - - return dependencies; } protected override string GetName(NodeFactory factory) { @@ -57,7 +55,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs index 0a6327db7e545d..99274ff7697715 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectedTypeNode.cs @@ -32,19 +32,14 @@ public ReflectedTypeNode(TypeDesc type) public TypeDesc Type => _type; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - var result = new DependencyList - { - new DependencyListEntry(factory.MaximallyConstructableType(_type), "Reflection target"), - }; + sink.Add(factory.MaximallyConstructableType(_type), "Reflection target"); if (_type.IsCanonicalSubtype(CanonicalFormKind.Any)) { - GenericTypesTemplateMap.GetTemplateTypeDependencies(ref result, factory, _type); + GenericTypesTemplateMap.AddTemplateTypeDependencies(sink, factory, _type); } - - return result; } protected override string GetName(NodeFactory factory) { @@ -55,7 +50,7 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } 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 7904d205ba0374..71ad47fb5ef50f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -9,6 +9,7 @@ using Debug = System.Diagnostics.Debug; using InvokeTableFlags = Internal.Runtime.InvokeTableFlags; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -37,12 +38,11 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - public static void AddDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void AddDependenciesDueToReflectability(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { Debug.Assert(factory.MetadataManager.IsReflectionInvokable(method)); Debug.Assert(method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method); - dependencies ??= new DependencyList(); dependencies.Add(factory.MaximallyConstructableType(method.OwningType), "Reflection invoke"); @@ -52,9 +52,9 @@ public static void AddDependenciesDueToReflectability(ref DependencyList depende dependencies.Add(factory.MethodEntrypoint(invokeStub), "Reflection invoke"); var signature = method.Signature; - AddSignatureDependency(ref dependencies, factory, method, signature.ReturnType, "Reflection invoke", isOut: true); + AddSignatureDependency(dependencies, factory, method, signature.ReturnType, "Reflection invoke", isOut: true); foreach (var parameterType in signature) - AddSignatureDependency(ref dependencies, factory, method, parameterType, "Reflection invoke", isOut: false); + AddSignatureDependency(dependencies, factory, method, parameterType, "Reflection invoke", isOut: false); } if (method.OwningType.IsValueType && !method.Signature.IsStatic) @@ -77,10 +77,10 @@ public static void AddDependenciesDueToReflectability(ref DependencyList depende } } - ReflectionVirtualInvokeMapNode.GetVirtualInvokeMapDependencies(ref dependencies, factory, method); + ReflectionVirtualInvokeMapNode.AddVirtualInvokeMapDependencies(dependencies, factory, method); } - internal static void AddSignatureDependency(ref DependencyList dependencies, NodeFactory factory, TypeSystemEntity referent, TypeDesc type, string reason, bool isOut) + internal static void AddSignatureDependency(IDependencySink dependencies, NodeFactory factory, TypeSystemEntity referent, TypeDesc type, string reason, bool isOut) { if (type.IsByRef) { @@ -104,7 +104,7 @@ internal static void AddSignatureDependency(ref DependencyList dependencies, Nod // Non-valuetypes are only needed for the purposes of casting/type checks. // If this is a non-exact type, we need the type loader template to get the type handle. if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - GenericTypesTemplateMap.GetTemplateTypeDependencies(ref dependencies, factory, type.NormalizeInstantiation()); + GenericTypesTemplateMap.AddTemplateTypeDependencies(dependencies, factory, type.NormalizeInstantiation()); else if (isOut && !type.IsGCPointer) dependencies.Add(factory.MaximallyConstructableType(type.NormalizeInstantiation()), reason); else diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeSupportDependencyAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeSupportDependencyAlgorithm.cs index 4e8ffb80febb79..1375123f7b315f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeSupportDependencyAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeSupportDependencyAlgorithm.cs @@ -7,6 +7,7 @@ using Internal.TypeSystem.Ecma; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -26,7 +27,7 @@ internal static class ReflectionInvokeSupportDependencyAlgorithm // typeof(MyStruct).InvokeMember(nameof(Count), BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { default(MyStruct) }); // } // } - public static void GetDependenciesFromParamsArray(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void GetDependenciesFromParamsArray(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { MethodSignature sig = method.Signature; if (sig.Length < 1 || !sig[sig.Length - 1].IsArray) @@ -45,7 +46,6 @@ public static void GetDependenciesFromParamsArray(ref DependencyList dependencie { if (!reader.GetCustomAttributeHandle(param.GetCustomAttributes(), "System", "ParamArrayAttribute").IsNil) { - dependencies ??= new DependencyList(); dependencies.Add( factory.ConstructedTypeSymbol(sig[sig.Length - 1].NormalizeInstantiation()), "Reflection invoke"); 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 51371d4fa06f54..b1204989c959b4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs @@ -10,6 +10,7 @@ using Internal.NativeFormat; using VirtualInvokeTableEntry = Internal.Runtime.VirtualInvokeTableEntry; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -76,11 +77,10 @@ public static MethodDesc GetDeclaringVirtualMethodAndHierarchyDistance(MethodDes return declaringMethodForSlot; } - public static void GetVirtualInvokeMapDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public static void AddVirtualInvokeMapDependencies(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { if (NeedsVirtualInvokeInfo(factory, method)) { - dependencies ??= new DependencyList(); dependencies.Add( factory.NecessaryTypeSymbol(method.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific)), 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 150d4d6a0e9a32..526fd16b2ba304 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs @@ -5,6 +5,7 @@ using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -38,11 +39,10 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) return ObjectNodeSection.DataSection; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList result = null; - factory.MetadataManager.GetDependenciesDueToLdToken(ref result, factory, _targetField); - return result; + DependencySink result = sink; + factory.MetadataManager.GetDependenciesDueToLdToken(result, factory, _targetField); } protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) 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 18462fbdc15e8e..d6051e9a816c05 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -6,6 +6,7 @@ using Internal.Runtime; using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -46,26 +47,23 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) return ObjectNodeSection.DataSection; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; + DependencySink dependencies = sink; if (!_targetMethod.IsMethodDefinition && !_targetMethod.OwningType.IsGenericDefinition && _targetMethod.HasInstantiation && _targetMethod.IsVirtual) { - dependencies ??= new DependencyList(); + MethodDesc canonMethod = _targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); dependencies.Add(factory.GVMDependencies(canonMethod), "GVM dependencies for runtime method handle"); // GVM analysis happens on canonical forms, but this is potentially injecting new genericness // into the system. Ensure reflection analysis can still see this. if (_targetMethod.IsAbstract) - factory.MetadataManager.GetDependenciesDueToMethodCodePresence(ref dependencies, factory, canonMethod, methodIL: null); + factory.MetadataManager.GetDependenciesDueToMethodCodePresence(dependencies, factory, canonMethod, methodIL: null); } - - factory.MetadataManager.GetDependenciesDueToLdToken(ref dependencies, factory, _targetMethod); - - return dependencies; + factory.MetadataManager.GetDependenciesDueToLdToken(dependencies, factory, _targetMethod); } protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ScannedMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ScannedMethodNode.cs index cd4dd351393edf..8fbf75165bf3af 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ScannedMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ScannedMethodNode.cs @@ -9,7 +9,7 @@ using Internal.Text; using Internal.TypeSystem; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; using Debug = System.Diagnostics.Debug; namespace ILCompiler.DependencyAnalysis @@ -76,17 +76,66 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.GetMangledMethodName(_method)); } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { Debug.Assert(_dependencies != null); - return _dependencies; + foreach (DependencyListEntry dependency in _dependencies) + { + sink.Add(dependency); + } + } + + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) + { + foreach (CombinedDependencyListEntry dependency in _conditionalDependencies) + { + sink.Add(dependency); + } + } + +#nullable enable + + public void AddRuntimeDeterminedStaticDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod) + { + foreach (DependencyListEntry dependency in _dependencies) + { + AddRuntimeDeterminedDependency(sink, factory, concreteMethod, dependency.Node, otherReasonNode: null); + } + } + + public void AddRuntimeDeterminedConditionalDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod) + { + foreach (CombinedDependencyListEntry dependency in _conditionalDependencies) + { + Debug.Assert(dependency.OtherReasonNode is not INodeWithRuntimeDeterminedDependencies); + AddRuntimeDeterminedDependency(sink, factory, concreteMethod, dependency.Node, dependency.OtherReasonNode); + } + } + + private static void AddRuntimeDeterminedDependency( + DependencySink sink, + NodeFactory factory, + MethodDesc concreteMethod, + DependencyNodeCore dependency, + DependencyNodeCore? otherReasonNode) + { + if (dependency is INodeWithRuntimeDeterminedDependencies runtimeDeterminedDependency) + { + runtimeDeterminedDependency.AddDependencies( + sink, + factory, + concreteMethod.OwningType.Instantiation, + concreteMethod.Instantiation, + isConcreteInstantiation: !concreteMethod.IsSharedByGenericInstantiations, + otherReasonNode); + } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => _conditionalDependencies; +#nullable restore protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } public override bool InterestingForDynamicDependencyAnalysis => _method.HasInstantiation || _method.OwningType.HasInstantiation; public override bool HasDynamicDependencies => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SealedVTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SealedVTableNode.cs index 2d994f76ec054c..f2db734b5abe1c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SealedVTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SealedVTableNode.cs @@ -8,6 +8,7 @@ using Internal.Runtime; using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -244,20 +245,24 @@ public bool BuildSealedVTableSlots(NodeFactory factory, bool relocsOnly) return true; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { BuildSealedVTableSlots(factory, relocsOnly: true); - var result = new DependencyList(_nonRelocationDependencies ?? []); + if (_nonRelocationDependencies is not null) + { + foreach (DependencyListEntry dependency in _nonRelocationDependencies) + { + sink.Add(dependency); + } + } // When building the sealed vtable, we consult the vtable layout of these types TypeDesc declType = _type.GetClosestDefType(); - result.Add(factory.VTable(declType), "VTable of the type"); + sink.Add(factory.VTable(declType), "VTable of the type"); foreach (var interfaceType in declType.RuntimeInterfaces) - result.Add(factory.VTable(interfaceType), "VTable of the interface"); - - return result; + sink.Add(factory.VTable(interfaceType), "VTable of the interface"); } public override ObjectData GetData(NodeFactory factory, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs index f3bb469c986942..cd8154afaa0c13 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs @@ -7,7 +7,8 @@ using Internal.Text; using Internal.TypeSystem; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -59,11 +60,9 @@ public override void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFacto public override bool HasConditionalStaticDependencies => _data.HasConditionalDependencies; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - CombinedDependencyList result = null; - _data.GetConditionalDependencies(ref result, factory); - return result; + _data.AddConditionalDependencies(sink, factory); } public override int ClassCode => 1789429316; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs index 5b7064d09d3b9d..f7aab7d479e6b7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.NativeFormat; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -40,7 +41,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) /// This helper is used by EETypeNode, which is used by the dependency analysis to compute the statics hashtable /// entries for the compiled types. /// - public static void AddStaticsInfoDependencies(ref DependencyList dependencies, NodeFactory factory, MetadataType metadataType) + public static void AddStaticsInfoDependencies(DependencySink dependencies, NodeFactory factory, MetadataType metadataType) { Debug.Assert(metadataType.HasInstantiation && !metadataType.IsCanonicalSubtype(CanonicalFormKind.Any)); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs index ff8277f1ea1fa7..2cfffaf87e4acc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs @@ -46,9 +46,9 @@ public StringAllocatorMethodNode(MethodDesc constructorMethod) _constructorMethod = constructorMethod; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList result = new DependencyList(); + DependencySink result = sink; result.Add( factory.ConstructedTypeSymbol(factory.TypeSystemContext.GetWellKnownType(WellKnownType.String)), @@ -56,10 +56,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto result.Add( factory.MethodEntrypoint(_allocationMethod), "String constructor call"); - - factory.MetadataManager.GetDependenciesDueToMethodCodePresence(ref result, factory, _constructorMethod, methodIL: null); - - return result; + factory.MetadataManager.GetDependenciesDueToMethodCodePresence(result, factory, _constructorMethod, methodIL: null); } public override bool HasConditionalStaticDependencies => false; @@ -67,8 +64,8 @@ public override IEnumerable GetStaticDependencies(NodeFacto public override bool InterestingForDynamicDependencyAnalysis => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingDataNode.cs index ffdb02e24d5d9c..79a7f3832ade0c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingDataNode.cs @@ -24,19 +24,19 @@ public StructMarshallingDataNode(DefType type) _type = type; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { InteropStateManager stateManager = ((CompilerGeneratedInteropStubManager)factory.InteropStubManager)._interopStateManager; - yield return new DependencyListEntry(factory.NecessaryTypeSymbol(_type), "Struct Marshalling Stub"); + sink.Add(factory.NecessaryTypeSymbol(_type), "Struct Marshalling Stub"); // Not all StructMarshalingDataNodes require marshalling - some are only present because we want to // generate field offset information for Marshal.OffsetOf. if (MarshalHelpers.IsStructMarshallingRequired(_type)) { - yield return new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetStructMarshallingManagedToNativeThunk(_type)), "Struct Marshalling stub"); - yield return new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetStructMarshallingNativeToManagedThunk(_type)), "Struct Marshalling stub"); - yield return new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetStructMarshallingCleanupThunk(_type)), "Struct Marshalling stub"); + sink.Add(factory.MethodEntrypoint(stateManager.GetStructMarshallingManagedToNativeThunk(_type)), "Struct Marshalling stub"); + sink.Add(factory.MethodEntrypoint(stateManager.GetStructMarshallingNativeToManagedThunk(_type)), "Struct Marshalling stub"); + sink.Add(factory.MethodEntrypoint(stateManager.GetStructMarshallingCleanupThunk(_type)), "Struct Marshalling stub"); } } @@ -49,7 +49,7 @@ protected override string GetName(NodeFactory context) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeInstanceMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeInstanceMethodNode.cs index 601e594bd69df5..2a3006b2721b8a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeInstanceMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeInstanceMethodNode.cs @@ -5,6 +5,7 @@ using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -37,7 +38,7 @@ protected override ISymbolNode GetTarget(NodeFactory factory) return helper == null ? RealBody: factory.MethodEntrypoint(helper); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { // Convert methods on Array into T[] TypeDesc owningType = Method.OwningType; @@ -48,13 +49,11 @@ public override IEnumerable GetConditionalStaticDep // If a constructed symbol for the owning type was included in the compilation, // include the real method body. - return new CombinedDependencyListEntry[] - { + sink.Add( new CombinedDependencyListEntry( RealBody, factory.ConstructedTypeSymbol(owningType), - "Instance method on a constructed type"), - }; + "Instance method on a constructed type")); } protected override string GetName(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeMethodNode.cs index dc3b811b873d2a..6d219e78e02c5d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TentativeMethodNode.cs @@ -49,8 +49,8 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return _methodNode.Marked; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs index a44f88e77c5581..b8bb629d9751c6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs @@ -6,6 +6,7 @@ using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -66,9 +67,9 @@ private ISymbolNode GetGCStaticEETypeNode(NodeFactory factory) return factory.GCStaticEEType(map, requiresAlign8); } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList result = new DependencyList(); + DependencySink result = sink; result.Add(new DependencyListEntry(GetGCStaticEETypeNode(factory), "ThreadStatic MethodTable")); @@ -79,7 +80,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto result.Add(new DependencyListEntry(factory.EagerCctorIndirection(_type.GetStaticConstructor()), "Eager .cctor")); } - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref result, factory, _type.Module); + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(result, factory, _type.Module); } else { @@ -93,11 +94,9 @@ public override IEnumerable GetStaticDependencies(NodeFacto // inlined threadstatics do not need the index for execution, but may need it for debug visualization. result.Add(new DependencyListEntry(factory.TypeThreadStaticIndex(type), "ThreadStatic index for debug visualization")); - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref result, factory, type.Module); + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(result, factory, type.Module); } } - - return result; } public override bool HasConditionalStaticDependencies => @@ -105,18 +104,16 @@ public override IEnumerable GetStaticDependencies(NodeFacto _type.ConvertToCanonForm(CanonicalFormKind.Specific) != _type: false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { Debug.Assert(_type != null); // If we have a type loader template for this type, we need to keep track of the generated // bases in the type info hashtable. The type symbol node does such accounting. - return new CombinedDependencyListEntry[] - { + sink.Add( new CombinedDependencyListEntry(factory.NecessaryTypeSymbol(_type), factory.NativeLayout.TemplateTypeLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), - "Keeping track of template-constructable type static bases"), - }; + "Keeping track of template-constructable type static bases")); } public override bool StaticDependenciesAreComputed => true; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TrimmingDescriptorNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TrimmingDescriptorNode.cs index 07a3b9aa8d0cdf..0e1bca39905f89 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TrimmingDescriptorNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TrimmingDescriptorNode.cs @@ -22,16 +22,19 @@ public TrimmingDescriptorNode(string fileName) _fileName = fileName; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { using (Stream fs = File.OpenRead(_fileName)) { #if ILTRIM - return DescriptorMarker.GetDependencies(factory.Logger, factory, fs, default, default, _fileName, factory.Settings.FeatureSettings); + foreach (DependencyListEntry dependency in DescriptorMarker.GetDependencies(factory.Logger, factory, fs, default, default, _fileName, factory.Settings.FeatureSettings)) #else var metadataManager = (UsageBasedMetadataManager)factory.MetadataManager; - return DescriptorMarker.GetDependencies(metadataManager.Logger, factory, fs, default, default, _fileName, metadataManager.FeatureSwitches); + foreach (DependencyListEntry dependency in DescriptorMarker.GetDependencies(metadataManager.Logger, factory, fs, default, default, _fileName, metadataManager.FeatureSwitches)) #endif + { + sink.Add(dependency); + } } } @@ -44,8 +47,8 @@ protected override string GetName(NodeFactory factory) 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; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } #if !ILTRIM void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) => rootProvider.AddCompilationRoot(this, "Descriptor from command line"); #endif 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 309ea19a4e090b..f7b0cafacba64b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeGVMEntriesNode.cs @@ -41,8 +41,6 @@ public InterfaceGVMEntryInfo(MethodDesc callingMethod, MethodDesc implementation } private readonly TypeDesc _associatedType; - private DependencyList _staticDependencies; - public TypeGVMEntriesNode(TypeDesc associatedType) { Debug.Assert(associatedType.IsTypeDefinition); @@ -57,23 +55,16 @@ public TypeGVMEntriesNode(TypeDesc associatedType) 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 void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, 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); - } + foreach (var entry in ScanForGenericVirtualMethodEntries()) + GenericVirtualMethodTableNode.AddGenericVirtualMethodImplementationDependencies(sink, context, entry.CallingMethod, entry.ImplementationMethod); - return _staticDependencies; + foreach (var entry in ScanForInterfaceGenericVirtualMethodEntries()) + InterfaceGenericVirtualMethodTableNode.AddGenericVirtualMethodImplementationDependencies(sink, context, entry.CallingMethod, entry.ImplementationType, entry.ImplementationMethod); } public IEnumerable ScanForGenericVirtualMethodEntries() diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs index ea8aba190fb095..6a9ada7f96b0cc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs @@ -33,9 +33,9 @@ public TypeMetadataNode(MetadataType type) public MetadataType Type => _type; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; MetadataType containingType = _type.ContainingType; if (containingType != null) @@ -45,13 +45,13 @@ public override IEnumerable GetStaticDependencies(NodeFacto MetadataType baseType = _type.BaseType; if (baseType != null) - GetMetadataDependencies(ref dependencies, factory, baseType, "Base type of a reflectable type"); + AddMetadataDependencies(dependencies, factory, baseType, "Base type of a reflectable type"); foreach (GenericParameterDesc genericParameter in _type.Instantiation) { foreach (TypeDesc typeConstraint in genericParameter.TypeConstraints) { - GetMetadataDependencies(ref dependencies, factory, typeConstraint, "Generic parameter constraint of a reflectable type"); + AddMetadataDependencies(dependencies, factory, typeConstraint, "Generic parameter constraint of a reflectable type"); } } @@ -104,22 +104,19 @@ public override IEnumerable GetStaticDependencies(NodeFacto dependencies.Add(factory.FieldMetadata(field), "Complete metadata for type"); } } - - return dependencies; } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - var dependencies = new List(); - CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ((EcmaType)_type)); - return dependencies; + DependencySink dependencies = sink; + CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(dependencies, factory, ((EcmaType)_type)); } /// /// Decomposes a constructed type into individual units that will be needed to /// express the constructed type in metadata. /// - public static void GetMetadataDependencies(ref DependencyList dependencies, NodeFactory nodeFactory, TypeDesc type, string reason) + public static void AddMetadataDependencies(IDependencySink dependencies, NodeFactory nodeFactory, TypeDesc type, string reason) { MetadataManager mdManager = nodeFactory.MetadataManager; @@ -129,13 +126,13 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node case TypeFlags.SzArray: case TypeFlags.ByRef: case TypeFlags.Pointer: - GetMetadataDependencies(ref dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason); + AddMetadataDependencies(dependencies, nodeFactory, ((ParameterizedType)type).ParameterType, reason); break; case TypeFlags.FunctionPointer: var pointerType = (FunctionPointerType)type; - GetMetadataDependencies(ref dependencies, nodeFactory, pointerType.Signature.ReturnType, reason); + AddMetadataDependencies(dependencies, nodeFactory, pointerType.Signature.ReturnType, reason); foreach (TypeDesc paramType in pointerType.Signature) - GetMetadataDependencies(ref dependencies, nodeFactory, paramType, reason); + AddMetadataDependencies(dependencies, nodeFactory, paramType, reason); break; case TypeFlags.SignatureMethodVariable: @@ -153,7 +150,6 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node // There's no dataflow annotations on the IDynamicInterfaceCastable.GetInterfaceImplementation API. if (type.IsInterface && ((MetadataType)type).IsDynamicInterfaceCastableImplementation()) { - dependencies ??= new DependencyList(); dependencies.Add(nodeFactory.ReflectedType(type), "Reflected IDynamicInterfaceCastableImplementation"); } @@ -162,20 +158,18 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node { if (mdManager.CanGenerateMetadata((MetadataType)typeDefinition)) { - dependencies ??= new DependencyList(); dependencies.Add(nodeFactory.TypeMetadata((MetadataType)typeDefinition), reason); } foreach (TypeDesc typeArg in type.Instantiation) { - GetMetadataDependencies(ref dependencies, nodeFactory, typeArg, reason); + AddMetadataDependencies(dependencies, nodeFactory, typeArg, reason); } } else { if (mdManager.CanGenerateMetadata((MetadataType)type)) { - dependencies ??= new DependencyList(); dependencies.Add(nodeFactory.TypeMetadata((MetadataType)type), reason); } } @@ -198,6 +192,6 @@ protected override void OnMarked(NodeFactory factory) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs index 95853fe6cf35cf..4270a4cb76a98a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -42,14 +43,11 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) public override bool IsShareable => true; public override bool StaticDependenciesAreComputed => true; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { ISymbolDefinitionNode node = _inlinedThreadStatics ?? factory.TypeThreadStaticsSymbol(_type); - return new DependencyList - { - new DependencyListEntry(node, "Thread static storage") - }; + sink.Add(node, "Thread static storage"); } protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs index c5b22842c46669..6b81f345498003 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs @@ -77,22 +77,22 @@ public abstract bool HasKnownVirtualMethodUse public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { if (_type.HasBaseType) { - yield return new DependencyListEntry(factory.VTable(_type.BaseType), "Base type VTable"); + sink.Add(factory.VTable(_type.BaseType), "Base type VTable"); } TypeDesc canonType = _type.ConvertToCanonForm(CanonicalFormKind.Specific); if (_type != canonType) { - yield return new DependencyListEntry(factory.VTable(canonType), "Canonical type VTable"); + sink.Add(factory.VTable(canonType), "Canonical type VTable"); } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; @@ -217,7 +217,7 @@ public override bool HasConditionalStaticDependencies } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { // VirtualMethodUse of Foo.Method will bring in VirtualMethodUse // of Foo<__Canon>.Method. This in turn should bring in Foo.Method. @@ -236,7 +236,7 @@ public override IEnumerable GetConditionalStaticDep continue; if (defType.Context.SupportsCanon) - yield return new CombinedDependencyListEntry( + sink.AddConditional( factory.VirtualMethodUse(method), factory.VirtualMethodUse(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Canonically equivalent virtual method use"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VariantInterfaceMethodUseNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VariantInterfaceMethodUseNode.cs index 91f851b8d5af75..1b5be1cac1e943 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VariantInterfaceMethodUseNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VariantInterfaceMethodUseNode.cs @@ -147,8 +147,8 @@ public static bool IsVariantMethodCall(NodeFactory factory, MethodDesc calledMet public override bool InterestingForDynamicDependencyAnalysis => false; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory factory) => null; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs index 29a6d241a0d792..7df49c456cfb53 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs @@ -118,25 +118,25 @@ private void MarkAndPreserve(TypeDesc type, XPathNavigator nav, TypePreserve pre switch (member) { case MethodDesc m: - RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, _factory, m, reason); + RootingHelpers.TryAddDependenciesForReflectedMethod(_dependencies, _factory, m, reason); break; case FieldDesc field: - RootingHelpers.TryGetDependenciesForReflectedField(ref _dependencies, _factory, field, reason); + RootingHelpers.TryAddDependenciesForReflectedField(_dependencies, _factory, field, reason); break; case MetadataType nestedType: - RootingHelpers.TryGetDependenciesForReflectedType(ref _dependencies, _factory, nestedType, reason); + RootingHelpers.TryAddDependenciesForReflectedType(_dependencies, _factory, nestedType, reason); break; case PropertyPseudoDesc property: if (property.GetMethod != null) - RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, _factory, property.GetMethod, reason); + RootingHelpers.TryAddDependenciesForReflectedMethod(_dependencies, _factory, property.GetMethod, reason); if (property.SetMethod != null) - RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, _factory, property.SetMethod, reason); + RootingHelpers.TryAddDependenciesForReflectedMethod(_dependencies, _factory, property.SetMethod, reason); break; case EventPseudoDesc @event: if (@event.AddMethod != null) - RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, _factory, @event.AddMethod, reason); + RootingHelpers.TryAddDependenciesForReflectedMethod(_dependencies, _factory, @event.AddMethod, reason); if (@event.RemoveMethod != null) - RootingHelpers.TryGetDependenciesForReflectedMethod(ref _dependencies, _factory, @event.RemoveMethod, reason); + RootingHelpers.TryAddDependenciesForReflectedMethod(_dependencies, _factory, @event.RemoveMethod, reason); break; default: Debug.Fail(member.GetType().ToString()); @@ -205,7 +205,7 @@ protected override void ProcessType(TypeDesc type, XPathNavigator nav) if (!required) return; - RootingHelpers.TryGetDependenciesForReflectedType(ref _dependencies, _factory, type, "member marked via descriptor"); + RootingHelpers.TryAddDependenciesForReflectedType(_dependencies, _factory, type, "member marked via descriptor"); #if false // Getting the dependencies of a nested type should mark the rest, this code is not needed diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs index 53dc3e7143a53d..bcbb12c30714cd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs @@ -6,6 +6,7 @@ using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; using Internal.IL; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler { @@ -19,15 +20,15 @@ public override PInvokeILProvider CreatePInvokeILProvider() return null; } - public override void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddDependenciesDueToMethodCodePresence(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { } - public override void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public override void AddInterestingInteropConstructedTypeDependencies(DependencySink dependencies, NodeFactory factory, TypeDesc type) { } - public override void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddMarshalAPIsGenericDependencies(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs index 3ea2357cda46cf..209bd66abb1815 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs @@ -6,6 +6,7 @@ using ILCompiler.DependencyAnalysis; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler { @@ -14,9 +15,9 @@ namespace ILCompiler /// public abstract class InteropStubManager : ICompilationRootProvider { - public abstract void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method); + public abstract void AddDependenciesDueToMethodCodePresence(IDependencySink dependencies, NodeFactory factory, MethodDesc method); - public abstract void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type); + public abstract void AddInterestingInteropConstructedTypeDependencies(DependencySink dependencies, NodeFactory factory, TypeDesc type); public abstract PInvokeILProvider CreatePInvokeILProvider(); @@ -24,7 +25,7 @@ public abstract class InteropStubManager : ICompilationRootProvider /// For Marshal generic APIs(eg. Marshal.StructureToPtr, GetFunctionPointerForDelegate) we add /// the generic parameter as dependencies so that we can generate runtime data for them /// - public abstract void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method); + public abstract void AddMarshalAPIsGenericDependencies(IDependencySink dependencies, NodeFactory factory, MethodDesc method); public virtual void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 7de1176f3cbbe4..7c965f6826504c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -16,7 +16,7 @@ using ReadyToRunSectionType = Internal.Runtime.ReadyToRunSectionType; using ReflectionMapBlob = Internal.Runtime.ReflectionMapBlob; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; using CombinedDependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyListEntry; using MethodIL = Internal.IL.MethodIL; using CustomAttributeValue = System.Reflection.Metadata.CustomAttributeValue; @@ -467,35 +467,34 @@ public bool ShouldMethodBeInInvokeMap(MethodDesc method) return true; } - public void GetDependenciesDueToGenericDictionary(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public void GetDependenciesDueToGenericDictionary(DependencySink dependencies, NodeFactory factory, MethodDesc method) { if (method.Signature.IsStatic && method.IsSynchronized) { - dependencies ??= new DependencyList(); dependencies.Add(factory.GenericMethodsHashtableEntry(method), "Will need to look up owning type from dictionary"); } } - public IEnumerable GetConditionalDependenciesDueToGenericDictionary(NodeFactory factory, MethodDesc method) + public void AddConditionalDependenciesDueToGenericDictionary(DependencySink dependencies, NodeFactory factory, MethodDesc method) { // If there's a template for this method, we need to keep track of the dictionary so that we // don't accidentally create a new dictionary for the same method at runtime. - yield return new CombinedDependencyListEntry( + dependencies.Add(new CombinedDependencyListEntry( factory.GenericMethodsHashtableEntry(method), factory.NativeLayout.TemplateMethodEntry(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), - "Runtime-constructable dictionary"); + "Runtime-constructable dictionary")); } /// /// This method is an extension point that can provide additional metadata-based dependencies to compiled method bodies. /// - public void GetDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public void GetDependenciesDueToReflectability(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { MetadataCategory category = GetMetadataCategory(method); if ((category & MetadataCategory.Description) != 0) { - GetMetadataDependenciesDueToReflectability(ref dependencies, factory, method); + GetMetadataDependenciesDueToReflectability(dependencies, factory, method); } if ((category & MetadataCategory.RuntimeMapping) != 0) @@ -503,62 +502,67 @@ public void GetDependenciesDueToReflectability(ref DependencyList dependencies, if (IsReflectionInvokable(method)) { // We're going to generate a mapping table entry for this. Collect dependencies. - ReflectionInvokeMapNode.AddDependenciesDueToReflectability(ref dependencies, factory, method); + ReflectionInvokeMapNode.AddDependenciesDueToReflectability(dependencies, factory, method); - ReflectionInvokeSupportDependencyAlgorithm.GetDependenciesFromParamsArray(ref dependencies, factory, method); + ReflectionInvokeSupportDependencyAlgorithm.GetDependenciesFromParamsArray(dependencies, factory, method); } if (!method.IsCanonicalMethod(CanonicalFormKind.Any) && method.IsStaticConstructor) { // Information about the static constructor prefixes the non-GC static base - dependencies ??= new DependencyList(); dependencies.Add(factory.TypeNonGCStaticsSymbol((MetadataType)method.OwningType), "Static constructor is reflection-callable"); } - GenericMethodsTemplateMap.GetTemplateMethodDependencies(ref dependencies, factory, method); - GenericTypesTemplateMap.GetTemplateTypeDependencies(ref dependencies, factory, method.OwningType); + GenericMethodsTemplateMap.AddTemplateMethodDependencies(dependencies, factory, method); + GenericTypesTemplateMap.AddTemplateTypeDependencies(dependencies, factory, method.OwningType); } } /// /// This method is an extension point that can provide additional metadata-based dependencies to generated fields. /// - public void GetDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) + public void GetDependenciesDueToReflectability(DependencySink dependencies, NodeFactory factory, FieldDesc field) { MetadataCategory category = GetMetadataCategory(field); if ((category & MetadataCategory.Description) != 0) { - GetMetadataDependenciesDueToReflectability(ref dependencies, factory, field); + GetMetadataDependenciesDueToReflectability(dependencies, factory, field); } if ((category & MetadataCategory.RuntimeMapping) != 0) { TypeDesc owningCanonicalType = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific); - GenericTypesTemplateMap.GetTemplateTypeDependencies(ref dependencies, factory, owningCanonicalType); + GenericTypesTemplateMap.AddTemplateTypeDependencies(dependencies, factory, owningCanonicalType); } } +#nullable enable /// /// This method is an extension point that can provide additional metadata-based dependencies on a virtual method. /// - public virtual void GetDependenciesDueToVirtualMethodReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public virtual void AddDependenciesDueToVirtualMethodReflectability( + DependencySink dependencies, + NodeFactory factory, + MethodDesc method, + DependencyNodeCore? otherReasonNode = null) { } +#nullable restore - protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + protected virtual void GetMetadataDependenciesDueToReflectability(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata // (E.g. dependencies caused by the method having custom attributes applied to it: making sure we compile the attribute constructor // and property setters) } - public virtual void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public virtual void AddNativeLayoutMetadataDependencies(DependencySink 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) + protected virtual void GetMetadataDependenciesDueToReflectability(DependencySink dependencies, NodeFactory factory, FieldDesc field) { // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata // (E.g. dependencies caused by the field having custom attributes applied to it: making sure we compile the attribute constructor @@ -568,29 +572,29 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency /// /// This method is an extension point that can provide additional metadata-based dependencies to generated EETypes. /// - public virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public virtual void GetDependenciesDueToEETypePresence(DependencySink dependencies, NodeFactory factory, TypeDesc type) { MetadataCategory category = GetMetadataCategory(type); if ((category & MetadataCategory.Description) != 0) { - GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type); + GetMetadataDependenciesDueToReflectability(dependencies, factory, type); } } - internal virtual void GetDependenciesDueToModuleUse(ref DependencyList dependencies, NodeFactory factory, ModuleDesc module) + internal virtual void GetDependenciesDueToModuleUse(IDependencySink dependencies, NodeFactory factory, ModuleDesc module) { // MetadataManagers can override this to provide additional dependencies caused by using a module } - protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + protected virtual void GetMetadataDependenciesDueToReflectability(DependencySink dependencies, NodeFactory factory, TypeDesc type) { // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata // (E.g. dependencies caused by the type having custom attributes applied to it: making sure we compile the attribute constructor // and property setters) } - public virtual void GetConditionalDependenciesDueToEETypePresence(ref CombinedDependencyList dependencies, NodeFactory factory, TypeDesc type, bool allocated) + public virtual void GetConditionalDependenciesDueToEETypePresence(DependencySink dependencies, NodeFactory factory, TypeDesc type, bool allocated) { // MetadataManagers can override this to provide additional dependencies caused by the presence of // an MethodTable. @@ -604,7 +608,7 @@ public virtual bool HasConditionalDependenciesDueToEETypePresence(TypeDesc type) /// /// This method is an extension point that can provide additional metadata-based dependencies to generated RuntimeMethodHandles. /// - public virtual void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public virtual void GetDependenciesDueToLdToken(DependencySink dependencies, NodeFactory factory, MethodDesc method) { // MetadataManagers can override this to provide additional dependencies caused by the presence of a // RuntimeMethodHandle data structure. @@ -613,17 +617,16 @@ public virtual void GetDependenciesDueToLdToken(ref DependencyList dependencies, /// /// This method is an extension point that can provide additional metadata-based dependencies to generated RuntimeFieldHandles. /// - public virtual void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) + public virtual void GetDependenciesDueToLdToken(DependencySink dependencies, NodeFactory factory, FieldDesc field) { // MetadataManagers can override this to provide additional dependencies caused by the presence of a // RuntimeFieldHandle data structure. } - public void GetDependenciesDueToDelegateCreation(ref DependencyList dependencies, NodeFactory factory, TypeDesc delegateType, MethodDesc target) + public void GetDependenciesDueToDelegateCreation(DependencySink dependencies, NodeFactory factory, TypeDesc delegateType, MethodDesc target) { if (target.IsVirtual) { - dependencies ??= new DependencyList(); dependencies.Add(factory.DelegateTargetVirtualMethod(target), "Delegate to a virtual method created"); } } @@ -631,7 +634,7 @@ public void GetDependenciesDueToDelegateCreation(ref DependencyList dependencies /// /// This method is an extension point that can provide additional metadata-based dependencies to delegate targets. /// - public virtual void GetDependenciesDueToDelegateCreation(ref CombinedDependencyList dependencies, NodeFactory factory, TypeDesc delegateType, MethodDesc target) + public virtual void GetConditionalDependenciesDueToDelegateCreation(DependencySink dependencies, NodeFactory factory, TypeDesc delegateType, MethodDesc target) { // MetadataManagers can override this to provide additional dependencies caused by the construction // of a delegate to a method. @@ -640,7 +643,7 @@ public virtual void GetDependenciesDueToDelegateCreation(ref CombinedDependencyL /// /// This method is an extension point that can provide additional dependencies for overridden methods on constructed types. /// - public virtual void GetDependenciesForOverridingMethod(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc decl, MethodDesc impl) + public virtual void GetDependenciesForOverridingMethod(DependencySink dependencies, NodeFactory factory, MethodDesc decl, MethodDesc impl) { } @@ -653,20 +656,20 @@ public virtual void GetDependenciesForOverridingMethod(ref CombinedDependencyLis /// /// This method is an extension point that can provide additional metadata-based dependencies to generated method bodies. /// - public void GetDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) + public void GetDependenciesDueToMethodCodePresence(IDependencySink dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) { - InlineableStringsResourceNode.AddDependenciesDueToResourceStringUse(ref dependencies, factory, method); + InlineableStringsResourceNode.AddDependenciesDueToResourceStringUse(dependencies, factory, method); - GetDependenciesDueToMethodCodePresenceInternal(ref dependencies, factory, method, methodIL); + GetDependenciesDueToMethodCodePresenceInternal(dependencies, factory, method, methodIL); } - public virtual void GetConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) + public virtual void GetConditionalDependenciesDueToMethodCodePresence(IConditionalDependencySink dependencies, NodeFactory factory, MethodDesc method) { // MetadataManagers can override this to provide additional dependencies caused by the presence of // method code. } - protected virtual void GetDependenciesDueToMethodCodePresenceInternal(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) + protected virtual void GetDependenciesDueToMethodCodePresenceInternal(IDependencySink dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) { // MetadataManagers can override this to provide additional dependencies caused by the presence of a // compiled method body. @@ -1296,15 +1299,15 @@ public bool CanGenerateMetadata(FieldDesc field) protected abstract MetadataCategory GetMetadataCategory(TypeDesc type); protected abstract MetadataCategory GetMetadataCategory(FieldDesc field); - public virtual void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, TypeDesc accessedType) + public virtual void GetDependenciesDueToAccess(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, TypeDesc accessedType) { } - public virtual void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, MethodDesc calledMethod) + public virtual void GetDependenciesDueToAccess(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, MethodDesc calledMethod) { } - public virtual void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, FieldDesc writtenField) + public virtual void GetDependenciesDueToAccess(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, FieldDesc writtenField) { } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReachabilityInstrumentationProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReachabilityInstrumentationProvider.cs index 199f92718e17cc..4b3e40236c3386 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReachabilityInstrumentationProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReachabilityInstrumentationProvider.cs @@ -220,9 +220,9 @@ public UntrackedSymbol(int offset, string name) string IDependencyNode.GetName(NodeFactory context) => _name; void ISymbolNode.AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) => sb.Append(_name); - IEnumerable IDependencyNode.GetConditionalStaticDependencies(NodeFactory context) => throw new NotImplementedException(); - IEnumerable IDependencyNode.GetStaticDependencies(NodeFactory context) => null; - IEnumerable IDependencyNode.SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => throw new NotImplementedException(); + void IDependencyNode.AddConditionalDependencies(DependencySink sink, NodeFactory context) => throw new NotImplementedException(); + void IDependencyNode.AddStaticDependencies(DependencySink sink, NodeFactory context) { } + void IDependencyNode.SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) => throw new NotImplementedException(); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs index ce222b1334e874..077b5776e8aacf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs @@ -1,11 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + +using System.Diagnostics; + using Internal.TypeSystem; using ILCompiler.DependencyAnalysis; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler { @@ -127,7 +132,44 @@ public static void RootField(IRootingServiceProvider rootProvider, FieldDesc fie rootProvider.AddReflectionRoot(field, reason); } - public static bool TryGetDependenciesForReflectedMethod(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, string reason) + public static bool TryAddDependenciesForReflectedMethod( + IDependencySink dependencies, + NodeFactory factory, + MethodDesc method, + string reason) + { + return TryAddDependenciesForReflectedMethod( + dependencies, + conditionalDependencies: null, + factory, + method, + reason, + otherReasonNode: null); + } + + public static bool TryAddDependenciesForReflectedMethod( + DependencySink dependencies, + NodeFactory factory, + MethodDesc method, + string reason, + DependencyNodeCore otherReasonNode) + { + return TryAddDependenciesForReflectedMethod( + dependencies, + dependencies, + factory, + method, + reason, + otherReasonNode); + } + + private static bool TryAddDependenciesForReflectedMethod( + IDependencySink dependencies, + DependencySink? conditionalDependencies, + NodeFactory factory, + MethodDesc method, + string reason, + DependencyNodeCore? otherReasonNode) { MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); if (factory.MetadataManager.IsReflectionBlocked(typicalMethod)) @@ -140,8 +182,7 @@ public static bool TryGetDependenciesForReflectedMethod(ref DependencyList depen // for it below. if (typicalMethod.IsGenericMethodDefinition || typicalMethod.OwningType.IsGenericDefinition) { - dependencies ??= new DependencyList(); - dependencies.Add(factory.ReflectedMethod(typicalMethod), reason); + AddDependency(dependencies, conditionalDependencies, factory.ReflectedMethod(typicalMethod), reason, otherReasonNode); } // If there's any genericness involved, try to create a fitting instantiation that would be usable at runtime. @@ -185,13 +226,17 @@ public static bool TryGetDependenciesForReflectedMethod(ref DependencyList depen return false; } - dependencies ??= new DependencyList(); - dependencies.Add(factory.ReflectedMethod(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), reason); + AddDependency( + dependencies, + conditionalDependencies, + factory.ReflectedMethod(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), + reason, + otherReasonNode); return true; } - public static bool TryGetDependenciesForReflectedField(ref DependencyList dependencies, NodeFactory factory, FieldDesc field, string reason) + public static bool TryAddDependenciesForReflectedField(IDependencySink dependencies, NodeFactory factory, FieldDesc field, string reason) { FieldDesc typicalField = field.GetTypicalFieldDefinition(); if (factory.MetadataManager.IsReflectionBlocked(typicalField)) @@ -199,7 +244,6 @@ public static bool TryGetDependenciesForReflectedField(ref DependencyList depend return false; } - dependencies ??= new DependencyList(); // If this is a field on generic type, make sure we at minimum have the metadata // for it. This hedges against the risk that we fail to figure out an instantiated base @@ -242,7 +286,44 @@ public static bool TryGetDependenciesForReflectedField(ref DependencyList depend return true; } - public static bool TryGetDependenciesForReflectedType(ref DependencyList dependencies, NodeFactory factory, TypeDesc type, string reason) + public static bool TryAddDependenciesForReflectedType( + IDependencySink dependencies, + NodeFactory factory, + TypeDesc type, + string reason) + { + return TryAddDependenciesForReflectedType( + dependencies, + conditionalDependencies: null, + factory, + type, + reason, + otherReasonNode: null); + } + + public static bool TryAddDependenciesForReflectedType( + DependencySink dependencies, + NodeFactory factory, + TypeDesc type, + string reason, + DependencyNodeCore otherReasonNode) + { + return TryAddDependenciesForReflectedType( + dependencies, + dependencies, + factory, + type, + reason, + otherReasonNode); + } + + private static bool TryAddDependenciesForReflectedType( + IDependencySink dependencies, + DependencySink? conditionalDependencies, + NodeFactory factory, + TypeDesc type, + string reason, + DependencyNodeCore? otherReasonNode) { try { @@ -257,9 +338,8 @@ public static bool TryGetDependenciesForReflectedType(ref DependencyList depende return false; } - dependencies ??= new DependencyList(); - dependencies.Add(factory.ReflectedType(type), reason); + AddDependency(dependencies, conditionalDependencies, factory.ReflectedType(type), reason, otherReasonNode); // If there's any unknown genericness involved, try to create a fitting instantiation that would be usable at runtime. // This is not a complete solution to the problem. @@ -270,7 +350,12 @@ public static bool TryGetDependenciesForReflectedType(ref DependencyList depende Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(type.Instantiation, allowCanon: true); if (!inst.IsNull) { - dependencies.Add(factory.ReflectedType(((MetadataType)type).MakeInstantiatedType(inst)), reason); + AddDependency( + dependencies, + conditionalDependencies, + factory.ReflectedType(((MetadataType)type).MakeInstantiatedType(inst)), + reason, + otherReasonNode); } } } @@ -281,5 +366,23 @@ public static bool TryGetDependenciesForReflectedType(ref DependencyList depende return true; } + + private static void AddDependency( + IDependencySink dependencies, + DependencySink? conditionalDependencies, + DependencyNodeCore dependency, + string reason, + DependencyNodeCore? otherReasonNode) + { + if (otherReasonNode is null) + { + dependencies.Add(dependency, reason); + } + else + { + Debug.Assert(conditionalDependencies is not null); + conditionalDependencies.AddConditional(dependency, otherReasonNode, reason); + } + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConstructableTypeDependencies.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConstructableTypeDependencies.cs index 98d86cb6c71f37..e2db8bf8a5d72e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConstructableTypeDependencies.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConstructableTypeDependencies.cs @@ -55,7 +55,7 @@ public static IEETypeNode GetEffectiveTrimTargetType(NodeFactory factory, TypeDe } public static void AddTypeLoaderDependencies( - List.CombinedDependencyListEntry> dependencies, + DependencySink dependencies, NodeFactory factory, IEETypeNode dependencyType, string reason) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 178515c0cea7a5..2db22b0ff6f78e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -12,8 +12,9 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; using FlowAnnotations = ILLink.Shared.TrimAnalysis.FlowAnnotations; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler { @@ -2251,7 +2252,7 @@ public interface ISerializableReference : ISerializableValue TypeDesc Type { get; } void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, NodeFactory factory); bool HasConditionalDependencies { get; } - void GetConditionalDependencies(ref CombinedDependencyList dependencies, NodeFactory factory); + void AddConditionalDependencies(DependencySink dependencies, NodeFactory factory); bool IsKnownImmutable { get; } int ArrayLength { get; } } @@ -3257,7 +3258,7 @@ public override bool GetRawData(NodeFactory factory, out object data) public virtual bool HasConditionalDependencies => false; - public virtual void GetConditionalDependencies(ref CombinedDependencyList dependencies, NodeFactory factory) + public virtual void AddConditionalDependencies(DependencySink dependencies, NodeFactory factory) { } } @@ -3284,14 +3285,13 @@ private DelegateCreationInfo GetDelegateCreationInfo(NodeFactory factory) public override bool HasConditionalDependencies => true; - public override void GetConditionalDependencies(ref CombinedDependencyList dependencies, NodeFactory factory) + public override void AddConditionalDependencies(DependencySink dependencies, NodeFactory factory) { - dependencies ??= new CombinedDependencyList(); DelegateCreationInfo creationInfo = GetDelegateCreationInfo(factory); MethodDesc targetMethod = creationInfo.PossiblyUnresolvedTargetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); - factory.MetadataManager.GetDependenciesDueToDelegateCreation(ref dependencies, factory, creationInfo.DelegateType, targetMethod); + factory.MetadataManager.GetConditionalDependenciesDueToDelegateCreation(dependencies, factory, creationInfo.DelegateType, targetMethod); } public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UnmanagedEntryPointsRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UnmanagedEntryPointsRootProvider.cs index c42ad3db2825ba..fd4bba6c34e884 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UnmanagedEntryPointsRootProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UnmanagedEntryPointsRootProvider.cs @@ -107,14 +107,13 @@ public static IEnumerable GetExportedMethods(EcmaModule module) } } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { foreach (EcmaMethod method in GetExportedMethods(_module)) { if (!method.IsUnmanagedCallersOnly) { - foreach (DependencyListEntry dependency in GetMethodStaticDependencies(context, method, "Runtime export", new Utf8String(method.GetRuntimeExportName()))) - yield return dependency; + AddMethodStaticDependencies(sink, context, method, "Runtime export", new Utf8String(method.GetRuntimeExportName())); continue; } @@ -122,14 +121,13 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (!TryGetAssociatedSourceType(method, out TypeDesc associatedSourceType) || associatedSourceType is not null) continue; - foreach (DependencyListEntry dependency in GetMethodStaticDependencies(context, method, "Native callable", new Utf8String(method.GetUnmanagedCallersOnlyExportName()))) - yield return dependency; + AddMethodStaticDependencies(sink, context, method, "Native callable", new Utf8String(method.GetUnmanagedCallersOnlyExportName())); } } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { - List dependencies = []; + DependencySink dependencies = sink; foreach (EcmaMethod method in GetExportedMethods(_module)) { @@ -148,16 +146,15 @@ public override IEnumerable GetConditionalStaticDep RuntimeConstructableTypeDependencies.AddTypeLoaderDependencies(dependencies, context, effectiveTrimTargetType, "Associated source type that could be loaded at runtime"); } - return dependencies; } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } - private IEnumerable GetMethodStaticDependencies(NodeFactory context, EcmaMethod method, string reason, Utf8String exportName) + private void AddMethodStaticDependencies(DependencySink sink, NodeFactory context, EcmaMethod method, string reason, Utf8String exportName) { IMethodNode methodEntryPoint = GetMethodEntrypointAndAddAlias(context, method, exportName); - yield return new DependencyListEntry(methodEntryPoint, reason); + sink.Add(methodEntryPoint, reason); } private IMethodNode GetMethodEntrypointAndAddAlias(NodeFactory context, EcmaMethod method, Utf8String exportName) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs index edae137c83b403..0bc23aab892fbc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs @@ -10,6 +10,7 @@ using Debug = System.Diagnostics.Debug; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler { @@ -26,23 +27,21 @@ public UsageBasedInteropStubManager(InteropStateManager interopStateManager, PIn _logger = logger; } - public override void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddDependenciesDueToMethodCodePresence(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { if (method.HasInstantiation) { - dependencies ??= new DependencyList(); - AddMarshalAPIsGenericDependencies(ref dependencies, factory, method); + AddMarshalAPIsGenericDependencies(dependencies, factory, method); } } - public override void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public override void AddInterestingInteropConstructedTypeDependencies(DependencySink dependencies, NodeFactory factory, TypeDesc type) { if (type.IsDelegate) { var delegateType = (MetadataType)type; if (delegateType.HasCustomAttribute("System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute")) { - dependencies ??= new DependencyList(); dependencies.Add(factory.DelegateMarshallingData(delegateType), "Delegate marshalling"); } } @@ -52,7 +51,7 @@ public override void AddInterestingInteropConstructedTypeDependencies(ref Depend /// For Marshal generic APIs(eg. Marshal.StructureToPtr, GetFunctionPointerForDelegate) we add /// the generic parameter as dependencies so that we can generate runtime data for them /// - public override void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddMarshalAPIsGenericDependencies(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { Debug.Assert(method.HasInstantiation); @@ -72,7 +71,6 @@ public override void AddMarshalAPIsGenericDependencies(ref DependencyList depend { foreach (TypeDesc type in method.Instantiation) { - dependencies ??= new DependencyList(); if (type.IsDelegate) { dependencies.Add(factory.DelegateMarshallingData((DefType)type), "Delegate marshlling"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index 9fa0543653dd79..c157ea044f5688 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -19,7 +19,7 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; using CustomAttributeHandle = System.Reflection.Metadata.CustomAttributeHandle; using CustomAttributeValue = System.Reflection.Metadata.CustomAttributeValue; using Debug = System.Diagnostics.Debug; @@ -238,17 +238,15 @@ protected override void ComputeMetadata(NodeFactory factory, factory, out metadataBlob, out typeMappings, out methodMappings, out methodMetadataMappings, out fieldMappings, out fieldMetadataMappings, out stackTraceMapping, out reflectionStackTraceMapping); } - protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + protected override void GetMetadataDependenciesDueToReflectability(IDependencySink dependencies, NodeFactory factory, MethodDesc method) { - dependencies ??= new DependencyList(); dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method"); } - public override void GetNativeLayoutMetadataDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void AddNativeLayoutMetadataDependencies(DependencySink dependencies, NodeFactory factory, MethodDesc method) { if (CanGenerateMetadata(method)) { - dependencies ??= new DependencyList(); dependencies.Add(factory.LimitedMethodMetadata(method.GetTypicalMethodDefinition()), "Method referenced from native layout"); } else @@ -259,15 +257,13 @@ public override void GetNativeLayoutMetadataDependencies(ref DependencyList depe } } - protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) + protected override void GetMetadataDependenciesDueToReflectability(DependencySink dependencies, NodeFactory factory, FieldDesc field) { - dependencies ??= new DependencyList(); dependencies.Add(factory.FieldMetadata(field.GetTypicalFieldDefinition()), "Reflectable field"); } - internal override void GetDependenciesDueToModuleUse(ref DependencyList dependencies, NodeFactory factory, ModuleDesc module) + internal override void GetDependenciesDueToModuleUse(IDependencySink dependencies, NodeFactory factory, ModuleDesc module) { - dependencies ??= new DependencyList(); if (module.GetGlobalModuleType().GetStaticConstructor() is MethodDesc moduleCctor) { dependencies.Add(factory.MethodEntrypoint(moduleCctor), "Module with a static constructor"); @@ -293,9 +289,9 @@ internal override void GetDependenciesDueToModuleUse(ref DependencyList dependen } } - protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + protected override void GetMetadataDependenciesDueToReflectability(DependencySink dependencies, NodeFactory factory, TypeDesc type) { - TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type"); + TypeMetadataNode.AddMetadataDependencies(dependencies, factory, type, "Reflectable type"); if (type.IsDelegate) { @@ -307,7 +303,6 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc MethodDesc invokeMethod = type.GetMethod("Invoke"u8, null); if (!IsReflectionBlocked(invokeMethod)) { - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedMethod(invokeMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Delegate invoke method is always reflectable"); } } @@ -322,7 +317,6 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc MethodDesc defaultConstructor = elementType.GetDefaultConstructor(); if (defaultConstructor is not null && !IsReflectionBlocked(defaultConstructor)) { - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedMethod(defaultConstructor.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Array.Initialize needs default constructor"); } } @@ -362,7 +356,6 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc if (fullyRoot) { - dependencies ??= new DependencyList(); var rootProvider = new RootingServiceProvider(factory, dependencies.Add); foreach (TypeDesc t in mdType.Module.GetAllTypes()) { @@ -400,11 +393,11 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly) return false; } - public override void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public override void GetDependenciesDueToEETypePresence(DependencySink dependencies, NodeFactory factory, TypeDesc type) { - base.GetDependenciesDueToEETypePresence(ref dependencies, factory, type); + base.GetDependenciesDueToEETypePresence(dependencies, factory, type); - DataflowAnalyzedTypeDefinitionNode.GetDependencies(ref dependencies, factory, FlowAnnotations, type); + DataflowAnalyzedTypeDefinitionNode.AddDependencies(dependencies, factory, FlowAnnotations, type); } public override bool HasConditionalDependenciesDueToEETypePresence(TypeDesc type) @@ -422,7 +415,7 @@ public override bool HasConditionalDependenciesDueToEETypePresence(TypeDesc type return false; } - public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedDependencyList dependencies, NodeFactory factory, TypeDesc type, bool allocated) + public override void GetConditionalDependenciesDueToEETypePresence(DependencySink dependencies, NodeFactory factory, TypeDesc type, bool allocated) { // Check to see if we have any dataflow annotations on the type. // The check below also covers flow annotations inherited through base classes and implemented interfaces. @@ -430,7 +423,6 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD if (allocatedWithFlowAnnotations) { - dependencies ??= new CombinedDependencyList(); dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ObjectGetTypeFlowDependencies((MetadataType)type), factory.ObjectGetTypeCalled((MetadataType)type), @@ -454,7 +446,6 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD // There's an annotation on the base type. If object.GetType was called on something // statically typed as the base type, we might actually be calling it on this type. // Ensure we have the flow dependencies. - dependencies ??= new CombinedDependencyList(); dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ObjectGetTypeCalled((MetadataType)type), factory.ObjectGetTypeCalled((MetadataType)baseType), @@ -470,7 +461,6 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD // There's an annotation on the interface type. If object.GetType was called on something // statically typed as the interface type, we might actually be calling it on this type. // Ensure we have the flow dependencies. - dependencies ??= new CombinedDependencyList(); dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ObjectGetTypeCalled((MetadataType)type), factory.ObjectGetTypeCalled((MetadataType)interfaceType), @@ -498,7 +488,6 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD if (IsReflectionBlocked(field)) continue; - dependencies ??= new CombinedDependencyList(); dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ReflectedField(field), factory.ReflectedField(field.GetTypicalFieldDefinition()), @@ -530,7 +519,6 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD reflectedMethod = method; } - dependencies ??= new CombinedDependencyList(); dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ReflectedMethod(reflectedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)), factory.ReflectedMethod(reflectedMethod.GetTypicalMethodDefinition()), @@ -539,18 +527,16 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD } } - public override void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) + public override void GetDependenciesDueToLdToken(DependencySink dependencies, NodeFactory factory, FieldDesc field) { if (!IsReflectionBlocked(field)) { - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedField(field), "LDTOKEN field"); } } - public override void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void GetDependenciesDueToLdToken(DependencySink dependencies, NodeFactory factory, MethodDesc method) { - dependencies ??= new DependencyList(); if (!IsReflectionBlocked(method)) { @@ -567,11 +553,10 @@ public override void GetDependenciesDueToLdToken(ref DependencyList dependencies } } - public override void GetDependenciesDueToDelegateCreation(ref CombinedDependencyList dependencies, NodeFactory factory, TypeDesc delegateType, MethodDesc target) + public override void GetConditionalDependenciesDueToDelegateCreation(DependencySink dependencies, NodeFactory factory, TypeDesc delegateType, MethodDesc target) { if (!IsReflectionBlocked(target)) { - dependencies ??= new CombinedDependencyList(); ReflectedMethodNode reflectedMethod = factory.ReflectedMethod(target.GetCanonMethodTarget(CanonicalFormKind.Specific)); @@ -619,7 +604,7 @@ public override void GetDependenciesDueToDelegateCreation(ref CombinedDependency } } - public override void GetDependenciesForOverridingMethod(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc decl, MethodDesc impl) + public override void GetDependenciesForOverridingMethod(DependencySink dependencies, NodeFactory factory, MethodDesc decl, MethodDesc impl) { Debug.Assert(decl.IsVirtual && MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(decl.GetMethodDefinition()) == decl.GetMethodDefinition()); @@ -628,17 +613,15 @@ public override void GetDependenciesForOverridingMethod(ref CombinedDependencyLi // to support Delegate.GetMethodInfo(). if (!IsReflectionBlocked(decl) && !IsReflectionBlocked(impl)) { - dependencies ??= new CombinedDependencyList(); - dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( + dependencies.Add( factory.ReflectableVirtualMethodImpl( decl.GetCanonMethodTarget(CanonicalFormKind.Specific), impl.GetCanonMethodTarget(CanonicalFormKind.Specific)), - null, - "Virtual method implementation discovered")); + "Virtual method implementation discovered"); } } - protected override void GetDependenciesDueToMethodCodePresenceInternal(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) + protected override void GetDependenciesDueToMethodCodePresenceInternal(IDependencySink dependencies, NodeFactory factory, MethodDesc method, MethodIL methodIL) { bool scanReflection = (_generationOptions & UsageBasedMetadataGenerationOptions.ReflectionILScanning) != 0; @@ -648,7 +631,7 @@ protected override void GetDependenciesDueToMethodCodePresenceInternal(ref Depen { if (methodIL != null && Dataflow.ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForMethodBody(FlowAnnotations, method)) { - AddDataflowDependency(ref dependencies, factory, methodIL, "Method has annotated parameters"); + AddDataflowDependency(dependencies, factory, methodIL, "Method has annotated parameters"); } if (method.IsStaticConstructor) @@ -679,17 +662,17 @@ protected override void GetDependenciesDueToMethodCodePresenceInternal(ref Depen if (method.GetTypicalMethodDefinition() is Internal.TypeSystem.Ecma.EcmaMethod ecmaMethod) { - DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaMethod); + DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(dependencies, factory, ecmaMethod); } // Presence of code might trigger the reflectability dependencies. if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) { - GetDependenciesDueToReflectability(ref dependencies, factory, method); + GetDependenciesDueToReflectability(dependencies, factory, method); } } - public override void GetConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) + public override void GetConditionalDependenciesDueToMethodCodePresence(IConditionalDependencySink dependencies, NodeFactory factory, MethodDesc method) { MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); @@ -697,13 +680,17 @@ public override void GetConditionalDependenciesDueToMethodCodePresence(ref Combi if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) == 0 && method != typicalMethod) { - dependencies ??= new CombinedDependencyList(); dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ReflectedMethod(method), factory.ReflectedMethod(typicalMethod), "Reflectability of methods is same across genericness")); } } - public override void GetDependenciesDueToVirtualMethodReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) +#nullable enable + public override void AddDependenciesDueToVirtualMethodReflectability( + DependencySink dependencies, + NodeFactory factory, + MethodDesc method, + DependencyNodeCore? otherReasonNode) { if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) { @@ -712,11 +699,19 @@ public override void GetDependenciesDueToVirtualMethodReflectability(ref Depende // for the metadata manager. Metadata manager treats that node the same as a body. if (method.IsAbstract && GetMetadataCategory(method) != 0) { - dependencies ??= new DependencyList(); - dependencies.Add(factory.ReflectedMethod(method.GetCanonMethodTarget(CanonicalFormKind.Specific)), "Abstract reflectable method"); + var dependency = factory.ReflectedMethod(method.GetCanonMethodTarget(CanonicalFormKind.Specific)); + if (otherReasonNode is null) + { + dependencies.Add(dependency, "Abstract reflectable method"); + } + else + { + dependencies.AddConditional(dependency, otherReasonNode, "Abstract reflectable method"); + } } } } +#nullable restore protected override IEnumerable GetFieldsWithRuntimeMapping() { @@ -728,12 +723,12 @@ public override IEnumerable GetCompilationModulesWithMetadata() return _modulesWithMetadata; } - public override void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, FieldDesc writtenField) + public override void GetDependenciesDueToAccess(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, FieldDesc writtenField) { bool scanReflection = (_generationOptions & UsageBasedMetadataGenerationOptions.ReflectionILScanning) != 0; if (scanReflection && Dataflow.ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForAccess(FlowAnnotations, writtenField)) { - AddDataflowDependency(ref dependencies, factory, methodIL, "Access to interesting field"); + AddDataflowDependency(dependencies, factory, methodIL, "Access to interesting field"); } if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0 @@ -754,31 +749,30 @@ public override void GetDependenciesDueToAccess(ref DependencyList dependencies, } } - dependencies ??= new DependencyList(); dependencies.Add(factory.ReflectedField(fieldToReport), "Use of a field"); } if (writtenField.GetTypicalFieldDefinition() is EcmaField ecmaField) { - DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(ref dependencies, factory, ecmaField); + DynamicDependencyAttributesOnEntityNode.AddDependenciesDueToDynamicDependencyAttribute(dependencies, factory, ecmaField); } } - public override void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, TypeDesc accessedType) + public override void GetDependenciesDueToAccess(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, TypeDesc accessedType) { bool scanReflection = (_generationOptions & UsageBasedMetadataGenerationOptions.ReflectionILScanning) != 0; if (scanReflection && Dataflow.ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForAccess(FlowAnnotations, accessedType)) { - AddDataflowDependency(ref dependencies, factory, methodIL, "Access to interesting type"); + AddDataflowDependency(dependencies, factory, methodIL, "Access to interesting type"); } } - public override void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, MethodDesc calledMethod) + public override void GetDependenciesDueToAccess(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, MethodDesc calledMethod) { bool scanReflection = (_generationOptions & UsageBasedMetadataGenerationOptions.ReflectionILScanning) != 0; if (scanReflection && Dataflow.ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForCallSite(FlowAnnotations, calledMethod)) { - AddDataflowDependency(ref dependencies, factory, methodIL, "Call to interesting method"); + AddDataflowDependency(dependencies, factory, methodIL, "Call to interesting method"); } } @@ -925,7 +919,7 @@ public MetadataManager ToAnalysisBasedMetadataManager() reflectableFields.ToEnumerable(), _customAttributesWithMetadata, _parametersWithMetadata, _options); } - private void AddDataflowDependency(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, string reason) + private void AddDataflowDependency(IDependencySink dependencies, NodeFactory factory, MethodIL methodIL, string reason) { if (ShouldSkipDataflowForMethod(methodIL)) return; @@ -956,7 +950,6 @@ private void AddDataflowDependency(ref DependencyList dependencies, NodeFactory // will not depend on stack modeling and of the other data flow functionality. // See https://github.com/dotnet/runtime/issues/82603 for more details and some ideas. - dependencies ??= new DependencyList(); dependencies.Add(factory.DataflowAnalyzedMethod(methodILDefinition), reason); // Some MethodIL implementations can't/don't provide the method definition version of the IL diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedTypeMapManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedTypeMapManager.cs index cdc4dd3f8b8494..b4f5d5ac38f504 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedTypeMapManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedTypeMapManager.cs @@ -26,20 +26,18 @@ private sealed class AllTypeMapsNode(TypeMapMetadata typeMapState) : DependencyN public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { - List entries = []; + DependencySink entries = sink; foreach ((TypeDesc typeMapGroup, TypeMapMetadata.Map typeMap) in typeMapState.Maps) { entries.Add(new CombinedDependencyListEntry(GetExternalTypeMapNode(typeMapGroup, typeMap), context.ExternalTypeMapRequest(typeMapGroup), "ExternalTypeMap")); entries.Add(new CombinedDependencyListEntry(GetProxyTypeMapNode(typeMapGroup, typeMap), context.ProxyTypeMapRequest(typeMapGroup), "ProxyTypeMap")); } - - return entries; } - public override IEnumerable GetStaticDependencies(NodeFactory context) => Array.Empty(); - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => Array.Empty(); + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"Type maps root node: {typeMapState.DiagnosticName}"; private static IExternalTypeMapNode GetExternalTypeMapNode(TypeDesc typeMapGroup, IExternalTypeMap map) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index 3859027176fe0d..c8b51da069372e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -12,7 +12,7 @@ using Debug = System.Diagnostics.Debug; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyListEntry; #pragma warning disable IDE0060 @@ -205,8 +205,9 @@ public ILImporter(ILScanner compilation, MethodDesc method, MethodIL methodIL = conditionalDependencies.Add(new(dep.Node, bb.Condition, dep.Reason)); } - CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(ref _unconditionalDependencies, _factory, _canonMethod, _canonMethodIL); - CodeBasedDependencyAlgorithm.AddConditionalDependenciesDueToMethodCodePresence(ref conditionalDependencies, _factory, _canonMethod); + conditionalDependencies ??= new CombinedDependencyList(); + CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(_unconditionalDependencies, _factory, _canonMethod, _canonMethodIL); + CodeBasedDependencyAlgorithm.AddConditionalDependenciesDueToMethodCodePresence(conditionalDependencies, _factory, _canonMethod); return (_unconditionalDependencies, conditionalDependencies); } @@ -549,7 +550,7 @@ private void ImportCall(ILOpcode opcode, int token) if ((method.Signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == MethodSignatureFlags.CallingConventionVarargs) ThrowHelper.ThrowInvalidProgramException(); - _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _compilation.NodeFactory, _canonMethodIL, method); + _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _compilation.NodeFactory, _canonMethodIL, method); if (method.IsRawPInvoke()) { @@ -1296,7 +1297,7 @@ private void ImportMkRefAny(int token) { _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.TypeHandleToRuntimeType), "mkrefany"); _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.TypeHandleToRuntimeTypeHandle), "mkrefany"); - _factory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _factory, _methodIL, (TypeDesc)_canonMethodIL.GetObject(token)); + _factory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _factory, _methodIL, (TypeDesc)_canonMethodIL.GetObject(token)); ImportTypedRefOperationDependencies(token, "mkrefany"); } @@ -1336,7 +1337,7 @@ private void ImportLdToken(int token) } } - _factory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _factory, _methodIL, (TypeDesc)_canonMethodIL.GetObject(token)); + _factory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _factory, _methodIL, (TypeDesc)_canonMethodIL.GetObject(token)); _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.GetRuntimeTypeHandle), "ldtoken"); _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.GetRuntimeType), "ldtoken"); @@ -1360,7 +1361,7 @@ private void ImportLdToken(int token) } else if (obj is MethodDesc method) { - _factory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _factory, _methodIL, (MethodDesc)_canonMethodIL.GetObject(token)); + _factory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _factory, _methodIL, (MethodDesc)_canonMethodIL.GetObject(token)); if (method.IsRuntimeDeterminedExactMethod) { @@ -1377,7 +1378,7 @@ private void ImportLdToken(int token) { var field = (FieldDesc)obj; - _factory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _factory, _methodIL, (FieldDesc)_canonMethodIL.GetObject(token)); + _factory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _factory, _methodIL, (FieldDesc)_canonMethodIL.GetObject(token)); RvaIntrinsicPatternAnalyzer analyzer = _rvaIntrinsicPatternAnalyzer; ILReader reader = GetRemainingBlockIL(); @@ -1432,7 +1433,7 @@ private void ImportFieldAccess(int token, bool isStatic, bool? write, string rea if (field.IsLiteral) ThrowHelper.ThrowMissingFieldException(field.OwningType, field.GetName()); - _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _compilation.NodeFactory, _canonMethodIL, canonField); + _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _compilation.NodeFactory, _canonMethodIL, canonField); // `write` will be null for ld(s)flda. Consider address loads write unless they were // for initonly static fields. We'll trust the initonly that this is not a write. @@ -1586,7 +1587,7 @@ private void AddBoxingDependencies(TypeDesc type, string reason) return; TypeDesc typeForAccessCheck = type.IsRuntimeDeterminedSubtype ? type.ConvertToCanonForm(CanonicalFormKind.Specific) : type; - _factory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _factory, _methodIL, typeForAccessCheck); + _factory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _factory, _methodIL, typeForAccessCheck); if (type.IsRuntimeDeterminedSubtype) { @@ -1615,7 +1616,7 @@ private void ImportLeave(BasicBlock target) private void ImportNewArray(int token) { var elementType = (TypeDesc)_methodIL.GetObject(token); - _factory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _factory, _methodIL, (TypeDesc)_canonMethodIL.GetObject(token)); + _factory.MetadataManager.GetDependenciesDueToAccess(_dependencies, _factory, _methodIL, (TypeDesc)_canonMethodIL.GetObject(token)); if (elementType.IsRuntimeDeterminedSubtype) { _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, elementType.MakeArrayType()), "newarr"); diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ComputedStaticDependencyNode.cs b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ComputedStaticDependencyNode.cs deleted file mode 100644 index 8e043a74a3916f..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ComputedStaticDependencyNode.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; - -namespace ILCompiler.DependencyAnalysisFramework -{ - public abstract class ComputedStaticDependencyNode : DependencyNodeCore - { - private IEnumerable _dependencies; - private IEnumerable _conditionalDependencies; - - public void SetStaticDependencies(IEnumerable dependencies, - IEnumerable conditionalDependencies) - { - Debug.Assert(_dependencies == null); - Debug.Assert(_conditionalDependencies == null); - Debug.Assert(dependencies != null); - - _dependencies = dependencies; - _conditionalDependencies = conditionalDependencies; - } - - public override bool HasConditionalStaticDependencies - { - get - { - return _conditionalDependencies != null; - } - } - - public override bool HasDynamicDependencies - { - get - { - return false; - } - } - - public override bool InterestingForDynamicDependencyAnalysis - { - get - { - return true; - } - } - - public override bool StaticDependenciesAreComputed - { - get - { - return _dependencies != null; - } - } - - public override IEnumerable GetConditionalStaticDependencies(DependencyContextType context) - { - return _conditionalDependencies; - } - - public override IEnumerable GetStaticDependencies(DependencyContextType context) - { - return _dependencies; - } - - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, DependencyContextType context) - { - return Array.Empty(); - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyAnalyzer.cs b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyAnalyzer.cs index f4adb44450ee85..5a1737a0eea425 100644 --- a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyAnalyzer.cs +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyAnalyzer.cs @@ -38,6 +38,7 @@ public sealed class DependencyAnalyzer : De private List> _dynamicDependencyInterestingList = new List>(); private List _markedNodesWithDynamicDependencies = new List(); private bool _newDynamicDependenciesMayHaveAppeared; + private readonly DependencySink _dependencySink = new DependencySink(); private Dictionary, HashSet.CombinedDependencyListEntry>> _conditional_dependency_store = new Dictionary, HashSet.CombinedDependencyListEntry>>(); private bool _markingCompleted; @@ -88,12 +89,9 @@ public DynamicDependencyNode(DependencyNodeCore node) public void MarkNewDynamicDependencies(DependencyAnalyzer analyzer) { - foreach (DependencyNodeCore.CombinedDependencyListEntry dependency in - _node.SearchDynamicDependencies(analyzer._dynamicDependencyInterestingList, _next, analyzer._dependencyContext)) - { - Debug.Assert(dependency.OtherReasonNode is null || dependency.OtherReasonNode.Marked); - analyzer.AddToMarkStack(dependency.Node, dependency.Reason, _node, dependency.OtherReasonNode); - } + DependencySink sink = analyzer._dependencySink; + _node.SearchDynamicDependencies(analyzer._dynamicDependencyInterestingList, _next, sink, analyzer._dependencyContext); + analyzer.CommitDependencies(sink, _node); _next = analyzer._dynamicDependencyInterestingList.Count; } } @@ -178,39 +176,43 @@ private void ComputeDependencies(List> } // Internal details - private void GetStaticDependenciesImpl(DependencyNodeCore node) + private void AddStaticDependencies(DependencyNodeCore node) { - IEnumerable.DependencyListEntry> staticDependencies = node.GetStaticDependencies(_dependencyContext); - if (staticDependencies != null) + DependencySink sink = _dependencySink; + node.AddStaticDependencies(sink, _dependencyContext); + + if (node.HasConditionalStaticDependencies) { - foreach (DependencyNodeCore.DependencyListEntry dependency in staticDependencies) - { - AddToMarkStack(dependency.Node, dependency.Reason, node, null); - } + node.AddConditionalDependencies(sink, _dependencyContext); } - if (node.HasConditionalStaticDependencies) + CommitDependencies(sink, node); + } + + private void CommitDependencies( + DependencySink sink, + DependencyNodeCore source) + { + using DependencySink.DrainEnumerator dependencies = sink.Drain(); + while (dependencies.MoveNext()) { - foreach (DependencyNodeCore.CombinedDependencyListEntry dependency in node.GetConditionalStaticDependencies(_dependencyContext)) + var otherReasonNode = dependencies.OtherReasonNode; + if (otherReasonNode is null || otherReasonNode.Marked) { - if (dependency.OtherReasonNode is null || dependency.OtherReasonNode.Marked) - { - AddToMarkStack(dependency.Node, dependency.Reason, node, dependency.OtherReasonNode); - } - else - { - HashSet.CombinedDependencyListEntry> storedDependencySet; - if (!_conditional_dependency_store.TryGetValue(dependency.OtherReasonNode, out storedDependencySet)) - { - storedDependencySet = new HashSet.CombinedDependencyListEntry>(); - _conditional_dependency_store.Add(dependency.OtherReasonNode, storedDependencySet); - } - // Swap out other reason node as we're storing that as the dictionary key - DependencyNodeCore.CombinedDependencyListEntry conditionalDependencyStoreEntry = - new DependencyNodeCore.CombinedDependencyListEntry(dependency.Node, node, dependency.Reason); - storedDependencySet.Add(conditionalDependencyStoreEntry); - } + AddToMarkStack(dependencies.Dependency, dependencies.Reason, source, otherReasonNode); + continue; } + + if (!_conditional_dependency_store.TryGetValue(otherReasonNode, out HashSet.CombinedDependencyListEntry> storedDependencySet)) + { + storedDependencySet = new HashSet.CombinedDependencyListEntry>(); + _conditional_dependency_store.Add(otherReasonNode, storedDependencySet); + } + + // Swap out other reason node as we're storing that as the dictionary key + var conditionalDependencyStoreEntry = + new DependencyNodeCore.CombinedDependencyListEntry(dependencies.Dependency, source, dependencies.Reason); + storedDependencySet.Add(conditionalDependencyStoreEntry); } } @@ -220,7 +222,7 @@ private void GetStaticDependencies(DependencyNodeCore nod { if (node.StaticDependenciesAreComputed) { - GetStaticDependenciesImpl(node); + AddStaticDependencies(node); } else { @@ -254,14 +256,14 @@ private void ProcessMarkStack() _newDynamicDependenciesMayHaveAppeared = true; } + bool staticDependenciesAreComputed = currentNode.StaticDependenciesAreComputed; + // Add all static dependencies to the mark stack GetStaticDependencies(currentNode); - // If there are dynamic dependencies, note for later - if (currentNode.HasDynamicDependencies) + if (staticDependenciesAreComputed) { - _newDynamicDependenciesMayHaveAppeared = true; - _markedNodesWithDynamicDependencies.Add(new DynamicDependencyNode(currentNode)); + RegisterDynamicDependencies(currentNode); } // If this new node satisfies any stored conditional dependencies, @@ -318,7 +320,8 @@ public override void ComputeMarkedNodes() foreach (DependencyNodeCore node in deferredDependenciesInCurrentPhase) { Debug.Assert(node.StaticDependenciesAreComputed); - GetStaticDependenciesImpl(node); + AddStaticDependencies(node); + RegisterDynamicDependencies(node); } deferredDependenciesInCurrentPhase.Clear(); @@ -351,6 +354,15 @@ public override void ComputeMarkedNodes() } } + private void RegisterDynamicDependencies(DependencyNodeCore node) + { + if (node.HasDynamicDependencies) + { + _newDynamicDependenciesMayHaveAppeared = true; + _markedNodesWithDynamicDependencies.Add(new DynamicDependencyNode(node)); + } + } + private bool AddToMarkStack(DependencyNodeCore node, string reason, DependencyNodeCore reason1, DependencyNodeCore reason2) { if (_marker.MarkNode(node, reason1, reason2, reason)) diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyNodeCore.cs b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyNodeCore.cs index 8c8e37893cc333..e1bb65e1a88e4f 100644 --- a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyNodeCore.cs +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencyNodeCore.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#nullable enable + using System; using System.Collections.Generic; @@ -8,27 +10,20 @@ namespace ILCompiler.DependencyAnalysisFramework { public abstract class DependencyNodeCore : DependencyNode, IDependencyNode { - public struct DependencyListEntry + public readonly struct DependencyListEntry( + DependencyNodeCore node, + string reason) { - public DependencyListEntry(DependencyNodeCore node, - string reason) - { - Node = node; - Reason = reason; - } - - public DependencyListEntry(object node, - string reason) + public DependencyListEntry(object node, string reason) + : this((DependencyNodeCore)node, reason) { - Node = (DependencyNodeCore)node; - Reason = reason; } - public DependencyNodeCore Node; - public string Reason; + public readonly DependencyNodeCore Node = node; + public readonly string Reason = reason; } - public class DependencyList : List + public class DependencyList : List, IDependencySink { public DependencyList() { } @@ -37,44 +32,62 @@ public DependencyList(IEnumerable collection) { } - public void Add(DependencyNodeCore node, - string reason) + public virtual void Add(DependencyNodeCore node, + string reason) { - this.Add(new DependencyListEntry(node, reason)); + Add(new DependencyListEntry(node, reason)); } - public void Add(object node, string reason) + public virtual void Add(object node, string reason) { - this.Add(new DependencyListEntry((DependencyNodeCore)node, reason)); + Add(new DependencyListEntry(node, reason)); + } + + public new virtual void Add(DependencyListEntry dependency) + { + base.Add(dependency); + } + + public virtual void AddRange(params ReadOnlySpan dependencies) + { + foreach (DependencyListEntry dependency in dependencies) + { + Add(dependency); + } } } - public struct CombinedDependencyListEntry : IEquatable + public class CombinedDependencyList : List, IConditionalDependencySink { - public CombinedDependencyListEntry(DependencyNodeCore node, - DependencyNodeCore otherReasonNode, - string reason) + public new virtual void Add(CombinedDependencyListEntry dependency) { - Node = node; - OtherReasonNode = otherReasonNode; - Reason = reason; + base.Add(dependency); } + } + public readonly struct CombinedDependencyListEntry( + DependencyNodeCore node, + DependencyNodeCore otherReasonNode, + string reason) : IEquatable + { public CombinedDependencyListEntry(object node, object otherReasonNode, string reason) + : this( + (DependencyNodeCore)node, + (DependencyNodeCore)otherReasonNode, + reason) { - Node = (DependencyNodeCore)node; - OtherReasonNode = (DependencyNodeCore)otherReasonNode; - Reason = reason; } - // Used by HashSet, so must have good Equals/GetHashCode - public readonly DependencyNodeCore Node; - public readonly DependencyNodeCore OtherReasonNode; - public readonly string Reason; + internal readonly DependencyListEntry Dependency = new(node, reason); + public readonly DependencyNodeCore OtherReasonNode = otherReasonNode; - public override bool Equals(object obj) + public readonly DependencyNodeCore Node => Dependency.Node; + public readonly string Reason => Dependency.Reason; + + // Used by HashSet, so must have good Equals/GetHashCode + public override bool Equals(object? obj) { return obj is CombinedDependencyListEntry && Equals((CombinedDependencyListEntry)obj); } @@ -83,9 +96,7 @@ public override int GetHashCode() { int hash = 23; hash = hash * 31 + Node.GetHashCode(); - - if (OtherReasonNode != null) - hash = hash * 31 + OtherReasonNode.GetHashCode(); + hash = hash * 31 + OtherReasonNode.GetHashCode(); if (Reason != null) hash = hash * 31 + Reason.GetHashCode(); @@ -123,11 +134,15 @@ public abstract bool StaticDependenciesAreComputed public virtual int DependencyPhaseForDeferredStaticComputation { get; } - public abstract IEnumerable GetStaticDependencies(DependencyContextType context); + public abstract void AddStaticDependencies(DependencySink sink, DependencyContextType context); - public abstract IEnumerable GetConditionalStaticDependencies(DependencyContextType context); + public virtual void AddConditionalDependencies(DependencySink sink, DependencyContextType context) + { + } - public abstract IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, DependencyContextType context); + public virtual void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, DependencyContextType context) + { + } internal void CallOnMarked(DependencyContextType context) { diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencySink.cs b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencySink.cs new file mode 100644 index 00000000000000..1a63542e6d3309 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/DependencySink.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace ILCompiler.DependencyAnalysisFramework +{ + public sealed class DependencySink : + IDependencySink, + IConditionalDependencySink + { + private readonly List.DependencyListEntry> _dependencies = + new List.DependencyListEntry>(); + private readonly List.CombinedDependencyListEntry> _combinedDependencies = + new List.CombinedDependencyListEntry>(); + + /// + /// A single-use enumerator that clears its sink when disposed. + /// + public struct DrainEnumerator : IDisposable + { + private readonly DependencySink _sink; + private List.DependencyListEntry>.Enumerator _enumerator; + private List.CombinedDependencyListEntry>.Enumerator _combinedEnumerator; + private bool _enumeratingCombinedDependencies; + + internal DrainEnumerator(DependencySink sink) + { + _sink = sink; + _enumerator = sink._dependencies.GetEnumerator(); + _combinedEnumerator = sink._combinedDependencies.GetEnumerator(); + _enumeratingCombinedDependencies = false; + } + + public DependencyNodeCore Dependency => + _enumeratingCombinedDependencies ? _combinedEnumerator.Current.Node : _enumerator.Current.Node; + + public string Reason => + _enumeratingCombinedDependencies ? _combinedEnumerator.Current.Reason : _enumerator.Current.Reason; + + public DependencyNodeCore? OtherReasonNode => + _enumeratingCombinedDependencies ? _combinedEnumerator.Current.OtherReasonNode : null; + + /// + /// Advances to the next dependency. + /// + public bool MoveNext() + { + if (!_enumeratingCombinedDependencies) + { + if (_enumerator.MoveNext()) + { + return true; + } + + _enumeratingCombinedDependencies = true; + } + + return _combinedEnumerator.MoveNext(); + } + + /// + public void Dispose() + { + _enumerator.Dispose(); + _combinedEnumerator.Dispose(); + _sink?.Clear(); + } + } + + /// + /// Returns a single-use enumerator over the current dependencies that clears the sink when disposed. + /// + public DrainEnumerator Drain() + { + return new DrainEnumerator(this); + } + + private void Clear() + { + _dependencies.Clear(); + _combinedDependencies.Clear(); + } + + public void Add(DependencyNodeCore node, string reason) + { + Add(new DependencyNodeCore.DependencyListEntry(node, reason)); + } + + public void AddConditional( + DependencyNodeCore node, + DependencyNodeCore otherReasonNode, + string reason) + { + Debug.Assert(otherReasonNode is not null); + Add(new DependencyNodeCore.CombinedDependencyListEntry(node, otherReasonNode, reason)); + } + + public void Add(object node, string reason) + { + Add((DependencyNodeCore)node, reason); + } + + public void AddConditional( + object node, + object otherReasonNode, + string reason) + { + Debug.Assert(otherReasonNode is not null); + Add(new DependencyNodeCore.CombinedDependencyListEntry(node, otherReasonNode, reason)); + } + + public void Add(DependencyNodeCore.DependencyListEntry dependency) + { + _dependencies.Add(dependency); + } + + public void Add(DependencyNodeCore.CombinedDependencyListEntry dependency) + { + _combinedDependencies.Add(dependency); + } + + public void AddRange(params ReadOnlySpan.DependencyListEntry> dependencies) + { + foreach (DependencyNodeCore.DependencyListEntry dependency in dependencies) + { + Add(dependency); + } + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs index fb0b622d59f4d4..7d266ab6baa114 100644 --- a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencyNode.cs @@ -35,11 +35,11 @@ bool StaticDependenciesAreComputed get; } - IEnumerable.DependencyListEntry> GetStaticDependencies(DependencyContextType context); + void AddStaticDependencies(DependencySink sink, DependencyContextType context); - IEnumerable.CombinedDependencyListEntry> GetConditionalStaticDependencies(DependencyContextType context); + void AddConditionalDependencies(DependencySink sink, DependencyContextType context); - IEnumerable.CombinedDependencyListEntry> SearchDynamicDependencies(List> markedNodes, int firstNode, DependencyContextType context); + void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, DependencyContextType context); string GetName(DependencyContextType context); } diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencySink.cs b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencySink.cs new file mode 100644 index 00000000000000..d6664b3c56ef4d --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/IDependencySink.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +using System; + +namespace ILCompiler.DependencyAnalysisFramework; + +public interface IDependencySink +{ + void Add(DependencyNodeCore node, string reason); + void Add(object node, string reason); + void Add(DependencyNodeCore.DependencyListEntry dependency); + void AddRange(params ReadOnlySpan.DependencyListEntry> dependencies); +} + +public interface IConditionalDependencySink +{ + void Add(DependencyNodeCore.CombinedDependencyListEntry dependency); +} diff --git a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj index 28aa33b5afe733..2fdf8ecf9331fb 100644 --- a/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj +++ b/src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj @@ -16,11 +16,11 @@ Debug;Release;Checked - + @@ -29,6 +29,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/AllMethodsOnTypeNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/AllMethodsOnTypeNode.cs index a89a3115cb102a..9accbcf042a72f 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/AllMethodsOnTypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/AllMethodsOnTypeNode.cs @@ -28,12 +28,12 @@ public AllMethodsOnTypeNode(TypeDesc type) public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; foreach (MethodDesc method in Type.GetAllMethods()) { @@ -50,8 +50,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto } } } - - return dependencies; } protected override string GetName(NodeFactory factory) => $"All methods on type {Type.ToString()}"; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayInterfaceMethodsNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayInterfaceMethodsNode.cs index a3ab8a014989ed..3dd0583efd3251 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayInterfaceMethodsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayInterfaceMethodsNode.cs @@ -37,16 +37,16 @@ public ArrayInterfaceMethodsNode(ArrayType arrayType) public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - List result = new List(); + DependencySink result = sink; MetadataType szArrayHelper = factory.TypeSystemContext.SystemModule.GetType("System"u8, "SZArrayHelper"u8, throwIfNotFound: false); if (szArrayHelper == null) - return result; + return; TypeDesc elementType = _arrayType.ElementType; @@ -75,8 +75,6 @@ public override IEnumerable GetConditionalStaticDep "Array generic interface method implemented by SZArrayHelper")); } } - - return result; } protected override string GetName(NodeFactory factory) => $"Array interface methods on {_arrayType}"; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs index 3882798c70239d..954f4ed56336be 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Internal.Text; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -91,13 +92,11 @@ protected override void OnMarked(NodeFactory factory) _parentNode.AddEmbeddedObject(this); } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - return new[] - { + sink.AddRange( new DependencyListEntry(Target, "reloc"), - new DependencyListEntry(_parentNode, "Pointer region") - }; + new DependencyListEntry(_parentNode, "Pointer region")); } public override int ClassCode => -66002498; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs index 33b7594383c49a..d7595c85b62ded 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs @@ -59,8 +59,8 @@ public void InitializeIndexFromBeginningOfArray(int index) public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } public abstract void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly); } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs index df108e701cb717..b2ae9a70258867 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Internal.Text; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -36,7 +37,7 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f } // At minimum, Target needs to be reported as a static dependency by inheritors. - public abstract override IEnumerable GetStaticDependencies(NodeFactory factory); + public abstract override void AddStaticDependencies(DependencySink sink, NodeFactory factory); int ISymbolNode.Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/InheritedVirtualMethodsNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/InheritedVirtualMethodsNode.cs index 331b8ea78cbc99..5485ca32d54852 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/InheritedVirtualMethodsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/InheritedVirtualMethodsNode.cs @@ -40,14 +40,14 @@ public InheritedVirtualMethodsNode(TypeDesc type) public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory context) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { DefType defType = (DefType)_type; - List result = new List(); + DependencySink result = sink; // Class virtual method path: for each virtual slot, compile the implementation // on this type if the slot-defining method is used. @@ -149,8 +149,6 @@ public override IEnumerable GetConditionalStaticDep { // TODO: https://github.com/dotnet/runtime/issues/132338 - Gate this recovery on --resilient and report a warning. } - - return result; } private static bool TypeHasGVMSlots(TypeDesc type) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs index bc31ff907f5fea..5751330b72f75d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs @@ -271,9 +271,9 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append($"__RSDSChecksum"); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) => []; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) { return "RSDSChecksum"; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DeferredTillPhaseNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DeferredTillPhaseNode.cs index bedb081f87447d..a24c0cc5fe029a 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DeferredTillPhaseNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DeferredTillPhaseNode.cs @@ -42,15 +42,15 @@ public void AddDependency(DependencyNodeCore newDependency) public override bool StaticDependenciesAreComputed => _dependenciesNoLongerMutable; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => null; - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { foreach (var dependencyNode in _dependencies) { - yield return new DependencyNodeCore.DependencyListEntry(dependencyNode, "DeferredDependency"); + sink.Add(new DependencyNodeCore.DependencyListEntry(dependencyNode, "DeferredDependency")); } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => throw new NotImplementedException(); + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) => throw new NotImplementedException(); protected override string GetName(NodeFactory context) => $"DeferredTillPhaseNode {_phase}"; public override int DependencyPhaseForDeferredStaticComputation => _phase; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs index 0785747f40e9b7..a3b81ddac51fdb 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperImport.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -97,21 +98,17 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f } } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { if (_delayLoadHelper is not null) { - return new DependencyListEntry[] - { + sink.AddRange( new DependencyListEntry(_delayLoadHelper, "Delay load helper thunk for ready-to-run fixup import"), - new DependencyListEntry(ImportSignature, "Signature for ready-to-run fixup import"), - }; + new DependencyListEntry(ImportSignature, "Signature for ready-to-run fixup import")); + return; } - return new DependencyListEntry[] - { - new DependencyListEntry(ImportSignature, "Signature for ready-to-run fixup import"), - }; + sink.Add(ImportSignature, "Signature for ready-to-run fixup import"); } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs index 980dfc535ceb88..ee160e6d3f17d2 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadHelperMethodImport.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -36,12 +37,9 @@ public DelayLoadHelperMethodImport( _useInstantiatingStub = useInstantiatingStub; } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - foreach (DependencyListEntry baseEntry in base.GetStaticDependencies(factory)) - { - yield return baseEntry; - } + base.AddStaticDependencies(sink, factory); if (_useInstantiatingStub) { // Require compilation of the canonical version for instantiating stubs @@ -60,7 +58,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto if (useDependency) { ISymbolNode canonMethodNode = factory.CompiledMethodNode(canonMethod); - yield return new DependencyListEntry(canonMethodNode, "Canonical method for instantiating stub"); + sink.Add(canonMethodNode, "Canonical method for instantiating stub"); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodImport.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodImport.cs index 3bdef8fb2f8be4..93e26481db24c9 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodImport.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodImport.cs @@ -6,6 +6,7 @@ using Internal.JitInterface; using Internal.TypeSystem; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -40,14 +41,11 @@ public DelayLoadMethodImport( public override int ClassCode => 459923351; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - foreach (DependencyListEntry entry in base.GetStaticDependencies(factory)) - { - yield return entry; - } + base.AddStaticDependencies(sink, factory); if (_localMethod != null) - yield return new DependencyListEntry(_localMethod, "Local method import"); + sink.Add(_localMethod, "Local method import"); } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs index 4fce8fa99bb579..0cbbda6d3b7abf 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelegateCtorSignature.cs @@ -5,6 +5,7 @@ using Internal.JitInterface; using Internal.Text; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -63,14 +64,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return builder.ToObjectData(); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - return new DependencyList( - new DependencyListEntry[] - { - new DependencyListEntry(_targetMethod, "Delegate target method") - } - ); + sink.Add(_targetMethod, "Delegate target method"); } public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs index 6480ded36ab382..bfa8f9177bed33 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs @@ -154,9 +154,9 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return _methodNodes.Count == 0; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - return new DependencyNodeCore.DependencyList(new DependencyListEntry[] { new DependencyListEntry(_ehInfoNode, "EH info array") }); + sink.Add(_ehInfoNode, "EH info array"); } public override int ClassCode => 582513248; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs index 94623a51708466..ba309518e2abd8 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GenericLookupSignature.cs @@ -9,6 +9,7 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -130,23 +131,21 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return dataBuilder.ToObjectData(); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = null; + DependencySink dependencies = sink; if (_fixupKind == ReadyToRunFixupKind.TypeHandle) { - TypeFixupSignature.AddDependenciesForAsyncStateMachineBox(ref dependencies, factory, _typeArgument); + TypeFixupSignature.AddDependenciesForAsyncStateMachineBox(dependencies, factory, _typeArgument); // In shared generic code, newobj uses a generic dictionary lookup for the type handle // rather than a direct READYTORUN_FIXUP_TypeHandle (TypeFixupSignature). Mirror the // creation of InheritedVirtualMethodsNode as it is done in TypeFixupSignature, so we // scan the virtual methods on this type for dependency analysis. if (_typeArgument != null) - factory.AddVirtualMethodDiscoveryDependencies(ref dependencies, _typeArgument); + factory.AddVirtualMethodDiscoveryDependencies(dependencies, _typeArgument); } - - return dependencies; } public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs index fba01e2a38c51d..7157028bdd7f8e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/Import.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -65,9 +66,9 @@ public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - return new DependencyListEntry[] { new DependencyListEntry(ImportSignature, "Signature for ready-to-run fixup import") }; + sink.Add(ImportSignature, "Signature for ready-to-run fixup import"); } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs index 6fb78cf67757f3..9b79638788388d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -142,13 +143,13 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f } } - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - yield return new DependencyListEntry(_imports, "Import section fixup data"); - yield return new DependencyListEntry(_signatures, "Import section signatures"); + sink.Add(_imports, "Import section fixup data"); + sink.Add(_signatures, "Import section signatures"); if (_gcRefMap != null) { - yield return new DependencyListEntry(_gcRefMap, "GC ref map"); + sink.Add(_gcRefMap, "GC ref map"); } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs index 8bf4b1ef8ac9e1..bafb6339eaaf4c 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportThunk.cs @@ -5,6 +5,7 @@ using Internal.Text; using Internal.TypeSystem; using System.Diagnostics; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -94,12 +95,11 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return comparer.Compare(_helperCell, otherNode._helperCell); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - Debug.Assert(base.ComputeNonRelocationBasedDependencies(factory) == null); - DependencyList dependencies = new DependencyList(); + base.ComputeNonRelocationBasedDependencies(sink, factory); + DependencySink dependencies = sink; dependencies.Add(factory.DelayLoadMethodCallThunks, "MethodCallThunksList"); - return dependencies; } protected override void OnMarked(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstrumentationDataTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstrumentationDataTableNode.cs index 9a152a33a61df2..15ec2f427723bf 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstrumentationDataTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstrumentationDataTableNode.cs @@ -17,6 +17,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -186,7 +187,7 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde // Register some MDs that had synthesized PGO data created to be physically embedded by this node, and add // the appropriate dependencies of the embedding to a dependency list. - public void EmbedSynthesizedPgoDataForMethods(ref DependencyList dependencies, IEnumerable mds) + public void EmbedSynthesizedPgoDataForMethods(IDependencySink dependencies, IEnumerable mds) { PgoValueEmitter pgoEmitter = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, false); foreach (MethodDesc md in mds) @@ -204,12 +205,11 @@ public void EmbedSynthesizedPgoDataForMethods(ref DependencyList dependencies, I foreach (Import imp in pgoEmitter.ReferencedImports) { - dependencies ??= new DependencyList(); dependencies.Add(imp, "Dependency of synthesized PGO data"); } } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { PgoValueEmitter pgoEmitter = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, false); foreach (EcmaModule inputModule in _factory.CompilationModuleGroup.CompilationModuleSet) @@ -223,13 +223,10 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact } } } - DependencyListEntry[] symbols = new DependencyListEntry[pgoEmitter.ReferencedImports.Count]; - for (int i = 0; i < symbols.Length; i++) + for (int i = 0; i < pgoEmitter.ReferencedImports.Count; i++) { - symbols[i] = new DependencyListEntry(pgoEmitter.ReferencedImports[i], "Pgo Instrumentation Data"); + sink.Add(pgoEmitter.ReferencedImports[i], "Pgo Instrumentation Data"); } - - return new DependencyList(symbols); } public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs index e7df30cb750397..f5c0c50ff1d09d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs @@ -13,6 +13,7 @@ using Internal.CorConstants; using Internal.ReadyToRunConstants; using ILCompiler.ReadyToRun.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -51,9 +52,10 @@ public MethodFixupSignature( public bool NeedsInstantiationArg => _method.ConstrainedType?.IsCanonicalSubtype(CanonicalFormKind.Any) ?? false; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList list = base.ComputeNonRelocationBasedDependencies(factory); + DependencySink list = sink; + base.ComputeNonRelocationBasedDependencies(sink, factory); MethodDesc canonMethod = Method.GetCanonMethodTarget(CanonicalFormKind.Specific); if (_fixupKind == ReadyToRunFixupKind.VirtualEntry && !Method.IsAbstract && @@ -62,7 +64,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact factory.CompilationModuleGroup.CrossModuleCompileable(canonMethod) && factory.CompilationModuleGroup.ContainsMethodBody(canonMethod, false)) { - list = list ?? new DependencyList(); try { factory.DetectGenericCycles(_method.Method, canonMethod); @@ -87,7 +88,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact // instantiations of virtual methods that have at least one non-canonical argument (aka a valuetype). if (HasNonCanonicalInstantiationArguments(canonMethod) && !factory.CanBeInGenericCycle(Method)) { - list = list ?? new DependencyList(); list.Add(factory.GVMDependencies(Method), "Virtual dispatch dependency"); } } @@ -101,11 +101,8 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact !Method.IsFinal && !Method.OwningType.IsGenericDefinition) { - list = list ?? new DependencyList(); list.Add(factory.VirtualMethodUse(canonMethod), "Non-GVM virtual slot use"); } - - return list; } private static bool HasNonCanonicalInstantiationArguments(MethodDesc canonMethod) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs index fe8c2ae0a5f3a4..6d9ec8795afb62 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodGCInfoNode.cs @@ -7,6 +7,7 @@ using System.Linq; using Internal.Text; using Internal.TypeSystem; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -312,7 +313,7 @@ protected override string GetName(NodeFactory context) return sb.ToString(); } - public override IEnumerable GetStaticDependencies(NodeFactory context) => null; + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs index d6077f3a6dd13d..9b910114788692 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs @@ -11,6 +11,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -262,26 +263,27 @@ public byte[] GetFixupBlob(NodeFactory factory) return writer.ToArray(); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencyList = new DependencyList(new DependencyListEntry[] { new DependencyListEntry(GCInfoNode, "Unwind & GC info") }); + sink.Add(GCInfoNode, "Unwind & GC info"); if (this.ColdCodeNode != null) { - dependencyList.Add(this.ColdCodeNode, "cold"); + sink.Add(this.ColdCodeNode, "cold"); } foreach (ISymbolNode node in _fixups) { - dependencyList.Add(node, "classMustBeLoadedBeforeCodeIsRun"); + sink.Add(node, "classMustBeLoadedBeforeCodeIsRun"); } if (_nonRelocationDependencies != null) { - dependencyList.AddRange(_nonRelocationDependencies); + foreach (DependencyListEntry dependency in _nonRelocationDependencies) + { + sink.Add(dependency); + } } - - return dependencyList; } public override bool StaticDependenciesAreComputed => _methodCode != null; @@ -291,6 +293,43 @@ public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb.Append(nameMangler.GetMangledMethodName(_method)); } + public void AddRuntimeDeterminedStaticDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod) + { + if (_nonRelocationDependencies is not null) + { + foreach (DependencyListEntry dependency in _nonRelocationDependencies) + { + AddRuntimeDeterminedDependency(sink, factory, concreteMethod, dependency.Node); + } + } + + if (_methodCode.Relocs is not null) + { + foreach (Relocation relocation in _methodCode.Relocs) + { + AddRuntimeDeterminedDependency(sink, factory, concreteMethod, relocation.Target); + } + } + } + + public void AddRuntimeDeterminedConditionalDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod) + { + } + + private static void AddRuntimeDeterminedDependency(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod, object dependency) + { + if (dependency is INodeWithRuntimeDeterminedDependencies runtimeDeterminedDependency) + { + runtimeDeterminedDependency.AddDependencies( + sink, + factory, + concreteMethod.OwningType.Instantiation, + concreteMethod.Instantiation, + isConcreteInstantiation: !concreteMethod.IsSharedByGenericInstantiations, + otherReasonNode: null); + } + } + protected override string GetName(NodeFactory factory) { Utf8StringBuilder sb = new Utf8StringBuilder(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs index de6f382cb96da7..b89434ca746e47 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/NewArrayFixupSignature.cs @@ -5,6 +5,7 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -51,13 +52,11 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return comparer.Compare(_arrayType, otherNode._arrayType); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = base.ComputeNonRelocationBasedDependencies(factory); - - factory.AddVirtualMethodDiscoveryDependencies(ref dependencies, _arrayType); - - return dependencies; + DependencySink dependencies = sink; + base.ComputeNonRelocationBasedDependencies(sink, factory); + factory.AddVirtualMethodDiscoveryDependencies(dependencies, _arrayType); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs index 7af2c99e1825c5..a5fa6266942777 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/PrecodeMethodImport.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -45,14 +46,11 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde base.AppendMangledName(nameMangler, sb); } - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - foreach (DependencyListEntry entry in base.GetStaticDependencies(factory)) - { - yield return entry; - } + base.AddStaticDependencies(sink, factory); if (_localMethod != null) - yield return new DependencyListEntry(_localMethod, "Precode Method Import"); + sink.Add(_localMethod, "Precode Method Import"); } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs index bf02034ec76403..dd8868e3bbce06 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureEmbeddedPointerIndirectionNode.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using ILCompiler.DependencyAnalysis.ReadyToRun; using Internal.Text; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -19,12 +20,9 @@ public SignatureEmbeddedPointerIndirectionNode(Import import, Signature signatur protected override string GetName(NodeFactory factory) => $"Embedded pointer to {Target.GetMangledName(factory.NameMangler)}"; - public override IEnumerable GetStaticDependencies(NodeFactory factory) + public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { - return new[] - { - new DependencyListEntry(Target, "reloc"), - }; + sink.Add(Target, "reloc"); } public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringDiscoverableAssemblyStubNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringDiscoverableAssemblyStubNode.cs index 133ac674549d47..08c86e9099d077 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringDiscoverableAssemblyStubNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/StringDiscoverableAssemblyStubNode.cs @@ -22,12 +22,10 @@ public abstract class StringDiscoverableAssemblyStubNode : AssemblyStubNode /// public abstract string LookupString { get; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; dependencies.Add(factory.InjectStringThunksImport, "StringDiscoverableAssemblyStubNode requires InjectStringThunks fixup"); - - return dependencies; } protected override void OnMarked(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SymbolNodeRange.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SymbolNodeRange.cs index 99847780826dfe..3628ddc6f19386 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SymbolNodeRange.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SymbolNodeRange.cs @@ -48,9 +48,9 @@ public void OnNodeInRangeMarked(ISortableSymbolNode node) public override bool StaticDependenciesAreComputed => true; public int Offset => 0; public bool RepresentsIndirectionCell => false; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) => []; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { } + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs index 0f6c9981d9a839..d02509960d5c9d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs @@ -11,6 +11,7 @@ using Internal.ReadyToRunConstants; using Internal.CorConstants; using Internal.JitInterface; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -201,9 +202,9 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return comparer.Compare(_typeDesc, otherNode._typeDesc); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = new DependencyList(); + DependencySink dependencies = sink; if (_typeDesc.HasInstantiation && !_typeDesc.IsGenericDefinition && @@ -213,16 +214,15 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencies.Add(factory.AllMethodsOnType(_typeDesc), "Methods on generic type instantiation"); } - factory.AddVirtualMethodDiscoveryDependencies(ref dependencies, _typeDesc); + factory.AddVirtualMethodDiscoveryDependencies(dependencies, _typeDesc); if (_fixupKind == ReadyToRunFixupKind.TypeHandle) { - AddDependenciesForAsyncStateMachineBox(ref dependencies, factory, _typeDesc); + AddDependenciesForAsyncStateMachineBox(dependencies, factory, _typeDesc); } - return dependencies; } - public static void AddDependenciesForAsyncStateMachineBox(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + public static void AddDependenciesForAsyncStateMachineBox(DependencySink dependencies, NodeFactory factory, TypeDesc type) { ReadyToRunCompilerContext context = (ReadyToRunCompilerContext)type.Context; // If adding a typehandle to the AsyncStateMachineBox, pre-compile the most commonly used methods. @@ -230,9 +230,6 @@ public static void AddDependenciesForAsyncStateMachineBox(ref DependencyList dep // simple examples of async will get compiled if (factory.OptimizationFlags.OptimizeAsyncMethods && type.GetTypeDefinition() == context.AsyncStateMachineBoxType && !type.IsGenericDefinition && factory.CompilationCurrentPhase <= 7) { - if (dependencies == null) - dependencies = new DependencyList(); - // This is the async state machine box, compile the cctor, and the MoveNext method. foreach (MethodDesc method in type.ConvertToCanonForm(CanonicalFormKind.Specific).GetAllMethods()) { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmInterpreterToR2RThunkNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmInterpreterToR2RThunkNode.cs index 577f0eae53b327..6f657cdd2fc69e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmInterpreterToR2RThunkNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmInterpreterToR2RThunkNode.cs @@ -100,12 +100,12 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return _wasmSignature.CompareTo(otherNode._wasmSignature); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = base.ComputeNonRelocationBasedDependencies(factory); + DependencySink dependencies = sink; + base.ComputeNonRelocationBasedDependencies(sink, factory); dependencies.Add(_targetTypeNode, "Wasm interpreter-to-R2R thunk requires target type node"); dependencies.Add(factory.WasmTypeNode(sigForInterpToR2RThunks), "Wasm interpreter-to-R2R thunk requires type for the function entry point"); - return dependencies; } protected override void EmitCode(NodeFactory factory, ref Wasm.WasmEmitter instructionEncoder, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmR2RToInterpreterThunkNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmR2RToInterpreterThunkNode.cs index 177d7dd928b7b4..a6a78d7e6f8d48 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmR2RToInterpreterThunkNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmR2RToInterpreterThunkNode.cs @@ -110,11 +110,11 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return _wasmSignature.CompareTo(otherNode._wasmSignature); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = base.ComputeNonRelocationBasedDependencies(factory); + DependencySink dependencies = sink; + base.ComputeNonRelocationBasedDependencies(sink, factory); dependencies.Add(_typeNode, "Wasm R2R to interpreter thunk requires type node"); - return dependencies; } protected override void EmitCode(NodeFactory factory, ref Wasm.WasmEmitter instructionEncoder, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index 291276e9bf20f0..cdf383172c24dd 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -199,7 +199,7 @@ public ArrayInterfaceMethodsNode ArrayInterfaceMethods(ArrayType arrayType) return _arrayInterfaceMethods.GetOrAdd((ArrayType)arrayType.ConvertToCanonForm(CanonicalFormKind.Specific)); } - public void AddVirtualMethodDiscoveryDependencies(ref DependencyList dependencies, TypeDesc type) + public void AddVirtualMethodDiscoveryDependencies(DependencySink dependencies, TypeDesc type) { if (CompilationCurrentPhase != 0) return; @@ -214,14 +214,12 @@ public void AddVirtualMethodDiscoveryDependencies(ref DependencyList dependencie type.IsDefType && CompilationModuleGroup.VersionsWithType(type)) { - dependencies ??= new DependencyList(); dependencies.Add(InheritedVirtualMethods(type), "Inherited virtual/interface methods on type"); } // Arrays implement the generic collection interfaces through SZArrayHelper. Discover those // implementations so that e.g. ((ICollection)intArray).Count gets discovered. else if (type.IsSzArray) { - dependencies ??= new DependencyList(); dependencies.Add(ArrayInterfaceMethods((ArrayType)type), "Array generic interface methods"); } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/FileLayoutOptimizer.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/FileLayoutOptimizer.cs index e46de02cbf8b77..238c8cd1121729 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/FileLayoutOptimizer.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/FileLayoutOptimizer.cs @@ -103,6 +103,9 @@ public ImmutableArray> ApplyProfilerGuidedMethod sortOrder++; } + const int MaxDependencyDepth = 5; + var dependencySinks = new DependencySink[MaxDependencyDepth + 1]; + if (_fileLayoutAlgorithm == FileLayoutAlgorithm.MethodOrder) { // Sort the dependencies of methods by the method order @@ -118,7 +121,7 @@ public ImmutableArray> ApplyProfilerGuidedMethod void ApplySortToDependencies(DependencyNodeCore node, int depth) { - if (depth > 5) + if (depth > MaxDependencyDepth) return; if (node is SortableDependencyNode sortableNode) @@ -127,9 +130,18 @@ void ApplySortToDependencies(DependencyNodeCore node, int depth) return; // Node already sorted sortableNode.CustomSort += sortOrder++; } - foreach (var dependency in node.GetStaticDependencies(_nodeFactory)) + var dependencySink = dependencySinks[depth]; + if (dependencySink is null) + { + dependencySink = new DependencySink(); + dependencySinks[depth] = dependencySink; + } + + node.AddStaticDependencies(dependencySink, _nodeFactory); + using var dependencies = dependencySink.Drain(); + while (dependencies.MoveNext()) { - ApplySortToDependencies(dependency.Node, depth + 1); + ApplySortToDependencies(dependencies.Dependency, depth + 1); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunExternalTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunExternalTypeMapNode.cs index d02586c9093220..974aa09d788df0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunExternalTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunExternalTypeMapNode.cs @@ -66,22 +66,22 @@ public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section se return section.Place(tuple); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - yield return new DependencyListEntry(importProvider.GetImportToType(TypeMapGroup, TriggeringModule), $"Type map '{TypeMapGroup}' key type"); + sink.Add(importProvider.GetImportToType(TypeMapGroup, TriggeringModule), $"Type map '{TypeMapGroup}' key type"); if (map.ThrowingMethodStub is not null) { - yield break; + return; } foreach (var entry in map.TypeMap) { - yield return new DependencyListEntry(importProvider.GetImportToType(entry.Value.type, TriggeringModule), $"External type map entry target for key '{entry.Key}'"); + sink.Add(importProvider.GetImportToType(entry.Value.type, TriggeringModule), $"External type map entry target for key '{entry.Key}'"); } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"ExternalTypeMap {TypeMapGroup} entries in assembly {TriggeringModule.GetDisplayName()}"; } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProxyTypeMapNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProxyTypeMapNode.cs index 6f5e80a00f2e4b..35fb28f9e842c7 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProxyTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProxyTypeMapNode.cs @@ -66,23 +66,23 @@ public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section se return section.Place(tuple); } - public override IEnumerable GetConditionalStaticDependencies(NodeFactory context) => []; - public override IEnumerable GetStaticDependencies(NodeFactory context) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory context) { } + public override void AddStaticDependencies(DependencySink sink, NodeFactory context) { - yield return new DependencyListEntry(importProvider.GetImportToType(TypeMapGroup, TriggeringModule), $"Type map '{TypeMapGroup}' key type"); + sink.Add(importProvider.GetImportToType(TypeMapGroup, TriggeringModule), $"Type map '{TypeMapGroup}' key type"); if (map.ThrowingMethodStub is not null) { - yield break; + return; } foreach (var entry in map.TypeMap) { - yield return new DependencyListEntry(importProvider.GetImportToType(entry.Key, TriggeringModule), $"Key type of Proxy type map entry"); - yield return new DependencyListEntry(importProvider.GetImportToType(entry.Value, TriggeringModule), $"Proxy type map entry target for key '{entry.Key}'"); + sink.Add(importProvider.GetImportToType(entry.Key, TriggeringModule), $"Key type of Proxy type map entry"); + sink.Add(importProvider.GetImportToType(entry.Value, TriggeringModule), $"Proxy type map entry target for key '{entry.Key}'"); } } - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => []; + public override void SearchDynamicDependencies(List> markedNodes, int firstNode, DependencySink sink, NodeFactory context) { } protected override string GetName(NodeFactory context) => $"ProxyTypeMap {TypeMapGroup} entries in assembly {TriggeringModule.GetDisplayName()}"; } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/TypeMapAssemblyTargetsNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/TypeMapAssemblyTargetsNode.cs index d723fc8857cbe0..42017f9d63d11f 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/TypeMapAssemblyTargetsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/TypeMapAssemblyTargetsNode.cs @@ -34,9 +34,9 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer public int Offset => 0; - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) { - DependencyList dependencies = []; + DependencySink dependencies = sink; foreach (var map in _assemblyTypeMaps.Maps) { // Skip groups where assembly target attributes were present but all failed to resolve @@ -54,7 +54,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact dependencies.Add(new DependencyListEntry(_importReferenceProvider.GetImportToModule(targetModule), "Type Map Assembly Target")); } } - return dependencies; } public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 8bd8d09541343c..7f6a6db230b78b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -502,7 +502,6 @@ private void AddPrecodeFixup(ISymbolNode node) private void AddAdditionalDependency(ISymbolNode node, string reason) { - _additionalDependencies ??= new DependencyList(); _additionalDependencies.Add(node, reason); } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/DependencyAnalysis/MethodCodeNode.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/DependencyAnalysis/MethodCodeNode.cs index f8418a8d67befc..c21498815b482e 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/DependencyAnalysis/MethodCodeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/DependencyAnalysis/MethodCodeNode.cs @@ -10,7 +10,8 @@ using Internal.Text; using Internal.TypeSystem; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; +using CombinedDependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.CombinedDependencyList; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { @@ -66,37 +67,74 @@ public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder public override bool HasConditionalStaticDependencies => CodeBasedDependencyAlgorithm.HasConditionalDependenciesDueToMethodCodePresence(_method); - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) + public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { - CombinedDependencyList dependencies = null; - CodeBasedDependencyAlgorithm.AddConditionalDependenciesDueToMethodCodePresence(ref dependencies, factory, _method); - return dependencies ?? (IEnumerable)Array.Empty(); + CodeBasedDependencyAlgorithm.AddConditionalDependenciesDueToMethodCodePresence(sink, factory, _method); } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) + public void AddRuntimeDeterminedStaticDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod) { - DependencyList dependencies = _nonRelocationDependencies != null ? new DependencyList(_nonRelocationDependencies) : null; + if (_nonRelocationDependencies is not null) + { + foreach (DependencyListEntry dependency in _nonRelocationDependencies) + { + AddRuntimeDeterminedDependency(sink, factory, concreteMethod, dependency.Node); + } + } + + if (_methodCode.Relocs is not null) + { + foreach (Relocation relocation in _methodCode.Relocs) + { + AddRuntimeDeterminedDependency(sink, factory, concreteMethod, relocation.Target); + } + } + } + + public void AddRuntimeDeterminedConditionalDependencies(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod) + { + } + + private static void AddRuntimeDeterminedDependency(DependencySink sink, NodeFactory factory, MethodDesc concreteMethod, object dependency) + { + if (dependency is INodeWithRuntimeDeterminedDependencies runtimeDeterminedDependency) + { + runtimeDeterminedDependency.AddDependencies( + sink, + factory, + concreteMethod.OwningType.Instantiation, + concreteMethod.Instantiation, + isConcreteInstantiation: !concreteMethod.IsSharedByGenericInstantiations, + otherReasonNode: null); + } + } + + protected override void ComputeNonRelocationBasedDependencies(DependencySink sink, NodeFactory factory) + { + DependencySink dependencies = sink; + if (_nonRelocationDependencies is not null) + { + foreach (DependencyListEntry dependency in _nonRelocationDependencies) + { + dependencies.Add(dependency); + } + } TypeDesc owningType = _method.OwningType; if (factory.PreinitializationManager.HasEagerStaticConstructor(owningType)) { - dependencies ??= new DependencyList(); dependencies.Add(factory.EagerCctorIndirection(owningType.GetStaticConstructor()), "Eager .cctor"); } if (_ehInfo != null) { - dependencies ??= new DependencyList(); dependencies.Add(_ehInfo, "Exception handling information"); } if (MethodAssociatedDataNode.MethodHasAssociatedData(this)) { - dependencies ??= new DependencyList(); dependencies.Add(new DependencyListEntry(factory.MethodAssociatedData(this), "Method associated data")); } - - return dependencies; } public override ObjectData GetData(NodeFactory factory, bool relocsOnly) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 23d0fd509dc85c..1ea9051e660b17 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -1892,7 +1892,7 @@ private void getMethodVTableOffset(CORINFO_METHOD_STRUCT_* method, ref uint offs } if (_compilation.NeedsSlotUseTracking(owningType)) - (_additionalDependencies ??= new ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList()).Add(_compilation.NodeFactory.VirtualMethodUse(methodDesc), "Virtual method call"); + _additionalDependencies.Add(_compilation.NodeFactory.VirtualMethodUse(methodDesc), "Virtual method call"); offsetAfterIndirection = (uint)(EETypeNode.GetVTableOffset(pointerSize) + slot * pointerSize); }