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//
34class MethodTableBuilder
35{
36
37public:
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 }
110public:
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
145private:
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
166private:
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 ************************************/
263private:
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
2369private:
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
2404public:
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
2423private:
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
2432public:
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
2449public:
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
2474private:
2475 static void
2476 InterfaceAmbiguityCheck(
2477 bmtInterfaceAmbiguityCheckInfo *,
2478 const Substitution *pSubstChain,
2479 MethodTable *pIntfMT);
2480
2481public:
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
2517private:
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