| File: Compiler\DependencyAnalysis\DataOnlyEETypeNode.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// 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.Runtime; using Internal.Text; using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; namespace ILCompiler.DependencyAnalysis { /// <summary> /// MethodTable for a piece of data that can be allocated on the GC heap, with GC-reported references in it. /// The shape of the data is described using a <see cref="GCPointerMap"/>. The generated data structure /// is a MethodTable that is valid for use with GC, however not all data on it is present. /// A lot of the MethodTable API surface on this will not work at runtime . /// </summary> public class DataOnlyEETypeNode : DehydratableObjectNode, ISymbolDefinitionNode { private readonly string _prefix; protected readonly GCPointerMap _gcMap; private readonly TypeDesc _baseType; protected readonly bool _requiresAlign8; public DataOnlyEETypeNode(string prefix, GCPointerMap gcMap, TypeDesc baseType, bool requiresAlign8) { _prefix = prefix; _gcMap = gcMap; _baseType = baseType; _requiresAlign8 = requiresAlign8; } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) { if (factory.Target.IsWindows) return ObjectNodeSection.ReadOnlyDataSection; else return ObjectNodeSection.DataSection; } public override bool StaticDependenciesAreComputed => true; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append($"__{_prefix}_").Append(_gcMap.ToString()); if (_requiresAlign8) { sb.Append("_align8"u8); } } int ISymbolDefinitionNode.Offset { get { int numSeries = _gcMap.NumSeries; return numSeries > 0 ? ((numSeries * 2) + 1) * _baseType.Context.Target.PointerSize : 0; } } int ISymbolNode.Offset => 0; public override bool IsShareable => true; protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); // +1 for SyncBlock (GCMap size already includes MethodTable field) int totalSize = (_gcMap.Size + 1) * factory.Target.PointerSize; bool containsPointers = _gcMap.NumSeries > 0; if (containsPointers) { GCDescEncoder.EncodeStandardGCDesc(ref dataBuilder, _gcMap, totalSize, 0); } Debug.Assert(dataBuilder.CountBytes == ((ISymbolDefinitionNode)this).Offset); // ComponentSize is always 0 uint flags = 0; if (containsPointers) flags |= (uint)EETypeFlags.HasPointersFlag; if (_requiresAlign8) { // Mark the method table as non-value type that requires 8-byte alignment flags |= (uint)EETypeFlagsEx.RequiresAlign8Flag; flags |= (uint)EETypeElementType.Class << (byte)EETypeFlags.ElementTypeShift; } dataBuilder.EmitUInt(flags); totalSize = Math.Max(totalSize, factory.Target.PointerSize * 3); // minimum GC MethodTable size is 3 pointers dataBuilder.EmitInt(totalSize); dataBuilder.EmitPointerReloc(factory.NecessaryTypeSymbol(_baseType)); return dataBuilder.ToObjectData(); } public override int ClassCode => 1304929125; public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { DataOnlyEETypeNode otherNode = (DataOnlyEETypeNode)other; int mapCompare = _gcMap.CompareTo(otherNode._gcMap); if (mapCompare == 0) { return _requiresAlign8.CompareTo(otherNode._requiresAlign8); } return mapCompare; } } }