| File: Compiler\DependencyAnalysis\ArrayInterfaceMethodsNode.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.Collections.Generic; using System.Diagnostics; using ILCompiler.DependencyAnalysisFramework; using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis.ReadyToRun { /// <summary> /// Discovery node for the generic collection interface methods implemented by arrays. /// /// Arrays implement the generic collection interfaces (IEnumerable, IList, ICollection, IReadOnlyList, /// IReadOnlyCollection). At runtime, a call through these interfaces is dispatched to methods on /// SZArrayHelper. The InheritedVirtualMethodsNode doesn't see these methods as part of the array type. /// /// This node is created whenever an array type is used. It has conditional static dependencies: /// the resolved SZArrayHelper implementation is compiled only when the corresponding interface slot is /// actually used (via VirtualMethodUseNode). /// </summary> public class ArrayInterfaceMethodsNode : DependencyNodeCore<NodeFactory> { private readonly ArrayType _arrayType; public ArrayInterfaceMethodsNode(ArrayType arrayType) { Debug.Assert(arrayType.IsSzArray); _arrayType = arrayType; } public ArrayType ArrayType => _arrayType; public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => true; public override bool StaticDependenciesAreComputed => true; public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) => null; public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null; public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) { List<CombinedDependencyListEntry> result = new List<CombinedDependencyListEntry>(); MetadataType szArrayHelper = factory.TypeSystemContext.SystemModule.GetType("System"u8, "SZArrayHelper"u8, throwIfNotFound: false); if (szArrayHelper == null) return result; TypeDesc elementType = _arrayType.ElementType; foreach (DefType interfaceType in _arrayType.RuntimeInterfaces) { // Only the generic collection interfaces are dispatched through SZArrayHelper. if (!interfaceType.HasInstantiation) continue; foreach (MethodDesc interfaceMethod in interfaceType.GetVirtualMethods()) { // SZArrayHelper provides one generic method per interface method, with a matching name. MethodDesc helperMethodDef = szArrayHelper.GetMethod(interfaceMethod.Name, null); if (helperMethodDef == null) continue; MethodDesc helperMethod = factory.TypeSystemContext.GetInstantiatedMethod(helperMethodDef, new Instantiation(elementType)); MethodDesc canonHelperMethod = helperMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); if (!factory.CompilationModuleGroup.ContainsMethodBody(canonHelperMethod, false)) continue; result.Add(new CombinedDependencyListEntry( factory.CompiledMethodNode(canonHelperMethod), factory.VirtualMethodUse(interfaceMethod), "Array generic interface method implemented by SZArrayHelper")); } } return result; } protected override string GetName(NodeFactory factory) => $"Array interface methods on {_arrayType}"; } }