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 | // ==++== |
6 | // |
7 | // |
8 | |
9 | // |
10 | // ==--== |
11 | // |
12 | // File: METHODTABLEBUILDER.H |
13 | // |
14 | |
15 | |
16 | // |
17 | |
18 | // |
19 | // ============================================================================ |
20 | |
21 | #ifndef METHODTABLEBUILDER_H |
22 | #define METHODTABLEBUILDER_H |
23 | |
24 | //--------------------------------------------------------------------------------------- |
25 | // |
26 | // MethodTableBuilder simply acts as a holder for the |
27 | // large algorithm that "compiles" a type into |
28 | // a MethodTable/EEClass/DispatchMap/VTable etc. etc. |
29 | // |
30 | // The user of this class (the ClassLoader) currently builds the EEClass |
31 | // first, and does a couple of other things too, though all |
32 | // that work should probably be folded into BuildMethodTableThrowing. |
33 | // |
34 | class MethodTableBuilder |
35 | { |
36 | |
37 | public: |
38 | |
39 | friend class EEClass; |
40 | |
41 | typedef UINT16 SLOT_INDEX; |
42 | typedef ClrSafeInt<SLOT_INDEX> S_SLOT_INDEX; |
43 | static const UINT16 INVALID_SLOT_INDEX = static_cast<UINT16>(-1); |
44 | static const UINT16 MAX_SLOT_INDEX = static_cast<UINT16>(-1) - 10; |
45 | |
46 | // Information gathered by the class loader relating to generics |
47 | // Fields in this structure are initialized very early in class loading |
48 | // See code:ClassLoader.CreateTypeHandleForTypeDefThrowing |
49 | struct bmtGenericsInfo |
50 | { |
51 | SigTypeContext typeContext; // Type context used for metadata parsing |
52 | WORD numDicts; // Number of dictionaries including this class |
53 | BYTE *pVarianceInfo; // Variance annotations on type parameters, NULL if none specified |
54 | BOOL fTypicalInstantiation; // TRUE if this is generic type definition |
55 | BOOL fSharedByGenericInstantiations; // TRUE if this is canonical type shared by instantiations |
56 | BOOL fContainsGenericVariables; // TRUE if this is an open type |
57 | |
58 | inline bmtGenericsInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
59 | inline DWORD GetNumGenericArgs() const { LIMITED_METHOD_CONTRACT; return typeContext.m_classInst.GetNumArgs(); } |
60 | inline BOOL HasInstantiation() const { LIMITED_METHOD_CONTRACT; return typeContext.m_classInst.GetNumArgs() != 0; } |
61 | inline BOOL IsTypicalTypeDefinition() const { LIMITED_METHOD_CONTRACT; return !HasInstantiation() || fTypicalInstantiation; } |
62 | |
63 | inline Instantiation GetInstantiation() const |
64 | { |
65 | LIMITED_METHOD_CONTRACT; |
66 | return typeContext.m_classInst; |
67 | } |
68 | |
69 | #ifdef _DEBUG |
70 | // Typical instantiation (= open type). Non-NULL only when loading any non-typical instantiation. |
71 | // NULL if 'this' is a typical instantiation or a non-generic type. |
72 | MethodTable * dbg_pTypicalInstantiationMT; |
73 | |
74 | inline MethodTable * Debug_GetTypicalMethodTable() const |
75 | { |
76 | LIMITED_METHOD_CONTRACT; |
77 | return dbg_pTypicalInstantiationMT; |
78 | } |
79 | #endif //_DEBUG |
80 | }; // struct bmtGenericsInfo |
81 | |
82 | MethodTableBuilder( |
83 | MethodTable * pHalfBakedMT, |
84 | EEClass * pHalfBakedClass, |
85 | StackingAllocator * pStackingAllocator, |
86 | AllocMemTracker * pAllocMemTracker) |
87 | : m_pHalfBakedClass(pHalfBakedClass), |
88 | m_pHalfBakedMT(pHalfBakedMT), |
89 | m_pStackingAllocator(pStackingAllocator), |
90 | m_pAllocMemTracker(pAllocMemTracker) |
91 | { |
92 | LIMITED_METHOD_CONTRACT; |
93 | SetBMTData( |
94 | NULL, |
95 | NULL, |
96 | NULL, |
97 | NULL, |
98 | NULL, |
99 | NULL, |
100 | NULL, |
101 | NULL, |
102 | NULL, |
103 | NULL, |
104 | NULL, |
105 | NULL, |
106 | NULL, |
107 | NULL, |
108 | NULL); |
109 | } |
110 | public: |
111 | //========================================================================== |
112 | // This function is very specific about how it constructs a EEClass. |
113 | //========================================================================== |
114 | static EEClass * CreateClass(Module *pModule, |
115 | mdTypeDef cl, |
116 | BOOL fHasLayout, |
117 | BOOL fDelegate, |
118 | BOOL fIsEnum, |
119 | const bmtGenericsInfo *bmtGenericsInfo, |
120 | LoaderAllocator *pAllocator, |
121 | AllocMemTracker *pamTracker); |
122 | |
123 | static void GatherGenericsInfo(Module *pModule, |
124 | mdTypeDef cl, |
125 | Instantiation inst, |
126 | bmtGenericsInfo *bmtGenericsInfo); |
127 | |
128 | MethodTable * |
129 | BuildMethodTableThrowing( |
130 | LoaderAllocator * pAllocator, |
131 | Module * pLoaderModule, |
132 | Module * pModule, |
133 | mdToken cl, |
134 | BuildingInterfaceInfo_t * pBuildingInterfaceList, |
135 | const LayoutRawFieldInfo * pLayoutRawFieldInfos, |
136 | MethodTable * pParentMethodTable, |
137 | const bmtGenericsInfo * bmtGenericsInfo, |
138 | SigPointer parentInst, |
139 | WORD wNumInterfaces); |
140 | |
141 | LPCWSTR GetPathForErrorMessages(); |
142 | |
143 | BOOL ChangesImplementationOfVirtualSlot(SLOT_INDEX idx); |
144 | |
145 | private: |
146 | enum METHOD_IMPL_TYPE |
147 | { |
148 | METHOD_IMPL_NOT, |
149 | METHOD_IMPL |
150 | }; |
151 | |
152 | enum METHOD_TYPE |
153 | { |
154 | // The values of the enum are in sync with MethodClassification. |
155 | // GetMethodClassification depends on this |
156 | METHOD_TYPE_NORMAL = 0, |
157 | METHOD_TYPE_FCALL = 1, |
158 | METHOD_TYPE_NDIRECT = 2, |
159 | METHOD_TYPE_EEIMPL = 3, |
160 | METHOD_TYPE_INSTANTIATED = 5, |
161 | #ifdef FEATURE_COMINTEROP |
162 | METHOD_TYPE_COMINTEROP = 6, |
163 | #endif |
164 | }; |
165 | |
166 | private: |
167 | // Determine if this is the special SIMD type System.Numerics.Vector<T>, and set its size. |
168 | BOOL CheckIfSIMDAndUpdateSize(); |
169 | |
170 | // <NICE> Get rid of this.</NICE> |
171 | PTR_EEClass m_pHalfBakedClass; |
172 | PTR_MethodTable m_pHalfBakedMT; |
173 | |
174 | // GetHalfBakedClass: The EEClass you get back from this function may not have all its fields filled in yet. |
175 | // Thus you have to make sure that the relevant item which you are accessing has |
176 | // been correctly initialized in the EEClass/MethodTable construction sequence |
177 | // at the point at which you access it. |
178 | // |
179 | // Gradually we will move the code to a model where the process of constructing an EEClass/MethodTable |
180 | // is more obviously correct, e.g. by relying much less on reading information using GetHalfBakedClass |
181 | // and GetHalfBakedMethodTable. |
182 | // |
183 | // <NICE> Get rid of this.</NICE> |
184 | PTR_EEClass GetHalfBakedClass() { LIMITED_METHOD_CONTRACT; return m_pHalfBakedClass; } |
185 | PTR_MethodTable GetHalfBakedMethodTable() { LIMITED_METHOD_CONTRACT; return m_pHalfBakedMT; } |
186 | |
187 | // <NOTE> The following functions are used during MethodTable construction to access/set information about the type being constructed. |
188 | // Beware that some of the fields of the underlying EEClass/MethodTable being constructed may not |
189 | // be initialized. Because of this, ideally the code will gradually be cleaned up so that |
190 | // none of these functions are used and instead we use the data in the bmt structures below |
191 | // or we explicitly pass around the data as arguments. </NOTE> |
192 | // |
193 | // <NICE> Get rid of all of these.</NICE> |
194 | mdTypeDef GetCl() { WRAPPER_NO_CONTRACT; return bmtInternal->pType->GetTypeDefToken(); } |
195 | BOOL IsGlobalClass() { WRAPPER_NO_CONTRACT; return GetCl() == COR_GLOBAL_PARENT_TOKEN; } |
196 | DWORD GetAttrClass() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetAttrClass(); } |
197 | WORD GetNumHandleRegularStatics() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetNumHandleRegularStatics(); } |
198 | WORD GetNumHandleThreadStatics() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetNumHandleThreadStatics(); } |
199 | WORD GetNumStaticFields() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetNumStaticFields(); } |
200 | WORD GetNumInstanceFields() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetNumInstanceFields(); } |
201 | BOOL IsInterface() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsInterface(); } |
202 | BOOL HasOverLayedField() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasOverLayedField(); } |
203 | BOOL IsComImport() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsComImport(); } |
204 | #ifdef FEATURE_COMINTEROP |
205 | void SetIsComClassInterface() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetIsComClassInterface(); } |
206 | #endif // FEATURE_COMINTEROP |
207 | BOOL IsEnum() { WRAPPER_NO_CONTRACT; return bmtProp->fIsEnum; } |
208 | BOOL HasNonPublicFields() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasNonPublicFields(); } |
209 | BOOL IsValueClass() { WRAPPER_NO_CONTRACT; return bmtProp->fIsValueClass; } |
210 | BOOL IsUnsafeValueClass() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsUnsafeValueClass(); } |
211 | BOOL IsAbstract() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsAbstract(); } |
212 | BOOL HasLayout() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasLayout(); } |
213 | BOOL IsDelegate() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsDelegate(); } |
214 | BOOL IsNested() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsNested(); } |
215 | BOOL HasFieldsWhichMustBeInited() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasFieldsWhichMustBeInited(); } |
216 | BOOL IsBlittable() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsBlittable(); } |
217 | PTR_MethodDescChunk GetChunks() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetChunks(); } |
218 | BOOL HasExplicitFieldOffsetLayout() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasExplicitFieldOffsetLayout(); } |
219 | BOOL IsManagedSequential() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsManagedSequential(); } |
220 | BOOL HasExplicitSize() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasExplicitSize(); } |
221 | |
222 | #ifdef _DEBUG |
223 | LPCUTF8 GetDebugClassName() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetDebugClassName(); } |
224 | #endif // _DEBUG |
225 | Assembly *GetAssembly() { WRAPPER_NO_CONTRACT; return GetModule()->GetAssembly(); } |
226 | Module *GetModule() { WRAPPER_NO_CONTRACT; return bmtInternal->pModule; } |
227 | ClassLoader *GetClassLoader() { WRAPPER_NO_CONTRACT; return GetModule()->GetClassLoader(); } |
228 | IMDInternalImport* GetMDImport() { WRAPPER_NO_CONTRACT; return bmtInternal->pInternalImport; } |
229 | FieldDesc *GetApproxFieldDescListRaw() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetFieldDescList(); } |
230 | EEClassLayoutInfo *GetLayoutInfo() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetLayoutInfo(); } |
231 | |
232 | // <NOTE> The following functions are used during MethodTable construction to setup information |
233 | // about the type being constructed in particular information stored in the EEClass. |
234 | // USE WITH CAUTION!! TRY NOT TO ADD MORE OF THESE!! </NOTE> |
235 | // |
236 | // <NICE> Get rid of all of these - we should be able to evaluate these conditions BEFORE |
237 | // we create the EEClass object, and thus set the flags immediately at the point |
238 | // we create that object.</NICE> |
239 | void SetUnsafeValueClass() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetUnsafeValueClass(); } |
240 | void SetCannotBeBlittedByObjectCloner() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetCannotBeBlittedByObjectCloner(); } |
241 | void SetHasFieldsWhichMustBeInited() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetHasFieldsWhichMustBeInited(); } |
242 | void SetHasNonPublicFields() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetHasNonPublicFields(); } |
243 | void SetModuleDynamicID(DWORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetModuleDynamicID(x); } |
244 | void SetNumHandleRegularStatics(WORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNumHandleRegularStatics(x); } |
245 | void SetNumHandleThreadStatics(WORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNumHandleThreadStatics(x); } |
246 | void SetNumBoxedRegularStatics(WORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNumBoxedRegularStatics(x); } |
247 | void SetNumBoxedThreadStatics(WORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNumBoxedThreadStatics(x); } |
248 | void SetAlign8Candidate() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetAlign8Candidate(); } |
249 | void SetHasOverLayedFields() { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetHasOverLayedFields(); } |
250 | void SetNonGCRegularStaticFieldBytes(DWORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNonGCRegularStaticFieldBytes(x); } |
251 | void SetNonGCThreadStaticFieldBytes(DWORD x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetNonGCThreadStaticFieldBytes(x); } |
252 | #ifdef _DEBUG |
253 | void SetDebugClassName(LPUTF8 x) { WRAPPER_NO_CONTRACT; GetHalfBakedClass()->SetDebugClassName(x); } |
254 | #endif |
255 | |
256 | // Must be called prior to setting the value of any optional field on EEClass (on a debug build an assert |
257 | // will fire if this invariant is violated). |
258 | static void EnsureOptionalFieldsAreAllocated(EEClass *pClass, AllocMemTracker *pamTracker, LoaderHeap *pHeap); |
259 | |
260 | /************************************ |
261 | * PRIVATE INTERNAL STRUCTS |
262 | ************************************/ |
263 | private: |
264 | //The following structs are used in buildmethodtable |
265 | // The 'bmt' in front of each struct reminds us these are for MethodTableBuilder |
266 | |
267 | // -------------------------------------------------------------------------------------------- |
268 | struct bmtErrorInfo |
269 | { |
270 | UINT resIDWhy; |
271 | LPCUTF8 szMethodNameForError; |
272 | mdToken dMethodDefInError; |
273 | Module* pModule; |
274 | mdTypeDef cl; |
275 | OBJECTREF *pThrowable; |
276 | |
277 | // Set the reason and the offending method def. If the method information |
278 | // is not from this class set the method name and it will override the method def. |
279 | inline bmtErrorInfo() |
280 | : resIDWhy(0), |
281 | szMethodNameForError(NULL), |
282 | dMethodDefInError(mdMethodDefNil), |
283 | pThrowable(NULL) |
284 | { LIMITED_METHOD_CONTRACT; } |
285 | }; |
286 | |
287 | // -------------------------------------------------------------------------------------------- |
288 | class bmtRTType |
289 | { |
290 | public: |
291 | //----------------------------------------------------------------------------------------- |
292 | // Note that the immediate substitution is copied, but this assumes that |
293 | // the remaining substitutions in the chain are in a stable memory location |
294 | // for the lifetime of this object. |
295 | bmtRTType( |
296 | const Substitution & subst, |
297 | MethodTable * pMT) |
298 | : m_subst(subst), |
299 | m_pMT(pMT), |
300 | m_pParent(NULL) |
301 | { LIMITED_METHOD_CONTRACT; } |
302 | |
303 | //----------------------------------------------------------------------------------------- |
304 | // Returns the parent type. Takes advantage of the fact that an RT type will |
305 | // have only RT types as parents. I don't anticipate this changing. |
306 | bmtRTType * |
307 | GetParentType() const |
308 | { LIMITED_METHOD_CONTRACT; return m_pParent; } |
309 | |
310 | //----------------------------------------------------------------------------------------- |
311 | // Sets the parent type. Used during construction of the type chain, due |
312 | // to the fact that types point up the chain but substitutions point down. |
313 | void |
314 | SetParentType( |
315 | bmtRTType * pParentType) |
316 | { LIMITED_METHOD_CONTRACT; m_pParent = pParentType; } |
317 | |
318 | //----------------------------------------------------------------------------------------- |
319 | bool |
320 | IsNested() const |
321 | { LIMITED_METHOD_CONTRACT; return GetMethodTable()->GetClass()->IsNested() != FALSE; } |
322 | |
323 | //----------------------------------------------------------------------------------------- |
324 | mdTypeDef |
325 | GetEnclosingTypeToken() const; |
326 | |
327 | //----------------------------------------------------------------------------------------- |
328 | // Reference to the substitution for this type. Substitutions are linked |
329 | // inline with the type chain; this is more efficient than creating an |
330 | // entire type chain for each parent type and also keeps the type and |
331 | // substitution tightly coupled for easier use. |
332 | const Substitution & |
333 | GetSubstitution() const |
334 | { LIMITED_METHOD_CONTRACT; return m_subst; } |
335 | |
336 | //----------------------------------------------------------------------------------------- |
337 | // Changes type's substitution - used for interface map building. |
338 | void |
339 | SetSubstitution(const Substitution & subst) |
340 | { |
341 | LIMITED_METHOD_CONTRACT; |
342 | m_subst = subst; |
343 | } |
344 | |
345 | //----------------------------------------------------------------------------------------- |
346 | // Returns the runtime Module that owns this type. |
347 | Module * |
348 | GetModule() const |
349 | { WRAPPER_NO_CONTRACT; return GetMethodTable()->GetModule(); } |
350 | |
351 | //----------------------------------------------------------------------------------------- |
352 | // Returns the runtime MethodTable for the type. |
353 | MethodTable * |
354 | GetMethodTable() const |
355 | { LIMITED_METHOD_CONTRACT; return m_pMT; } |
356 | |
357 | //----------------------------------------------------------------------------------------- |
358 | // Returns the metadata token for this type. |
359 | mdTypeDef |
360 | GetTypeDefToken() const |
361 | { WRAPPER_NO_CONTRACT; return GetMethodTable()->GetCl();} |
362 | |
363 | //----------------------------------------------------------------------------------------- |
364 | // Returns the metadata attributes for this type. |
365 | DWORD |
366 | GetAttrs() const |
367 | { WRAPPER_NO_CONTRACT; return GetMethodTable()->GetClass()->GetAttrClass(); } |
368 | |
369 | //----------------------------------------------------------------------------------------- |
370 | // true if the type is an interface; false otherwise. |
371 | bool |
372 | IsInterface() const |
373 | { WRAPPER_NO_CONTRACT; return GetMethodTable()->IsInterface() != FALSE; } |
374 | |
375 | //----------------------------------------------------------------------------------------- |
376 | // Helper function to find a type associated with pTargetMT in the |
377 | // chain pointed to by pType. |
378 | static |
379 | bmtRTType * |
380 | FindType( |
381 | bmtRTType * pType, |
382 | MethodTable * pTargetMT); |
383 | |
384 | private: |
385 | //----------------------------------------------------------------------------------------- |
386 | Substitution m_subst; |
387 | MethodTable * m_pMT; |
388 | bmtRTType * m_pParent; |
389 | }; // class bmtRTType |
390 | |
391 | // -------------------------------------------------------------------------------------------- |
392 | // This creates a chain of bmtRTType objects representing pMT and all of pMT's parent types. |
393 | bmtRTType * |
394 | CreateTypeChain( |
395 | MethodTable * pMT, |
396 | const Substitution & subst); |
397 | |
398 | // -------------------------------------------------------------------------------------------- |
399 | class bmtMDType |
400 | { |
401 | public: |
402 | //----------------------------------------------------------------------------------------- |
403 | bmtMDType( |
404 | bmtRTType * pParentType, |
405 | Module * pModule, |
406 | mdTypeDef tok, |
407 | const SigTypeContext & sigContext); |
408 | |
409 | //----------------------------------------------------------------------------------------- |
410 | // Returns the parent type. This takes advantage of teh fact that an MD type |
411 | // will always have an RT type as a parent. This could change, at which point |
412 | // it would have to return a bmtTypeHandle. |
413 | bmtRTType * |
414 | GetParentType() const |
415 | { LIMITED_METHOD_CONTRACT; return m_pParentType; } |
416 | |
417 | //----------------------------------------------------------------------------------------- |
418 | // Used during construction of the type chain, due to the fact that types point |
419 | // up the chain but substitutions point down. |
420 | void |
421 | SetParentType( |
422 | bmtRTType * pParentType) |
423 | { LIMITED_METHOD_CONTRACT; m_pParentType = pParentType; } |
424 | |
425 | //----------------------------------------------------------------------------------------- |
426 | bool |
427 | IsNested() const |
428 | { LIMITED_METHOD_CONTRACT; return m_enclTok != mdTypeDefNil; } |
429 | |
430 | //----------------------------------------------------------------------------------------- |
431 | mdTypeDef |
432 | GetEnclosingTypeToken() const |
433 | { LIMITED_METHOD_CONTRACT; return m_enclTok; } |
434 | |
435 | //----------------------------------------------------------------------------------------- |
436 | // Returns a reference to the substitution. Currently, no substitution exists |
437 | // for the type being built, but it adds uniformity to the types and so a NULL |
438 | // substitution is created. |
439 | const Substitution & |
440 | GetSubstitution() const |
441 | { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(m_subst.GetModule() == NULL); return m_subst; } |
442 | |
443 | //----------------------------------------------------------------------------------------- |
444 | // Returns the runtime Module that owns this type. |
445 | Module * |
446 | GetModule() const |
447 | { LIMITED_METHOD_CONTRACT; return m_pModule; } |
448 | |
449 | //----------------------------------------------------------------------------------------- |
450 | // Returns the MethodTable for the type. This is null until the very end |
451 | // of BuildMethodTableThrowing when the MethodTable for this type is finally |
452 | // created in SetupMethodTable2. |
453 | MethodTable * |
454 | GetMethodTable() const |
455 | { LIMITED_METHOD_CONTRACT; return m_pMT; } |
456 | |
457 | //----------------------------------------------------------------------------------------- |
458 | // Returns the token for the type. |
459 | mdTypeDef |
460 | GetTypeDefToken() const |
461 | { LIMITED_METHOD_CONTRACT; return m_tok;} |
462 | |
463 | //----------------------------------------------------------------------------------------- |
464 | // Returns the metadata attributes for the type. |
465 | DWORD |
466 | GetAttrs() const |
467 | { WRAPPER_NO_CONTRACT; return m_dwAttrs; } |
468 | |
469 | //----------------------------------------------------------------------------------------- |
470 | // true if the type is an interface; false otherwise. |
471 | bool |
472 | IsInterface() const |
473 | { WRAPPER_NO_CONTRACT; return IsTdInterface(GetAttrs()); } |
474 | |
475 | private: |
476 | //----------------------------------------------------------------------------------------- |
477 | bmtRTType * m_pParentType; |
478 | Module * m_pModule; |
479 | mdTypeDef m_tok; |
480 | mdTypeDef m_enclTok; |
481 | SigTypeContext m_sigContext; |
482 | Substitution m_subst; |
483 | DWORD m_dwAttrs; |
484 | |
485 | MethodTable * m_pMT; |
486 | }; // class bmtMDType |
487 | |
488 | // -------------------------------------------------------------------------------------------- |
489 | // This is similar to the known and loved TypeHandle class, but tailored for use during |
490 | // type building. It allows for homogeneous collections of heterogeneous implementations. |
491 | // Currently, it knows the difference between a bmtRTType and a bmtMDType and will |
492 | // forward method calls such as GetModule, GetParentType and more to the appropriate |
493 | // target. |
494 | class bmtTypeHandle |
495 | { |
496 | public: |
497 | //----------------------------------------------------------------------------------------- |
498 | // Creates a type handle for a bmtRTType pointer. For ease of use, this conversion |
499 | // constructor is not declared as explicit. |
500 | bmtTypeHandle( |
501 | bmtRTType * pRTType) |
502 | : m_handle(HandleFromRTType(pRTType)) |
503 | { NOT_DEBUG(static_assert_no_msg(sizeof(bmtTypeHandle) == sizeof(UINT_PTR));) INDEBUG(m_pAsRTType = pRTType;) } |
504 | |
505 | //----------------------------------------------------------------------------------------- |
506 | // Creates a type handle for a bmtMDType pointer. For ease of use, this conversion |
507 | // constructor is not declared as explicit. |
508 | bmtTypeHandle( |
509 | bmtMDType * pMDType) |
510 | : m_handle(HandleFromMDType(pMDType)) |
511 | { NOT_DEBUG(static_assert_no_msg(sizeof(bmtTypeHandle) == sizeof(UINT_PTR));) INDEBUG(m_pAsMDType = pMDType;) } |
512 | |
513 | //----------------------------------------------------------------------------------------- |
514 | // Copy constructor. |
515 | bmtTypeHandle( |
516 | const bmtTypeHandle &other) |
517 | { LIMITED_METHOD_CONTRACT; m_handle = other.m_handle; INDEBUG(m_pAsRTType = other.m_pAsRTType;) } |
518 | |
519 | //----------------------------------------------------------------------------------------- |
520 | // Default, null constructor. |
521 | bmtTypeHandle() |
522 | { LIMITED_METHOD_CONTRACT; m_handle = 0; INDEBUG(m_pAsRTType = NULL;) } |
523 | |
524 | //----------------------------------------------------------------------------------------- |
525 | // Assignment operator |
526 | bmtTypeHandle & |
527 | operator=( |
528 | const bmtTypeHandle &rhs) |
529 | { LIMITED_METHOD_CONTRACT; m_handle = rhs.m_handle; INDEBUG(m_pAsRTType = rhs.m_pAsRTType;) return *this; } |
530 | |
531 | //----------------------------------------------------------------------------------------- |
532 | // Returns true if null (constructed using default ctor, or assigned from one); otherwise false. |
533 | bool |
534 | IsNull() const |
535 | { LIMITED_METHOD_CONTRACT; return m_handle == 0; } |
536 | |
537 | //----------------------------------------------------------------------------------------- |
538 | // Returns true if this handle contains a bmtRTType pointer; otherwise returns false. |
539 | bool |
540 | IsRTType() const |
541 | { LIMITED_METHOD_CONTRACT; return (m_handle & RTTYPE_FLAG) != 0; } |
542 | |
543 | //----------------------------------------------------------------------------------------- |
544 | // Returns true if this handle contains a bmtMDType pointer; otherwise returns false. |
545 | bool |
546 | IsMDType() const |
547 | { LIMITED_METHOD_CONTRACT; return (m_handle & MDTYPE_FLAG) != 0; } |
548 | |
549 | //----------------------------------------------------------------------------------------- |
550 | // Returns pointer to bmtRTType. IsRTType is required |
551 | // to return true before calling this method. |
552 | bmtRTType * |
553 | AsRTType() const |
554 | { |
555 | WRAPPER_NO_CONTRACT; |
556 | CONSISTENCY_CHECK(IsRTType()); |
557 | return (bmtRTType *) Decode(m_handle); |
558 | } |
559 | |
560 | //----------------------------------------------------------------------------------------- |
561 | // Returns pointer to bmtMDType. IsMDType is required |
562 | // to return true before calling this method. |
563 | bmtMDType * |
564 | AsMDType() const |
565 | { |
566 | WRAPPER_NO_CONTRACT; |
567 | CONSISTENCY_CHECK(IsMDType()); |
568 | return (bmtMDType *) Decode(m_handle); |
569 | } |
570 | |
571 | //----------------------------------------------------------------------------------------- |
572 | // Returns the parent type handle, or the null type handle if no parent exists. |
573 | bmtTypeHandle |
574 | GetParentType() const; |
575 | |
576 | //----------------------------------------------------------------------------------------- |
577 | bool |
578 | IsNested() const; |
579 | |
580 | //----------------------------------------------------------------------------------------- |
581 | mdTypeDef |
582 | GetEnclosingTypeToken() const; |
583 | |
584 | //----------------------------------------------------------------------------------------- |
585 | // Returns the runtime Module* for this type. |
586 | Module * |
587 | GetModule() const; |
588 | |
589 | //----------------------------------------------------------------------------------------- |
590 | // Returns the token for the type. |
591 | mdTypeDef |
592 | GetTypeDefToken() const; |
593 | |
594 | //----------------------------------------------------------------------------------------- |
595 | // Returns reference to the substitution for this type. |
596 | const Substitution & |
597 | GetSubstitution() const; |
598 | |
599 | //----------------------------------------------------------------------------------------- |
600 | // Returns the MethodTable* for the type. |
601 | MethodTable * |
602 | GetMethodTable() const; |
603 | |
604 | //----------------------------------------------------------------------------------------- |
605 | // Returns the metadata attributes for the type. |
606 | DWORD |
607 | GetAttrs() const; |
608 | |
609 | //----------------------------------------------------------------------------------------- |
610 | // Returns true if this type is an interface; returns false otherwise. |
611 | bool |
612 | IsInterface() const; |
613 | |
614 | //----------------------------------------------------------------------------------------- |
615 | static bool |
616 | Equal( |
617 | const bmtTypeHandle &lhs, |
618 | const bmtTypeHandle &rhs) |
619 | { |
620 | return lhs.m_handle == rhs.m_handle; |
621 | } |
622 | |
623 | protected: |
624 | //----------------------------------------------------------------------------------------- |
625 | static const UINT_PTR RTTYPE_FLAG = 0x1; |
626 | static const UINT_PTR MDTYPE_FLAG = 0x2; |
627 | static const UINT_PTR MASK_FLAG = 0x3; |
628 | |
629 | //----------------------------------------------------------------------------------------- |
630 | // Takes a pointer and encodes it with the flag. |
631 | static UINT_PTR |
632 | Encode( |
633 | LPVOID pv, |
634 | UINT_PTR flag) |
635 | { |
636 | LIMITED_METHOD_CONTRACT; |
637 | CONSISTENCY_CHECK((reinterpret_cast<UINT_PTR>(pv) & MASK_FLAG) == 0); |
638 | return (reinterpret_cast<UINT_PTR>(pv) | flag); |
639 | } |
640 | |
641 | //----------------------------------------------------------------------------------------- |
642 | // Takes an encoded handle and removes encoding bits. |
643 | static LPVOID |
644 | Decode( |
645 | UINT_PTR handle) |
646 | { LIMITED_METHOD_CONTRACT; return reinterpret_cast<LPVOID>(handle & ~MASK_FLAG); } |
647 | |
648 | //----------------------------------------------------------------------------------------- |
649 | // Uses encode to produce a handle for a bmtRTType* |
650 | static UINT_PTR |
651 | HandleFromRTType( |
652 | bmtRTType * pRTType) |
653 | { WRAPPER_NO_CONTRACT; return Encode(pRTType, RTTYPE_FLAG); } |
654 | |
655 | //----------------------------------------------------------------------------------------- |
656 | // Uses encode to produce a handle for a bmtMDType* |
657 | static UINT_PTR |
658 | HandleFromMDType( |
659 | bmtMDType * pMDType) |
660 | { WRAPPER_NO_CONTRACT; return Encode(pMDType, MDTYPE_FLAG); } |
661 | |
662 | //----------------------------------------------------------------------------------------- |
663 | UINT_PTR m_handle; |
664 | |
665 | #ifdef _DEBUG |
666 | //----------------------------------------------------------------------------------------- |
667 | // Used in debug builds to quickly access the type in a debugger. |
668 | union |
669 | { |
670 | bmtRTType * m_pAsRTType; |
671 | bmtMDType * m_pAsMDType; |
672 | }; |
673 | #endif |
674 | }; // class bmtTypeHandle |
675 | |
676 | // -------------------------------------------------------------------------------------------- |
677 | // MethodSignature encapsulates the name and metadata signature of a method, as well as |
678 | // the scope (Module*) and substitution for the signature. It is intended to facilitate |
679 | // passing around this tuple of information as well as providing efficient comparison |
680 | // operations when looking for types. |
681 | // |
682 | // Meant to be passed around by reference or by value. Please make sure this is declared |
683 | // on the stack or properly deleted after use. |
684 | |
685 | class MethodSignature |
686 | { |
687 | public: |
688 | //----------------------------------------------------------------------------------------- |
689 | // This is the constructor usually used, and is typically contained inside a |
690 | // bmtMDMethod or bmtRTMethod. |
691 | MethodSignature( |
692 | Module * pModule, |
693 | mdToken tok, |
694 | const Substitution * pSubst) |
695 | : m_pModule(pModule), |
696 | m_tok(tok), |
697 | m_szName(NULL), |
698 | m_pSig(NULL), |
699 | m_cSig(0), |
700 | m_pSubst(pSubst), |
701 | m_nameHash(INVALID_NAME_HASH) |
702 | { |
703 | CONTRACTL { |
704 | PRECONDITION(CheckPointer(pModule)); |
705 | PRECONDITION(TypeFromToken(tok) == mdtMethodDef || |
706 | TypeFromToken(tok) == mdtMemberRef); |
707 | } CONTRACTL_END; |
708 | INDEBUG(CheckGetMethodAttributes();) |
709 | } |
710 | |
711 | //----------------------------------------------------------------------------------------- |
712 | // This constructor can be used with hard-coded signatures that are used for |
713 | // locating .ctor and .cctor methods. |
714 | MethodSignature( |
715 | Module * pModule, |
716 | LPCUTF8 szName, |
717 | PCCOR_SIGNATURE pSig, |
718 | size_t cSig, |
719 | const Substitution * pSubst = NULL) |
720 | : m_pModule(pModule), |
721 | m_tok(mdTokenNil), |
722 | m_szName(szName), |
723 | m_pSig(pSig), |
724 | m_cSig(cSig), |
725 | m_pSubst(pSubst), |
726 | m_nameHash(INVALID_NAME_HASH) |
727 | { |
728 | CONTRACTL { |
729 | PRECONDITION(CheckPointer(pModule)); |
730 | PRECONDITION(CheckPointer(szName)); |
731 | PRECONDITION(CheckPointer(pSig)); |
732 | PRECONDITION(cSig != 0); |
733 | } CONTRACTL_END; |
734 | } |
735 | |
736 | //----------------------------------------------------------------------------------------- |
737 | // Copy constructor. |
738 | MethodSignature( |
739 | const MethodSignature & s) |
740 | : m_pModule(s.m_pModule), |
741 | m_tok(s.m_tok), |
742 | m_szName(s.m_szName), |
743 | m_pSig(s.m_pSig), |
744 | m_cSig(s.m_cSig), |
745 | m_pSubst(s.m_pSubst), |
746 | m_nameHash(s.m_nameHash) |
747 | { } |
748 | |
749 | //----------------------------------------------------------------------------------------- |
750 | // Returns the module that is the scope within which the signature itself lives. |
751 | Module * |
752 | GetModule() const |
753 | { LIMITED_METHOD_CONTRACT; return m_pModule; } |
754 | |
755 | //----------------------------------------------------------------------------------------- |
756 | // Returns the signature token. Note that this can be mdTokenNil if the second |
757 | // constructor above is used. |
758 | mdToken |
759 | GetToken() const |
760 | { LIMITED_METHOD_CONTRACT; return m_tok; } |
761 | |
762 | //----------------------------------------------------------------------------------------- |
763 | // Returns the name of the method. |
764 | inline LPCUTF8 |
765 | GetName() const |
766 | { WRAPPER_NO_CONTRACT; CheckGetMethodAttributes(); return m_szName; } |
767 | |
768 | //----------------------------------------------------------------------------------------- |
769 | // Returns the metadata signature for the method. |
770 | inline PCCOR_SIGNATURE |
771 | GetSignature() const |
772 | { WRAPPER_NO_CONTRACT; CheckGetMethodAttributes(); return m_pSig; } |
773 | |
774 | //----------------------------------------------------------------------------------------- |
775 | // Returns the signature length. |
776 | inline size_t |
777 | GetSignatureLength() const |
778 | { WRAPPER_NO_CONTRACT; CheckGetMethodAttributes(); return m_cSig; } |
779 | |
780 | //----------------------------------------------------------------------------------------- |
781 | // Returns the substitution to be used in interpreting the signature. |
782 | const Substitution & |
783 | GetSubstitution() const |
784 | { return *m_pSubst; } |
785 | |
786 | //----------------------------------------------------------------------------------------- |
787 | // Returns true if the names are equal; otherwise returns false. This is a |
788 | // case-sensitive comparison. |
789 | static bool |
790 | NamesEqual( |
791 | const MethodSignature & sig1, |
792 | const MethodSignature & sig2); |
793 | |
794 | //----------------------------------------------------------------------------------------- |
795 | // Returns true if the metadata signatures (PCCOR_SIGNATURE) are equivalent. (Type equivalence permitted) |
796 | static bool |
797 | SignaturesEquivalent( |
798 | const MethodSignature & sig1, |
799 | const MethodSignature & sig2); |
800 | |
801 | //----------------------------------------------------------------------------------------- |
802 | // Returns true if the metadata signatures (PCCOR_SIGNATURE) are exactly equal. (No type equivalence permitted) |
803 | static bool |
804 | SignaturesExactlyEqual( |
805 | const MethodSignature & sig1, |
806 | const MethodSignature & sig2); |
807 | //----------------------------------------------------------------------------------------- |
808 | // This is a combined name and sig comparison. Semantically equivalent to |
809 | // "NamesEqual(*this, rhs) && SignaturesEquivalent(*this, rhs)". |
810 | bool |
811 | Equivalent( |
812 | const MethodSignature &rhs) const; |
813 | |
814 | //----------------------------------------------------------------------------------------- |
815 | // This is a combined name and sig comparison. Semantically equivalent to |
816 | // "NamesEqual(*this, rhs) && SignaturesExactlyEqual(*this, rhs)". |
817 | bool |
818 | ExactlyEqual( |
819 | const MethodSignature &rhs) const; |
820 | |
821 | //----------------------------------------------------------------------------------------- |
822 | // Conversion operator to Module*. This should possibly be removed. |
823 | operator Module *() const |
824 | { return GetModule(); } |
825 | |
826 | //----------------------------------------------------------------------------------------- |
827 | // Conversion operator to LPCUTF8, returning name. This should possibly be removed. |
828 | operator LPCUTF8() const |
829 | { return GetName(); } |
830 | |
831 | //----------------------------------------------------------------------------------------- |
832 | // Conversion operator to PCCOR_SIGNATURE. This should possibly be removed. |
833 | operator PCCOR_SIGNATURE() const |
834 | { return GetSignature(); } |
835 | |
836 | protected: |
837 | //----------------------------------------------------------------------------------------- |
838 | Module * m_pModule; |
839 | mdToken m_tok; |
840 | mutable LPCUTF8 m_szName; // mutable because it is lazily evaluated. |
841 | mutable PCCOR_SIGNATURE m_pSig; // mutable because it is lazily evaluated. |
842 | mutable size_t m_cSig; // mutable because it is lazily evaluated. |
843 | const Substitution * m_pSubst; |
844 | |
845 | static const ULONG INVALID_NAME_HASH = static_cast<ULONG>(-1); |
846 | mutable ULONG m_nameHash; // mutable because it is lazily evaluated. |
847 | |
848 | //----------------------------------------------------------------------------------------- |
849 | inline void |
850 | CheckGetMethodAttributes() const |
851 | { |
852 | WRAPPER_NO_CONTRACT; |
853 | if (m_tok != mdTokenNil && m_szName == NULL) |
854 | { |
855 | GetMethodAttributes(); |
856 | } |
857 | } |
858 | |
859 | //----------------------------------------------------------------------------------------- |
860 | void |
861 | GetMethodAttributes() const; |
862 | |
863 | //----------------------------------------------------------------------------------------- |
864 | UINT32 |
865 | GetNameHash() const; |
866 | |
867 | private: |
868 | //----------------------------------------------------------------------------------- |
869 | // Private to prevent use. |
870 | MethodSignature * |
871 | operator&() |
872 | { return this; } |
873 | }; // class MethodSignature |
874 | |
875 | // -------------------------------------------------------------------------------------------- |
876 | class bmtRTMethod |
877 | { |
878 | public: |
879 | //----------------------------------------------------------------------------------------- |
880 | // Constructor. |
881 | bmtRTMethod( |
882 | bmtRTType * pOwningType, |
883 | MethodDesc * pMD); |
884 | |
885 | //----------------------------------------------------------------------------------------- |
886 | // Returns owning type for this method. |
887 | bmtRTType * |
888 | GetOwningType() const |
889 | { LIMITED_METHOD_CONTRACT; return m_pOwningType; } |
890 | |
891 | //----------------------------------------------------------------------------------------- |
892 | // Returns MethodDesc* for this method. |
893 | MethodDesc * |
894 | GetMethodDesc() const |
895 | { LIMITED_METHOD_CONTRACT; return m_pMD; } |
896 | |
897 | //----------------------------------------------------------------------------------------- |
898 | // Returns reference to MethodSignature object for this type. |
899 | const MethodSignature & |
900 | GetMethodSignature() const |
901 | { LIMITED_METHOD_CONTRACT; return m_methodSig; } |
902 | |
903 | //----------------------------------------------------------------------------------------- |
904 | // Returns metadata declaration attributes for this method. |
905 | DWORD |
906 | GetDeclAttrs() const; |
907 | |
908 | //----------------------------------------------------------------------------------------- |
909 | // Returns metadata implementation attributes for this method. |
910 | DWORD |
911 | GetImplAttrs() const; |
912 | |
913 | //----------------------------------------------------------------------------------------- |
914 | // Returns the slot in which this method is placed. |
915 | SLOT_INDEX |
916 | GetSlotIndex() const; |
917 | |
918 | private: |
919 | //----------------------------------------------------------------------------------------- |
920 | bmtRTType * m_pOwningType; |
921 | MethodDesc * m_pMD; |
922 | MethodSignature m_methodSig; |
923 | }; // class bmtRTMethod |
924 | |
925 | // -------------------------------------------------------------------------------------------- |
926 | // Encapsulates method data for a method described by metadata. |
927 | class bmtMDMethod |
928 | { |
929 | public: |
930 | //----------------------------------------------------------------------------------------- |
931 | // Constructor. This takes all the information already extracted from metadata interface |
932 | // because the place that creates these types already has this data. Alternatively, |
933 | // a constructor could be written to take a token and metadata scope instead. Also, |
934 | // it might be interesting to move METHOD_TYPE and METHOD_IMPL_TYPE to setter functions. |
935 | bmtMDMethod( |
936 | bmtMDType * pOwningType, |
937 | mdMethodDef tok, |
938 | DWORD dwDeclAttrs, |
939 | DWORD dwImplAttrs, |
940 | DWORD dwRVA, |
941 | METHOD_TYPE type, |
942 | METHOD_IMPL_TYPE implType); |
943 | |
944 | //----------------------------------------------------------------------------------------- |
945 | // Returns the type that owns the *declaration* of this method. This makes sure that a |
946 | // method can be properly interpreted in the context of substitutions at any time. |
947 | bmtMDType * |
948 | GetOwningType() const |
949 | { LIMITED_METHOD_CONTRACT; return m_pOwningType; } |
950 | |
951 | //----------------------------------------------------------------------------------------- |
952 | // Returns a reference to the MethodSignature for this method. |
953 | const MethodSignature & |
954 | GetMethodSignature() const |
955 | { LIMITED_METHOD_CONTRACT; return m_methodSig; } |
956 | |
957 | //----------------------------------------------------------------------------------------- |
958 | // Sets the slot that this method is assigned to. |
959 | void |
960 | SetSlotIndex(SLOT_INDEX idx); |
961 | |
962 | //----------------------------------------------------------------------------------------- |
963 | // Returns the slot that this method is assigned to. |
964 | SLOT_INDEX |
965 | GetSlotIndex() const |
966 | { LIMITED_METHOD_CONTRACT; return m_slotIndex; } |
967 | |
968 | //----------------------------------------------------------------------------------------- |
969 | // Returns the method type (normal, fcall, etc.) that this type was constructed with. |
970 | METHOD_TYPE |
971 | GetMethodType() const |
972 | { LIMITED_METHOD_CONTRACT; return m_type; } |
973 | |
974 | //----------------------------------------------------------------------------------------- |
975 | // Returns the method impl type (is or isn't) that this type was constructed with. |
976 | METHOD_IMPL_TYPE |
977 | GetMethodImplType() const |
978 | { LIMITED_METHOD_CONTRACT; return m_implType; } |
979 | |
980 | //----------------------------------------------------------------------------------------- |
981 | // Gets the MethodDesc* for this method. Defaults to NULL until SetMethodDesc is called |
982 | // with a non-NULL MethodDesc* value. |
983 | MethodDesc * |
984 | GetMethodDesc() const |
985 | { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pMD != NULL); return m_pMD; } |
986 | |
987 | //----------------------------------------------------------------------------------------- |
988 | // Once a MethodDesc* is created for this method, this method will store the association. |
989 | void |
990 | SetMethodDesc(MethodDesc * pMD) |
991 | { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pMD == NULL); m_pMD = pMD; } |
992 | |
993 | //----------------------------------------------------------------------------------------- |
994 | // Virtual slots for ValueTypes are converted to stubs which unbox the incoming boxed |
995 | // "this" argument, and forward the call to the unboxed entrypoint. |
996 | bool |
997 | IsUnboxing() |
998 | { WRAPPER_NO_CONTRACT; return GetUnboxedSlotIndex() != INVALID_SLOT_INDEX; } |
999 | |
1000 | //----------------------------------------------------------------------------------------- |
1001 | // This and SetUnboxedMethodDesc are used to indicate that this method exists as a dual |
1002 | // entrypoint method for a ValueType. |
1003 | void |
1004 | SetUnboxedSlotIndex(SLOT_INDEX idx); |
1005 | |
1006 | //----------------------------------------------------------------------------------------- |
1007 | // Returns the slot for the unboxed entrypoint. If no such slot exists, returns |
1008 | // INVALID_SLOT_INDEX. |
1009 | SLOT_INDEX |
1010 | GetUnboxedSlotIndex() const |
1011 | { LIMITED_METHOD_CONTRACT; return m_unboxedSlotIndex; } |
1012 | |
1013 | //----------------------------------------------------------------------------------------- |
1014 | // Returns the MethodDesc* for the unboxed entrypoint. If no such pointer exists, returns |
1015 | // NULL. |
1016 | MethodDesc * |
1017 | GetUnboxedMethodDesc() const |
1018 | { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pMD != NULL); return m_pUnboxedMD; } |
1019 | |
1020 | //----------------------------------------------------------------------------------------- |
1021 | // Sets the MethodDesc* for the unboxed entrypoint. |
1022 | void |
1023 | SetUnboxedMethodDesc(MethodDesc * pUnboxingMD) |
1024 | { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pUnboxedMD == NULL); m_pUnboxedMD = pUnboxingMD; } |
1025 | |
1026 | //----------------------------------------------------------------------------------------- |
1027 | // Returns the metadata declaration attributes for this method. |
1028 | DWORD |
1029 | GetDeclAttrs() const |
1030 | { LIMITED_METHOD_CONTRACT; return m_dwDeclAttrs; } |
1031 | |
1032 | //----------------------------------------------------------------------------------------- |
1033 | // Returns the metadata implementation attributes for this method. |
1034 | DWORD |
1035 | GetImplAttrs() const |
1036 | { LIMITED_METHOD_CONTRACT; return m_dwImplAttrs; } |
1037 | |
1038 | //----------------------------------------------------------------------------------------- |
1039 | // Returns the RVA for the metadata of this method. |
1040 | DWORD |
1041 | GetRVA() const |
1042 | { LIMITED_METHOD_CONTRACT; return m_dwRVA; } |
1043 | |
1044 | private: |
1045 | //----------------------------------------------------------------------------------------- |
1046 | bmtMDType * m_pOwningType; |
1047 | |
1048 | DWORD m_dwDeclAttrs; |
1049 | DWORD m_dwImplAttrs; |
1050 | DWORD m_dwRVA; |
1051 | METHOD_TYPE m_type; // Specific MethodDesc flavour |
1052 | METHOD_IMPL_TYPE m_implType; // Whether or not the method is a methodImpl body |
1053 | MethodSignature m_methodSig; |
1054 | |
1055 | MethodDesc * m_pMD; // MethodDesc created and assigned to this method |
1056 | MethodDesc * m_pUnboxedMD; // Unboxing MethodDesc if this is a virtual method on a valuetype |
1057 | SLOT_INDEX m_slotIndex; // Vtable slot number this method is assigned to |
1058 | SLOT_INDEX m_unboxedSlotIndex; |
1059 | }; // class bmtMDMethod |
1060 | |
1061 | // -------------------------------------------------------------------------------------------- |
1062 | // Provides a homogeneous view over potentially different types similar to bmtTypeHandle and |
1063 | // TypeHandle. Currently can handle |
1064 | class bmtMethodHandle |
1065 | { |
1066 | public: |
1067 | //----------------------------------------------------------------------------------------- |
1068 | // Constructor taking a bmtRTMethod*. |
1069 | bmtMethodHandle( |
1070 | bmtRTMethod * pRTMethod) |
1071 | : m_handle(HandleFromRTMethod(pRTMethod)) |
1072 | { NOT_DEBUG(static_assert_no_msg(sizeof(bmtMethodHandle) == sizeof(UINT_PTR));) INDEBUG(m_pAsRTMethod = pRTMethod;) } |
1073 | |
1074 | //----------------------------------------------------------------------------------------- |
1075 | // Constructor taking a bmtMDMethod*. |
1076 | bmtMethodHandle( |
1077 | bmtMDMethod * pMDMethod) |
1078 | : m_handle(HandleFromMDMethod(pMDMethod)) |
1079 | { NOT_DEBUG(static_assert_no_msg(sizeof(bmtMethodHandle) == sizeof(UINT_PTR));) INDEBUG(m_pAsMDMethod = pMDMethod;) } |
1080 | |
1081 | //----------------------------------------------------------------------------------------- |
1082 | // Copy constructor. |
1083 | bmtMethodHandle( |
1084 | const bmtMethodHandle &other) |
1085 | { LIMITED_METHOD_CONTRACT; m_handle = other.m_handle; INDEBUG(m_pAsRTMethod = other.m_pAsRTMethod;) } |
1086 | |
1087 | //----------------------------------------------------------------------------------------- |
1088 | // Default constructor. Handle defaults to NULL. |
1089 | bmtMethodHandle() |
1090 | { LIMITED_METHOD_CONTRACT; m_handle = 0; INDEBUG(m_pAsRTMethod = NULL;) } |
1091 | |
1092 | //----------------------------------------------------------------------------------------- |
1093 | // Assignment. |
1094 | bmtMethodHandle & |
1095 | operator=( |
1096 | const bmtMethodHandle &rhs) |
1097 | { |
1098 | LIMITED_METHOD_CONTRACT; |
1099 | m_handle = rhs.m_handle; |
1100 | INDEBUG(m_pAsRTMethod = rhs.m_pAsRTMethod;) |
1101 | return *this; |
1102 | } |
1103 | |
1104 | //----------------------------------------------------------------------------------------- |
1105 | // Returns true if default constructed or assigned to from a NULL handle. |
1106 | bool |
1107 | IsNull() const |
1108 | { LIMITED_METHOD_CONTRACT; return m_handle == 0; } |
1109 | |
1110 | //----------------------------------------------------------------------------------------- |
1111 | // Returns true if the handle points to a bmtRTMethod; returns false otherwise. |
1112 | bool |
1113 | IsRTMethod() const |
1114 | { LIMITED_METHOD_CONTRACT; return (m_handle & RTMETHOD_FLAG) != 0; } |
1115 | |
1116 | //----------------------------------------------------------------------------------------- |
1117 | // Returns true if the handle points to a bmtMDMethod; returns false otherwise. |
1118 | bool |
1119 | IsMDMethod() const |
1120 | { LIMITED_METHOD_CONTRACT; return (m_handle & MDMETHOD_FLAG) != 0; } |
1121 | |
1122 | //----------------------------------------------------------------------------------------- |
1123 | // Returns pointer to bmtRTMethod. IsRTMethod is required to return true before |
1124 | // calling this method. |
1125 | bmtRTMethod * |
1126 | AsRTMethod() const |
1127 | { |
1128 | WRAPPER_NO_CONTRACT; |
1129 | CONSISTENCY_CHECK(IsRTMethod()); |
1130 | return (bmtRTMethod *) Decode(m_handle); |
1131 | } |
1132 | |
1133 | //----------------------------------------------------------------------------------------- |
1134 | // Returns pointer to bmtMDMethod. IsMDMethod is required to return true before |
1135 | // calling this method. |
1136 | bmtMDMethod * |
1137 | AsMDMethod() const |
1138 | { |
1139 | WRAPPER_NO_CONTRACT; |
1140 | CONSISTENCY_CHECK(IsMDMethod()); |
1141 | return (bmtMDMethod *) Decode(m_handle); |
1142 | } |
1143 | |
1144 | //----------------------------------------------------------------------------------------- |
1145 | // Comparison operator. Returns true if handles point to the same object; returns |
1146 | // false otherwise. |
1147 | bool |
1148 | operator==( |
1149 | const bmtMethodHandle &rhs) const; |
1150 | |
1151 | bool operator !=(const bmtMethodHandle &rhs) const { return !((*this) == rhs); } |
1152 | |
1153 | //----------------------------------------------------------------------------------------- |
1154 | // Returns the owning type. |
1155 | bmtTypeHandle |
1156 | GetOwningType() const; |
1157 | |
1158 | //----------------------------------------------------------------------------------------- |
1159 | // Returns the metadata declaration attributes for this method. |
1160 | DWORD |
1161 | GetDeclAttrs() const; |
1162 | |
1163 | //----------------------------------------------------------------------------------------- |
1164 | // Returns the metadata implementation attributes for this method. |
1165 | DWORD |
1166 | GetImplAttrs() const; |
1167 | |
1168 | //----------------------------------------------------------------------------------------- |
1169 | // Returns the slot that this method is assigned to. |
1170 | SLOT_INDEX |
1171 | GetSlotIndex() const; |
1172 | |
1173 | //----------------------------------------------------------------------------------------- |
1174 | // Returns a reference to the MethodSignature for this method. |
1175 | const MethodSignature & |
1176 | GetMethodSignature() const; |
1177 | |
1178 | //----------------------------------------------------------------------------------------- |
1179 | // Returns the MethodDesc* associated with this method. |
1180 | MethodDesc * |
1181 | GetMethodDesc() const; |
1182 | |
1183 | protected: |
1184 | //----------------------------------------------------------------------------------------- |
1185 | static const UINT_PTR RTMETHOD_FLAG = 0x1; |
1186 | static const UINT_PTR MDMETHOD_FLAG = 0x2; |
1187 | static const UINT_PTR MASK_FLAG = 0x3; |
1188 | |
1189 | //----------------------------------------------------------------------------------------- |
1190 | // Takes a pointer and encodes it with the flag. |
1191 | static UINT_PTR |
1192 | Encode( |
1193 | LPVOID pv, |
1194 | UINT_PTR flag) |
1195 | { |
1196 | LIMITED_METHOD_CONTRACT; |
1197 | CONSISTENCY_CHECK((reinterpret_cast<UINT_PTR>(pv) & MASK_FLAG) == 0); |
1198 | return (reinterpret_cast<UINT_PTR>(pv) | flag); |
1199 | } |
1200 | |
1201 | //----------------------------------------------------------------------------------------- |
1202 | // Takes an encoded handle and removes encoding bits. |
1203 | static LPVOID |
1204 | Decode( |
1205 | UINT_PTR handle) |
1206 | { LIMITED_METHOD_CONTRACT; return reinterpret_cast<LPVOID>(handle & ~MASK_FLAG); } |
1207 | |
1208 | //----------------------------------------------------------------------------------------- |
1209 | // Uses encode to produce a handle for a bmtRTMethod* |
1210 | static UINT_PTR |
1211 | HandleFromRTMethod( |
1212 | bmtRTMethod * pRTMethod) |
1213 | { WRAPPER_NO_CONTRACT; return Encode(pRTMethod, RTMETHOD_FLAG); } |
1214 | |
1215 | //----------------------------------------------------------------------------------------- |
1216 | // Uses encode to produce a handle for a bmtMDMethod* |
1217 | static UINT_PTR |
1218 | HandleFromMDMethod( |
1219 | bmtMDMethod * pMDMethod) |
1220 | { WRAPPER_NO_CONTRACT; return Encode(pMDMethod, MDMETHOD_FLAG); } |
1221 | |
1222 | //----------------------------------------------------------------------------------------- |
1223 | // This is the value of the encoded pointer. |
1224 | UINT_PTR m_handle; |
1225 | |
1226 | #ifdef _DEBUG |
1227 | //----------------------------------------------------------------------------------------- |
1228 | // Used in debug builds to quickly access the type in a debugger. |
1229 | union |
1230 | { |
1231 | bmtRTMethod * m_pAsRTMethod; |
1232 | bmtMDMethod * m_pAsMDMethod; |
1233 | }; |
1234 | #endif |
1235 | }; // class bmtMethodHandle |
1236 | |
1237 | // -------------------------------------------------------------------------------------------- |
1238 | // Represents a method slot. It has a declaration and implementation value because these can |
1239 | // differ if the slot has been modified with a methodImpl. Otherwise, these two values are |
1240 | // typically identical. |
1241 | class bmtMethodSlot |
1242 | { |
1243 | public: |
1244 | //----------------------------------------------------------------------------------------- |
1245 | // Constructor for an empty slot. Both handles default to null. |
1246 | bmtMethodSlot() |
1247 | : m_decl(), |
1248 | m_impl() |
1249 | { LIMITED_METHOD_CONTRACT; } |
1250 | |
1251 | //----------------------------------------------------------------------------------------- |
1252 | // Constructor with both values explicitly provided. Either use this constructor or assign |
1253 | // to each value individually using non-const Decl and Impl methods. |
1254 | bmtMethodSlot( |
1255 | const bmtMethodHandle & decl, |
1256 | const bmtMethodHandle & impl) |
1257 | : m_decl(decl), |
1258 | m_impl(impl) |
1259 | { LIMITED_METHOD_CONTRACT; } |
1260 | |
1261 | //----------------------------------------------------------------------------------------- |
1262 | // Copy constructor. |
1263 | bmtMethodSlot( |
1264 | const bmtMethodSlot & other) |
1265 | : m_decl(other.m_decl), |
1266 | m_impl(other.m_impl) |
1267 | { LIMITED_METHOD_CONTRACT; } |
1268 | |
1269 | //----------------------------------------------------------------------------------------- |
1270 | // Returns a reference to the declaration method for this slot. This can be used as a |
1271 | // getter or a setter. |
1272 | bmtMethodHandle & |
1273 | Decl() |
1274 | { LIMITED_METHOD_CONTRACT; return m_decl; } |
1275 | |
1276 | //----------------------------------------------------------------------------------------- |
1277 | // Returns a reference to the implementation method for this slot. This can be used as a |
1278 | // getter or a setter. |
1279 | bmtMethodHandle & |
1280 | Impl() |
1281 | { LIMITED_METHOD_CONTRACT; return m_impl; } |
1282 | |
1283 | //----------------------------------------------------------------------------------------- |
1284 | // Const version of Decl. |
1285 | const bmtMethodHandle & |
1286 | Decl() const |
1287 | { LIMITED_METHOD_CONTRACT; return m_decl; } |
1288 | |
1289 | //----------------------------------------------------------------------------------------- |
1290 | // Const version of Impl. |
1291 | const bmtMethodHandle & |
1292 | Impl() const |
1293 | { LIMITED_METHOD_CONTRACT; return m_impl; } |
1294 | |
1295 | private: |
1296 | bmtMethodHandle m_decl; |
1297 | bmtMethodHandle m_impl; |
1298 | }; // class bmtMethodSlot |
1299 | |
1300 | // -------------------------------------------------------------------------------------------- |
1301 | struct bmtProperties |
1302 | { |
1303 | bool fIsValueClass; |
1304 | bool fIsEnum; |
1305 | bool fNoSanityChecks; |
1306 | bool fSparse; // Set to true if a sparse interface is being used. |
1307 | |
1308 | // Com Interop, ComWrapper classes extend from ComObject |
1309 | bool fIsComObjectType; // whether this class is an instance of ComObject class |
1310 | #ifdef FEATURE_COMINTEROP |
1311 | bool fIsMngStandardItf; // Set to true if the interface is a manages standard interface. |
1312 | bool fComEventItfType; // Set to true if the class is a special COM event interface. |
1313 | bool fIsRedirectedInterface; // Set to true if the class is an interface redirected for WinRT |
1314 | bool fNeedsRCWPerTypeData; // Set to true if the class needs optional RCW data attached to the MethodTable |
1315 | #endif // FEATURE_COMINTEROP |
1316 | #ifdef FEATURE_TYPEEQUIVALENCE |
1317 | bool fHasTypeEquivalence; // Set to true if the class is decorated by TypeIdentifierAttribute, or through some other technique is influenced by type equivalence |
1318 | bool fIsTypeEquivalent; // Set to true if the class is decorated by TypeIdentifierAttribute |
1319 | #endif |
1320 | |
1321 | bool fDynamicStatics; // Set to true if the statics will be allocated in the dynamic |
1322 | bool fGenericsStatics; // Set to true if the there are per-instantiation statics |
1323 | |
1324 | bool fIsIntrinsicType; // Set to true if the type has an [Intrinsic] attribute on it |
1325 | bool fIsHardwareIntrinsic; // Set to true if the class is a hardware intrinsic |
1326 | |
1327 | DWORD dwNonGCRegularStaticFieldBytes; |
1328 | DWORD dwNonGCThreadStaticFieldBytes; |
1329 | |
1330 | inline bmtProperties() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
1331 | }; // struct bmtProperties |
1332 | |
1333 | // -------------------------------------------------------------------------------------------- |
1334 | // Holds an array of bmtMethodSlot values. |
1335 | class bmtMethodSlotTable |
1336 | { |
1337 | public: |
1338 | //----------------------------------------------------------------------------------------- |
1339 | // Create a table that can hold maxSlotIdx slots. All slots up to maxSlotIdx is initialized |
1340 | // with the default constructor. |
1341 | bmtMethodSlotTable( |
1342 | SLOT_INDEX maxSlotIdx, |
1343 | StackingAllocator * pStackingAllocator) |
1344 | : m_curSlotIdx(0), |
1345 | m_maxSlotIdx(maxSlotIdx), |
1346 | m_rgSlots(new (pStackingAllocator) bmtMethodSlot[maxSlotIdx]) |
1347 | { CONTRACTL { THROWS; } CONTRACTL_END; } |
1348 | |
1349 | //----------------------------------------------------------------------------------------- |
1350 | // Subscript operator |
1351 | template <typename INDEX_TYPE> |
1352 | bmtMethodSlot & operator[](INDEX_TYPE idx) const |
1353 | { WRAPPER_NO_CONTRACT; ValidateIdx(idx); return m_rgSlots[idx]; } |
1354 | |
1355 | //----------------------------------------------------------------------------------------- |
1356 | // Pushes the value of slot to the end of the array. |
1357 | bool |
1358 | AddMethodSlot(const bmtMethodSlot & slot) |
1359 | { |
1360 | LIMITED_METHOD_CONTRACT; |
1361 | CONSISTENCY_CHECK(m_curSlotIdx <= m_maxSlotIdx); |
1362 | if (m_curSlotIdx == m_maxSlotIdx) |
1363 | return false; |
1364 | (*this)[m_curSlotIdx++] = slot; |
1365 | return true; |
1366 | } |
1367 | |
1368 | //----------------------------------------------------------------------------------------- |
1369 | // The current size of the used entries in the array. |
1370 | SLOT_INDEX |
1371 | GetSlotCount() |
1372 | { LIMITED_METHOD_CONTRACT; return m_curSlotIdx; } |
1373 | |
1374 | //----------------------------------------------------------------------------------------- |
1375 | // Used to iterate the contents of the array. |
1376 | typedef IteratorUtil::ArrayIterator<bmtMethodSlot> Iterator; |
1377 | |
1378 | Iterator |
1379 | IterateSlots() |
1380 | { return Iterator(m_rgSlots, GetSlotCount()); } |
1381 | |
1382 | private: |
1383 | //----------------------------------------------------------------------------------------- |
1384 | SLOT_INDEX m_curSlotIdx; |
1385 | SLOT_INDEX m_maxSlotIdx; |
1386 | bmtMethodSlot * m_rgSlots; |
1387 | |
1388 | template <typename INDEX_TYPE> |
1389 | void |
1390 | ValidateIdx( |
1391 | INDEX_TYPE idx) const |
1392 | { CONSISTENCY_CHECK(idx < m_curSlotIdx); } |
1393 | }; // class bmtMethodSlotTable |
1394 | |
1395 | // -------------------------------------------------------------------------------------------- |
1396 | struct bmtParentInfo; |
1397 | |
1398 | // -------------------------------------------------------------------------------------------- |
1399 | // This type is used in creating the slot layout that will be used in the MethodTable. |
1400 | struct bmtVtable |
1401 | { |
1402 | #ifdef _DEBUG |
1403 | //----------------------------------------------------------------------------------------- |
1404 | // Used to make sure no virtual methods are added to the vtable after non-virtuals have |
1405 | // begun to be added. |
1406 | bool m_fIsVirtualSlotSectionSealed; |
1407 | |
1408 | bool |
1409 | IsVirtualSlotSectionSealed() const |
1410 | { LIMITED_METHOD_CONTRACT; return m_fIsVirtualSlotSectionSealed; } |
1411 | |
1412 | void |
1413 | SealVirtualSlotSection() |
1414 | { LIMITED_METHOD_CONTRACT; m_fIsVirtualSlotSectionSealed = true; } |
1415 | #endif |
1416 | |
1417 | //----------------------------------------------------------------------------------------- |
1418 | // Implemented using a bmtMethodSlotTable |
1419 | bmtMethodSlotTable * pSlotTable; |
1420 | |
1421 | // Used to keep track of the default and static type constructors. |
1422 | bmtMDMethod * pDefaultCtor; |
1423 | bmtMDMethod * pCCtor; |
1424 | |
1425 | // Upper bound on size of vtable. Used in initializing pSlotTable |
1426 | DWORD dwMaxVtableSize; |
1427 | |
1428 | // Used to keep track of how many virtual and total slots are in the vtable |
1429 | SLOT_INDEX cVirtualSlots; |
1430 | SLOT_INDEX cTotalSlots; |
1431 | |
1432 | // Number of slots allocated in Vtable |
1433 | SLOT_INDEX cVtableSlots; |
1434 | |
1435 | // The dispatch map builder for this type. |
1436 | //@TODO: This should be moved. |
1437 | DispatchMapBuilder *pDispatchMapBuilder; |
1438 | |
1439 | //----------------------------------------------------------------------------------------- |
1440 | // Appends this method to the vtable as a newslot virtual. Decl and Impl are both set to be |
1441 | // the value of pMethod. |
1442 | bool |
1443 | AddVirtualMethod(bmtMDMethod * pMethod) |
1444 | { |
1445 | CONSISTENCY_CHECK(!IsVirtualSlotSectionSealed()); |
1446 | pMethod->SetSlotIndex(pSlotTable->GetSlotCount()); |
1447 | if (!pSlotTable->AddMethodSlot(bmtMethodSlot(pMethod, pMethod))) |
1448 | return false; |
1449 | ++cVirtualSlots; |
1450 | ++cTotalSlots; |
1451 | return true; |
1452 | } |
1453 | |
1454 | //----------------------------------------------------------------------------------------- |
1455 | // Overwrites an existing slot's Decl and Impl values that of pMethod. |
1456 | void |
1457 | SetVirtualMethodOverride(SLOT_INDEX idx, bmtMDMethod * pMethod) |
1458 | { |
1459 | CONSISTENCY_CHECK(!IsVirtualSlotSectionSealed()); |
1460 | pMethod->SetSlotIndex(idx); |
1461 | (*pSlotTable)[idx] = bmtMethodSlot(pMethod, pMethod); |
1462 | } |
1463 | |
1464 | //----------------------------------------------------------------------------------------- |
1465 | // Overwrites an existing slot's Impl value (but *NOT* Decl) that of pMethod. |
1466 | void |
1467 | SetVirtualMethodImpl(SLOT_INDEX idx, bmtMDMethod * pImplMethod) |
1468 | { |
1469 | LIMITED_METHOD_CONTRACT; |
1470 | (*pSlotTable)[idx] = bmtMethodSlot((*pSlotTable)[idx].Decl(), pImplMethod); |
1471 | } |
1472 | |
1473 | //----------------------------------------------------------------------------------------- |
1474 | // Appends this method to the vtable as a newslot non-virtual. Decl and Impl are both set to be |
1475 | // the value of pMethod. |
1476 | bool |
1477 | AddNonVirtualMethod(bmtMDMethod * pMethod) |
1478 | { |
1479 | INDEBUG(SealVirtualSlotSection()); |
1480 | CONSISTENCY_CHECK(!IsMdVirtual(pMethod->GetDeclAttrs())); |
1481 | pMethod->SetSlotIndex(pSlotTable->GetSlotCount()); |
1482 | if (!pSlotTable->AddMethodSlot(bmtMethodSlot(pMethod, pMethod))) |
1483 | return false; |
1484 | ++cTotalSlots; |
1485 | return true; |
1486 | } |
1487 | |
1488 | //----------------------------------------------------------------------------------------- |
1489 | // Adds this method as an unboxed entrypoint to the vtable as a newslot non-virtual. |
1490 | bool |
1491 | AddUnboxedMethod(bmtMDMethod * pMethod) |
1492 | { |
1493 | INDEBUG(SealVirtualSlotSection()); |
1494 | CONSISTENCY_CHECK(IsMdVirtual(pMethod->GetDeclAttrs())); |
1495 | pMethod->SetUnboxedSlotIndex(pSlotTable->GetSlotCount()); |
1496 | if (!pSlotTable->AddMethodSlot(bmtMethodSlot(pMethod, pMethod))) |
1497 | return false; |
1498 | ++cTotalSlots; |
1499 | return true; |
1500 | } |
1501 | |
1502 | //----------------------------------------------------------------------------------------- |
1503 | // If a default constructor has been set, this returns the slot assigned to the method; |
1504 | // otherwise returns INVALID_SLOT_INDEX. |
1505 | SLOT_INDEX |
1506 | GetDefaultCtorSlotIndex() const |
1507 | { |
1508 | if (pDefaultCtor != NULL) |
1509 | { |
1510 | return pDefaultCtor->GetSlotIndex(); |
1511 | } |
1512 | else |
1513 | { |
1514 | return INVALID_SLOT_INDEX; |
1515 | } |
1516 | } |
1517 | |
1518 | //----------------------------------------------------------------------------------------- |
1519 | // If a static type constructor has been set, this returns the slot assigned to the method; |
1520 | // otherwise returns INVALID_SLOT_INDEX. |
1521 | SLOT_INDEX |
1522 | GetClassCtorSlotIndex() const |
1523 | { |
1524 | if (pCCtor != NULL) |
1525 | { |
1526 | return pCCtor->GetSlotIndex(); |
1527 | } |
1528 | else |
1529 | { |
1530 | return INVALID_SLOT_INDEX; |
1531 | } |
1532 | } |
1533 | |
1534 | //----------------------------------------------------------------------------------------- |
1535 | // Subscript operator |
1536 | bmtMethodSlot & operator[](SLOT_INDEX idx) const |
1537 | { WRAPPER_NO_CONTRACT; return (*pSlotTable)[idx]; } |
1538 | |
1539 | //----------------------------------------------------------------------------------------- |
1540 | inline bmtVtable() |
1541 | : INDEBUG_COMMA(m_fIsVirtualSlotSectionSealed(false)) |
1542 | pSlotTable(NULL), |
1543 | pDefaultCtor(NULL), |
1544 | pCCtor(NULL), |
1545 | dwMaxVtableSize(0), |
1546 | cVirtualSlots(0), |
1547 | cTotalSlots(0), |
1548 | pDispatchMapBuilder(NULL) |
1549 | { LIMITED_METHOD_CONTRACT; } |
1550 | |
1551 | typedef bmtMethodSlotTable::Iterator Iterator; |
1552 | |
1553 | Iterator |
1554 | IterateSlots() |
1555 | { return pSlotTable->IterateSlots(); } |
1556 | }; // struct bmtVtable |
1557 | |
1558 | // -------------------------------------------------------------------------------------------- |
1559 | typedef FixedCapacityStackingAllocatedUTF8StringHash<bmtRTMethod *> MethodNameHash; |
1560 | |
1561 | // -------------------------------------------------------------------------------------------- |
1562 | struct bmtParentInfo |
1563 | { |
1564 | bmtMethodSlotTable *pSlotTable; |
1565 | |
1566 | typedef bmtMethodSlotTable::Iterator Iterator; |
1567 | |
1568 | //----------------------------------------------------------------------------------------- |
1569 | // Iterate the slots of the parent type. |
1570 | Iterator |
1571 | IterateSlots() |
1572 | { return pSlotTable->IterateSlots(); } |
1573 | |
1574 | //----------------------------------------------------------------------------------------- |
1575 | // Subscript operator |
1576 | bmtMethodSlot & operator[](SLOT_INDEX idx) const |
1577 | { WRAPPER_NO_CONTRACT; return (*pSlotTable)[idx]; } |
1578 | |
1579 | DWORD NumParentPointerSeries; |
1580 | MethodNameHash *pParentMethodHash; |
1581 | |
1582 | inline bmtParentInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
1583 | }; // struct bmtParentInfo |
1584 | |
1585 | // -------------------------------------------------------------------------------------------- |
1586 | // This will create bmtMethodSlotTable fully describing the vtable of the parent type. This |
1587 | // currently includes both virtual and non-virtual, though for the purposes of building the |
1588 | // current type virtual methods are the only ones that are necessary and so we could remove |
1589 | // the non-virtual method importing if it proves to be a performance bottleneck. |
1590 | void |
1591 | ImportParentMethods(); |
1592 | |
1593 | // -------------------------------------------------------------------------------------------- |
1594 | // Copies the virtual slots from the parent into the current type's vtable, effectively |
1595 | // performing the virtual method inheritance step of type layout. |
1596 | void |
1597 | CopyParentVtable(); |
1598 | |
1599 | // -------------------------------------------------------------------------------------------- |
1600 | // The ECMA spec declares that interfaces get placed differently depending on how they |
1601 | // are declared (see comment before the implementation of PlaceInterfaceMethods for details). |
1602 | // This is used to keep track of the declaration conditions as interfaces are expanded. |
1603 | struct InterfaceDeclarationScope |
1604 | { |
1605 | //----------------------------------------------------------------------------------------- |
1606 | // States that the interface has been declared by a parent. |
1607 | bool fIsInterfaceDeclaredOnParent; |
1608 | |
1609 | //----------------------------------------------------------------------------------------- |
1610 | // States that the interface has been explicitly declared in the interface implementation |
1611 | // list of this type. |
1612 | bool fIsInterfaceDeclaredOnType; |
1613 | |
1614 | // If both of the above members are FALSE, then the interface was not declared by a |
1615 | // parent and was not explicitly declared in the interface implementation list, but it |
1616 | // was declared transitively through one of the interfaces appearing in the implementation |
1617 | // list. |
1618 | |
1619 | //----------------------------------------------------------------------------------------- |
1620 | InterfaceDeclarationScope( |
1621 | bool fIsInterfaceDeclaredOnParent, |
1622 | bool fIsInterfaceDeclaredOnType) |
1623 | { |
1624 | this->fIsInterfaceDeclaredOnParent = fIsInterfaceDeclaredOnParent; |
1625 | this->fIsInterfaceDeclaredOnType = fIsInterfaceDeclaredOnType; |
1626 | } |
1627 | }; // struct InterfaceDeclarationScope |
1628 | |
1629 | // -------------------------------------------------------------------------------------------- |
1630 | // This type contains information about the implementation of a particular interface slot. |
1631 | class bmtInterfaceSlotImpl |
1632 | { |
1633 | public: |
1634 | //----------------------------------------------------------------------------------------- |
1635 | // Default constructor. |
1636 | bmtInterfaceSlotImpl() |
1637 | : m_decl(), |
1638 | m_implSlotIndex(INVALID_SLOT_INDEX) |
1639 | { LIMITED_METHOD_CONTRACT; } |
1640 | |
1641 | //----------------------------------------------------------------------------------------- |
1642 | // Constructor. |
1643 | bmtInterfaceSlotImpl( |
1644 | const bmtMethodHandle & decl, |
1645 | SLOT_INDEX implSlotIndex) |
1646 | : m_decl(decl), |
1647 | m_implSlotIndex(implSlotIndex) |
1648 | { LIMITED_METHOD_CONTRACT; } |
1649 | |
1650 | //----------------------------------------------------------------------------------------- |
1651 | // Copy constructor |
1652 | bmtInterfaceSlotImpl( |
1653 | const bmtInterfaceSlotImpl & other) |
1654 | : m_decl(other.m_decl), |
1655 | m_implSlotIndex(other.m_implSlotIndex) |
1656 | { LIMITED_METHOD_CONTRACT; } |
1657 | |
1658 | //----------------------------------------------------------------------------------------- |
1659 | // Returns a mutable reference to the decl of the slot. |
1660 | bmtMethodHandle & |
1661 | Decl() |
1662 | { LIMITED_METHOD_CONTRACT; return m_decl; } |
1663 | |
1664 | //----------------------------------------------------------------------------------------- |
1665 | // Returns a mutable reference to the slot index for the impl of the slot. |
1666 | SLOT_INDEX & |
1667 | Impl() |
1668 | { LIMITED_METHOD_CONTRACT; return m_implSlotIndex; } |
1669 | |
1670 | //----------------------------------------------------------------------------------------- |
1671 | // Returns a constant reference to the decl of the slot. |
1672 | const bmtMethodHandle & |
1673 | Decl() const |
1674 | { LIMITED_METHOD_CONTRACT; return m_decl; } |
1675 | |
1676 | //----------------------------------------------------------------------------------------- |
1677 | // Returns a constant reference to the slot index for the impl of the slot. |
1678 | const SLOT_INDEX & |
1679 | Impl() const |
1680 | { LIMITED_METHOD_CONTRACT; return m_implSlotIndex; } |
1681 | |
1682 | private: |
1683 | bmtMethodHandle m_decl; |
1684 | SLOT_INDEX m_implSlotIndex; |
1685 | }; // class bmtInterfaceSlotImpl |
1686 | |
1687 | // -------------------------------------------------------------------------------------------- |
1688 | // This type contains information about the implementation of an interface by the type that |
1689 | // is being built. It includes the declaration context in the form of an |
1690 | // InterfaceDeclarationScope (see comments on type for explanation) as well as an array of |
1691 | // bmtInterfaceSlotImpl values, with the number of entries corresponding to the number of |
1692 | // virtual methods declared on the interface. The slots are constructed with default values |
1693 | // which are interpreted as meaning that the slot has no implementation. Only when an |
1694 | // implementation is found for a slot is the slot updated. Note that this does not include |
1695 | // overrides for methods in slots that already contributed to this interface's implementation, |
1696 | // which can happen when an interface implementation is inherited. |
1697 | class bmtInterfaceEntry |
1698 | { |
1699 | public: |
1700 | //----------------------------------------------------------------------------------------- |
1701 | // Constructor. A default constructor would not be appropriate. |
1702 | bmtInterfaceEntry( |
1703 | bmtRTType * pItfType, |
1704 | const InterfaceDeclarationScope & declScope) |
1705 | : m_pType(pItfType), |
1706 | m_pImplTable(NULL), // Lazily created |
1707 | m_cImplTable(0), |
1708 | m_declScope(declScope), |
1709 | m_equivalenceSet(0), |
1710 | m_fEquivalenceSetWithMultipleEntries(false) |
1711 | { LIMITED_METHOD_CONTRACT; } |
1712 | |
1713 | //----------------------------------------------------------------------------------------- |
1714 | // Returns the bmtRTType for the interface type. |
1715 | bmtRTType * |
1716 | GetInterfaceType() const |
1717 | { LIMITED_METHOD_CONTRACT; return m_pType; } |
1718 | |
1719 | //----------------------------------------------------------------------------------------- |
1720 | // Returns a reference to a bool. The value is true if the interface is explicitly |
1721 | // declared within the type's interface list; false otherwise. |
1722 | bool & |
1723 | IsDeclaredOnType() |
1724 | { LIMITED_METHOD_CONTRACT; return m_declScope.fIsInterfaceDeclaredOnType; } |
1725 | |
1726 | //----------------------------------------------------------------------------------------- |
1727 | // const version |
1728 | const bool & |
1729 | IsDeclaredOnType() const |
1730 | { LIMITED_METHOD_CONTRACT; return m_declScope.fIsInterfaceDeclaredOnType; } |
1731 | |
1732 | //----------------------------------------------------------------------------------------- |
1733 | // Returns a reference to a bool. The value is true if the interface is implemented |
1734 | // by a parent type; false otherwise. Const version only because this does not need to |
1735 | // be changed in a dynamic fashion. |
1736 | const bool & |
1737 | IsImplementedByParent() |
1738 | { LIMITED_METHOD_CONTRACT; return m_declScope.fIsInterfaceDeclaredOnParent; } |
1739 | |
1740 | //----------------------------------------------------------------------------------------- |
1741 | // Used to iterate the interface implementation slots. |
1742 | typedef IteratorUtil::ArrayIterator<bmtInterfaceSlotImpl> |
1743 | InterfaceSlotIterator; |
1744 | |
1745 | InterfaceSlotIterator |
1746 | IterateInterfaceSlots( |
1747 | StackingAllocator * pStackingAllocator) |
1748 | { |
1749 | WRAPPER_NO_CONTRACT; |
1750 | CheckCreateSlotTable(pStackingAllocator); |
1751 | return InterfaceSlotIterator(m_pImplTable, m_cImplTable); |
1752 | } |
1753 | |
1754 | //----------------------------------------------------------------------------------------- |
1755 | // Returns the number of interface implementation slots. |
1756 | SLOT_INDEX |
1757 | GetInterfaceSlotImplCount() |
1758 | { LIMITED_METHOD_CONTRACT; return m_cImplTable; } |
1759 | |
1760 | //----------------------------------------------------------------------------------------- |
1761 | // Subscript operator. |
1762 | bmtInterfaceSlotImpl & |
1763 | operator[]( |
1764 | SLOT_INDEX idx) |
1765 | { |
1766 | LIMITED_METHOD_CONTRACT; |
1767 | CONSISTENCY_CHECK(CheckPointer(m_pImplTable)); |
1768 | CONSISTENCY_CHECK(idx < m_cImplTable); |
1769 | return m_pImplTable[idx]; |
1770 | } |
1771 | |
1772 | //----------------------------------------------------------------------------------------- |
1773 | const bmtInterfaceSlotImpl & |
1774 | operator[]( |
1775 | SLOT_INDEX idx) const |
1776 | { |
1777 | return (*const_cast<bmtInterfaceEntry *>(this))[idx]; |
1778 | } |
1779 | |
1780 | //----------------------------------------------------------------------------------------- |
1781 | void SetInterfaceEquivalenceSet(UINT32 iEquivalenceSet, bool fEquivalenceSetWithMultipleEntries) |
1782 | { |
1783 | LIMITED_METHOD_CONTRACT; |
1784 | // The equivalence set of 0 indicates the value has not yet been calculated |
1785 | // We should set the equivalence set to only one value |
1786 | _ASSERTE((m_equivalenceSet == 0) || (m_equivalenceSet == iEquivalenceSet)); |
1787 | m_equivalenceSet = iEquivalenceSet; |
1788 | m_fEquivalenceSetWithMultipleEntries = fEquivalenceSetWithMultipleEntries; |
1789 | } |
1790 | |
1791 | UINT32 GetInterfaceEquivalenceSet() |
1792 | { |
1793 | LIMITED_METHOD_CONTRACT; |
1794 | // The equivalence set of 0 indicates the value has not yet been calculated. |
1795 | // We should not be calling this method before calculating equivalence sets |
1796 | _ASSERTE(m_equivalenceSet != 0); |
1797 | return m_equivalenceSet; |
1798 | } |
1799 | |
1800 | bool InEquivalenceSetWithMultipleEntries() |
1801 | { |
1802 | LIMITED_METHOD_CONTRACT; |
1803 | // The equivalence set of 0 indicates the value has not yet been calculated. |
1804 | // We should not be calling this method before calculating equivalence sets |
1805 | _ASSERTE(m_equivalenceSet != 0); |
1806 | return m_fEquivalenceSetWithMultipleEntries; |
1807 | } |
1808 | |
1809 | private: |
1810 | //----------------------------------------------------------------------------------------- |
1811 | void |
1812 | CheckCreateSlotTable( |
1813 | StackingAllocator * pStackingAllocator) |
1814 | { |
1815 | LIMITED_METHOD_CONTRACT; |
1816 | if (m_pImplTable == NULL) |
1817 | { |
1818 | CreateSlotTable(pStackingAllocator); |
1819 | } |
1820 | } |
1821 | |
1822 | //----------------------------------------------------------------------------------------- |
1823 | // This creates the interface slot implementation table and correctly creates interface |
1824 | // methods and sets them in the Decl property for each slot. |
1825 | void |
1826 | CreateSlotTable( |
1827 | StackingAllocator * pStackingAllocator); |
1828 | |
1829 | //----------------------------------------------------------------------------------------- |
1830 | bmtRTType * m_pType; |
1831 | bmtInterfaceSlotImpl * m_pImplTable; |
1832 | SLOT_INDEX m_cImplTable; |
1833 | InterfaceDeclarationScope m_declScope; |
1834 | UINT32 m_equivalenceSet; |
1835 | bool m_fEquivalenceSetWithMultipleEntries; |
1836 | }; // class bmtInterfaceEntry |
1837 | |
1838 | // -------------------------------------------------------------------------------------------- |
1839 | // Contains the list of implemented interfaces as an array of bmtInterfaceEntry values. |
1840 | struct bmtInterfaceInfo |
1841 | { |
1842 | bmtInterfaceEntry * pInterfaceMap; |
1843 | DWORD dwInterfaceMapSize; // count of entries in interface map |
1844 | DWORD dwInterfaceMapAllocated; // upper bound on size of interface map |
1845 | #ifdef _DEBUG |
1846 | // Should we inject interface duplicates for this type? (Parent has its own value stored in |
1847 | // code:MethodTable::dbg_m_fHasInjectedInterfaceDuplicates) |
1848 | BOOL dbg_fShouldInjectInterfaceDuplicates; |
1849 | #endif //_DEBUG |
1850 | |
1851 | //----------------------------------------------------------------------------------------- |
1852 | // Used to iterate the interface entries in the map. |
1853 | typedef IteratorUtil::ArrayIterator<bmtInterfaceEntry> MapIterator; |
1854 | |
1855 | MapIterator |
1856 | IterateInterfaceMap() |
1857 | { return MapIterator(pInterfaceMap, dwInterfaceMapSize); } |
1858 | |
1859 | //----------------------------------------------------------------------------------------- |
1860 | // Constructor |
1861 | inline bmtInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
1862 | }; // struct bmtInterfaceInfo |
1863 | |
1864 | // -------------------------------------------------------------------------------------------- |
1865 | // Contains information on fields derived from the metadata of the type. |
1866 | struct bmtEnumFieldInfo |
1867 | { |
1868 | // Counts instance fields |
1869 | DWORD dwNumInstanceFields; |
1870 | |
1871 | // Counts both regular statics and thread statics. Currently RVA |
1872 | // get lumped in with "regular statics". |
1873 | DWORD dwNumStaticFields; |
1874 | DWORD dwNumStaticObjRefFields; |
1875 | DWORD dwNumStaticBoxedFields; |
1876 | |
1877 | // We keep a separate count for just thread statics |
1878 | DWORD dwNumThreadStaticFields; |
1879 | DWORD dwNumThreadStaticObjRefFields; |
1880 | DWORD dwNumThreadStaticBoxedFields; |
1881 | |
1882 | DWORD dwNumDeclaredFields; // For calculating amount of FieldDesc's to allocate |
1883 | |
1884 | IMDInternalImport *m_pInternalImport; |
1885 | |
1886 | //----------------------------------------------------------------------------------------- |
1887 | inline bmtEnumFieldInfo(IMDInternalImport *pInternalImport) |
1888 | { |
1889 | LIMITED_METHOD_CONTRACT; |
1890 | memset((void *)this, NULL, sizeof(*this)); |
1891 | m_pInternalImport = pInternalImport; |
1892 | } |
1893 | }; // struct bmtEnumFieldInfo |
1894 | |
1895 | // -------------------------------------------------------------------------------------------- |
1896 | // This contains information specifically about the methods declared by the type being built. |
1897 | struct bmtMethodInfo |
1898 | { |
1899 | //----------------------------------------------------------------------------------------- |
1900 | // The array and bounds of the bmtMDMethod array |
1901 | SLOT_INDEX m_cDeclaredMethods; |
1902 | SLOT_INDEX m_cMaxDeclaredMethods; |
1903 | bmtMDMethod ** m_rgDeclaredMethods; |
1904 | |
1905 | //----------------------------------------------------------------------------------------- |
1906 | DWORD dwNumDeclaredNonAbstractMethods; // For calculating approx generic dictionary size |
1907 | DWORD dwNumberMethodImpls; // Number of method impls defined for this type |
1908 | DWORD dwNumberInexactMethodImplCandidates; // Number of inexact method impl candidates (used for type equivalent interfaces) |
1909 | |
1910 | //----------------------------------------------------------------------------------------- |
1911 | // Constructor |
1912 | inline bmtMethodInfo() |
1913 | { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
1914 | |
1915 | //----------------------------------------------------------------------------------------- |
1916 | // Add a declared method to the array |
1917 | void |
1918 | AddDeclaredMethod( |
1919 | bmtMDMethod * pMethod) |
1920 | { |
1921 | CONSISTENCY_CHECK(m_cDeclaredMethods < m_cMaxDeclaredMethods); |
1922 | m_rgDeclaredMethods[m_cDeclaredMethods++] = pMethod; |
1923 | } |
1924 | |
1925 | //----------------------------------------------------------------------------------------- |
1926 | // Subscript operator |
1927 | bmtMDMethod * |
1928 | operator[]( |
1929 | SLOT_INDEX idx) const |
1930 | { |
1931 | CONSISTENCY_CHECK(idx < m_cDeclaredMethods); |
1932 | return m_rgDeclaredMethods[idx]; |
1933 | } |
1934 | |
1935 | //----------------------------------------------------------------------------------------- |
1936 | // Returns the number of declared methods. |
1937 | SLOT_INDEX |
1938 | GetDeclaredMethodCount() |
1939 | { LIMITED_METHOD_CONTRACT; return m_cDeclaredMethods; } |
1940 | |
1941 | //----------------------------------------------------------------------------------------- |
1942 | // Searches the declared methods for a method with a token value equal to tok. |
1943 | bmtMDMethod * |
1944 | FindDeclaredMethodByToken( |
1945 | mdMethodDef tok) |
1946 | { |
1947 | LIMITED_METHOD_CONTRACT; |
1948 | for (SLOT_INDEX i = 0; i < m_cDeclaredMethods; ++i) |
1949 | { |
1950 | if ((*this)[i]->GetMethodSignature().GetToken() == tok) |
1951 | { |
1952 | return (*this)[i]; |
1953 | } |
1954 | } |
1955 | return NULL; |
1956 | } |
1957 | }; // struct bmtMethodInfo |
1958 | |
1959 | // -------------------------------------------------------------------------------------------- |
1960 | // Stores metadata info for a |
1961 | struct bmtMetaDataInfo |
1962 | { |
1963 | //----------------------------------------------------------------------------------------- |
1964 | DWORD cFields; // # meta-data fields of this class |
1965 | mdToken *pFields; // Enumeration of metadata fields |
1966 | DWORD *pFieldAttrs; // Enumeration of the attributes of the fields |
1967 | |
1968 | //----------------------------------------------------------------------------------------- |
1969 | // Stores the method impl tokens as a pair structure to enable qsort to be |
1970 | // performed on the array. |
1971 | struct MethodImplTokenPair |
1972 | { |
1973 | mdToken methodBody; // MethodDef's for the bodies of MethodImpls. Must be defined in this type. |
1974 | mdToken methodDecl; // Method token that body implements. Is a MethodDef or MemberRef |
1975 | // Does this methodimpl need to be considered during inexact methodimpl processing |
1976 | bool fConsiderDuringInexactMethodImplProcessing; |
1977 | // If when considered during inexact methodimpl processing it does not match any declaration method, throw. |
1978 | // This is to detect situations where a methodimpl does not match any method on any equivalent interface. |
1979 | bool fThrowIfUnmatchedDuringInexactMethodImplProcessing; |
1980 | UINT32 interfaceEquivalenceSet;// Equivalence set in the interface map to examine |
1981 | static int __cdecl Compare(const void *elem1, const void *elem2); |
1982 | static BOOL Equal(const MethodImplTokenPair *elem1, const MethodImplTokenPair *elem2); |
1983 | }; |
1984 | |
1985 | //----------------------------------------------------------------------------------------- |
1986 | MethodImplTokenPair *rgMethodImplTokens; |
1987 | Substitution *pMethodDeclSubsts; // Used to interpret generic variables in the interface of the declaring type |
1988 | |
1989 | //----------------------------------------------------------------------------------------- |
1990 | inline bmtMetaDataInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
1991 | }; // struct bmtMetaDataInfo |
1992 | |
1993 | // -------------------------------------------------------------------------------------------- |
1994 | // Stores a bunch of random info related to method and field descs. This should be separated |
1995 | // into appropriate data structures. |
1996 | struct bmtMethAndFieldDescs |
1997 | { |
1998 | //----------------------------------------------------------------------------------------- |
1999 | FieldDesc **ppFieldDescList; // FieldDesc pointer (or NULL if field not preserved) for each field |
2000 | |
2001 | |
2002 | //----------------------------------------------------------------------------------------- |
2003 | inline bmtMethAndFieldDescs() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
2004 | }; // struct bmtMethAndFieldDescs |
2005 | |
2006 | // -------------------------------------------------------------------------------------------- |
2007 | // Information about the placement of fields during field layout. |
2008 | struct bmtFieldPlacement |
2009 | { |
2010 | // For compacting field placement |
2011 | DWORD InstanceFieldStart[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; |
2012 | |
2013 | DWORD NumInstanceFieldsOfSize[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; |
2014 | DWORD FirstInstanceFieldOfSize[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; |
2015 | DWORD GCPointerFieldStart; |
2016 | DWORD NumInstanceGCPointerFields; // does not include inherited pointer fields |
2017 | DWORD NumGCPointerSeries; |
2018 | DWORD NumInstanceFieldBytes; |
2019 | |
2020 | bool fIsByRefLikeType; |
2021 | bool fHasFixedAddressValueTypes; |
2022 | bool fHasSelfReferencingStaticValueTypeField_WithRVA; |
2023 | |
2024 | // These data members are specific to regular statics |
2025 | DWORD RegularStaticFieldStart[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; // Byte offset where to start placing fields of this size |
2026 | DWORD NumRegularStaticFieldsOfSize[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; // # Fields of this size |
2027 | DWORD NumRegularStaticGCPointerFields; // does not include inherited pointer fields |
2028 | DWORD NumRegularStaticGCBoxedFields; // does not include inherited pointer fields |
2029 | |
2030 | // These data members are specific to thread statics |
2031 | DWORD ThreadStaticFieldStart[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; // Byte offset where to start placing fields of this size |
2032 | DWORD NumThreadStaticFieldsOfSize[MAX_LOG2_PRIMITIVE_FIELD_SIZE+1]; // # Fields of this size |
2033 | DWORD NumThreadStaticGCPointerFields; // does not include inherited pointer fields |
2034 | DWORD NumThreadStaticGCBoxedFields; // does not include inherited pointer fields |
2035 | |
2036 | inline bmtFieldPlacement() { LIMITED_METHOD_CONTRACT; memset((void *)this, 0, sizeof(*this)); } |
2037 | }; // struct bmtFieldPlacement |
2038 | |
2039 | // -------------------------------------------------------------------------------------------- |
2040 | // Miscelaneous information about the type being built. |
2041 | struct bmtInternalInfo |
2042 | { |
2043 | //----------------------------------------------------------------------------------------- |
2044 | // Metadata for accessing information on the type |
2045 | IMDInternalImport *pInternalImport; |
2046 | Module *pModule; |
2047 | |
2048 | //----------------------------------------------------------------------------------------- |
2049 | // Parent method table. It is identical to pType->GetParentType()->GetMethodTable(), |
2050 | // except for EnC. pParentMT is initialized but pType is not when InitializeFieldDesc |
2051 | // is directly called by EnC. |
2052 | MethodTable * pParentMT; |
2053 | |
2054 | //----------------------------------------------------------------------------------------- |
2055 | // The representation of the type being built |
2056 | bmtMDType * pType; |
2057 | |
2058 | //----------------------------------------------------------------------------------------- |
2059 | // Constructor |
2060 | inline bmtInternalInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
2061 | }; // struct bmtInternalInfo |
2062 | |
2063 | |
2064 | // -------------------------------------------------------------------------------------------- |
2065 | // Used for analyzing overlapped fields defined by explicit layout types. |
2066 | enum bmtFieldLayoutTag {empty, nonoref, oref}; |
2067 | |
2068 | // -------------------------------------------------------------------------------------------- |
2069 | // used for calculating pointer series for tdexplicit |
2070 | struct bmtGCSeriesInfo |
2071 | { |
2072 | UINT numSeries; |
2073 | struct Series { |
2074 | UINT offset; |
2075 | UINT len; |
2076 | } *pSeries; |
2077 | bmtGCSeriesInfo() : numSeries(0), pSeries(NULL) {LIMITED_METHOD_CONTRACT;} |
2078 | }; // struct bmtGCSeriesInfo |
2079 | |
2080 | // -------------------------------------------------------------------------------------------- |
2081 | struct bmtMethodImplInfo |
2082 | { |
2083 | //----------------------------------------------------------------------------------------- |
2084 | // This struct represents the resolved methodimpl pair. |
2085 | struct Entry |
2086 | { |
2087 | bmtMethodHandle declMethod; |
2088 | bmtMDMethod * pImplMethod; |
2089 | mdToken declToken; |
2090 | |
2091 | Entry(bmtMDMethod * pImplMethodIn, |
2092 | bmtMethodHandle declMethodIn, |
2093 | mdToken declToken) |
2094 | : declMethod(declMethodIn), |
2095 | pImplMethod(pImplMethodIn), |
2096 | declToken(declToken) |
2097 | {} |
2098 | |
2099 | Entry() |
2100 | : declMethod(), |
2101 | pImplMethod(NULL), |
2102 | declToken() |
2103 | {} |
2104 | }; |
2105 | |
2106 | //----------------------------------------------------------------------------------------- |
2107 | // The allocated array of entries and the count indicating how many entries are in use. |
2108 | private: |
2109 | Entry *rgEntries; |
2110 | DWORD cMaxIndex; |
2111 | |
2112 | //----------------------------------------------------------------------------------------- |
2113 | // Returns the MethodDesc* for the implementation of the methodimpl pair. |
2114 | MethodDesc* |
2115 | GetBodyMethodDesc( |
2116 | DWORD i) |
2117 | { |
2118 | LIMITED_METHOD_CONTRACT; |
2119 | _ASSERTE(i < pIndex); |
2120 | return GetImplementationMethod(i)->GetMethodDesc(); |
2121 | } |
2122 | |
2123 | public: |
2124 | |
2125 | DWORD pIndex; // Next open spot in array, we load the BodyDesc's up in order of |
2126 | // appearance in the type's list of methods (a body can appear |
2127 | // more then once in the list of MethodImpls) |
2128 | |
2129 | |
2130 | //----------------------------------------------------------------------------------------- |
2131 | // Add a methodimpl to the list. |
2132 | void |
2133 | AddMethodImpl( |
2134 | bmtMDMethod * pImplMethod, |
2135 | bmtMethodHandle declMethod, |
2136 | mdToken declToken, |
2137 | StackingAllocator * pStackingAllocator); |
2138 | |
2139 | //----------------------------------------------------------------------------------------- |
2140 | // Get the decl method for a particular methodimpl entry. |
2141 | bmtMethodHandle |
2142 | GetDeclarationMethod( |
2143 | DWORD i) |
2144 | { LIMITED_METHOD_CONTRACT; _ASSERTE(i < pIndex); return rgEntries[i].declMethod; } |
2145 | |
2146 | //----------------------------------------------------------------------------------------- |
2147 | // Get the decl method for a particular methodimpl entry. |
2148 | mdToken |
2149 | GetDeclarationToken( |
2150 | DWORD i) |
2151 | { LIMITED_METHOD_CONTRACT; _ASSERTE(i < pIndex); return rgEntries[i].declToken; } |
2152 | |
2153 | //----------------------------------------------------------------------------------------- |
2154 | // Get the impl method for a particular methodimpl entry. |
2155 | bmtMDMethod * |
2156 | GetImplementationMethod( |
2157 | DWORD i) |
2158 | { LIMITED_METHOD_CONTRACT; _ASSERTE(i < pIndex); return rgEntries[i].pImplMethod; } |
2159 | |
2160 | //----------------------------------------------------------------------------------------- |
2161 | // Constructor |
2162 | inline bmtMethodImplInfo() |
2163 | { LIMITED_METHOD_CONTRACT; memset((void*) this, NULL, sizeof(*this)); } |
2164 | |
2165 | //----------------------------------------------------------------------------------------- |
2166 | // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise. |
2167 | BOOL IsBody( |
2168 | mdToken tok); |
2169 | }; // struct bmtMethodImplInfo |
2170 | |
2171 | // -------------------------------------------------------------------------------------------- |
2172 | // These are all the memory allocators available to MethodTableBuilder |
2173 | |
2174 | StackingAllocator * m_pStackingAllocator; |
2175 | AllocMemTracker * m_pAllocMemTracker; |
2176 | |
2177 | StackingAllocator * |
2178 | GetStackingAllocator() |
2179 | { LIMITED_METHOD_CONTRACT; return m_pStackingAllocator; } |
2180 | |
2181 | LoaderAllocator * |
2182 | GetLoaderAllocator() |
2183 | { LIMITED_METHOD_CONTRACT; return bmtAllocator; } |
2184 | |
2185 | AllocMemTracker * |
2186 | GetMemTracker() |
2187 | { LIMITED_METHOD_CONTRACT; return m_pAllocMemTracker; } |
2188 | |
2189 | BYTE * |
2190 | AllocateFromHighFrequencyHeap(S_SIZE_T cbMem); |
2191 | |
2192 | BYTE * |
2193 | AllocateFromLowFrequencyHeap(S_SIZE_T cbMem); |
2194 | |
2195 | // -------------------------------------------------------------------------------------------- |
2196 | // The following structs, defined as private members of MethodTableBuilder, contain the necessary local |
2197 | // parameters needed for BuildMethodTable |
2198 | |
2199 | // Look at the struct definitions for a detailed list of all parameters available |
2200 | // to BuildMethodTable. |
2201 | |
2202 | LoaderAllocator *bmtAllocator; |
2203 | bmtErrorInfo *bmtError; |
2204 | bmtProperties *bmtProp; |
2205 | bmtVtable *bmtVT; |
2206 | bmtParentInfo *bmtParent; |
2207 | bmtInterfaceInfo *bmtInterface; |
2208 | bmtMetaDataInfo *bmtMetaData; |
2209 | bmtMethodInfo *bmtMethod; |
2210 | bmtMethAndFieldDescs *bmtMFDescs; |
2211 | bmtFieldPlacement *bmtFP; |
2212 | bmtInternalInfo *bmtInternal; |
2213 | bmtGCSeriesInfo *bmtGCSeries; |
2214 | bmtMethodImplInfo *bmtMethodImpl; |
2215 | const bmtGenericsInfo *bmtGenerics; |
2216 | bmtEnumFieldInfo *bmtEnumFields; |
2217 | |
2218 | void SetBMTData( |
2219 | LoaderAllocator *bmtAllocator, |
2220 | bmtErrorInfo *bmtError, |
2221 | bmtProperties *bmtProp, |
2222 | bmtVtable *bmtVT, |
2223 | bmtParentInfo *bmtParent, |
2224 | bmtInterfaceInfo *bmtInterface, |
2225 | bmtMetaDataInfo *bmtMetaData, |
2226 | bmtMethodInfo *bmtMethod, |
2227 | bmtMethAndFieldDescs *bmtMFDescs, |
2228 | bmtFieldPlacement *bmtFP, |
2229 | bmtInternalInfo *bmtInternal, |
2230 | bmtGCSeriesInfo *bmtGCSeries, |
2231 | bmtMethodImplInfo *bmtMethodImpl, |
2232 | const bmtGenericsInfo *bmtGenerics, |
2233 | bmtEnumFieldInfo *bmtEnumFields); |
2234 | |
2235 | // -------------------------------------------------------------------------------------------- |
2236 | // Returns the parent bmtRTType pointer. Can be null if no parent exists. |
2237 | inline bmtRTType * |
2238 | GetParentType() |
2239 | { WRAPPER_NO_CONTRACT; return bmtInternal->pType->GetParentType(); } |
2240 | |
2241 | // -------------------------------------------------------------------------------------------- |
2242 | // Takes care of checking against NULL on the pointer returned by GetParentType. Returns true |
2243 | // if the type being built has a parent; returns false otherwise. |
2244 | // NOTE: false will typically only be returned for System.Object and interfaces. |
2245 | inline bool |
2246 | HasParent() |
2247 | { |
2248 | LIMITED_METHOD_CONTRACT; return bmtInternal->pParentMT != NULL; |
2249 | } |
2250 | |
2251 | // -------------------------------------------------------------------------------------------- |
2252 | inline MethodTable * |
2253 | GetParentMethodTable() |
2254 | { |
2255 | LIMITED_METHOD_CONTRACT; return bmtInternal->pParentMT; |
2256 | } |
2257 | |
2258 | // -------------------------------------------------------------------------------------------- |
2259 | // Created to help centralize knowledge of where all the information about each method is |
2260 | // stored. Eventually, this can hopefully be removed and it should be sufficient to iterate |
2261 | // over the array of bmtMDMethod* that hold all the declared methods. |
2262 | class DeclaredMethodIterator |
2263 | { |
2264 | private: |
2265 | MethodTableBuilder &m_mtb; |
2266 | int m_idx; // not SLOT_INDEX? |
2267 | #ifdef _DEBUG |
2268 | bmtMDMethod * m_debug_pMethod; |
2269 | #endif |
2270 | |
2271 | public: |
2272 | inline DeclaredMethodIterator(MethodTableBuilder &mtb); |
2273 | inline int CurrentIndex(); |
2274 | inline BOOL Next(); |
2275 | inline BOOL Prev(); |
2276 | inline void ResetToEnd(); |
2277 | inline mdToken Token(); |
2278 | inline DWORD Attrs(); |
2279 | inline DWORD RVA(); |
2280 | inline DWORD ImplFlags(); |
2281 | inline LPCSTR Name(); |
2282 | inline PCCOR_SIGNATURE GetSig(DWORD *pcbSig); |
2283 | inline METHOD_IMPL_TYPE MethodImpl(); |
2284 | inline BOOL IsMethodImpl(); |
2285 | inline METHOD_TYPE MethodType(); |
2286 | inline bmtMDMethod *GetMDMethod(); |
2287 | inline MethodDesc *GetIntroducingMethodDesc(); |
2288 | inline bmtMDMethod * operator->(); |
2289 | inline bmtMDMethod * operator*() { WRAPPER_NO_CONTRACT; return GetMDMethod(); } |
2290 | }; // class DeclaredMethodIterator |
2291 | friend class DeclaredMethodIterator; |
2292 | |
2293 | inline SLOT_INDEX NumDeclaredMethods() { LIMITED_METHOD_CONTRACT; return bmtMethod->GetDeclaredMethodCount(); } |
2294 | inline DWORD NumDeclaredFields() { LIMITED_METHOD_CONTRACT; return bmtEnumFields->dwNumDeclaredFields; } |
2295 | |
2296 | // -------------------------------------------------------------------------------------------- |
2297 | // Used to report an error building this type. |
2298 | static VOID DECLSPEC_NORETURN |
2299 | BuildMethodTableThrowException( |
2300 | HRESULT hr, |
2301 | const bmtErrorInfo & bmtError); |
2302 | |
2303 | // -------------------------------------------------------------------------------------------- |
2304 | // Used to report an error building this type. |
2305 | inline VOID DECLSPEC_NORETURN |
2306 | BuildMethodTableThrowException( |
2307 | HRESULT hr, |
2308 | UINT idResWhy, |
2309 | mdMethodDef tokMethodDef) |
2310 | { |
2311 | CONTRACTL |
2312 | { |
2313 | THROWS; |
2314 | GC_TRIGGERS; |
2315 | MODE_ANY; |
2316 | } |
2317 | CONTRACTL_END; |
2318 | bmtError->resIDWhy = idResWhy; |
2319 | bmtError->dMethodDefInError = tokMethodDef; |
2320 | bmtError->szMethodNameForError = NULL; |
2321 | bmtError->cl = GetCl(); |
2322 | BuildMethodTableThrowException(hr, *bmtError); |
2323 | } |
2324 | |
2325 | // -------------------------------------------------------------------------------------------- |
2326 | // Used to report an error building this type. |
2327 | inline VOID DECLSPEC_NORETURN |
2328 | BuildMethodTableThrowException( |
2329 | HRESULT hr, |
2330 | UINT idResWhy, |
2331 | LPCUTF8 szMethodName) |
2332 | { |
2333 | CONTRACTL |
2334 | { |
2335 | THROWS; |
2336 | GC_TRIGGERS; |
2337 | MODE_ANY; |
2338 | } |
2339 | CONTRACTL_END; |
2340 | bmtError->resIDWhy = idResWhy; |
2341 | bmtError->dMethodDefInError = mdMethodDefNil; |
2342 | bmtError->szMethodNameForError = szMethodName; |
2343 | bmtError->cl = GetCl(); |
2344 | BuildMethodTableThrowException(hr, *bmtError); |
2345 | } |
2346 | |
2347 | // -------------------------------------------------------------------------------------------- |
2348 | // Used to report an error building this type. |
2349 | inline VOID DECLSPEC_NORETURN |
2350 | BuildMethodTableThrowException( |
2351 | UINT idResWhy, |
2352 | mdMethodDef tokMethodDef = mdMethodDefNil) |
2353 | { |
2354 | WRAPPER_NO_CONTRACT; |
2355 | BuildMethodTableThrowException(COR_E_TYPELOAD, idResWhy, tokMethodDef); |
2356 | } |
2357 | |
2358 | // -------------------------------------------------------------------------------------------- |
2359 | // Used to report an error building this type. |
2360 | inline VOID DECLSPEC_NORETURN |
2361 | BuildMethodTableThrowException( |
2362 | UINT idResWhy, |
2363 | LPCUTF8 szMethodName) |
2364 | { |
2365 | WRAPPER_NO_CONTRACT; |
2366 | BuildMethodTableThrowException(COR_E_TYPELOAD, idResWhy, szMethodName); |
2367 | } |
2368 | |
2369 | private: |
2370 | // -------------------------------------------------------------------------------------------- |
2371 | // To be removed. Creates a hash table of all the names of the virtual methods in pMT, |
2372 | // and associates them with their corresponding bmtRTMethod* values. |
2373 | MethodNameHash *CreateMethodChainHash( |
2374 | MethodTable *pMT); |
2375 | |
2376 | // -------------------------------------------------------------------------------------------- |
2377 | // Only used in the resolve phase of the classloader. These are used to calculate |
2378 | // the interface implementation map. The reason it is done in this way is that the |
2379 | // interfaces must be resolved in light of generic types and substitutions, and the fact |
2380 | // that substitutions can make interfaces resolve to be identical when given a child's |
2381 | // instantiation. |
2382 | // |
2383 | // NOTE: See DevDiv bug 795 for details. |
2384 | |
2385 | void ExpandApproxInterface( |
2386 | bmtInterfaceInfo * bmtInterface, // out parameter, various parts cumulatively written to. |
2387 | const Substitution * pNewInterfaceSubstChain, |
2388 | MethodTable * pNewInterface, |
2389 | InterfaceDeclarationScope declScope |
2390 | COMMA_INDEBUG(MethodTable * dbg_pClassMT)); |
2391 | |
2392 | void ExpandApproxDeclaredInterfaces( |
2393 | bmtInterfaceInfo * bmtInterface, // out parameter, various parts cumulatively written to. |
2394 | bmtTypeHandle thType, |
2395 | InterfaceDeclarationScope declScope |
2396 | COMMA_INDEBUG(MethodTable * dbg_pClassMT)); |
2397 | |
2398 | void ExpandApproxInheritedInterfaces( |
2399 | bmtInterfaceInfo * bmtInterface, // out parameter, various parts cumulatively written to. |
2400 | bmtRTType * pParentType); |
2401 | |
2402 | void LoadApproxInterfaceMap(); |
2403 | |
2404 | public: |
2405 | //------------------------------------------------------------------------ |
2406 | // Loading exact interface instantiations.(slow technique) |
2407 | // |
2408 | // These place the exact interface instantiations into the interface map at the |
2409 | // appropriate locations. |
2410 | |
2411 | struct bmtExactInterfaceInfo |
2412 | { |
2413 | DWORD nAssigned; |
2414 | MethodTable **pExactMTs; |
2415 | |
2416 | // Array of substitutions for each interface in the interface map |
2417 | Substitution * pInterfaceSubstitution; |
2418 | SigTypeContext typeContext; // Exact type context used to supply final instantiation to substitution chains |
2419 | |
2420 | inline bmtExactInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
2421 | }; // struct bmtExactInterfaceInfo |
2422 | |
2423 | private: |
2424 | static void |
2425 | ExpandExactInterface( |
2426 | bmtExactInterfaceInfo * bmtInfo, |
2427 | MethodTable * pIntf, |
2428 | const Substitution * pSubstForTypeLoad_OnStack, // Allocated on stack! |
2429 | const Substitution * pSubstForComparing_OnStack // Allocated on stack! |
2430 | COMMA_INDEBUG(MethodTable * dbg_pClassMT)); |
2431 | |
2432 | public: |
2433 | static void |
2434 | ExpandExactDeclaredInterfaces( |
2435 | bmtExactInterfaceInfo * bmtInfo, |
2436 | Module * pModule, |
2437 | mdToken typeDef, |
2438 | const Substitution * pSubstForTypeLoad, |
2439 | Substitution * pSubstForComparing |
2440 | COMMA_INDEBUG(MethodTable * dbg_pClassMT)); |
2441 | |
2442 | static void |
2443 | ExpandExactInheritedInterfaces( |
2444 | bmtExactInterfaceInfo * bmtInfo, |
2445 | MethodTable * pParentMT, |
2446 | const Substitution * pSubstForTypeLoad, |
2447 | Substitution * pSubstForComparing); |
2448 | |
2449 | public: |
2450 | // -------------------------------------------------------------------------------------------- |
2451 | // Interface ambiguity checks when loading exact interface instantiations |
2452 | // |
2453 | // These implement the check that the exact instantiation does not introduce any |
2454 | // ambiguity in the interface dispatch logic, i.e. amongst the freshly declared interfaces. |
2455 | |
2456 | struct bmtInterfaceAmbiguityCheckInfo |
2457 | { |
2458 | MethodTable *pMT; |
2459 | DWORD nAssigned; |
2460 | MethodTable **ppExactDeclaredInterfaces; |
2461 | Substitution **ppInterfaceSubstitutionChains; |
2462 | SigTypeContext typeContext; |
2463 | |
2464 | inline bmtInterfaceAmbiguityCheckInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } |
2465 | }; // struct bmtInterfaceAmbiguityCheckInfo |
2466 | |
2467 | static void |
2468 | InterfacesAmbiguityCheck( |
2469 | bmtInterfaceAmbiguityCheckInfo *, |
2470 | Module *pModule, |
2471 | mdToken typeDef, |
2472 | const Substitution *pSubstChain); |
2473 | |
2474 | private: |
2475 | static void |
2476 | InterfaceAmbiguityCheck( |
2477 | bmtInterfaceAmbiguityCheckInfo *, |
2478 | const Substitution *pSubstChain, |
2479 | MethodTable *pIntfMT); |
2480 | |
2481 | public: |
2482 | static void |
2483 | LoadExactInterfaceMap( |
2484 | MethodTable *pMT); |
2485 | |
2486 | // -------------------------------------------------------------------------------------------- |
2487 | // Copy virtual slots inherited from parent: |
2488 | // |
2489 | // In types created at runtime, inherited virtual slots are initialized using approximate parent |
2490 | // during method table building. This method will update them based on the exact parent. |
2491 | // In types loaded from NGen image, inherited virtual slots from cross-module parents are not |
2492 | // initialized. This method will initialize them based on the actually loaded exact parent |
2493 | // if necessary. |
2494 | // |
2495 | static void |
2496 | CopyExactParentSlots( |
2497 | MethodTable *pMT, |
2498 | MethodTable *pApproxParentMT); |
2499 | |
2500 | // -------------------------------------------------------------------------------------------- |
2501 | // This is used at load time, using metadata-based comparisons. It returns the array of dispatch |
2502 | // map TypeIDs to be used for pDeclIntfMT. |
2503 | // |
2504 | // Arguments: |
2505 | // rg/c DispatchMapTypeIDs - Array of TypeIDs and its count of elements. |
2506 | // pcIfaceDuplicates - Number of duplicate occurences of the interface in the interface map (ideally <= |
2507 | // count of elements TypeIDs). |
2508 | // |
2509 | void |
2510 | ComputeDispatchMapTypeIDs( |
2511 | MethodTable * pDeclInftMT, |
2512 | const Substitution * pDeclIntfSubst, |
2513 | DispatchMapTypeID * rgDispatchMapTypeIDs, |
2514 | UINT32 cDispatchMapTypeIDs, |
2515 | UINT32 * pcIfaceDuplicates); |
2516 | |
2517 | private: |
2518 | // -------------------------------------------------------------------------------------------- |
2519 | // Looks for a virtual method in the parent matching methodSig. pMethodConstraintsMatch is |
2520 | // set if a match is found indicating whether or not the method constraint check passes. |
2521 | bmtRTMethod * |
2522 | LoaderFindMethodInParentClass( |
2523 | const MethodSignature & methodSig, |
2524 | BOOL * pMethodConstraintsMatch); |
2525 | |
2526 | // -------------------------------------------------------------------------------------------- |
2527 | // |
2528 | VOID |
2529 | ResolveInterfaces( |
2530 | WORD cEntries, |
2531 | BuildingInterfaceInfo_t* pEntries); |
2532 | |
2533 | // -------------------------------------------------------------------------------------------- |
2534 | VOID |
2535 | ComputeModuleDependencies(); |
2536 | |
2537 | // -------------------------------------------------------------------------------------------- |
2538 | // Finds a method declaration from a MemberRef or Def. It handles the case where |
2539 | // the Ref or Def point back to this class even though it has not been fully |
2540 | // laid out. |
2541 | HRESULT |
2542 | FindMethodDeclarationForMethodImpl( |
2543 | mdToken pToken, // Token that is being located (MemberRef or MemberDef) |
2544 | mdToken* pDeclaration, // Method definition for Member |
2545 | BOOL fSameClass); // Does the declaration need to be in this class |
2546 | |
2547 | // -------------------------------------------------------------------------------------------- |
2548 | // Enumerates the method impl token pairs and resolves the impl tokens to mdtMethodDef |
2549 | // tokens, since we currently have the limitation that all impls are in the current class. |
2550 | VOID |
2551 | EnumerateMethodImpls(); |
2552 | |
2553 | // -------------------------------------------------------------------------------------------- |
2554 | // Enumerates the methods declared by the class and populates the bmtMethod member with |
2555 | // bmtMDMethods* for each declared method. |
2556 | VOID |
2557 | EnumerateClassMethods(); |
2558 | |
2559 | // -------------------------------------------------------------------------------------------- |
2560 | // Enumerates the fields declared by the type and populates bmtEnumFields. |
2561 | VOID |
2562 | EnumerateClassFields(); |
2563 | |
2564 | // -------------------------------------------------------------------------------------------- |
2565 | // Allocate temporary memory for tracking all information used in building the MethodTable |
2566 | VOID |
2567 | AllocateWorkingSlotTables(); |
2568 | |
2569 | // -------------------------------------------------------------------------------------------- |
2570 | // Allocates all of the FieldDeses required after enumerating the fields declared by the type. |
2571 | VOID |
2572 | AllocateFieldDescs(); |
2573 | |
2574 | // -------------------------------------------------------------------------------------------- |
2575 | // Initializes all allocated FieldDescs |
2576 | VOID |
2577 | InitializeFieldDescs( |
2578 | FieldDesc *, |
2579 | const LayoutRawFieldInfo*, |
2580 | bmtInternalInfo*, |
2581 | const bmtGenericsInfo*, |
2582 | bmtMetaDataInfo*, |
2583 | bmtEnumFieldInfo*, |
2584 | bmtErrorInfo*, |
2585 | MethodTable***, |
2586 | bmtMethAndFieldDescs*, |
2587 | bmtFieldPlacement*, |
2588 | unsigned * totalDeclaredSize); |
2589 | |
2590 | // -------------------------------------------------------------------------------------------- |
2591 | // Verify self-referencing static ValueType fields with RVA (when the size of the ValueType is known). |
2592 | void |
2593 | VerifySelfReferencingStaticValueTypeFields_WithRVA( |
2594 | MethodTable ** pByValueClassCache); |
2595 | |
2596 | // -------------------------------------------------------------------------------------------- |
2597 | // Returns TRUE if dwByValueClassToken refers to the type being built; otherwise returns FALSE. |
2598 | BOOL |
2599 | IsSelfReferencingStaticValueTypeField( |
2600 | mdToken dwByValueClassToken, |
2601 | bmtInternalInfo* bmtInternal, |
2602 | const bmtGenericsInfo * bmtGenericsInfo, |
2603 | PCCOR_SIGNATURE pMemberSignature, |
2604 | DWORD cMemberSignature); |
2605 | |
2606 | // -------------------------------------------------------------------------------------------- |
2607 | // Performs rudimentary stand-alone validation of methods declared by the type. |
2608 | VOID |
2609 | ValidateMethods(); |
2610 | |
2611 | // -------------------------------------------------------------------------------------------- |
2612 | // Initialize an allocated MethodDesc. |
2613 | VOID |
2614 | InitMethodDesc( |
2615 | MethodDesc * pNewMD, |
2616 | DWORD Classification, |
2617 | mdToken tok, |
2618 | DWORD dwImplFlags, |
2619 | DWORD dwMemberAttrs, |
2620 | BOOL fEnC, |
2621 | DWORD RVA, // Only needed for NDirect case |
2622 | IMDInternalImport * pIMDII, // Needed for NDirect, EEImpl(Delegate) cases |
2623 | LPCSTR pMethodName // Only needed for mcEEImpl (Delegate) case |
2624 | COMMA_INDEBUG(LPCUTF8 pszDebugMethodName) |
2625 | COMMA_INDEBUG(LPCUTF8 pszDebugClassName) |
2626 | COMMA_INDEBUG(LPCUTF8 pszDebugMethodSignature)); |
2627 | |
2628 | // -------------------------------------------------------------------------------------------- |
2629 | // Convert code:MethodTableBuilder::METHOD_TYPE to code:MethodClassification |
2630 | static DWORD |
2631 | GetMethodClassification(METHOD_TYPE type); |
2632 | |
2633 | // -------------------------------------------------------------------------------------------- |
2634 | // Essentially, this is a helper method that combines calls to InitMethodDesc and |
2635 | // SetSecurityFlagsOnMethod. It then assigns the newly initialized MethodDesc to |
2636 | // the bmtMDMethod. |
2637 | VOID |
2638 | InitNewMethodDesc( |
2639 | bmtMDMethod * pMethod, |
2640 | MethodDesc * pNewMD); |
2641 | |
2642 | // -------------------------------------------------------------------------------------------- |
2643 | // For every declared virtual method, determines if the method is an overload or requires a |
2644 | // new slot, performs the proper checks to ensure that an override is valid, and then |
2645 | // places the method in the appropriate slot in bmtVT and sets the SLOT_INDEX value in the |
2646 | // bmtMDMethod and it's MethodDesc. |
2647 | VOID |
2648 | PlaceVirtualMethods(); |
2649 | |
2650 | // -------------------------------------------------------------------------------------------- |
2651 | // For every declared non-virtual method, places the method in the next available slot in |
2652 | // the non-virtual section of bmtVT and sets the SLOT_INDEX value in the bmtMDMethod and it's |
2653 | // MethodDesc. |
2654 | VOID |
2655 | PlaceNonVirtualMethods(); |
2656 | |
2657 | // -------------------------------------------------------------------------------------------- |
2658 | // Determine the equivalence sets within the interface map |
2659 | // See comment in implementation for more details. |
2660 | VOID ComputeInterfaceMapEquivalenceSet(); |
2661 | |
2662 | // -------------------------------------------------------------------------------------------- |
2663 | // Given an interface in our interface map, and a particular method on that interface, place |
2664 | // a method from the parent types implementation of an equivalent interface into that method |
2665 | // slot. Used by PlaceInterfaceMethods to make equivalent interface implementations have the |
2666 | // same behavior as if the parent interface was implemented on this type instead of an equivalent interface. |
2667 | // See comment in implementation for example of where this is necessary. |
2668 | VOID PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot( |
2669 | bmtInterfaceEntry::InterfaceSlotIterator &itfSlotIt, |
2670 | bmtInterfaceEntry * pCurItfEntry, |
2671 | DispatchMapTypeID ** prgInterfaceDispatchMapTypeIDs, |
2672 | DWORD dwCurInterface); |
2673 | |
2674 | // -------------------------------------------------------------------------------------------- |
2675 | // Matches interface methods with implementation methods in this type or a parent type. |
2676 | // See comment in implementation for more details. |
2677 | VOID |
2678 | PlaceInterfaceMethods(); |
2679 | |
2680 | // -------------------------------------------------------------------------------------------- |
2681 | // For every MethodImpl pair (represented by Entry) in bmtMethodImpl, place the body in the |
2682 | // appropriate interface or virtual slot. |
2683 | VOID |
2684 | PlaceMethodImpls(); |
2685 | |
2686 | // -------------------------------------------------------------------------------------------- |
2687 | // This will take the array of bmtMetaData->rgMethodImplTokens and further resolve the tokens |
2688 | // to their corresponding bmtMDMethod or bmtRTMethod pointers and then populate the array |
2689 | // in bmtMethodImpl, which will be used by PlaceMethodImpls |
2690 | VOID |
2691 | ProcessMethodImpls(); |
2692 | |
2693 | // -------------------------------------------------------------------------------------------- |
2694 | // This will take the array of bmtMetaData->rgMethodImplTokens and further resolve the tokens |
2695 | // to their corresponding bmtMDMethod or bmtRTMethod pointers and then populate the array |
2696 | // in bmtMethodImpl for the methodimpls which can resolve to more than one declaration method, |
2697 | // which will be used by PlaceMethodImpls |
2698 | VOID |
2699 | ProcessInexactMethodImpls(); |
2700 | |
2701 | // -------------------------------------------------------------------------------------------- |
2702 | // Find the decl method on a given interface entry that matches the method name+signature specified |
2703 | // If none is found, return a null method handle |
2704 | bmtMethodHandle |
2705 | FindDeclMethodOnInterfaceEntry(bmtInterfaceEntry *pItfEntry, MethodSignature &declSig); |
2706 | |
2707 | // -------------------------------------------------------------------------------------------- |
2708 | // Throws if an entry already exists that has been MethodImpl'd. Adds the interface slot and |
2709 | // implementation method to the mapping used by virtual stub dispatch. |
2710 | VOID |
2711 | AddMethodImplDispatchMapping( |
2712 | DispatchMapTypeID typeID, |
2713 | SLOT_INDEX slotNumber, |
2714 | bmtMDMethod * pImplMethod); |
2715 | |
2716 | // -------------------------------------------------------------------------------------------- |
2717 | // Throws if the signatures (excluding names) are not equal or the constraints don't match. |
2718 | // dwConstraintErrorCode is an input argument that states what error to throw in such a case |
2719 | // as the constraints don't match. |
2720 | VOID |
2721 | MethodImplCompareSignatures( |
2722 | bmtMethodHandle hDecl, |
2723 | bmtMethodHandle hImpl, |
2724 | DWORD dwConstraintErrorCode); |
2725 | |
2726 | // -------------------------------------------------------------------------------------------- |
2727 | // This will provide the array of decls for the slots implemented by a methodImpl MethodDesc. |
2728 | // These are then used to map a slot in a MethodTable to the declaration method to be used in |
2729 | // name+sig matching through method calls and child types. |
2730 | VOID |
2731 | WriteMethodImplData( |
2732 | bmtMDMethod * pImplMethod, |
2733 | DWORD cSlots, |
2734 | DWORD * rgSlots, |
2735 | mdToken * rgTokens, |
2736 | RelativePointer<MethodDesc *> * rgDeclMD); |
2737 | |
2738 | // -------------------------------------------------------------------------------------------- |
2739 | // Places a methodImpl pair where the decl is declared by the type being built. |
2740 | VOID |
2741 | PlaceLocalDeclarationOnClass( |
2742 | bmtMDMethod * pDecl, |
2743 | bmtMDMethod * pImpl, |
2744 | DWORD* slots, |
2745 | RelativePointer<MethodDesc *> * replaced, |
2746 | DWORD* pSlotIndex, |
2747 | DWORD dwMaxSlotSize); |
2748 | |
2749 | // -------------------------------------------------------------------------------------------- |
2750 | // Places a methodImpl pair where the decl is declared by a parent type. |
2751 | VOID |
2752 | PlaceParentDeclarationOnClass( |
2753 | bmtRTMethod * pDecl, |
2754 | bmtMDMethod * pImpl, |
2755 | DWORD* slots, |
2756 | RelativePointer<MethodDesc *> * replaced, |
2757 | DWORD* pSlotIndex, |
2758 | DWORD dwMaxSlotSize); |
2759 | |
2760 | // -------------------------------------------------------------------------------------------- |
2761 | // Places a methodImpl pair on a class where the decl is declared by an interface. |
2762 | VOID |
2763 | PlaceInterfaceDeclarationOnClass( |
2764 | bmtRTMethod * pDecl, |
2765 | bmtMDMethod * pImpl); |
2766 | |
2767 | // -------------------------------------------------------------------------------------------- |
2768 | // Places a methodImpl pair on an interface where the decl is declared by an interface. |
2769 | VOID |
2770 | PlaceInterfaceDeclarationOnInterface( |
2771 | bmtMethodHandle hDecl, |
2772 | bmtMDMethod * pImpl, |
2773 | DWORD* slots, |
2774 | RelativePointer<MethodDesc *> * replaced, |
2775 | DWORD* pSlotIndex, |
2776 | DWORD dwMaxSlotSize); |
2777 | |
2778 | // -------------------------------------------------------------------------------------------- |
2779 | // This will validate that all interface methods that were matched during |
2780 | // layout also validate against type constraints. |
2781 | VOID |
2782 | ValidateInterfaceMethodConstraints(); |
2783 | |
2784 | // -------------------------------------------------------------------------------------------- |
2785 | // Used to allocate and initialize MethodDescs (both the boxed and unboxed entrypoints) |
2786 | VOID |
2787 | AllocAndInitMethodDescs(); |
2788 | |
2789 | // -------------------------------------------------------------------------------------------- |
2790 | // Allocates and initializes one method desc chunk. |
2791 | // |
2792 | // Arguments: |
2793 | // startIndex - index of first method in bmtMethod array. |
2794 | // count - number of methods in this chunk (contiguous region from startIndex) |
2795 | // sizeOfMethodDescs - total expected size of MethodDescs in this chunk |
2796 | // |
2797 | // Used by AllocAndInitMethodDescs. |
2798 | // |
2799 | VOID |
2800 | AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T count, SIZE_T sizeOfMethodDescs); |
2801 | |
2802 | // -------------------------------------------------------------------------------------------- |
2803 | // MethodTableBuilder equivant of |
2804 | // code:MethodDesc::IsUnboxingStub && code:MethodDesc::IsTightlyBoundToMethodTable. |
2805 | // Returns true if the MethodTable has to have true slot for unboxing stub of this method. |
2806 | // Used for MethodDesc layout. |
2807 | BOOL |
2808 | NeedsTightlyBoundUnboxingStub(bmtMDMethod * pMDMethod); |
2809 | |
2810 | // -------------------------------------------------------------------------------------------- |
2811 | // MethodTableBuilder equivalent of code:MethodDesc::HasNativeCodeSlot. |
2812 | // Used for MethodDesc layout. |
2813 | BOOL |
2814 | NeedsNativeCodeSlot(bmtMDMethod * pMDMethod); |
2815 | |
2816 | // -------------------------------------------------------------------------------------------- |
2817 | // Used to allocate and initialize the dictionary used with generic types. |
2818 | VOID |
2819 | AllocAndInitDictionary(); |
2820 | |
2821 | VOID |
2822 | PlaceRegularStaticFields(); |
2823 | |
2824 | VOID |
2825 | PlaceThreadStaticFields(); |
2826 | |
2827 | VOID |
2828 | PlaceInstanceFields( |
2829 | MethodTable **); |
2830 | |
2831 | BOOL |
2832 | CheckForVtsEventMethod( |
2833 | IMDInternalImport *pImport, |
2834 | MethodDesc *pMD, |
2835 | DWORD dwAttrs, |
2836 | LPCUTF8 szAttrName, |
2837 | MethodDesc **ppMethodDesc); |
2838 | |
2839 | |
2840 | VOID |
2841 | CheckForSystemTypes(); |
2842 | |
2843 | VOID SetupMethodTable2( |
2844 | Module* pLoaderModule |
2845 | #ifdef FEATURE_PREJIT |
2846 | , Module* pComputedPZM |
2847 | #endif // FEATURE_PREJIT |
2848 | ); |
2849 | |
2850 | VOID HandleGCForValueClasses( |
2851 | MethodTable **); |
2852 | |
2853 | BOOL HasDefaultInterfaceImplementation(bmtRTType *pIntfType, MethodDesc *pIntfMD); |
2854 | VOID VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData); |
2855 | |
2856 | VOID CheckForTypeEquivalence( |
2857 | WORD cBuildingInterfaceList, |
2858 | BuildingInterfaceInfo_t *pBuildingInterfaceList); |
2859 | |
2860 | VOID EnsureRIDMapsCanBeFilled(); |
2861 | |
2862 | VOID CheckForRemotingProxyAttrib(); |
2863 | |
2864 | #ifdef FEATURE_COMINTEROP |
2865 | |
2866 | VOID GetCoClassAttribInfo(); |
2867 | |
2868 | #endif // FEATURE_COMINTEROP |
2869 | |
2870 | VOID CheckForSpecialTypes(); |
2871 | |
2872 | #ifdef FEATURE_READYTORUN |
2873 | |
2874 | VOID CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT); |
2875 | |
2876 | BOOL NeedsAlignedBaseOffset(); |
2877 | |
2878 | #endif // FEATURE_READYTORUN |
2879 | |
2880 | VOID SetFinalizationSemantics(); |
2881 | |
2882 | VOID HandleExplicitLayout( |
2883 | MethodTable **pByValueClassCache); |
2884 | |
2885 | static ExplicitFieldTrust::TrustLevel CheckValueClassLayout( |
2886 | MethodTable * pMT, |
2887 | BYTE * pFieldLayout, |
2888 | DWORD * pFirstObjectOverlapOffset); |
2889 | |
2890 | void FindPointerSeriesExplicit( |
2891 | UINT instanceSliceSize, |
2892 | BYTE * pFieldLayout); |
2893 | |
2894 | VOID HandleGCForExplicitLayout(); |
2895 | |
2896 | VOID CheckForHFA(MethodTable ** pByValueClassCache); |
2897 | |
2898 | VOID CheckForNativeHFA(); |
2899 | |
2900 | #ifdef UNIX_AMD64_ABI |
2901 | // checks whether the struct is enregisterable. |
2902 | void SystemVAmd64CheckForPassStructInRegister(); |
2903 | void SystemVAmd64CheckForPassNativeStructInRegister(); |
2904 | // Store the eightbyte classification into the EEClass |
2905 | void StoreEightByteClassification(SystemVStructRegisterPassingHelper* helper); |
2906 | |
2907 | #endif // UNIX_AMD64_ABI |
2908 | |
2909 | // this accesses the field size which is temporarily stored in m_pMTOfEnclosingClass |
2910 | // during class loading. Don't use any other time |
2911 | DWORD GetFieldSize(FieldDesc *pFD); |
2912 | |
2913 | bool IsEnclosingNestedTypePair( |
2914 | bmtTypeHandle hBase, |
2915 | bmtTypeHandle hChild); |
2916 | |
2917 | bool IsBaseTypeAlsoEnclosingType( |
2918 | bmtTypeHandle hBase, |
2919 | bmtTypeHandle hChild); |
2920 | |
2921 | BOOL TestOverrideForAccessibility( |
2922 | bmtMethodHandle hParentMethod, |
2923 | bmtTypeHandle hChildType); |
2924 | |
2925 | VOID TestOverRide( |
2926 | bmtMethodHandle hParentMethod, |
2927 | bmtMethodHandle hChildMethod); |
2928 | |
2929 | VOID TestMethodImpl( |
2930 | bmtMethodHandle hDeclMethod, |
2931 | bmtMethodHandle hImplMethod); |
2932 | |
2933 | // Heuristic to detemine if we would like instances of this class 8 byte aligned |
2934 | BOOL ShouldAlign8( |
2935 | DWORD dwR8Fields, |
2936 | DWORD dwTotalFields); |
2937 | |
2938 | MethodTable * AllocateNewMT(Module *pLoaderModule, |
2939 | DWORD dwVtableSlots, |
2940 | DWORD dwVirtuals, |
2941 | DWORD dwGCSize, |
2942 | DWORD dwNumInterfaces, |
2943 | DWORD dwNumDicts, |
2944 | DWORD dwNumTypeSlots, |
2945 | MethodTable *pMTParent, |
2946 | ClassLoader *pClassLoader, |
2947 | LoaderAllocator *pAllocator, |
2948 | BOOL isIFace, |
2949 | BOOL fDynamicStatics, |
2950 | BOOL fHasGenericsStaticsInfo, |
2951 | BOOL fNeedsRCWPerTypeData |
2952 | #ifdef FEATURE_COMINTEROP |
2953 | , BOOL bHasDynamicInterfaceMap |
2954 | #endif |
2955 | #ifdef FEATURE_PREJIT |
2956 | , Module *pComputedPZM |
2957 | #endif // FEATURE_PREJIT |
2958 | , AllocMemTracker *pamTracker |
2959 | ); |
2960 | |
2961 | }; // class MethodTableBuilder |
2962 | |
2963 | #include "methodtablebuilder.inl" |
2964 | |
2965 | #endif // !METHODTABLEBUILDER_H |
2966 | |