|
// 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 Internal.TypeSystem;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents a stand-in for a real method body that can turn into the real method
/// body at object emission phase if the real method body was marked.
/// It the real method body wasn't marked, this stub will tail-call into a throw helper.
/// This node conditionally depends on the real method body - the real method body
/// will be brough into compilation if the owning type was marked.
/// This operates under the assumption that instance methods don't get called with
/// a null `this`. While it's possible to call instance methods with a null `this`,
/// there are many reasons why it's a bad idea (C# language assumes `this` can never be null;
/// generically shared native code generated by this compiler assumes `this` is not null and
/// we can get the generic dictionary out of it, etc.).
public class TentativeInstanceMethodNode : TentativeMethodNode
{
public TentativeInstanceMethodNode(IMethodBodyNode methodNode)
: base(methodNode)
{
Debug.Assert(!methodNode.Method.Signature.IsStatic);
Debug.Assert(!methodNode.Method.OwningType.IsValueType);
}
public override bool HasConditionalStaticDependencies => true;
protected override ISymbolNode GetTarget(NodeFactory factory)
{
// If the class library doesn't provide this helper, the optimization is disabled.
MethodDesc helper = factory.InstanceMethodRemovedHelper;
return helper == null ? RealBody: factory.MethodEntrypoint(helper);
}
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
// Convert methods on Array<T> into T[]
TypeDesc owningType = Method.OwningType;
if (owningType.HasSameTypeDefinition(factory.ArrayOfTClass))
{
owningType = owningType.Instantiation[0].MakeArrayType();
}
// If a constructed symbol for the owning type was included in the compilation,
// include the real method body.
return new CombinedDependencyListEntry[]
{
new CombinedDependencyListEntry(
RealBody,
factory.ConstructedTypeSymbol(owningType),
"Instance method on a constructed type"),
};
}
protected override string GetName(NodeFactory factory)
{
return "Tentative instance method: " + RealBody.GetMangledName(factory.NameMangler);
}
public override int ClassCode => 0x8905207;
public override string ToString() => Method.ToString();
}
}
|