| 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 void AddStaticDependencies(DependencySink sink, NodeFactory factory) { MethodDesc canonDecl = _decl.GetCanonMethodTarget(CanonicalFormKind.Specific); if (canonDecl != _decl) sink.Add(factory.VirtualMethodUse(canonDecl), "Canonical method"); sink.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.AddDependenciesDueToVirtualMethodReflectability(sink, factory, _decl); if (VariantInterfaceMethodUseNode.IsVariantMethodCall(factory, _decl)) sink.Add(factory.VariantInterfaceMethodUse(_decl.GetTypicalMethodDefinition()), "Variant interface call"); } #else public override void AddStaticDependencies(DependencySink sink, NodeFactory factory) { } #endif public override void AddConditionalDependencies(DependencySink sink, NodeFactory factory) { } public override void SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, DependencySink sink, NodeFactory factory) { } } }