| File: Compiler\ReadyToRunTableManager.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.ReadyToRun\ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun) |
// 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.Reflection.Metadata; using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; using ILCompiler.ReadyToRun.TypeSystem; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; using Debug = System.Diagnostics.Debug; namespace ILCompiler { public struct TypeInfo<THandle> { public readonly MetadataReader MetadataReader; public readonly THandle Handle; public TypeInfo(MetadataReader metadataReader, THandle handle) { MetadataReader = metadataReader; Handle = handle; } } public enum CompiledMethodCategory { NonInstantiated, Instantiated, All } // TODO-REFACTOR: merge with the table manager public class MetadataManager { protected readonly CompilerTypeSystemContext _typeSystemContext; private class PerModuleMethodsGenerated { public PerModuleMethodsGenerated(EcmaModule module) { Module = module; } public readonly EcmaModule Module; public List<IMethodNode> MethodsGenerated = new List<IMethodNode>(); public List<IMethodNode> GenericMethodsGenerated = new List<IMethodNode>(); } private Dictionary<EcmaModule, PerModuleMethodsGenerated> _methodsGenerated = new Dictionary<EcmaModule, PerModuleMethodsGenerated>(); private List<IMethodNode> _completeSortedMethods = new List<IMethodNode>(); private List<IMethodNode> _completeSortedGenericMethods = new List<IMethodNode>(); private NodeFactory _factory; private bool _sortedMethods = false; public MetadataManager(CompilerTypeSystemContext context) { _typeSystemContext = context; } public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph, NodeFactory factory) { graph.NewMarkedNode += Graph_NewMarkedNode; _factory = factory; } protected virtual void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj) { IMethodBodyNode methodBodyNode = obj as IMethodBodyNode; var methodNode = methodBodyNode as IMethodNode; if (methodNode != null) { lock (_methodsGenerated) { Debug.Assert(!_sortedMethods); MethodDesc method = methodNode.Method; EcmaModule module = (EcmaModule)((EcmaMethod)method.GetPrimaryMethodDesc().GetTypicalMethodDefinition()).Module; if (!_methodsGenerated.TryGetValue(module, out var perModuleData)) { perModuleData = new PerModuleMethodsGenerated(module); _methodsGenerated[module] = perModuleData; } if (method.HasInstantiation || method.OwningType.HasInstantiation || method.IsAsyncVariant() || method is AsyncResumptionStub) { perModuleData.GenericMethodsGenerated.Add(methodNode); } else { perModuleData.MethodsGenerated.Add(methodNode); } } } } public IEnumerable<IMethodNode> GetCompiledMethods(EcmaModule moduleToEnumerate, CompiledMethodCategory methodCategory) { lock (_methodsGenerated) { if (!_sortedMethods) { CompilerComparer comparer = CompilerComparer.Instance; SortableDependencyNode.ObjectNodeComparer objectNodeComparer = new SortableDependencyNode.ObjectNodeComparer(comparer); Comparison<IMethodNode> sortHelper = (x, y) => { int nodeComparerResult = objectNodeComparer.Compare((SortableDependencyNode)x, (SortableDependencyNode)y); #if DEBUG int methodOnlyResult = comparer.Compare(x.Method, y.Method); // Assert the two sorting techniques produce the same result unless there is a CustomSort applied // or MethodWithGCInfo ordering is keeping async resumption stubs next to their target methods. Debug.Assert((nodeComparerResult == methodOnlyResult) || x.Method is AsyncResumptionStub || y.Method is AsyncResumptionStub || ((x is SortableDependencyNode sortableX && sortableX.CustomSort != Int32.MaxValue) || (y is SortableDependencyNode sortableY && sortableY.CustomSort != Int32.MaxValue))); #endif return nodeComparerResult; }; Comparison<IMethodNode> sortHelperNoCustomSort = (x, y) => comparer.Compare(x, y); List<PerModuleMethodsGenerated> perModuleDatas = new List<PerModuleMethodsGenerated>(_methodsGenerated.Values); perModuleDatas.Sort((x, y) => x.Module.CompareTo(y.Module)); foreach (var perModuleData in perModuleDatas) { perModuleData.MethodsGenerated.MergeSort(sortHelperNoCustomSort); perModuleData.GenericMethodsGenerated.MergeSort(sortHelperNoCustomSort); _completeSortedMethods.AddRange(perModuleData.MethodsGenerated); _completeSortedMethods.AddRange(perModuleData.GenericMethodsGenerated); _completeSortedGenericMethods.AddRange(perModuleData.GenericMethodsGenerated); } _completeSortedMethods.MergeSort(sortHelper); _completeSortedGenericMethods.MergeSort(sortHelper); _sortedMethods = true; } } if (moduleToEnumerate == null) { if (methodCategory == CompiledMethodCategory.All) { return _completeSortedMethods; } else if (methodCategory == CompiledMethodCategory.Instantiated) { return _completeSortedGenericMethods; } else { // This isn't expected to be needed, and thus isn't implemented throw new ArgumentException(); } } else if (_methodsGenerated.TryGetValue(moduleToEnumerate, out var perModuleData)) { if (methodCategory == CompiledMethodCategory.All) { return GetCompiledMethodsAllMethodsInModuleHelper(moduleToEnumerate); } if (methodCategory == CompiledMethodCategory.Instantiated) { return perModuleData.GenericMethodsGenerated; } else { Debug.Assert(methodCategory == CompiledMethodCategory.NonInstantiated); return perModuleData.MethodsGenerated; } } else { return Array.Empty<IMethodNode>(); } } private IEnumerable<IMethodNode> GetCompiledMethodsAllMethodsInModuleHelper(EcmaModule moduleToEnumerate) { foreach (var node in GetCompiledMethods(moduleToEnumerate, CompiledMethodCategory.Instantiated)) { yield return node; } foreach (var node in GetCompiledMethods(moduleToEnumerate, CompiledMethodCategory.NonInstantiated)) { yield return node; } } } public class ReadyToRunTableManager : MetadataManager { public ReadyToRunTableManager(CompilerTypeSystemContext typeSystemContext) : base(typeSystemContext) {} public IEnumerable<TypeInfo<TypeDefinitionHandle>> GetDefinedTypes(EcmaModule module) { foreach (TypeDefinitionHandle typeDefHandle in module.MetadataReader.TypeDefinitions) { yield return new TypeInfo<TypeDefinitionHandle>(module.MetadataReader, typeDefHandle); } } public IEnumerable<TypeInfo<ExportedTypeHandle>> GetExportedTypes(EcmaModule module) { foreach (ExportedTypeHandle exportedTypeHandle in module.MetadataReader.ExportedTypes) { yield return new TypeInfo<ExportedTypeHandle>(module.MetadataReader, exportedTypeHandle); } } } }