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