| File: Compiler\UsageBasedTypeMapManager.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// 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.Text; using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; using Internal.IL; using Internal.IL.Stubs; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; using static ILCompiler.TypeMapMetadata; namespace ILCompiler { public sealed class UsageBasedTypeMapManager : TypeMapManager { private sealed class AllTypeMapsNode(TypeMapMetadata typeMapState) : DependencyNodeCore<NodeFactory> { public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) { List<CombinedDependencyListEntry> entries = []; 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<DependencyListEntry> GetStaticDependencies(NodeFactory context) => Array.Empty<DependencyListEntry>(); public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => Array.Empty<CombinedDependencyListEntry>(); protected override string GetName(NodeFactory context) => $"Type maps root node: {typeMapState.DiagnosticName}"; private static IExternalTypeMapNode GetExternalTypeMapNode(TypeDesc typeMapGroup, IExternalTypeMap map) { return map.ThrowingMethodStub is not null ? new InvalidExternalTypeMapNode(typeMapGroup, map.ThrowingMethodStub) : new ExternalTypeMapNode(typeMapGroup, map.TypeMap); } private static IProxyTypeMapNode GetProxyTypeMapNode(TypeDesc typeMapGroup, IProxyTypeMap map) { return map.ThrowingMethodStub is not null ? new InvalidProxyTypeMapNode(typeMapGroup, map.ThrowingMethodStub) : new ProxyTypeMapNode(typeMapGroup, map.TypeMap); } } private readonly HashSet<TypeDesc> _requestedExternalTypeMaps = []; private readonly HashSet<TypeDesc> _requestedProxyTypeMaps = []; private readonly SortedSet<IExternalTypeMapNode> _externalTypeMaps = new SortedSet<IExternalTypeMapNode>(CompilerComparer.Instance); private readonly SortedSet<IProxyTypeMapNode> _proxyTypeMaps = new SortedSet<IProxyTypeMapNode>(CompilerComparer.Instance); private readonly TypeMapMetadata _typeMaps; public UsageBasedTypeMapManager(TypeMapMetadata state) { _typeMaps = state; } protected override bool IsEmpty => _typeMaps.IsEmpty; public override void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph) { base.AttachToDependencyGraph(graph); graph.NewMarkedNode += Graph_NewMarkedNode; } private void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj) { if (obj is IExternalTypeMapNode externalTypeMapNode) { _externalTypeMaps.Add(externalTypeMapNode); } if (obj is IProxyTypeMapNode proxyTypeMapNode) { _proxyTypeMaps.Add(proxyTypeMapNode); } if (obj is ExternalTypeMapRequestNode externalTypeMapRequestNode) { _requestedExternalTypeMaps.Add(externalTypeMapRequestNode.TypeMapGroup); } if (obj is ProxyTypeMapRequestNode proxyTypeMapRequestNode) { _requestedProxyTypeMaps.Add(proxyTypeMapRequestNode.TypeMapGroup); } } internal override IEnumerable<IExternalTypeMapNode> GetExternalTypeMaps() { List<IExternalTypeMapNode> typeMaps = [.._externalTypeMaps]; SortedSet<TypeDesc> generatedMaps = new(TypeSystemComparer.Instance); foreach (var generatedMap in typeMaps) { generatedMaps.Add(generatedMap.TypeMapGroup); } SortedSet<TypeDesc> emptyMapsToGenerate = new SortedSet<TypeDesc>(_requestedExternalTypeMaps, TypeSystemComparer.Instance); emptyMapsToGenerate.ExceptWith(generatedMaps); foreach (var emptyMap in emptyMapsToGenerate) { typeMaps.Add(new ExternalTypeMapNode(emptyMap, [])); } return typeMaps; } internal override IEnumerable<IProxyTypeMapNode> GetProxyTypeMaps() { List<IProxyTypeMapNode> typeMaps = [.. _proxyTypeMaps]; SortedSet<TypeDesc> generatedMaps = new(TypeSystemComparer.Instance); foreach (var generatedMap in typeMaps) { generatedMaps.Add(generatedMap.TypeMapGroup); } SortedSet<TypeDesc> emptyMapsToGenerate = new SortedSet<TypeDesc>(_requestedProxyTypeMaps, TypeSystemComparer.Instance); emptyMapsToGenerate.ExceptWith(generatedMaps); foreach (var emptyMap in emptyMapsToGenerate) { typeMaps.Add(new ProxyTypeMapNode(emptyMap, [])); } return typeMaps; } public override void AddCompilationRoots(IRootingServiceProvider rootProvider) { if (_typeMaps.IsEmpty) { return; // No type maps to process } rootProvider.AddCompilationRoot(new AllTypeMapsNode(_typeMaps), "TypeMapManager"); } } }