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// typectxt.h
6//
7
8//
9
10#ifndef _H_TYPECTXT
11#define _H_TYPECTXT
12
13//------------------------------------------------------------------------
14// A signature type context gives the information necessary to interpret
15// the ELEMENT_TYPE_VAR and ELEMENT_TYPE_MVAR elements of a regular
16// metadata signature. These are usually stack allocated at appropriate
17// points where the SigPointer objects are created, or are allocated
18// inside a MetaSig (which are themselves normally stack allocated)
19//
20// They are normally passed as "const SigTypeContext *".
21//------------------------------------------------------------------------
22
23class SigTypeContext
24{
25public:
26 // Store pointers first and DWORDs second to ensure good packing on 64-bit
27 Instantiation m_classInst;
28 Instantiation m_methodInst;
29
30 // Default constructor for non-generic code
31 inline SigTypeContext()
32 { WRAPPER_NO_CONTRACT; InitTypeContext(this); }
33
34
35 // Initialize a type context given instantiations.
36 inline SigTypeContext(Instantiation classInst, Instantiation methodInst)
37 { WRAPPER_NO_CONTRACT; InitTypeContext(classInst, methodInst, this); }
38
39
40 // Initialize a type context from a MethodDesc. If this is a MethodDesc that gets
41 // shared between generic instantiations (e.g. one being jitted by a code-sharing JIT)
42 // and a null declaring Type is passed then the type context will
43 // be a representative context, not an exact one.
44 // This is sufficient for most purposes, e.g. GC and field layout, because
45 // these operations are "parametric", i.e. behave the same for all shared types.
46 //
47 // If declaringType is non-null, then the MethodDesc is assumed to be
48 // shared between generic classes, and the type handle is used to give the
49 // exact type context. The method should be one of the methods supported by the
50 // given type handle.
51 //
52 // If the method is a method in an array type then the type context will
53 // contain one item in the class instantiation corresponding to the
54 // element type of the array.
55 //
56 // Finally, exactMethodInst should be specified if md might represent a generic method definition,
57 // as type parameters are not always available off the method desc for generic method definitions without
58 // forcing a load. Typically the caller will use MethodDesc::LoadMethodInstantiation.
59 inline SigTypeContext(MethodDesc *md)
60 { WRAPPER_NO_CONTRACT; InitTypeContext(md,this); }
61
62 inline SigTypeContext(MethodDesc *md, TypeHandle declaringType)
63 { WRAPPER_NO_CONTRACT; InitTypeContext(md,declaringType,this); }
64
65 inline SigTypeContext(MethodDesc *md, TypeHandle declaringType, Instantiation exactMethodInst)
66 { WRAPPER_NO_CONTRACT; InitTypeContext(md,declaringType,exactMethodInst,this); }
67
68 // This is similar to the one above except that exact
69 // instantiations are provided explicitly.
70 // This will only normally be used when the code is shared
71 // between generic instantiations and after fetching the
72 // exact instantiations from the stack.
73 //
74 inline SigTypeContext(MethodDesc *md, Instantiation exactClassInst, Instantiation exactMethodInst)
75 { WRAPPER_NO_CONTRACT; InitTypeContext(md,exactClassInst,exactMethodInst,this); }
76
77 // Initialize a type context from a type handle. This is used when
78 // generating the type context for a
79 // any of the metadata in the class covered by the type handle apart from
80 // the metadata for any generic methods in the class.
81 // If the type handle satisfies th.IsNull() then the created type context
82 // will be empty.
83 inline SigTypeContext(TypeHandle th)
84 { WRAPPER_NO_CONTRACT; InitTypeContext(th,this); }
85
86 inline SigTypeContext(FieldDesc *pFD, TypeHandle declaringType = TypeHandle())
87 { WRAPPER_NO_CONTRACT; InitTypeContext(pFD,declaringType,this); }
88
89 // Copy contructor - try not to use this. The C++ compiler is not doing a good job
90 // of copy-constructor based code, and we've had perf regressions when using this too
91 // much for this simple objects. Use an explicit call to InitTypeContext instead,
92 // or use GetOptionalTypeContext.
93 inline SigTypeContext(const SigTypeContext &c)
94 { WRAPPER_NO_CONTRACT; InitTypeContext(&c,this); }
95
96 // Copy contructor from a possibly-NULL pointer.
97 inline SigTypeContext(const SigTypeContext *c)
98 { WRAPPER_NO_CONTRACT; InitTypeContext(c,this); }
99
100 static void InitTypeContext(MethodDesc *md, SigTypeContext *pRes);
101 static void InitTypeContext(MethodDesc *md, TypeHandle declaringType, SigTypeContext *pRes);
102 static void InitTypeContext(MethodDesc *md, TypeHandle declaringType, Instantiation exactMethodInst, SigTypeContext *pRes);
103 static void InitTypeContext(MethodDesc *md, Instantiation exactClassInst, Instantiation exactMethodInst, SigTypeContext *pRes);
104 static void InitTypeContext(TypeHandle th, SigTypeContext *pRes);
105 static void InitTypeContext(FieldDesc *pFD, TypeHandle declaringType, SigTypeContext *pRes);
106 inline static void InitTypeContext(Instantiation classInst, Instantiation methodInst, SigTypeContext *pRes);
107 inline static void InitTypeContext(SigTypeContext *);
108 inline static void InitTypeContext(const SigTypeContext *c, SigTypeContext *pRes);
109
110 // These are allowed to return NULL if an empty type context is generated. The NULL value
111 // can then be passed around to represent the empty type context.
112 // pRes must be non-null.
113 // pRes must initially be zero-initialized, e.g. by the default SigTypeContext constructor.
114 static const SigTypeContext * GetOptionalTypeContext(MethodDesc *md, TypeHandle declaringType, SigTypeContext *pRes);
115 static const SigTypeContext * GetOptionalTypeContext(TypeHandle th, SigTypeContext *pRes);
116
117 // SigTypeContexts are used as part of keys for various data structures indiexed by instantiation
118 static BOOL Equal(const SigTypeContext *pCtx1, const SigTypeContext *pCtx2);
119 static BOOL IsValidTypeOnlyInstantiationOf(const SigTypeContext *pCtxTypicalMethodInstantiation, const SigTypeContext *pCtxTypeOnlyInstantiation);
120 BOOL IsEmpty() const { LIMITED_METHOD_CONTRACT; return m_classInst.IsEmpty() && m_methodInst.IsEmpty(); }
121
122};
123
124inline void SigTypeContext::InitTypeContext(SigTypeContext *pRes)
125{
126 LIMITED_METHOD_DAC_CONTRACT;
127}
128
129inline void SigTypeContext::InitTypeContext(Instantiation classInst,
130 Instantiation methodInst,
131 SigTypeContext *pRes)
132{
133 LIMITED_METHOD_CONTRACT;
134 pRes->m_classInst = classInst;
135 pRes->m_methodInst = methodInst;
136}
137
138
139// Copy contructor from a possibly-NULL pointer.
140inline void SigTypeContext::InitTypeContext(const SigTypeContext *c,SigTypeContext *pRes)
141{
142 LIMITED_METHOD_DAC_CONTRACT;
143 if (c)
144 {
145 pRes->m_classInst = c->m_classInst;
146 pRes->m_methodInst = c->m_methodInst;
147 }
148 else
149 {
150 pRes->m_classInst = Instantiation();
151 pRes->m_methodInst = Instantiation();
152 }
153}
154
155//------------------------------------------------------------------------
156// Encapsulates pointers to code:SigTypeContext and code:Substitution chain
157// that have been used to instantiate a generic type. The context is passed
158// as "const InstantiationContext *" from code:SigPointer.GetTypeHandleThrowing
159// down to code:TypeVarTypeDesc.SatisfiesConstraints where it is needed for
160// instantiating constraints attached to type arguments.
161//
162// The reason why we need to pass these pointers down to the code that verifies
163// that constraints are satisified is the case when another type variable is
164// substituted for a type variable and this argument is constrained by a generic
165// type. In order to verify that constraints of the argument satisfy constraints
166// of the parameter, the argument constraints must be instantiated in the same
167// "instantiation context" as the original signature - and unfortunately this
168// context cannot be extracted from the rest of the information that we have
169// about the type that is being loaded.
170//
171// See code:TypeVarTypeDesc.SatisfiesConstraints for more details and an
172// example scenario in which we are unable to verify constraints without this
173// context.
174//------------------------------------------------------------------------
175
176class InstantiationContext
177{
178public:
179 const SigTypeContext *m_pArgContext;
180 const Substitution *m_pSubstChain;
181
182 inline InstantiationContext(const SigTypeContext *pArgContext = NULL, const Substitution *pSubstChain = NULL)
183 {
184 LIMITED_METHOD_DAC_CONTRACT;
185
186 m_pArgContext = pArgContext;
187 m_pSubstChain = pSubstChain;
188 }
189};
190
191#endif
192