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

CanonicalEETypeNode.cs « DependencyAnalysis « Compiler « src « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 945e49c39cfb634f3d046409ddd4c0b680884dfe (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
// 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.Collections.Generic;
using System.Diagnostics;

using Internal.TypeSystem;
using Internal.Runtime;

namespace ILCompiler.DependencyAnalysis
{
    /// <summary>
    /// Canonical type instantiations are emitted, not because they are used directly by the user code, but because
    /// they are used by the dynamic type loader when dynamically instantiating types at runtime.
    /// The data that we emit on canonical type instantiations should just be the minimum that is needed by the template 
    /// type loader. 
    /// Similarly, the dependencies that we track for canonicl type instantiations are minimal, and are just the ones used
    /// by the dynamic type loader
    /// </summary>
    internal sealed class CanonicalEETypeNode : EETypeNode
    {
        public CanonicalEETypeNode(NodeFactory factory, TypeDesc type) : base(factory, type)
        {
            Debug.Assert(!type.IsCanonicalDefinitionType(CanonicalFormKind.Any));
            Debug.Assert(type.IsCanonicalSubtype(CanonicalFormKind.Any));
            Debug.Assert(type == type.ConvertToCanonForm(CanonicalFormKind.Specific));
            Debug.Assert(!type.IsMdArray);
        }

        public override bool StaticDependenciesAreComputed => true;
        public override bool IsShareable => IsTypeNodeShareable(_type);
        protected override bool EmitVirtualSlotsAndInterfaces => true;
        public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => false;

        protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
        {
            DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);

            // Ensure that we track the necessary type symbol if we are working with a constructed type symbol.
            // The emitter will ensure we don't emit both, but this allows us assert that we only generate
            // relocs to nodes we emit.
            dependencyList.Add(factory.NecessaryTypeSymbol(_type), "Necessary type symbol related to CanonicalEETypeNode");

            DefType closestDefType = _type.GetClosestDefType();

            if (InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
                dependencyList.Add(factory.InterfaceDispatchMap(_type), "Canonical interface dispatch map");

            dependencyList.Add(factory.VTable(closestDefType), "VTable");

            if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal))
                dependencyList.Add(factory.NativeLayout.TemplateTypeLayout(_type), "Universal generic types always have template layout");

            // Track generic virtual methods that will get added to the GVM tables
            if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
            {
                dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type), "Type with generic virtual methods"));

                AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
            }

            // Keep track of the default constructor map dependency for this type if it has a default constructor
            MethodDesc defaultCtor = closestDefType.GetDefaultConstructor();
            if (defaultCtor != null)
            {
                dependencyList.Add(new DependencyListEntry(
                    factory.MethodEntrypoint(defaultCtor, closestDefType.IsValueType),
                    "DefaultConstructorNode"));
            }

            return dependencyList;
        }

        protected override ISymbolNode GetBaseTypeNode(NodeFactory factory)
        {
            return _type.BaseType != null ? factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(_type.BaseType)) : null;
        }

        protected override int GCDescSize
        {
            get
            {
                // No GCDescs for universal canonical types
                if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal))
                    return 0;

                Debug.Assert(_type.IsCanonicalSubtype(CanonicalFormKind.Specific));
                return GCDescEncoder.GetGCDescSize(_type);
            }
        }

        protected override void OutputGCDesc(ref ObjectDataBuilder builder)
        {
            // No GCDescs for universal canonical types
            if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal))
                return;

            Debug.Assert(_type.IsCanonicalSubtype(CanonicalFormKind.Specific));
            GCDescEncoder.EncodeGCDesc(ref builder, _type);
        }

        protected override void OutputInterfaceMap(NodeFactory factory, ref ObjectDataBuilder objData)
        {
            foreach (var itf in _type.RuntimeInterfaces)
            {
                // Interface omitted for canonical instantiations (constructed at runtime for dynamic types from the native layout info)
                objData.EmitZeroPointer();
            }
        }

        protected override int BaseSize
        {
            get
            {
                if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal) && _type.IsDefType)
                {
                    LayoutInt instanceByteCount = ((DefType)_type).InstanceByteCount;

                    if (instanceByteCount.IsIndeterminate)
                    {
                        // For USG types, they may be of indeterminate size, and the size of the type may be meaningless. 
                        // In that case emit a fixed constant.
                        return MinimumObjectSize;
                    }
                }

                return base.BaseSize;
            }
        }

        protected override void ComputeValueTypeFieldPadding()
        {
            DefType defType = _type as DefType;

            // Types of indeterminate sizes don't have computed ValueTypeFieldPadding
            if (defType != null && defType.InstanceByteCount.IsIndeterminate)
            {
                Debug.Assert(_type.IsCanonicalSubtype(CanonicalFormKind.Universal));
                return;
            }

            base.ComputeValueTypeFieldPadding();
        }

        public override int ClassCode => -1798018602;
    }
}