diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index 0af151dddc520..27a8dd31db8eb 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -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 { - /// - /// Represents a frozen object that is statically preallocated within the data section - /// of the executable instead of on the GC heap. - /// - 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 GetStaticDependencies(NodeFactory factory) + public sealed override IEnumerable 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) @@ -83,23 +60,15 @@ public override IEnumerable 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); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs index 66f386785ef61..f00c508f26524 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs @@ -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); @@ -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 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) @@ -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}\""; } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index b7322bdd3df5e..0400ba0b77a8a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -360,12 +360,12 @@ private void CreateNodeCaches() _frozenStringNodes = new NodeCache((string data) => { - return new FrozenStringNode(data, Target); + return new FrozenStringNode(data, TypeSystemContext); }); - _frozenObjectNodes = new NodeCache(key => + _frozenObjectNodes = new NodeCache(key => { - return new FrozenObjectNode(key.OwnerType, key.AllocationSiteId, key.SerializableObject); + return new SerializedFrozenObjectNode(key.OwnerType, key.AllocationSiteId, key.SerializableObject); }); _interfaceDispatchCells = new NodeCache(callSiteCell => @@ -1220,9 +1220,9 @@ public FrozenStringNode SerializedStringObject(string data) return _frozenStringNodes.GetOrAdd(data); } - private NodeCache _frozenObjectNodes; + private NodeCache _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)); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs new file mode 100644 index 0000000000000..c1d71f6572ece --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs @@ -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 +{ + /// + /// Represents a frozen object that is statically preallocated within the data section + /// of the executable instead of on the GC heap. + /// + 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"; + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 73133b10de83a..98f2f238b8ca5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -57,7 +57,7 @@ public abstract class MetadataManager : ICompilationRootProvider private readonly SortedSet _reflectableMethods = new SortedSet(TypeSystemComparer.Instance); private readonly SortedSet _genericDictionariesGenerated = new SortedSet(CompilerComparer.Instance); private readonly SortedSet _methodBodiesGenerated = new SortedSet(CompilerComparer.Instance); - private readonly SortedSet _frozenObjects = new SortedSet(CompilerComparer.Instance); + private readonly SortedSet _frozenObjects = new SortedSet(CompilerComparer.Instance); private readonly SortedSet _typeGVMEntries = new SortedSet(Comparer.Create((a, b) => TypeSystemComparer.Instance.Compare(a.AssociatedType, b.AssociatedType))); private readonly SortedSet _typesWithDelegateMarshalling = new SortedSet(TypeSystemComparer.Instance); @@ -293,11 +293,6 @@ protected virtual void Graph_NewMarkedNode(DependencyNodeCore obj) _frozenObjects.Add(frozenObj); } - if (obj is FrozenStringNode frozenStr) - { - _frozenObjects.Add(frozenStr); - } - if (obj is GenericStaticBaseInfoNode genericStaticBaseInfo) { _typesWithGenericStaticBaseInfo.Add(genericStaticBaseInfo.Type); @@ -751,7 +746,7 @@ public IEnumerable GetTypeTemplates() return _typeTemplates; } - public IEnumerable GetFrozenObjects() + public IEnumerable GetFrozenObjects() { return _frozenObjects; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 31afdea851adb..2cfb3e3b811fa 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -412,6 +412,7 @@ + @@ -460,7 +461,7 @@ - + diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 5e612ac997350..23146ce32d40c 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2261,7 +2261,7 @@ private bool getStaticFieldContent(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buf } return false; - case FrozenObjectNode or FrozenStringNode: + case FrozenObjectNode: Debug.Assert(valueOffset == 0); Debug.Assert(bufferSize == targetPtrSize); @@ -2315,13 +2315,7 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* objPtr, byte* buffer, int private CORINFO_CLASS_STRUCT_* getObjectType(CORINFO_OBJECT_STRUCT_* objPtr) { - object obj = HandleToObject(objPtr); - return obj switch - { - FrozenStringNode => ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)), - FrozenObjectNode frozenObj => ObjectToHandle(frozenObj.ObjectType), - _ => throw new NotImplementedException($"Unexpected object in getObjectType: {obj}") - }; + return ObjectToHandle(((FrozenObjectNode)HandleToObject(objPtr)).ObjectType); } #pragma warning disable CA1822 // Mark members as static @@ -2334,13 +2328,7 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* objPtr, byte* buffer, int private bool isObjectImmutable(CORINFO_OBJECT_STRUCT_* objPtr) { - object obj = HandleToObject(objPtr); - return obj switch - { - FrozenStringNode => true, - FrozenObjectNode frozenObj => frozenObj.IsKnownImmutable, - _ => throw new NotImplementedException($"Unexpected object in isObjectImmutable: {obj}") - }; + return ((FrozenObjectNode)HandleToObject(objPtr)).IsKnownImmutable; } private bool getStringChar(CORINFO_OBJECT_STRUCT_* strObj, int index, ushort* value) @@ -2355,13 +2343,7 @@ private bool getStringChar(CORINFO_OBJECT_STRUCT_* strObj, int index, ushort* va private int getArrayOrStringLength(CORINFO_OBJECT_STRUCT_* objHnd) { - object obj = HandleToObject(objHnd); - return obj switch - { - FrozenStringNode frozenStr => frozenStr.Data.Length, - FrozenObjectNode frozenObj when frozenObj.ObjectType.IsArray => frozenObj.GetArrayLength(), - _ => -1 - }; + return ((FrozenObjectNode)HandleToObject(objHnd)).ArrayLength ?? -1; } private bool getIsClassInitedFlagAddress(CORINFO_CLASS_STRUCT_* cls, ref CORINFO_CONST_LOOKUP addr, ref int offset)