Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
public override bool HasConditionalStaticDependencies => false;
public override bool StaticDependenciesAreComputed => true;

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
public override void AddStaticDependencies(DependencySink<NodeFactory> sink, NodeFactory factory) { }
public override void AddConditionalDependencies(DependencySink<NodeFactory> sink, NodeFactory factory) { }
public override void SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, DependencySink<NodeFactory> sink, NodeFactory factory) { }

#if !SUPPORT_JIT
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,24 @@ public GVMDependenciesNode(MethodDesc method)
public override bool StaticDependenciesAreComputed => true;
protected override string GetName(NodeFactory factory) => "__GVMDependenciesNode_" + factory.NameMangler.GetMangledMethodName(_method);

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
public override void AddStaticDependencies(DependencySink<NodeFactory> sink, NodeFactory factory)
{
if (!_method.IsAbstract)
{
DependencyNodeCore<NodeFactory> node = GetVirtualMethodImplNode(factory, _method);
if (node != null)
yield return new DependencyListEntry(node, "Implementation of the generic virtual method");
sink.Add(node, "Implementation of the generic virtual method");
}
#if !READYTORUN
if (!_method.OwningType.IsInterface)
{
yield return new DependencyListEntry(factory.TypeGVMEntries(_method.OwningType.GetTypeDefinition()), "Resolution metadata");
sink.Add(factory.TypeGVMEntries(_method.OwningType.GetTypeDefinition()), "Resolution metadata");
}
yield return new DependencyListEntry(factory.AnalysisCharacteristic("GenericVirtualMethodsPresent"), "Runtime GVM resolution needed");
sink.Add(factory.AnalysisCharacteristic("GenericVirtualMethodsPresent"), "Runtime GVM resolution needed");
#endif
}

public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
public override void AddConditionalDependencies(DependencySink<NodeFactory> sink, NodeFactory context) { }

public override bool HasDynamicDependencies
{
Expand All @@ -76,9 +76,9 @@ public override bool HasDynamicDependencies
}
}

public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory)
public override void SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, DependencySink<NodeFactory> sink, NodeFactory factory)
{
List<CombinedDependencyListEntry> dynamicDependencies = new List<CombinedDependencyListEntry>();
DependencySink<NodeFactory> dynamicDependencies = sink;

TypeDesc methodOwningType = _method.OwningType;
bool methodIsShared = _method.IsSharedByGenericInstantiations;
Expand Down Expand Up @@ -174,22 +174,22 @@ public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependenci
{
DependencyNodeCore<NodeFactory> node = GetVirtualMethodImplNode(factory, canonImpl);
if (node != null)
dynamicDependencies.Add(new CombinedDependencyListEntry(node, null, "ImplementingMethodInstantiation"));
dynamicDependencies.Add(node, "ImplementingMethodInstantiation");
}
else
{
#if READYTORUN
if (!factory.CanBeInGenericCycle(canonImpl))
#endif
{
dynamicDependencies.Add(new CombinedDependencyListEntry(factory.GVMDependencies(canonImpl), null, "ImplementingMethodInstantiation"));
dynamicDependencies.Add(factory.GVMDependencies(canonImpl), "ImplementingMethodInstantiation");
}
}

#if !READYTORUN
TypeSystemEntity origin = (implementingMethodInstantiation.OwningType != potentialOverrideType) ? potentialOverrideType : null;
factory.MetadataManager.NoteOverridingMethod(_method, implementingMethodInstantiation, origin);
factory.MetadataManager.GetDependenciesForOverridingMethod(ref dynamicDependencies, factory, _method, implementingMethodInstantiation);
factory.MetadataManager.GetDependenciesForOverridingMethod(dynamicDependencies, factory, _method, implementingMethodInstantiation);
#endif
}

Expand Down Expand Up @@ -245,10 +245,10 @@ public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependenci
{
DependencyNodeCore<NodeFactory> node = GetVirtualMethodImplNode(factory, instantiatedTargetMethod);
if (node != null)
dynamicDependencies.Add(new CombinedDependencyListEntry(node, null, "DerivedMethodInstantiation"));
dynamicDependencies.Add(node, "DerivedMethodInstantiation");
#if !READYTORUN
factory.MetadataManager.NoteOverridingMethod(_method, instantiatedTargetMethod);
factory.MetadataManager.GetDependenciesForOverridingMethod(ref dynamicDependencies, factory, _method, instantiatedTargetMethod);
factory.MetadataManager.GetDependenciesForOverridingMethod(dynamicDependencies, factory, _method, instantiatedTargetMethod);

foundImpl = true;
#endif
Expand All @@ -261,15 +261,13 @@ public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependenci
TypeDesc currentType = potentialOverrideType;
do
{
dynamicDependencies.Add(new CombinedDependencyListEntry(factory.TypeGVMEntries(currentType.GetTypeDefinition()), null, "Resolution metadata"));
dynamicDependencies.Add(factory.TypeGVMEntries(currentType.GetTypeDefinition()), "Resolution metadata");
currentType = currentType.BaseType;
}
while (currentType != null);
}
#endif
}

return dynamicDependencies;
}

private static DependencyNodeCore<NodeFactory> GetVirtualMethodImplNode(NodeFactory factory, MethodDesc method)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using ILCompiler.DependencyAnalysisFramework;

using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Marker interface that identifies the node representing a compiled method body.
/// Represents a compiled method body whose dependencies can vary by generic instantiation.
/// </summary>
public interface IMethodBodyNode : IMethodNode, IPCodeSymbolNode
{
/// <summary>
/// Specializes this canonical body's runtime-determined dependencies for <paramref name="concreteMethod"/>
/// and streams the resulting static dependencies to <paramref name="sink"/>.
/// </summary>
void AddRuntimeDeterminedStaticDependencies(DependencySink<NodeFactory> sink, NodeFactory factory, MethodDesc concreteMethod);

/// <summary>
/// Specializes this canonical body's runtime-determined conditional dependencies for <paramref name="concreteMethod"/>
/// and streams them to <paramref name="sink"/>, preserving their conditions.
/// </summary>
void AddRuntimeDeterminedConditionalDependencies(DependencySink<NodeFactory> sink, NodeFactory factory, MethodDesc concreteMethod);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// 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;
#nullable enable

using Internal.TypeSystem;
using DependencyListEntry = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyListEntry;
using ILCompiler.DependencyAnalysisFramework;

namespace ILCompiler.DependencyAnalysis
{
Expand All @@ -15,8 +15,16 @@ namespace ILCompiler.DependencyAnalysis
public interface INodeWithRuntimeDeterminedDependencies
{
/// <summary>
/// Instantiates runtime determined dependencies of this node using the supplied generic context.
/// Instantiates runtime determined dependencies of this node using the
/// supplied generic context. If <paramref name="otherReasonNode"/> is
/// not null, the dependencies are considered conditional.
/// </summary>
IEnumerable<DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, bool isConcreteInstantiation);
void AddDependencies(
DependencySink<NodeFactory> sink,
NodeFactory factory,
Instantiation typeInstantiation,
Instantiation methodInstantiation,
bool isConcreteInstantiation,
DependencyNodeCore<NodeFactory>? otherReasonNode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,41 +53,31 @@ public virtual bool ShouldSkipEmittingObjectNode(NodeFactory factory)
public override bool HasDynamicDependencies => false;
public override bool InterestingForDynamicDependencyAnalysis => false;

public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
public sealed override void AddStaticDependencies(DependencySink<NodeFactory> sink, NodeFactory factory)
{
DependencyList dependencies = ComputeNonRelocationBasedDependencies(factory);
ComputeNonRelocationBasedDependencies(sink, factory);
Relocation[] relocs = GetData(factory, true).Relocs;

if (relocs != null)
{
dependencies ??= new DependencyList();

foreach (Relocation reloc in relocs)
{
dependencies.Add(reloc.Target, "reloc");
sink.Add(reloc.Target, "reloc");
}
}

if (factory.Target.IsWasm && this is IMethodCodeNodeWithTypeSignature wasmMethodCodeNode)
{
dependencies ??= new DependencyList();

WasmTypeNode wasmTypeNode = factory.WasmTypeNode(wasmMethodCodeNode.Method);
dependencies.Add(wasmTypeNode, "Wasm Method Code Nodes Require Signature");
sink.Add(wasmTypeNode, "Wasm Method Code Nodes Require Signature");
}

if (dependencies == null)
return Array.Empty<DependencyListEntry>();
else
return dependencies;
}

protected virtual DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
protected virtual void ComputeNonRelocationBasedDependencies(DependencySink<NodeFactory> sink, NodeFactory factory)
{
return null;
}

public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
public override void AddConditionalDependencies(DependencySink<NodeFactory> sink, NodeFactory factory) { }
public override void SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, DependencySink<NodeFactory> sink, NodeFactory factory) { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis
/// </summary>
public class ShadowConcreteMethodNode : ShadowMethodNode, IMethodNode, ISymbolNodeWithLinkage
{
public ShadowConcreteMethodNode(MethodDesc method, IMethodNode canonicalMethod)
public ShadowConcreteMethodNode(MethodDesc method, IMethodBodyNode canonicalMethod)
: base(method, canonicalMethod)
{
Debug.Assert(!method.IsSharedByGenericInstantiations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public abstract class ShadowMethodNode : DependencyNodeCore<NodeFactory>, IMetho
/// <summary>
/// Gets the canonical method body that defines the dependencies of this node.
/// </summary>
public IMethodNode CanonicalMethodNode { get; }
public IMethodBodyNode CanonicalMethodNode { get; }

/// <summary>
/// Gets the generic method represented by this node.
Expand All @@ -42,7 +42,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
public override bool StaticDependenciesAreComputed
=> CanonicalMethodNode.StaticDependenciesAreComputed;

public ShadowMethodNode(MethodDesc method, IMethodNode canonicalMethod)
public ShadowMethodNode(MethodDesc method, IMethodBodyNode canonicalMethod)
{
Debug.Assert(!method.IsRuntimeDeterminedExactMethod);
Debug.Assert(canonicalMethod.Method == method.GetCanonMethodTarget(CanonicalFormKind.Specific));
Expand All @@ -56,56 +56,17 @@ public ISymbolNode NodeForLinkage(NodeFactory factory)
return CanonicalMethodNode;
}

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
public override void AddStaticDependencies(DependencySink<NodeFactory> sink, NodeFactory factory)
{
DependencyList dependencies = new DependencyList();

// Make sure the canonical body gets generated
dependencies.Add(new DependencyListEntry(CanonicalMethodNode, "Canonical body"));

// Instantiate the runtime determined dependencies of the canonical method body
// with the concrete instantiation of the method to get concrete dependencies.
Instantiation typeInst = Method.OwningType.Instantiation;
Instantiation methodInst = Method.Instantiation;
IEnumerable<DependencyListEntry> staticDependencies = CanonicalMethodNode.GetStaticDependencies(factory);

if (staticDependencies != null)
{
foreach (DependencyListEntry canonDep in staticDependencies)
{
var runtimeDep = canonDep.Node as INodeWithRuntimeDeterminedDependencies;
if (runtimeDep != null)
{
dependencies.AddRange(runtimeDep.InstantiateDependencies(factory, typeInst, methodInst, isConcreteInstantiation: !Method.IsSharedByGenericInstantiations));
}
}
}

return dependencies;
sink.Add(new DependencyListEntry(CanonicalMethodNode, "Canonical body"));

CanonicalMethodNode.AddRuntimeDeterminedStaticDependencies(sink, factory, Method);
}

public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
public sealed override void AddConditionalDependencies(DependencySink<NodeFactory> sink, NodeFactory factory)
{
// Instantiate the runtime determined dependencies of the canonical method body
// with the concrete instantiation of the method to get concrete dependencies.
Instantiation typeInst = Method.OwningType.Instantiation;
Instantiation methodInst = Method.Instantiation;
IEnumerable<CombinedDependencyListEntry> staticDependencies = CanonicalMethodNode.GetConditionalStaticDependencies(factory);

if (staticDependencies != null)
{
foreach (CombinedDependencyListEntry canonDep in staticDependencies)
{
Debug.Assert(canonDep.OtherReasonNode is not INodeWithRuntimeDeterminedDependencies);

var node = canonDep.Node;
if (node is INodeWithRuntimeDeterminedDependencies runtimeDeterminedNode)
{
foreach (var nodeInner in runtimeDeterminedNode.InstantiateDependencies(factory, typeInst, methodInst, isConcreteInstantiation: !Method.IsSharedByGenericInstantiations))
yield return new CombinedDependencyListEntry(nodeInner.Node, canonDep.OtherReasonNode, nodeInner.Reason);
}
}
}
CanonicalMethodNode.AddRuntimeDeterminedConditionalDependencies(sink, factory, Method);
}


Expand All @@ -115,7 +76,7 @@ public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalSt
public sealed override bool HasDynamicDependencies => false;
public sealed override bool InterestingForDynamicDependencyAnalysis => false;

public sealed override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
public sealed override void SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, DependencySink<NodeFactory> sink, NodeFactory factory) { }

int ISortableNode.ClassCode => ClassCode;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis
/// </summary>
public class ShadowNonConcreteMethodNode : ShadowMethodNode, IMethodNode, ISymbolNodeWithLinkage
{
public ShadowNonConcreteMethodNode(MethodDesc method, IMethodNode canonicalMethod)
public ShadowNonConcreteMethodNode(MethodDesc method, IMethodBodyNode canonicalMethod)
: base(method, canonicalMethod)
{
Debug.Assert(method.IsSharedByGenericInstantiations);
Expand Down
Loading
Loading