| File: Compiler\DependencyAnalysis\TypeGVMEntriesNode.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.Collections.Generic; using System.Diagnostics; using Internal.TypeSystem; using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis { /// <summary> /// This node is used for GVM dependency analysis and GVM tables building. Given an input /// type, this node can scan the type for a list of GVM table entries, and compute their dependencies. /// </summary> internal sealed class TypeGVMEntriesNode : DependencyNodeCore<NodeFactory> { internal class TypeGVMEntryInfo { public TypeGVMEntryInfo(MethodDesc callingMethod, MethodDesc implementationMethod) { CallingMethod = callingMethod; ImplementationMethod = implementationMethod; } public MethodDesc CallingMethod { get; } public MethodDesc ImplementationMethod { get; } } internal sealed class InterfaceGVMEntryInfo : TypeGVMEntryInfo { public InterfaceGVMEntryInfo(MethodDesc callingMethod, MethodDesc implementationMethod, TypeDesc implementationType, DefaultInterfaceMethodResolution defaultResolution) : base(callingMethod, implementationMethod) { ImplementationType = implementationType; DefaultResolution = defaultResolution; } public TypeDesc ImplementationType { get; } public DefaultInterfaceMethodResolution DefaultResolution { get; } } private readonly TypeDesc _associatedType; private DependencyList _staticDependencies; public TypeGVMEntriesNode(TypeDesc associatedType) { Debug.Assert(associatedType.IsTypeDefinition); Debug.Assert(!associatedType.IsInterface); _associatedType = associatedType; } public TypeDesc AssociatedType => _associatedType; public override bool HasConditionalStaticDependencies => false; public override bool HasDynamicDependencies => false; public override bool InterestingForDynamicDependencyAnalysis => false; public override bool StaticDependenciesAreComputed => true; protected override string GetName(NodeFactory factory) => "__TypeGVMEntriesNode_" + factory.NameMangler.GetMangledTypeName(_associatedType); public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null; public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null; public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) { if (_staticDependencies == null) { _staticDependencies = new DependencyList(); foreach (var entry in ScanForGenericVirtualMethodEntries()) GenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref _staticDependencies, context, entry.CallingMethod, entry.ImplementationMethod); foreach (var entry in ScanForInterfaceGenericVirtualMethodEntries()) InterfaceGenericVirtualMethodTableNode.GetGenericVirtualMethodImplementationDependencies(ref _staticDependencies, context, entry.CallingMethod, entry.ImplementationType, entry.ImplementationMethod); } return _staticDependencies; } public IEnumerable<TypeGVMEntryInfo> ScanForGenericVirtualMethodEntries() { foreach (MethodDesc decl in _associatedType.EnumAllVirtualSlots()) { // Non-Generic virtual methods are tracked by an orthogonal mechanism. if (!decl.HasInstantiation) continue; // We don't need to emit async variants since this is just a copy // of the metadata if (decl.IsAsyncVariant()) continue; MethodDesc impl = _associatedType.FindVirtualFunctionTargetMethodOnObjectType(decl); if (impl.OwningType == _associatedType) yield return new TypeGVMEntryInfo(decl, impl); } } public IEnumerable<InterfaceGVMEntryInfo> ScanForInterfaceGenericVirtualMethodEntries() { foreach (var iface in _associatedType.RuntimeInterfaces) { foreach (var method in iface.GetVirtualMethods()) { if (!method.HasInstantiation) continue; // We don't need to emit async variants since this is just a copy // of the metadata if (method.IsAsyncVariant()) continue; DefaultInterfaceMethodResolution resolution = DefaultInterfaceMethodResolution.None; MethodDesc slotDecl = method.Signature.IsStatic ? _associatedType.ResolveInterfaceMethodToStaticVirtualMethodOnType(method) : _associatedType.ResolveInterfaceMethodTarget(method); if (slotDecl == null) { resolution = _associatedType.ResolveInterfaceMethodToDefaultImplementationOnType(method, out slotDecl); if (resolution != DefaultInterfaceMethodResolution.DefaultImplementation) slotDecl = null; } if (slotDecl != null || resolution == DefaultInterfaceMethodResolution.Diamond || resolution == DefaultInterfaceMethodResolution.Reabstraction) { yield return new InterfaceGVMEntryInfo(method, slotDecl, _associatedType, resolution); } } } } } }