| File: parent\parent\Common\Compiler\DependencyAnalysis\VirtualMethodUseNode.cs | Web Access |
| Project: 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 ILCompiler.DependencyAnalysisFramework; using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; namespace ILCompiler.DependencyAnalysis { /// <summary> /// This node represents the concept of a virtual method being used. /// It has no direct dependencies, but may be referred to by conditional static /// dependencies, or static dependencies from elsewhere. /// /// It is used to keep track of uses of virtual methods to ensure that the /// vtables are properly constructed. /// </summary> public sealed class VirtualMethodUseNode : DependencyNodeCore<NodeFactory> { private readonly MethodDesc _decl; public MethodDesc Method => _decl; public VirtualMethodUseNode(MethodDesc decl) { Debug.Assert(!decl.IsRuntimeDeterminedExactMethod); Debug.Assert(decl.IsVirtual); // Virtual method use always represents the slot defining method of the virtual. // Places that might see virtual methods being used through an override need to normalize // to the slot defining method. Debug.Assert(MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(decl) == decl); // Generic virtual methods are tracked by an orthogonal mechanism. Debug.Assert(!decl.HasInstantiation); _decl = decl; } protected override string GetName(NodeFactory factory) => $"VirtualMethodUse {_decl}"; #if !READYTORUN protected override void OnMarked(NodeFactory factory) { // If the VTable slice is getting built on demand, the fact that the virtual method is used means // that the slot is used. var lazyVTableSlice = factory.VTable(_decl.OwningType) as LazilyBuiltVTableSliceNode; lazyVTableSlice?.AddEntry(_decl); } #endif public override bool HasConditionalStaticDependencies => false; public override bool HasDynamicDependencies => false; public override bool InterestingForDynamicDependencyAnalysis => false; public override bool StaticDependenciesAreComputed => true; #if !READYTORUN public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) { DependencyList dependencies = new DependencyList(); MethodDesc canonDecl = _decl.GetCanonMethodTarget(CanonicalFormKind.Specific); if (canonDecl != _decl) dependencies.Add(factory.VirtualMethodUse(canonDecl), "Canonical method"); dependencies.Add(factory.VTable(_decl.OwningType), "VTable of a VirtualMethodUse"); // Do not report things like Foo<object, __Canon>.Frob(). if (!_decl.IsCanonicalMethod(CanonicalFormKind.Any) || canonDecl == _decl) factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref dependencies, factory, _decl); if (VariantInterfaceMethodUseNode.IsVariantMethodCall(factory, _decl)) dependencies.Add(factory.VariantInterfaceMethodUse(_decl.GetTypicalMethodDefinition()), "Variant interface call"); return dependencies; } #else public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) => null; #endif public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; } }