1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 7 using Internal.Text; 8 using Internal.TypeSystem; 9 10 namespace ILCompiler.DependencyAnalysis 11 { 12 public class FrozenStringNode : EmbeddedObjectNode, ISymbolDefinitionNode 13 { 14 private string _data; 15 private int _syncBlockSize; 16 FrozenStringNode(string data, TargetDetails target)17 public FrozenStringNode(string data, TargetDetails target) 18 { 19 _data = data; 20 _syncBlockSize = target.PointerSize; 21 } 22 AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)23 public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) 24 { 25 sb.Append(nameMangler.CompilationUnitPrefix).Append("__Str_").Append(nameMangler.GetMangledStringName(_data)); 26 } 27 28 public override bool StaticDependenciesAreComputed => true; 29 30 int ISymbolNode.Offset => 0; 31 32 int ISymbolDefinitionNode.Offset 33 { 34 get 35 { 36 // The frozen string symbol points at the EEType portion of the object, skipping over the sync block 37 return OffsetFromBeginningOfArray + _syncBlockSize; 38 } 39 } 40 GetEETypeNode(NodeFactory factory)41 private static IEETypeNode GetEETypeNode(NodeFactory factory) 42 { 43 DefType systemStringType = factory.TypeSystemContext.GetWellKnownType(WellKnownType.String); 44 45 // 46 // The GC requires a direct reference to frozen objects' EETypes. If System.String will be compiled into a separate 47 // binary, it must be cloned into this one. 48 // 49 IEETypeNode stringSymbol = factory.ConstructedTypeSymbol(systemStringType); 50 51 if (stringSymbol.RepresentsIndirectionCell) 52 { 53 return factory.ConstructedClonedTypeSymbol(systemStringType); 54 } 55 else 56 { 57 return stringSymbol; 58 } 59 } 60 EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)61 public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) 62 { 63 dataBuilder.EmitZeroPointer(); // Sync block 64 65 dataBuilder.EmitPointerReloc(GetEETypeNode(factory)); 66 67 dataBuilder.EmitInt(_data.Length); 68 69 foreach (char c in _data) 70 { 71 dataBuilder.EmitShort((short)c); 72 } 73 74 // Null-terminate for friendliness with interop 75 dataBuilder.EmitShort(0); 76 77 } 78 79 protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); 80 GetStaticDependencies(NodeFactory factory)81 public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) 82 { 83 return new DependencyListEntry[] 84 { 85 new DependencyListEntry(GetEETypeNode(factory), "Frozen string literal EEType"), 86 }; 87 } 88 OnMarked(NodeFactory factory)89 protected override void OnMarked(NodeFactory factory) 90 { 91 factory.FrozenSegmentRegion.AddEmbeddedObject(this); 92 } 93 94 protected internal override int ClassCode => -1733946122; 95 CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)96 protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) 97 { 98 return string.CompareOrdinal(_data, ((FrozenStringNode)other)._data); 99 } 100 } 101 } 102