Welcome to mirror list, hosted at ThFree Co, Russian Federation.

StaticsInfoHashtableNode.cs « DependencyAnalysis « Compiler « src « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d1ea7d3d4a5541e6651ed9b1b3fd521394c10c5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;

using Internal.Text;
using Internal.TypeSystem;
using Internal.NativeFormat;

namespace ILCompiler.DependencyAnalysis
{
    /// <summary>
    /// Represents a hashtable with information about all statics regions for all compiled generic types.
    /// </summary>
    internal sealed class StaticsInfoHashtableNode : ObjectNode, ISymbolDefinitionNode
    {
        private ObjectAndOffsetSymbolNode _endSymbol;
        private ExternalReferencesTableNode _externalReferences;
        private ExternalReferencesTableNode _nativeStaticsReferences;

        public StaticsInfoHashtableNode(ExternalReferencesTableNode externalReferences, ExternalReferencesTableNode nativeStaticsReferences)
        {
            _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "_StaticsInfoHashtableNode_End", true);
            _externalReferences = externalReferences;
            _nativeStaticsReferences = nativeStaticsReferences;
        }

        public ISymbolNode EndSymbol => _endSymbol;

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(nameMangler.CompilationUnitPrefix).Append("_StaticsInfoHashtableNode");
        }

        public int Offset => 0;
        public override bool IsShareable => false;
        public override ObjectNodeSection Section => _externalReferences.Section;
        public override bool StaticDependenciesAreComputed => true;
        protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
        

        /// <summary>
        /// Helper method to compute the dependencies that would be needed by a hashtable entry for statics info lookup.
        /// This helper is used by EETypeNode, which is used by the dependency analysis to compute the statics hashtable
        /// entries for the compiled types.
        /// </summary>
        public static void AddStaticsInfoDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
        {
            if (!factory.MetadataManager.SupportsReflection)
                return;

            if (type is MetadataType && type.HasInstantiation && !type.IsCanonicalSubtype(CanonicalFormKind.Any))
            {
                MetadataType metadataType = (MetadataType)type;

                // NOTE: The StaticsInfoHashtable entries need to reference the gc and non-gc static nodes through an indirection cell.
                // The StaticsInfoHashtable entries only exist for static fields on generic types.

                if (metadataType.GCStaticFieldSize.AsInt > 0)
                {
                    dependencies.Add(factory.Indirection(factory.TypeGCStaticsSymbol(metadataType)), "GC statics indirection for StaticsInfoHashtable");
                }

                if (metadataType.NonGCStaticFieldSize.AsInt > 0 || factory.TypeSystemContext.HasLazyStaticConstructor(type))
                {
                    // The entry in the StaticsInfoHashtable points at the beginning of the static fields data, rather than the cctor 
                    // context offset.
                    dependencies.Add(factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType)), "Non-GC statics indirection for StaticsInfoHashtable");
                }

                if (metadataType.ThreadGcStaticFieldSize.AsInt > 0)
                {
                    if (factory.Target.Abi == TargetAbi.ProjectN)
                    {
                        UtcNodeFactory utcFactory = (UtcNodeFactory)factory;
                        dependencies.Add(utcFactory.TypeThreadStaticsIndexSymbol(metadataType), "Thread statics index indirection for StaticsInfoHashtable");
                        dependencies.Add(utcFactory.TypeThreadStaticsOffsetSymbol(metadataType), "Thread statics offset indirection for StaticsInfoHashtable");
                    }
                    // TODO: TLS for CoreRT
                }
            }
        }

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // This node does not trigger generation of other nodes.
            if (relocsOnly)
                return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });

            NativeWriter writer = new NativeWriter();
            VertexHashtable hashtable = new VertexHashtable();
            Section section = writer.NewSection();

            section.Place(hashtable);

            foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                if (!type.HasInstantiation || type.IsCanonicalSubtype(CanonicalFormKind.Any) || type.IsGenericDefinition)
                    continue;

                MetadataType metadataType = type as MetadataType;
                if (metadataType == null)
                    continue;

                VertexBag bag = new VertexBag();

                if (metadataType.GCStaticFieldSize.AsInt > 0)
                {
                    ISymbolNode gcStaticIndirection = factory.Indirection(factory.TypeGCStaticsSymbol(metadataType));
                    bag.AppendUnsigned(BagElementKind.GcStaticData, _nativeStaticsReferences.GetIndex(gcStaticIndirection));
                }
                if (metadataType.NonGCStaticFieldSize.AsInt > 0 || factory.TypeSystemContext.HasLazyStaticConstructor(type))
                {
                    ISymbolNode nonGCStaticIndirection = factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType));
                    bag.AppendUnsigned(BagElementKind.NonGcStaticData, _nativeStaticsReferences.GetIndex(nonGCStaticIndirection));
                }
                if (metadataType.ThreadGcStaticFieldSize.AsInt > 0)
                {
                    if (factory.Target.Abi == TargetAbi.ProjectN)
                    {
                        UtcNodeFactory utcFactory = (UtcNodeFactory)factory;

                        ISymbolNode threadStaticIndexIndirection = utcFactory.TypeThreadStaticsIndexSymbol(metadataType);
                        bag.AppendUnsigned(BagElementKind.ThreadStaticIndex, _nativeStaticsReferences.GetIndex(threadStaticIndexIndirection));

                        ISymbolNode threadStaticOffsetIndirection = utcFactory.TypeThreadStaticsOffsetSymbol(metadataType);
                        bag.AppendUnsigned(BagElementKind.ThreadStaticOffset, _nativeStaticsReferences.GetIndex(threadStaticOffsetIndirection));
                    }
                    // TODO: TLS for CoreRT
                }

                if (bag.ElementsCount > 0)
                {
                    uint typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(type));
                    Vertex staticsInfo = writer.GetTuple(writer.GetUnsignedConstant(typeId), bag);

                    hashtable.Append((uint)type.GetHashCode(), section.Place(staticsInfo));
                }
            }

            byte[] hashTableBytes = writer.Save();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol });
        }

        protected internal override int Phase => (int)ObjectNodePhase.Ordered;
        public override int ClassCode => (int)ObjectNodeOrder.StaticsInfoHashtableNode;
    }
}