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
20inline mdTypeDef TypeHandle::GetCl() const
21{
22 LIMITED_METHOD_DAC_CONTRACT;
23
24 PREFIX_ASSUME(GetMethodTable() != NULL);
25 return GetMethodTable()->GetCl();
26}
27
28inline 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
38inline void TypeHandle::SetIsFullyLoaded()
39{
40 LIMITED_METHOD_CONTRACT;
41
42 if (IsTypeDesc())
43 return AsTypeDesc()->SetIsFullyLoaded();
44 else
45 return AsMethodTable()->SetIsFullyLoaded();
46}
47
48inline 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
63inline 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
75inline 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
92inline BOOL TypeHandle::IsZapped() const
93{
94 LIMITED_METHOD_DAC_CONTRACT;
95
96 return (GetZapModule() != NULL);
97}
98
99inline 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
111inline PTR_MethodTable TypeHandle::AsMethodTable() const
112{
113 LIMITED_METHOD_DAC_CONTRACT;
114
115 _ASSERTE(!IsTypeDesc());
116
117 return PTR_MethodTable(m_asTAddr);
118}
119
120inline 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
131inline 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
142inline 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
153inline BOOL TypeHandle::IsNativeValueType() const
154{
155 LIMITED_METHOD_DAC_CONTRACT;
156 return (IsTypeDesc() && AsTypeDesc()->IsNativeValueType());
157}
158
159inline MethodTable *TypeHandle::AsNativeValueType() const
160{
161 LIMITED_METHOD_CONTRACT;
162
163 _ASSERTE(IsNativeValueType());
164 return AsTypeDesc()->GetMethodTable();
165}
166
167inline BOOL TypeHandle::IsTypicalTypeDefinition() const
168{
169 LIMITED_METHOD_CONTRACT;
170
171 return !HasInstantiation() || IsGenericTypeDefinition();
172}
173
174inline BOOL TypeHandle::SupportsGenericInterop(InteropKind interopKind) const
175{
176 LIMITED_METHOD_CONTRACT;
177 return (!IsTypeDesc() && AsMethodTable()->SupportsGenericInterop(interopKind));
178}
179
180inline 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
199inline 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
233template<class T>
234inline 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