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 | // File: typehandle.inl |
6 | // |
7 | |
8 | |
9 | // |
10 | |
11 | // |
12 | // ============================================================================ |
13 | |
14 | |
15 | #ifndef _TYPEHANDLE_INL_ |
16 | #define _TYPEHANDLE_INL_ |
17 | |
18 | #include "typehandle.h" |
19 | |
20 | inline mdTypeDef TypeHandle::GetCl() const |
21 | { |
22 | LIMITED_METHOD_DAC_CONTRACT; |
23 | |
24 | PREFIX_ASSUME(GetMethodTable() != NULL); |
25 | return GetMethodTable()->GetCl(); |
26 | } |
27 | |
28 | inline PTR_MethodTable TypeHandle::GetMethodTable() const |
29 | { |
30 | LIMITED_METHOD_DAC_CONTRACT; |
31 | |
32 | if (IsTypeDesc()) |
33 | return(AsTypeDesc()->GetMethodTable()); |
34 | else |
35 | return AsMethodTable(); |
36 | } |
37 | |
38 | inline void TypeHandle::SetIsFullyLoaded() |
39 | { |
40 | LIMITED_METHOD_CONTRACT; |
41 | |
42 | if (IsTypeDesc()) |
43 | return AsTypeDesc()->SetIsFullyLoaded(); |
44 | else |
45 | return AsMethodTable()->SetIsFullyLoaded(); |
46 | } |
47 | |
48 | inline MethodTable* TypeHandle::GetMethodTableOfElementType() const |
49 | { |
50 | LIMITED_METHOD_CONTRACT; |
51 | |
52 | if (IsTypeDesc()) |
53 | { |
54 | TypeHandle elementType = AsTypeDesc()->GetTypeParam(); |
55 | return elementType.GetMethodTableOfElementType(); |
56 | } |
57 | else |
58 | { |
59 | return AsMethodTable(); |
60 | } |
61 | } |
62 | |
63 | inline MethodTable * TypeHandle::GetPossiblySharedArrayMethodTable() const |
64 | { |
65 | LIMITED_METHOD_CONTRACT; |
66 | |
67 | _ASSERTE(IsArrayType()); |
68 | |
69 | if (IsArray()) |
70 | return AsArray()->GetTemplateMethodTable(); |
71 | else |
72 | return AsMethodTable(); |
73 | } |
74 | |
75 | inline TypeHandle TypeHandle::GetElementType() const |
76 | { |
77 | LIMITED_METHOD_CONTRACT; |
78 | |
79 | if (IsTypeDesc()) |
80 | { |
81 | if (IsGenericVariable()) |
82 | return *this; |
83 | |
84 | return AsTypeDesc()->GetTypeParam().GetElementType(); |
85 | } |
86 | else |
87 | { |
88 | return *this; |
89 | } |
90 | } |
91 | |
92 | inline BOOL TypeHandle::IsZapped() const |
93 | { |
94 | LIMITED_METHOD_DAC_CONTRACT; |
95 | |
96 | return (GetZapModule() != NULL); |
97 | } |
98 | |
99 | inline PTR_ArrayTypeDesc TypeHandle::AsArray() const |
100 | { |
101 | LIMITED_METHOD_DAC_CONTRACT; |
102 | |
103 | _ASSERTE(IsArray()); |
104 | |
105 | PTR_ArrayTypeDesc result = PTR_ArrayTypeDesc(m_asTAddr - 2); |
106 | PREFIX_ASSUME(result != NULL); |
107 | return result; |
108 | } |
109 | |
110 | // Methods to allow you get get a the two possible representations |
111 | inline PTR_MethodTable TypeHandle::AsMethodTable() const |
112 | { |
113 | LIMITED_METHOD_DAC_CONTRACT; |
114 | |
115 | _ASSERTE(!IsTypeDesc()); |
116 | |
117 | return PTR_MethodTable(m_asTAddr); |
118 | } |
119 | |
120 | inline PTR_TypeDesc TypeHandle::AsTypeDesc() const |
121 | { |
122 | LIMITED_METHOD_DAC_CONTRACT; |
123 | |
124 | _ASSERTE(IsTypeDesc()); |
125 | |
126 | PTR_TypeDesc result = PTR_TypeDesc(m_asTAddr - 2); |
127 | PREFIX_ASSUME(result != NULL); |
128 | return result; |
129 | } |
130 | |
131 | inline FnPtrTypeDesc* TypeHandle::AsFnPtrType() const |
132 | { |
133 | LIMITED_METHOD_DAC_CONTRACT; |
134 | |
135 | _ASSERTE(IsFnPtrType()); |
136 | |
137 | FnPtrTypeDesc* result = PTR_FnPtrTypeDesc(m_asTAddr - 2); |
138 | PREFIX_ASSUME(result != NULL); |
139 | return result; |
140 | } |
141 | |
142 | inline TypeVarTypeDesc* TypeHandle::AsGenericVariable() const |
143 | { |
144 | LIMITED_METHOD_DAC_CONTRACT; |
145 | |
146 | _ASSERTE(IsGenericVariable()); |
147 | |
148 | TypeVarTypeDesc* result = PTR_TypeVarTypeDesc(m_asTAddr - 2); |
149 | PREFIX_ASSUME(result != NULL); |
150 | return result; |
151 | } |
152 | |
153 | inline BOOL TypeHandle::IsNativeValueType() const |
154 | { |
155 | LIMITED_METHOD_DAC_CONTRACT; |
156 | return (IsTypeDesc() && AsTypeDesc()->IsNativeValueType()); |
157 | } |
158 | |
159 | inline MethodTable *TypeHandle::AsNativeValueType() const |
160 | { |
161 | LIMITED_METHOD_CONTRACT; |
162 | |
163 | _ASSERTE(IsNativeValueType()); |
164 | return AsTypeDesc()->GetMethodTable(); |
165 | } |
166 | |
167 | inline BOOL TypeHandle::IsTypicalTypeDefinition() const |
168 | { |
169 | LIMITED_METHOD_CONTRACT; |
170 | |
171 | return !HasInstantiation() || IsGenericTypeDefinition(); |
172 | } |
173 | |
174 | inline BOOL TypeHandle::SupportsGenericInterop(InteropKind interopKind) const |
175 | { |
176 | LIMITED_METHOD_CONTRACT; |
177 | return (!IsTypeDesc() && AsMethodTable()->SupportsGenericInterop(interopKind)); |
178 | } |
179 | |
180 | inline BOOL TypeHandle::HasTypeEquivalence() const |
181 | { |
182 | LIMITED_METHOD_CONTRACT; |
183 | |
184 | if (IsTypeDesc()) |
185 | return AsTypeDesc()->HasTypeEquivalence(); |
186 | else |
187 | return AsMethodTable()->HasTypeEquivalence(); |
188 | } |
189 | |
190 | |
191 | //-------------------------------------------------------------------------------------- |
192 | // IsEquivalentTo is based on Guid and TypeIdentifier attributes to support the "no-PIA" |
193 | // feature. The idea is that compilers pull types from the PIA into different assemblies |
194 | // and these types - represented by separate MTs/TypeHandles - are considered equivalent |
195 | // for certain operations. |
196 | |
197 | |
198 | #ifndef DACCESS_COMPILE |
199 | inline BOOL TypeHandle::IsEquivalentTo(TypeHandle type COMMA_INDEBUG(TypeHandlePairList *pVisited /*= NULL*/)) const |
200 | { |
201 | CONTRACTL |
202 | { |
203 | THROWS; |
204 | GC_TRIGGERS; |
205 | MODE_ANY; |
206 | SO_TOLERANT; |
207 | } |
208 | CONTRACTL_END; |
209 | |
210 | if (*this == type) |
211 | return TRUE; |
212 | |
213 | #ifdef FEATURE_TYPEEQUIVALENCE |
214 | // bail early for normal types |
215 | if (!HasTypeEquivalence() || !type.HasTypeEquivalence()) |
216 | return FALSE; |
217 | |
218 | if (IsTypeDesc()) |
219 | return AsTypeDesc()->IsEquivalentTo(type COMMA_INDEBUG(pVisited)); |
220 | |
221 | if (type.IsTypeDesc()) |
222 | return FALSE; |
223 | |
224 | return AsMethodTable()->IsEquivalentTo_Worker(type.AsMethodTable() COMMA_INDEBUG(pVisited)); |
225 | #else |
226 | return FALSE; |
227 | #endif |
228 | } |
229 | #endif |
230 | |
231 | // Execute the callback functor for each MethodTable that makes up the given type handle. This method |
232 | // does not invoke the functor for generic variables |
233 | template<class T> |
234 | inline void TypeHandle::ForEachComponentMethodTable(T &callback) const |
235 | { |
236 | CONTRACTL |
237 | { |
238 | THROWS; |
239 | GC_TRIGGERS; |
240 | MODE_ANY; |
241 | } |
242 | CONTRACTL_END; |
243 | |
244 | if (IsTypeDesc() && AsTypeDesc()->HasTypeParam()) |
245 | { |
246 | // If we have a type parameter, then we just need to invoke ourselves on that parameter |
247 | AsTypeDesc()->GetTypeParam().ForEachComponentMethodTable(callback); |
248 | } |
249 | else if (IsFnPtrType()) |
250 | { |
251 | // If we are a function pointer, then we need to invoke the callback method on the function |
252 | // pointer's return type as well as each of its argument types |
253 | FnPtrTypeDesc *pFnPtr = AsFnPtrType(); |
254 | for (DWORD iArg = 0; iArg < pFnPtr->GetNumArgs() + 1; ++iArg) |
255 | { |
256 | pFnPtr->GetRetAndArgTypesPointer()[iArg].ForEachComponentMethodTable(callback); |
257 | } |
258 | } |
259 | else if (HasInstantiation()) |
260 | { |
261 | // If we have a generic instantiation, we need to invoke the callback on each of the generic |
262 | // parameters as well as the root method table. |
263 | callback(GetMethodTable()); |
264 | |
265 | Instantiation instantiation = GetInstantiation(); |
266 | for (DWORD iGenericArg = 0; iGenericArg < instantiation.GetNumArgs(); ++iGenericArg) |
267 | { |
268 | instantiation[iGenericArg].ForEachComponentMethodTable(callback); |
269 | } |
270 | } |
271 | else if (IsGenericVariable()) |
272 | { |
273 | // We don't invoke the callback on generic variables since they don't have method tables |
274 | return; |
275 | } |
276 | else |
277 | { |
278 | // Otherwise, we must be a simple type, so just do the callback directly on the method table |
279 | callback(GetMethodTable()); |
280 | } |
281 | } |
282 | |
283 | |
284 | #endif // _TYPEHANDLE_INL_ |
285 | |
286 |