Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add common parent for frozen objects #93773

Merged
merged 1 commit into from
Oct 21, 2023
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
@@ -1,77 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;

using Internal.Text;
using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents a frozen object that is statically preallocated within the data section
/// of the executable instead of on the GC heap.
/// </summary>
public sealed class FrozenObjectNode : EmbeddedObjectNode, ISymbolDefinitionNode
public abstract class FrozenObjectNode : EmbeddedObjectNode, ISymbolDefinitionNode
{
private readonly MetadataType _owningType;
private readonly TypePreinit.ISerializableReference _data;
private readonly int _allocationSiteId;

public FrozenObjectNode(MetadataType owningType, int allocationSiteId, TypePreinit.ISerializableReference data)
{
_owningType = owningType;
_allocationSiteId = allocationSiteId;
_data = data;
}

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenObj_")
.Append(nameMangler.GetMangledTypeName(_owningType))
.Append(_allocationSiteId.ToStringInvariant());
}

public override bool StaticDependenciesAreComputed => true;

public TypeDesc ObjectType => _data.Type;

public bool IsKnownImmutable => _data.IsKnownImmutable;

public int GetArrayLength()
{
Debug.Assert(ObjectType.IsArray);
return _data.ArrayLength;
}

int ISymbolNode.Offset => 0;

int ISymbolDefinitionNode.Offset
{
get
{
// The frozen object symbol points at the MethodTable portion of the object, skipping over the sync block
return OffsetFromBeginningOfArray + _owningType.Context.Target.PointerSize;
// The frozen symbol points at the MethodTable portion of the object, skipping over the sync block
return OffsetFromBeginningOfArray + ObjectType.Context.Target.PointerSize;
}
}

public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
public abstract TypeDesc ObjectType { get; }

public abstract int? ArrayLength { get; }
public abstract bool IsKnownImmutable { get; }
public int Size => ObjectType.Context.Target.PointerSize + ContentSize; // SyncBlock + size of contents
protected abstract int ContentSize { get; }

public abstract void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb);

public sealed override bool StaticDependenciesAreComputed => true;

public sealed override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
// Sync Block
dataBuilder.EmitZeroPointer();
dataBuilder.EmitZeroPointer(); // Sync block

// byte contents
_data.WriteContent(ref dataBuilder, this, factory);
int sizeBefore = dataBuilder.CountBytes;
EncodeContents(ref dataBuilder, factory, relocsOnly);
Debug.Assert(dataBuilder.CountBytes == sizeBefore + ContentSize);
}

protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, true);
EncodeData(ref builder, factory, true);
var builder = new ObjectDataBuilder(factory, relocsOnly: true);
EncodeData(ref builder, factory, relocsOnly: true);
Relocation[] relocs = builder.ToObjectData().Relocs;

DependencyList dependencies = null;

if (relocs != null)
Expand All @@ -83,23 +60,15 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
}
}

_data.GetNonRelocationDependencies(ref dependencies, factory);
GetNonRelocationDependencies(ref dependencies, factory);

return dependencies;
}

public override int ClassCode => 1789429316;

public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
public virtual void GetNonRelocationDependencies(ref DependencyList dependencies, NodeFactory factory)
{
var otherFrozenObjectNode = (FrozenObjectNode)other;
int result = comparer.Compare(otherFrozenObjectNode._owningType, _owningType);
if (result != 0)
return result;

return _allocationSiteId.CompareTo(otherFrozenObjectNode._allocationSiteId);
}

public override string ToString() => $"Frozen {_data.Type.GetDisplayNameWithoutNamespace()} object";
public abstract void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly);
}
}
Original file line number Diff line number Diff line change
@@ -1,63 +1,32 @@
// 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.Text;
using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler.DependencyAnalysis
{
public sealed class FrozenStringNode : EmbeddedObjectNode, ISymbolDefinitionNode
public sealed class FrozenStringNode : FrozenObjectNode
{
private string _data;
private int _syncBlockSize;
private readonly DefType _stringType;

public FrozenStringNode(string data, TargetDetails target)
public FrozenStringNode(string data, CompilerTypeSystemContext context)
{
_data = data;
_syncBlockSize = target.PointerSize;
_stringType = context.GetWellKnownType(WellKnownType.String);
}

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix).Append("__Str_").Append(nameMangler.GetMangledStringName(_data));
}

public override bool StaticDependenciesAreComputed => true;

int ISymbolNode.Offset => 0;
protected override int ContentSize => _stringType.Context.Target.PointerSize + sizeof(int) + (_data.Length + 1) * sizeof(char);

int ISymbolDefinitionNode.Offset
public override void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
get
{
// The frozen string symbol points at the MethodTable portion of the object, skipping over the sync block
return OffsetFromBeginningOfArray + _syncBlockSize;
}
}

private static IEETypeNode GetEETypeNode(NodeFactory factory)
{
DefType systemStringType = factory.TypeSystemContext.GetWellKnownType(WellKnownType.String);

IEETypeNode stringSymbol = factory.ConstructedTypeSymbol(systemStringType);

//
// The GC requires a direct reference to frozen objects' EETypes. System.String needs
// to be compiled into this binary.
//
Debug.Assert(!stringSymbol.RepresentsIndirectionCell);
return stringSymbol;
}

public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
dataBuilder.EmitZeroPointer(); // Sync block

dataBuilder.EmitPointerReloc(GetEETypeNode(factory));
dataBuilder.EmitPointerReloc(factory.ConstructedTypeSymbol(ObjectType));

dataBuilder.EmitInt(_data.Length);

Expand All @@ -72,14 +41,6 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f

protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);

public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
return new DependencyListEntry[]
{
new DependencyListEntry(GetEETypeNode(factory), "Frozen string literal MethodTable"),
};
}

public override int ClassCode => -1733946122;

public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
Expand All @@ -89,6 +50,12 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer

public string Data => _data;

public override int? ArrayLength => _data.Length;

public override bool IsKnownImmutable => true;

public override TypeDesc ObjectType => _stringType;

public override string ToString() => $"\"{_data}\"";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -360,12 +360,12 @@ private void CreateNodeCaches()

_frozenStringNodes = new NodeCache<string, FrozenStringNode>((string data) =>
{
return new FrozenStringNode(data, Target);
return new FrozenStringNode(data, TypeSystemContext);
});

_frozenObjectNodes = new NodeCache<SerializedFrozenObjectKey, FrozenObjectNode>(key =>
_frozenObjectNodes = new NodeCache<SerializedFrozenObjectKey, SerializedFrozenObjectNode>(key =>
{
return new FrozenObjectNode(key.OwnerType, key.AllocationSiteId, key.SerializableObject);
return new SerializedFrozenObjectNode(key.OwnerType, key.AllocationSiteId, key.SerializableObject);
});

_interfaceDispatchCells = new NodeCache<DispatchCellKey, InterfaceDispatchCellNode>(callSiteCell =>
Expand Down Expand Up @@ -1220,9 +1220,9 @@ public FrozenStringNode SerializedStringObject(string data)
return _frozenStringNodes.GetOrAdd(data);
}

private NodeCache<SerializedFrozenObjectKey, FrozenObjectNode> _frozenObjectNodes;
private NodeCache<SerializedFrozenObjectKey, SerializedFrozenObjectNode> _frozenObjectNodes;

public FrozenObjectNode SerializedFrozenObject(MetadataType owningType, int allocationSiteId, TypePreinit.ISerializableReference data)
public SerializedFrozenObjectNode SerializedFrozenObject(MetadataType owningType, int allocationSiteId, TypePreinit.ISerializableReference data)
{
return _frozenObjectNodes.GetOrAdd(new SerializedFrozenObjectKey(owningType, allocationSiteId, data));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

using Internal.Text;
using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents a frozen object that is statically preallocated within the data section
/// of the executable instead of on the GC heap.
/// </summary>
public sealed class SerializedFrozenObjectNode : FrozenObjectNode
{
private readonly MetadataType _owningType;
private readonly TypePreinit.ISerializableReference _data;
private readonly int _allocationSiteId;

public MetadataType OwningType => _owningType;

public SerializedFrozenObjectNode(MetadataType owningType, int allocationSiteId, TypePreinit.ISerializableReference data)
{
_owningType = owningType;
_allocationSiteId = allocationSiteId;
_data = data;
}

public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenObj_")
.Append(nameMangler.GetMangledTypeName(_owningType))
.Append(_allocationSiteId.ToStringInvariant());
}

public override TypeDesc ObjectType => _data.Type;

public override bool IsKnownImmutable => _data.IsKnownImmutable;

protected override int ContentSize
=> _data.Type.IsArray
? _data.Type.Context.Target.PointerSize * 2 + ((ArrayType)_data.Type).ElementType.GetElementSize().AsInt * _data.ArrayLength
: ((DefType)_data.Type).InstanceByteCount.AsInt + (_data.Type.IsValueType ? _data.Type.Context.Target.PointerSize : 0);

public override int? ArrayLength => _data.Type.IsArray ? _data.ArrayLength : null;

public override void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
// byte contents
_data.WriteContent(ref dataBuilder, this, factory);
}

protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);

public override void GetNonRelocationDependencies(ref DependencyList dependencies, NodeFactory factory)
{
_data.GetNonRelocationDependencies(ref dependencies, factory);
}

public override int ClassCode => 1789429316;

public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var otherFrozenObjectNode = (SerializedFrozenObjectNode)other;
int result = comparer.Compare(otherFrozenObjectNode._owningType, _owningType);
if (result != 0)
return result;

return _allocationSiteId.CompareTo(otherFrozenObjectNode._allocationSiteId);
}

public override string ToString() => $"Frozen {_data.Type.GetDisplayNameWithoutNamespace()} object";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public abstract class MetadataManager : ICompilationRootProvider
private readonly SortedSet<MethodDesc> _reflectableMethods = new SortedSet<MethodDesc>(TypeSystemComparer.Instance);
private readonly SortedSet<GenericDictionaryNode> _genericDictionariesGenerated = new SortedSet<GenericDictionaryNode>(CompilerComparer.Instance);
private readonly SortedSet<IMethodBodyNode> _methodBodiesGenerated = new SortedSet<IMethodBodyNode>(CompilerComparer.Instance);
private readonly SortedSet<EmbeddedObjectNode> _frozenObjects = new SortedSet<EmbeddedObjectNode>(CompilerComparer.Instance);
private readonly SortedSet<FrozenObjectNode> _frozenObjects = new SortedSet<FrozenObjectNode>(CompilerComparer.Instance);
private readonly SortedSet<TypeGVMEntriesNode> _typeGVMEntries
= new SortedSet<TypeGVMEntriesNode>(Comparer<TypeGVMEntriesNode>.Create((a, b) => TypeSystemComparer.Instance.Compare(a.AssociatedType, b.AssociatedType)));
private readonly SortedSet<DefType> _typesWithDelegateMarshalling = new SortedSet<DefType>(TypeSystemComparer.Instance);
Expand Down Expand Up @@ -293,11 +293,6 @@ protected virtual void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj)
_frozenObjects.Add(frozenObj);
}

if (obj is FrozenStringNode frozenStr)
{
_frozenObjects.Add(frozenStr);
}

if (obj is GenericStaticBaseInfoNode genericStaticBaseInfo)
{
_typesWithGenericStaticBaseInfo.Add(genericStaticBaseInfo.Type);
Expand Down Expand Up @@ -751,7 +746,7 @@ public IEnumerable<TypeDesc> GetTypeTemplates()
return _typeTemplates;
}

public IEnumerable<EmbeddedObjectNode> GetFrozenObjects()
public IEnumerable<FrozenObjectNode> GetFrozenObjects()
{
return _frozenObjects;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@
<Compile Include="Compiler\DependencyAnalysis\DynamicDependencyAttributesOnEntityNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ExternSymbolsImportedNodeProvider.cs" />
<Compile Include="Compiler\DependencyAnalysis\FieldRvaDataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\FrozenObjectNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\FunctionPointerMapNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\GenericMethodsHashtableEntryNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\GenericStaticBaseInfoNode.cs" />
Expand Down Expand Up @@ -460,7 +461,7 @@
<Compile Include="Compiler\InlinedThreadStatics.cs" />
<Compile Include="Compiler\MstatObjectDumper.cs" />
<Compile Include="Compiler\NoMetadataBlockingPolicy.cs" />
<Compile Include="Compiler\DependencyAnalysis\FrozenObjectNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\SerializedFrozenObjectNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\GCStaticsPreInitDataNode.cs" />
<Compile Include="Compiler\MetadataBlockingPolicy.cs" />
<Compile Include="Compiler\DependencyAnalysis\MethodMetadataNode.cs" />
Expand Down
Loading
Loading