Skip to content
Merged
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 @@ -210,6 +210,12 @@ protected virtual MethodDesc ResolveVirtualMethod(MethodDesc declMethod, DefType
/// </summary>
public virtual bool CanReferenceConstructedMethodTable(TypeDesc type) => true;

/// <summary>
/// Gets a value indicating whether it might be possible to obtain a metadata type data structure for the given type
/// in this compilation (i.e. is it possible to reference a metadata MethodTable symbol for this).
/// </summary>
public virtual bool CanReferenceMetadataMethodTable(TypeDesc type) => true;

/// <summary>
/// Gets a value indicating whether a (potentially canonically-equlivalent) constructed MethodTable could
/// exist. This is similar to <see cref="CanReferenceConstructedMethodTable"/>, but will return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ public bool NeedsRuntimeLookup(ReadyToRunHelperId lookupKind, object targetOfLoo
{
case ReadyToRunHelperId.TypeHandle:
case ReadyToRunHelperId.NecessaryTypeHandle:
case ReadyToRunHelperId.MetadataTypeHandle:
case ReadyToRunHelperId.DefaultConstructor:
case ReadyToRunHelperId.TypeHandleForCasting:
case ReadyToRunHelperId.ObjectAllocator:
Expand Down Expand Up @@ -271,13 +272,17 @@ public ReadyToRunHelperId GetLdTokenHelperForType(TypeDesc type)
// We need to make a small exception for canonical definitions because of RuntimeAugments.GetCanonType
Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Any) || type.IsCanonicalDefinitionType(CanonicalFormKind.Any));

bool canPotentiallyConstruct = ConstructedEETypeNode.CreationAllowed(type)
&& NodeFactory.DevirtualizationManager.CanReferenceConstructedMethodTable(type.NormalizeInstantiation());
if (canPotentiallyConstruct)
return ReadyToRunHelperId.TypeHandle;

if (type.IsGenericDefinition && NodeFactory.DevirtualizationManager.IsGenericDefinitionMethodTableReflectionVisible(type))
return ReadyToRunHelperId.TypeHandle;
return ReadyToRunHelperId.MetadataTypeHandle;

if (ConstructedEETypeNode.CreationAllowed(type))
{
if (NodeFactory.DevirtualizationManager.CanReferenceConstructedMethodTable(type.NormalizeInstantiation()))
return ReadyToRunHelperId.TypeHandle;

if (NodeFactory.DevirtualizationManager.CanReferenceMetadataMethodTable(type.NormalizeInstantiation()))
return ReadyToRunHelperId.MetadataTypeHandle;
}

return ReadyToRunHelperId.NecessaryTypeHandle;
}
Expand Down Expand Up @@ -307,6 +312,8 @@ public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object t
{
case ReadyToRunHelperId.TypeHandle:
return NodeFactory.ConstructedTypeSymbol((TypeDesc)targetOfLookup);
case ReadyToRunHelperId.MetadataTypeHandle:
return NodeFactory.MetadataTypeSymbol((TypeDesc)targetOfLookup);
case ReadyToRunHelperId.NecessaryTypeHandle:
return NecessaryTypeSymbolIfPossible((TypeDesc)targetOfLookup);
case ReadyToRunHelperId.TypeHandleForCasting:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ public ConstructedEETypeNode(NodeFactory factory, TypeDesc type) : base(factory,

protected override bool EmitVirtualSlots => true;

protected override bool IsReflectionVisible => true;

protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);

// Ensure that we track the necessary type symbol if we are working with a constructed type symbol.
// Ensure that we track the metadata type symbol if we are working with a constructed type symbol.
// The emitter will ensure we don't emit both, but this allows us assert that we only generate
// relocs to nodes we emit.
dependencyList.Add(factory.NecessaryTypeSymbol(_type), "NecessaryType for constructed type");

if (_type is MetadataType mdType)
ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencyList, factory, mdType.Module);
dependencyList.Add(factory.MetadataTypeSymbol(_type), "MetadataType for constructed type");

DefType closestDefType = _type.GetClosestDefType();

Expand Down Expand Up @@ -63,9 +62,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
}
else
{
// Ask the metadata manager if we have any dependencies due to the presence of the EEType.
factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type);

factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);
}

Expand All @@ -80,7 +76,7 @@ protected override ISymbolNode GetBaseTypeNode(NodeFactory factory)
protected override FrozenRuntimeTypeNode GetFrozenRuntimeTypeNode(NodeFactory factory)
{
Debug.Assert(!_type.IsCanonicalSubtype(CanonicalFormKind.Any));
return factory.SerializedConstructedRuntimeTypeObject(_type);
return factory.SerializedMetadataRuntimeTypeObject(_type);
}

protected override ISymbolNode GetNonNullableValueTypeArrayElementTypeNode(NodeFactory factory)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,23 @@ public override bool TryGetSlotForEntry(GenericLookupResult entry, out int slot)
{
slot = Array.IndexOf(_layout, entry);

// If we're looking for a necessary type handle and it doesn't exist, check for a constructed type handle.
if (slot < 0 && entry is NecessaryTypeHandleGenericLookupResult necessaryLookup)

// If we're looking for a low type handle load level and it doesn't exist, check for a higher load level.
var necessaryLookup = entry as NecessaryTypeHandleGenericLookupResult;
var metadataLookup = entry as MetadataTypeHandleGenericLookupResult;
if (slot < 0
&& (necessaryLookup != null || metadataLookup != null))
{
for (int i = 0; i < _layout.Length; i++)
{
if (_layout[i] is TypeHandleGenericLookupResult other
&& other.Type == necessaryLookup.Type)
if (_layout[i] is TypeHandleGenericLookupResult thOther
&& (thOther.Type == necessaryLookup?.Type || thOther.Type == metadataLookup?.Type))
{
slot = i;
return true;
}
if (_layout[i] is MetadataTypeHandleGenericLookupResult mdOther
&& mdOther.Type == necessaryLookup?.Type)
{
slot = i;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,7 @@ protected bool MightHaveInterfaceDispatchMap(NodeFactory factory)

public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)
{
// If there is a constructed version of this node in the graph, emit that instead
if (ConstructedEETypeNode.CreationAllowed(_type))
return factory.ConstructedTypeSymbol(_type).Marked;

return false;
return factory.MetadataTypeSymbol(_type).Marked;
}

public virtual ISymbolNode NodeForLinkage(NodeFactory factory)
Expand All @@ -226,6 +222,8 @@ protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory)

protected virtual bool EmitVirtualSlots => false;

protected virtual bool IsReflectionVisible => false;

public override bool InterestingForDynamicDependencyAnalysis
=> (_virtualMethodAnalysisFlags & VirtualMethodAnalysisFlags.InterestingForDynamicDependencies) != 0;

Expand Down Expand Up @@ -283,6 +281,9 @@ public override bool HasConditionalStaticDependencies
if (_type.RuntimeInterfaces.Length > 0)
return true;

if (IsReflectionVisible && _hasConditionalDependenciesFromMetadataManager)
return true;

if (!EmitVirtualSlots)
return false;

Expand Down Expand Up @@ -312,14 +313,31 @@ public override bool HasConditionalStaticDependencies
currentType = currentType.BaseType;
}

return _hasConditionalDependenciesFromMetadataManager;
return false;
}
}

public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
List<CombinedDependencyListEntry> result = new List<CombinedDependencyListEntry>();

if (IsReflectionVisible)
{
factory.MetadataManager.GetConditionalDependenciesDueToEETypePresence(ref result, factory, _type, allocated: EmitVirtualSlots);

if (!_type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
foreach (DefType iface in _type.RuntimeInterfaces)
{
var ifaceDefinition = (DefType)iface.GetTypeDefinition();
result.Add(new CombinedDependencyListEntry(
GetInterfaceTypeNode(factory, iface),
factory.InterfaceUse(ifaceDefinition),
"Interface definition was visible"));
}
}
}

IEETypeNode maximallyConstructableType = factory.MaximallyConstructableType(_type);

if (maximallyConstructableType != this)
Expand All @@ -343,18 +361,6 @@ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDep
"Information about static bases for type with template"));
}

if (!_type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
foreach (DefType iface in _type.RuntimeInterfaces)
{
var ifaceDefinition = (DefType)iface.GetTypeDefinition();
result.Add(new CombinedDependencyListEntry(
GetInterfaceTypeNode(factory, iface),
factory.InterfaceUse(ifaceDefinition),
"Interface definition was visible"));
}
}

if (!EmitVirtualSlots)
return result;

Expand Down Expand Up @@ -555,8 +561,6 @@ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDep
}
}

factory.MetadataManager.GetConditionalDependenciesDueToEETypePresence(ref result, factory, _type);

return result;
}

Expand Down Expand Up @@ -1132,16 +1136,16 @@ protected void OutputGenericInstantiationDetails(NodeFactory factory, ref Object
{
if (!_type.IsTypeDefinition)
{
IEETypeNode typeDefNode = factory.MaximallyConstructableType(_type) == this ?
factory.ConstructedTypeSymbol(_type.GetTypeDefinition()) : factory.NecessaryTypeSymbol(_type.GetTypeDefinition());
IEETypeNode typeDefNode = IsReflectionVisible ?
factory.MetadataTypeSymbol(_type.GetTypeDefinition()) : factory.NecessaryTypeSymbol(_type.GetTypeDefinition());
if (factory.Target.SupportsRelativePointers)
objData.EmitReloc(typeDefNode, RelocType.IMAGE_REL_BASED_RELPTR32);
else
objData.EmitPointerReloc(typeDefNode);

ISymbolNode compositionNode;

if (this == factory.MaximallyConstructableType(_type)
if (IsReflectionVisible
&& factory.MetadataManager.IsTypeInstantiationReflectionVisible(_type))
{
compositionNode = _type.Instantiation.Length > 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ namespace ILCompiler.DependencyAnalysis
public sealed class FrozenRuntimeTypeNode : FrozenObjectNode
{
private readonly TypeDesc _type;
private readonly bool _constructed;
private readonly bool _withMetadata;

public FrozenRuntimeTypeNode(TypeDesc type, bool constructed)
public FrozenRuntimeTypeNode(TypeDesc type, bool withMetadata)
{
Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Any));
_type = type;
_constructed = constructed;
_withMetadata = withMetadata;
}

public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
Expand All @@ -30,8 +30,8 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde

public override void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
IEETypeNode typeSymbol = _constructed
? factory.ConstructedTypeSymbol(_type)
IEETypeNode typeSymbol = _withMetadata
? factory.MetadataTypeSymbol(_type)
: factory.NecessaryTypeSymbol(_type);

dataBuilder.EmitPointerReloc(factory.ConstructedTypeSymbol(ObjectType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public ReflectionInvisibleGenericDefinitionEETypeNode(NodeFactory factory, TypeD

public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)
{
return factory.ConstructedTypeSymbol(_type).Marked;
return factory.MetadataTypeSymbol(_type).Marked;
}

protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
Expand All @@ -93,7 +93,7 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory)

protected override FrozenRuntimeTypeNode GetFrozenRuntimeTypeNode(NodeFactory factory)
{
return factory.SerializedConstructedRuntimeTypeObject(_type);
return factory.SerializedMetadataRuntimeTypeObject(_type);
}

protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler) + " reflection visible";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,60 @@ protected override bool EqualsImpl(GenericLookupResult obj)
}
}

/// <summary>
/// Generic lookup result that points to an MethodTable.
/// </summary>
public sealed class MetadataTypeHandleGenericLookupResult : GenericLookupResult
{
private TypeDesc _type;

protected override int ClassCode => -4892308;

public MetadataTypeHandleGenericLookupResult(TypeDesc type)
{
Debug.Assert(type.IsRuntimeDeterminedSubtype, "Concrete type in a generic dictionary?");
_type = type;
}

public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultContext dictionary)
{
TypeDesc instantiatedType = _type.GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(dictionary.TypeInstantiation, dictionary.MethodInstantiation);

factory.TypeSystemContext.DetectGenericCycles(dictionary.Context, instantiatedType);

return factory.MetadataTypeSymbol(instantiatedType);
}

public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append("MetadataTypeHandle_"u8);
sb.Append(nameMangler.GetMangledTypeName(_type));
}

public TypeDesc Type => _type;
public override string ToString() => $"MetadataTypeHandle: {_type}";

public override NativeLayoutVertexNode TemplateDictionaryNode(NodeFactory factory)
{
return factory.NativeLayout.TypeHandleDictionarySlot(_type);
}

protected override int CompareToImpl(GenericLookupResult other, TypeSystemComparer comparer)
{
return comparer.Compare(_type, ((MetadataTypeHandleGenericLookupResult)other)._type);
}

protected override int GetHashCodeImpl()
{
return _type.GetHashCode();
}

protected override bool EqualsImpl(GenericLookupResult obj)
{
return ((MetadataTypeHandleGenericLookupResult)obj)._type == _type;
}
}

/// <summary>
/// Generic lookup result that points to an MethodTable where if the type is Nullable&lt;X&gt; the MethodTable is X
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ public static void GetGenericVirtualMethodImplementationDependencies(ref Depende
MethodDesc openImplementationMethod = implementationMethod.GetTypicalMethodDefinition();

factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openCallingMethod);
dependencies.Add(factory.NecessaryTypeSymbol(openCallingMethod.OwningType), "Owning type of GVM declaration");
factory.MetadataManager.GetNativeLayoutMetadataDependencies(ref dependencies, factory, openImplementationMethod);
dependencies.Add(factory.NecessaryTypeSymbol(openImplementationMethod.OwningType), "Owning type of GVM implementation");
}

private void AddGenericVirtualMethodImplementation(MethodDesc callingMethod, MethodDesc implementationMethod)
Expand Down
Loading
Loading