b12542a1e7352c3b2e431b572a44fbb273effcfb
[platform/upstream/dotnet/runtime.git] / src / coreclr / vm / methodtable.h
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 //
4 // File: methodtable.h
5 //
6
7 #ifndef _METHODTABLE_H_
8 #define _METHODTABLE_H_
9
10 /*
11  *  Include Files
12  */
13 #include "vars.hpp"
14 #include "cor.h"
15 #include "hash.h"
16 #include "crst.h"
17 #include "cgensys.h"
18 #ifdef FEATURE_COMINTEROP
19 #include "stdinterfaces.h"
20 #endif
21 #include "slist.h"
22 #include "spinlock.h"
23 #include "typehandle.h"
24 #include "eehash.h"
25 #include "contractimpl.h"
26 #include "generics.h"
27 #include "gcinfotypes.h"
28 #include "enum_class_flags.h"
29
30 /*
31  * Forward Declarations
32  */
33 class    AppDomain;
34 class    ArrayClass;
35 class    ArrayMethodDesc;
36 class ClassLoader;
37 class FCallMethodDesc;
38 class    EEClass;
39 class    EnCFieldDesc;
40 class FieldDesc;
41 class JIT_TrialAlloc;
42 struct LayoutRawFieldInfo;
43 class MetaSig;
44 class    MethodDesc;
45 class    MethodDescChunk;
46 class    MethodTable;
47 class    Module;
48 class    Object;
49 class    Stub;
50 class    Substitution;
51 class    TypeHandle;
52 class   Dictionary;
53 class   AllocMemTracker;
54 class   SimpleRWLock;
55 class   MethodDataCache;
56 class   EEClassLayoutInfo;
57 class   EEClassNativeLayoutInfo;
58 #ifdef FEATURE_COMINTEROP
59 class   ComCallWrapperTemplate;
60 #endif
61 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
62 class ClassFactoryBase;
63 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
64 class ArgDestination;
65 enum class WellKnownAttribute : DWORD;
66
67 enum class ResolveVirtualStaticMethodFlags
68 {
69     None = 0,
70     AllowNullResult = 1,
71     VerifyImplemented = 2,
72     AllowVariantMatches = 4,
73     InstantiateResultOverFinalMethodDesc = 8,
74
75     support_use_as_flags // Enable the template functions in enum_class_flags.h
76 };
77
78
79 enum class FindDefaultInterfaceImplementationFlags
80 {
81     None,
82     AllowVariance = 1,
83     ThrowOnConflict = 2,
84     InstantiateFoundMethodDesc = 4,
85
86     support_use_as_flags // Enable the template functions in enum_class_flags.h
87 };
88
89 //============================================================================
90 // This is the in-memory structure of a class and it will evolve.
91 //============================================================================
92
93 // <TODO>
94 // Add a sync block
95 // Also this class currently has everything public - this may changes
96 // Might also need to hold onto the meta data loader fot this class</TODO>
97
98 //
99 // A MethodTable contains an array of these structures, which describes each interface implemented
100 // by this class (directly declared or indirectly declared).
101 //
102 // Generic type instantiations (in C# syntax: C<ty_1,...,ty_n>) are represented by
103 // MethodTables, i.e. a new MethodTable gets allocated for each such instantiation.
104 // The entries in these tables (i.e. the code) are, however, often shared.
105 //
106 // In particular, a MethodTable's vtable contents (and hence method descriptors) may be
107 // shared between compatible instantiations (e.g. List<string> and List<object> have
108 // the same vtable *contents*).  Likewise the EEClass will be shared between
109 // compatible instantiations whenever the vtable contents are.
110 //
111 // !!! Thus that it is _not_ generally the case that GetClass.GetMethodTable() == t. !!!
112 //
113 // Instantiated interfaces have their own method tables unique to the instantiation e.g. I<string> is
114 // distinct from I<int> and I<object>
115 //
116 // For generic types the interface map lists generic interfaces
117 // For instantiated types the interface map lists instantiated interfaces
118 //   e.g. for C<T> : I<T>, J<string>
119 // the interface map for C would list I and J
120 // the interface map for C<int> would list I<int> and J<string>
121 //
122 struct InterfaceInfo_t
123 {
124
125     // Method table of the interface
126     PTR_MethodTable m_pMethodTable;
127
128 public:
129     FORCEINLINE PTR_MethodTable GetMethodTable()
130     {
131         LIMITED_METHOD_CONTRACT;
132         return VolatileLoadWithoutBarrier(&m_pMethodTable);
133     }
134
135 #ifndef DACCESS_COMPILE
136     void SetMethodTable(MethodTable * pMT)
137     {
138         LIMITED_METHOD_CONTRACT;
139         return VolatileStoreWithoutBarrier(&m_pMethodTable, pMT);
140     }
141
142     // Get approximate method table. This is used by the type loader before the type is fully loaded.
143     PTR_MethodTable GetApproxMethodTable(Module * pContainingModule);
144 #endif // !DACCESS_COMPILE
145
146 #ifndef DACCESS_COMPILE
147     InterfaceInfo_t(InterfaceInfo_t &right)
148     {
149         VolatileStoreWithoutBarrier(&m_pMethodTable, VolatileLoadWithoutBarrier(&right.m_pMethodTable));
150     }
151 #else // !DACCESS_COMPILE
152 private:
153     InterfaceInfo_t(InterfaceInfo_t &right);
154 #endif // !DACCESS_COMPILE
155 };  // struct InterfaceInfo_t
156
157 typedef DPTR(InterfaceInfo_t) PTR_InterfaceInfo;
158
159 namespace ClassCompat
160 {
161     struct InterfaceInfo_t;
162 };
163
164 // Data needed when simulating old VTable layout for COM Interop
165 // This is necessary as the data is saved in MethodDescs and we need
166 // to simulate different values without copying or changing the existing
167 // MethodDescs
168 //
169 // This will be created in a parallel array to ppMethodDescList and
170 // ppUnboxMethodDescList in the bmtMethAndFieldDescs structure below
171 struct InteropMethodTableSlotData
172 {
173     enum
174     {
175         e_DUPLICATE = 0x0001              // The entry is duplicate
176     };
177
178     MethodDesc *pMD;                // The MethodDesc for this slot
179     WORD        wSlot;              // The simulated slot value for the MethodDesc
180     WORD        wFlags;             // The simulated duplicate value
181     MethodDesc *pDeclMD;            // To keep track of MethodImpl's
182
183     void SetDuplicate()
184     {
185         wFlags |= e_DUPLICATE;
186     }
187
188     BOOL IsDuplicate() {
189         return ((BOOL)(wFlags & e_DUPLICATE));
190     }
191
192     WORD GetSlot() {
193         return wSlot;
194     }
195
196     void SetSlot(WORD wSlot) {
197         this->wSlot = wSlot;
198     }
199 };  // struct InteropMethodTableSlotData
200
201 #ifdef FEATURE_COMINTEROP
202 struct InteropMethodTableData
203 {
204     WORD cVTable;                          // Count of vtable slots
205     InteropMethodTableSlotData *pVTable;    // Data for each slot
206
207     WORD cNonVTable;                       // Count of non-vtable slots
208     InteropMethodTableSlotData *pNonVTable; // Data for each slot
209
210     WORD            cInterfaceMap;         // Count of interfaces
211     ClassCompat::InterfaceInfo_t *
212                     pInterfaceMap;         // The interface map
213
214     // Utility methods
215     static WORD GetRealMethodDesc(MethodTable *pMT, MethodDesc *pMD);
216     static WORD GetSlotForMethodDesc(MethodTable *pMT, MethodDesc *pMD);
217     ClassCompat::InterfaceInfo_t* FindInterface(MethodTable *pInterface);
218     WORD GetStartSlotForInterface(MethodTable* pInterface);
219 };
220
221 class InteropMethodTableSlotDataMap
222 {
223 protected:
224     InteropMethodTableSlotData *m_pSlotData;
225     DWORD                       m_cSlotData;
226     DWORD                       m_iCurSlot;
227
228 public:
229     InteropMethodTableSlotDataMap(InteropMethodTableSlotData *pSlotData, DWORD cSlotData);
230     InteropMethodTableSlotData *GetData(MethodDesc *pMD);
231     BOOL Exists(MethodDesc *pMD);
232
233 protected:
234     InteropMethodTableSlotData *Exists_Helper(MethodDesc *pMD);
235     InteropMethodTableSlotData *GetNewEntry();
236 };  // class InteropMethodTableSlotDataMap
237 #endif // FEATURE_COMINTEROP
238
239 //
240 // This struct contains cached information on the GUID associated with a type.
241 //
242
243 struct GuidInfo
244 {
245     GUID         m_Guid;                // The actual guid of the type.
246     BOOL         m_bGeneratedFromName;  // A boolean indicating if it was generated from the
247                                         // name of the type.
248 };
249
250 typedef DPTR(GuidInfo) PTR_GuidInfo;
251
252
253 // GenericsDictInfo is stored at negative offset of the dictionary
254 struct GenericsDictInfo
255 {
256 #ifdef HOST_64BIT
257     DWORD m_dwPadding;               // Just to keep the size a multiple of 8
258 #endif
259
260     // Total number of instantiation dictionaries including inherited ones
261     //   i.e. how many instantiated classes (including this one) are there in the hierarchy?
262     // See comments about PerInstInfo
263     WORD   m_wNumDicts;
264
265     // Number of type parameters (NOT including those of superclasses).
266     WORD   m_wNumTyPars;
267 };  // struct GenericsDictInfo
268 typedef DPTR(GenericsDictInfo) PTR_GenericsDictInfo;
269
270 struct GenericsStaticsInfo
271 {
272     // Pointer to field descs for statics
273     PTR_FieldDesc       m_pFieldDescs;
274
275     // Method table ID for statics
276     SIZE_T              m_DynamicTypeID;
277
278 };  // struct GenericsStaticsInfo
279 typedef DPTR(GenericsStaticsInfo) PTR_GenericsStaticsInfo;
280
281 //
282 // This struct consolidates the writeable parts of the MethodTable
283 // so that we can layout a read-only MethodTable with a pointer
284 // to the writeable parts of the MethodTable in an ngen image
285 //
286 struct MethodTableWriteableData
287 {
288     friend class MethodTable;
289 #if defined(DACCESS_COMPILE)
290     friend class NativeImageDumper;
291 #endif
292
293     enum
294     {
295         // AS YOU ADD NEW FLAGS PLEASE CONSIDER WHETHER Generics::NewInstantiation NEEDS
296         // TO BE UPDATED IN ORDER TO ENSURE THAT METHODTABLES DUPLICATED FOR GENERIC INSTANTIATIONS
297         // CARRY THE CORRECT INITIAL FLAGS.
298
299         enum_flag_Unrestored                = 0x00000004,
300         enum_flag_HasApproxParent           = 0x00000010,
301         enum_flag_UnrestoredTypeKey         = 0x00000020,
302         enum_flag_IsNotFullyLoaded          = 0x00000040,
303         enum_flag_DependenciesLoaded        = 0x00000080,     // class and all dependencies loaded up to CLASS_LOADED_BUT_NOT_VERIFIED
304
305         // enum_unused                      = 0x00000100,
306
307         enum_flag_CanCompareBitsOrUseFastGetHashCode       = 0x00000200,     // Is any field type or sub field type overrode Equals or GetHashCode
308         enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode   = 0x00000400,  // Whether we have checked the overridden Equals or GetHashCode
309
310         // enum_unused                      = 0x00010000,
311         // enum_unused                      = 0x00020000,
312         // enum_unused                      = 0x00040000,
313         // enum_unused                      = 0x00080000,        // enum_unused                      = 0x0010000,
314         // enum_unused                      = 0x0020000,
315         // enum_unused                      = 0x0040000,
316         // enum_unused                      = 0x0080000,
317
318 #ifdef _DEBUG
319         enum_flag_ParentMethodTablePointerValid =  0x40000000,
320         enum_flag_HasInjectedInterfaceDuplicates = 0x80000000,
321 #endif
322     };
323     DWORD      m_dwFlags;                  // Lot of empty bits here.
324
325     // Non-unloadable context: internal RuntimeType object handle
326     // Unloadable context: slot index in LoaderAllocator's pinned table
327     RUNTIMETYPEHANDLE m_hExposedClassObject;
328
329 #ifdef _DEBUG
330     // to avoid verify same method table too many times when it's not changing, we cache the GC count
331     // on which the method table is verified. When fast GC STRESS is turned on, we only verify the MT if
332     // current GC count is bigger than the number. Note most thing which will invalidate a MT will require a
333     // GC (like AD unload)
334     Volatile<DWORD> m_dwLastVerifedGCCnt;
335
336 #ifdef HOST_64BIT
337     DWORD m_dwPadding;               // Just to keep the size a multiple of 8
338 #endif
339
340 #endif
341
342 public:
343 #ifdef _DEBUG
344     inline BOOL IsParentMethodTablePointerValid() const
345     {
346         LIMITED_METHOD_DAC_CONTRACT;
347
348         return (m_dwFlags & enum_flag_ParentMethodTablePointerValid);
349     }
350     inline void SetParentMethodTablePointerValid()
351     {
352         LIMITED_METHOD_CONTRACT;
353
354         m_dwFlags |= enum_flag_ParentMethodTablePointerValid;
355     }
356 #endif
357
358
359     inline RUNTIMETYPEHANDLE GetExposedClassObjectHandle() const
360     {
361         LIMITED_METHOD_CONTRACT;
362         return m_hExposedClassObject;
363     }
364
365     void SetIsNotFullyLoadedForBuildMethodTable()
366     {
367         LIMITED_METHOD_CONTRACT;
368
369         // Used only during method table initialization - no need for logging or Interlocked Exchange.
370         m_dwFlags |= (MethodTableWriteableData::enum_flag_UnrestoredTypeKey |
371                       MethodTableWriteableData::enum_flag_Unrestored |
372                       MethodTableWriteableData::enum_flag_IsNotFullyLoaded |
373                       MethodTableWriteableData::enum_flag_HasApproxParent);
374     }
375
376     void SetIsRestoredForBuildMethodTable()
377     {
378         LIMITED_METHOD_CONTRACT;
379
380         // Used only during method table initialization - no need for logging or Interlocked Exchange.
381         m_dwFlags &= ~(MethodTableWriteableData::enum_flag_UnrestoredTypeKey |
382                        MethodTableWriteableData::enum_flag_Unrestored);
383     }
384
385     void SetIsRestoredForBuildArrayMethodTable()
386     {
387         LIMITED_METHOD_CONTRACT;
388
389         // Used only during method table initialization - no need for logging or Interlocked Exchange.
390         SetIsRestoredForBuildMethodTable();
391
392         // Array's parent is always precise
393         m_dwFlags &= ~(MethodTableWriteableData::enum_flag_HasApproxParent);
394
395     }
396 };  // struct MethodTableWriteableData
397
398 typedef DPTR(MethodTableWriteableData) PTR_MethodTableWriteableData;
399 typedef DPTR(MethodTableWriteableData const) PTR_Const_MethodTableWriteableData;
400
401 #ifdef UNIX_AMD64_ABI_ITF
402 inline
403 SystemVClassificationType CorInfoType2UnixAmd64Classification(CorElementType eeType)
404 {
405     static const SystemVClassificationType toSystemVAmd64ClassificationTypeMap[] = {
406         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_END
407         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_VOID
408         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_BOOLEAN
409         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_CHAR
410         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_I1
411         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_U1
412         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_I2
413         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_U2
414         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_I4
415         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_U4
416         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_I8
417         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_U8
418         SystemVClassificationTypeSSE,                   // ELEMENT_TYPE_R4
419         SystemVClassificationTypeSSE,                   // ELEMENT_TYPE_R8
420         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_STRING
421         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_PTR
422         SystemVClassificationTypeIntegerByRef,          // ELEMENT_TYPE_BYREF
423         SystemVClassificationTypeStruct,                // ELEMENT_TYPE_VALUETYPE
424         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_CLASS
425         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_VAR (type variable)
426         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_ARRAY
427         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_GENERICINST
428         SystemVClassificationTypeStruct,                // ELEMENT_TYPE_TYPEDBYREF
429         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED
430         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_I
431         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_U
432         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_R_UNSUPPORTED
433
434         // put the correct type when we know our implementation
435         SystemVClassificationTypeInteger,               // ELEMENT_TYPE_FNPTR
436         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_OBJECT
437         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_SZARRAY
438         SystemVClassificationTypeIntegerReference,      // ELEMENT_TYPE_MVAR
439
440         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_CMOD_REQD
441         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_CMOD_OPT
442         SystemVClassificationTypeUnknown,               // ELEMENT_TYPE_INTERNAL
443     };
444
445     _ASSERTE(sizeof(toSystemVAmd64ClassificationTypeMap) == ELEMENT_TYPE_MAX);
446     _ASSERTE(eeType < (CorElementType) sizeof(toSystemVAmd64ClassificationTypeMap));
447     // spot check of the map
448     _ASSERTE((SystemVClassificationType)toSystemVAmd64ClassificationTypeMap[ELEMENT_TYPE_I4] == SystemVClassificationTypeInteger);
449     _ASSERTE((SystemVClassificationType)toSystemVAmd64ClassificationTypeMap[ELEMENT_TYPE_PTR] == SystemVClassificationTypeInteger);
450     _ASSERTE((SystemVClassificationType)toSystemVAmd64ClassificationTypeMap[ELEMENT_TYPE_VALUETYPE] == SystemVClassificationTypeStruct);
451     _ASSERTE((SystemVClassificationType)toSystemVAmd64ClassificationTypeMap[ELEMENT_TYPE_TYPEDBYREF] == SystemVClassificationTypeStruct);
452     _ASSERTE((SystemVClassificationType)toSystemVAmd64ClassificationTypeMap[ELEMENT_TYPE_BYREF] == SystemVClassificationTypeIntegerByRef);
453
454     return (((unsigned)eeType) < ELEMENT_TYPE_MAX) ? (toSystemVAmd64ClassificationTypeMap[(unsigned)eeType]) : SystemVClassificationTypeUnknown;
455 };
456
457 #define SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES                    8 // Size of an eightbyte in bytes.
458 #define SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT    16 // Maximum number of fields in struct passed in registers
459
460 struct SystemVStructRegisterPassingHelper
461 {
462     SystemVStructRegisterPassingHelper(unsigned int totalStructSize) :
463         structSize(totalStructSize),
464         eightByteCount(0),
465         inEmbeddedStruct(false),
466         currentUniqueOffsetField(0),
467         largestFieldOffset(-1)
468     {
469         for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++)
470         {
471             eightByteClassifications[i] = SystemVClassificationTypeNoClass;
472             eightByteSizes[i] = 0;
473             eightByteOffsets[i] = 0;
474         }
475
476         // Initialize the work arrays
477         for (int i = 0; i < SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT; i++)
478         {
479             fieldClassifications[i] = SystemVClassificationTypeNoClass;
480             fieldSizes[i] = 0;
481             fieldOffsets[i] = 0;
482         }
483     }
484
485     // Input state.
486     unsigned int                    structSize;
487
488     // These fields are the output; these are what is computed by the classification algorithm.
489     unsigned int                    eightByteCount;
490     SystemVClassificationType       eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
491     unsigned int                    eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
492     unsigned int                    eightByteOffsets[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
493
494     // Helper members to track state.
495     bool                            inEmbeddedStruct;
496     unsigned int                    currentUniqueOffsetField; // A virtual field that could encompass many overlapping fields.
497     int                             largestFieldOffset;
498     SystemVClassificationType       fieldClassifications[SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT];
499     unsigned int                    fieldSizes[SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT];
500     unsigned int                    fieldOffsets[SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT];
501 };
502
503 typedef DPTR(SystemVStructRegisterPassingHelper) SystemVStructRegisterPassingHelperPtr;
504
505 #endif // UNIX_AMD64_ABI_ITF
506
507 //===============================================================================================
508 //
509 // GC data appears before the beginning of the MethodTable
510 //
511 //@GENERICS:
512 // Each generic type has a corresponding "generic" method table that serves the following
513 // purposes:
514 // * The method table pointer is used as a representative for the generic type e.g. in reflection
515 // * MethodDescs for methods in the vtable are used for reflection; they should never be invoked.
516 // Some other information (e.g. BaseSize) makes no sense "generically" but unfortunately gets put in anyway.
517 //
518 // Each distinct instantiation of a generic type has its own MethodTable structure.
519 // However, the EEClass structure can be shared between compatible instantiations e.g. List<string> and List<object>.
520 // In that case, MethodDescs are also shared between compatible instantiations (but see below about generic methods).
521 // Hence the vtable entries for MethodTables belonging to such an EEClass are the same.
522 //
523 // The non-vtable section of such MethodTables are only present for one of the instantiations (the first one
524 // requested) as non-vtable entries are never accessed through the vtable pointer of an object so it's always possible
525 // to ensure that they are accessed through the representative MethodTable that contains them.
526
527 // A MethodTable is the fundamental representation of type in the runtime.  It is this structure that
528 // objects point at (see code:Object).  It holds the size and GC layout of the type, as well as the dispatch table
529 // for virtual dispach (but not interface dispatch).  There is a distinct method table for every instance of
530 // a generic type. From here you can get to
531 //
532 // * code:EEClass
533 //
534 // Important fields
535 //     * code:MethodTable.m_pEEClass - pointer to the cold part of the type.
536 //     * code:MethodTable.m_pParentMethodTable - the method table of the parent type.
537 //
538 class MethodTableBuilder;
539 class MethodTable
540 {
541     /************************************
542      *  FRIEND FUNCTIONS
543      ************************************/
544     // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
545     // USE ACCESSORS TO READ/WRITE private field members
546
547     // Special access for setting up String object method table correctly
548     friend class ClassLoader;
549     friend class JIT_TrialAlloc;
550     friend class Module;
551     friend class EEClass;
552     friend class MethodTableBuilder;
553     friend class CheckAsmOffsets;
554 #if defined(DACCESS_COMPILE)
555     friend class NativeImageDumper;
556 #endif
557
558 public:
559     // Do some sanity checking to make sure it's a method table
560     // and not pointing to some random memory.  In particular
561     // check that (apart from the special case of instantiated generic types) we have
562     // GetCanonicalMethodTable() == this;
563     BOOL SanityCheck();
564
565     static void         CallFinalizer(Object *obj);
566
567 public:
568     PTR_Module GetModule();
569     Assembly *GetAssembly();
570
571     PTR_Module GetModuleIfLoaded();
572
573     // GetDomain on an instantiated type, e.g. C<ty1,ty2> returns the SharedDomain if all the
574     // constituent parts of the type are SharedDomain (i.e. domain-neutral),
575     // and returns an AppDomain if any of the parts are from an AppDomain,
576     // i.e. are domain-bound.  Note that if any of the parts are domain-bound
577     // then they will all belong to the same domain.
578     PTR_BaseDomain GetDomain();
579
580     // For regular, non-constructed types, GetLoaderModule() == GetModule()
581     // For constructed types (e.g. int[], Dict<int[], C>) the hash table through which a type
582     // is accessed lives in a "loader module". The rule for determining the loader module must ensure
583     // that a type never outlives its loader module with respect to app-domain unloading
584     //
585     // GetModuleForStatics() is the third kind of module. GetModuleForStatics() is module that
586     // statics are attached to.
587     PTR_Module GetLoaderModule();
588     PTR_LoaderAllocator GetLoaderAllocator();
589
590     void SetLoaderModule(Module* pModule);
591     void SetLoaderAllocator(LoaderAllocator* pAllocator);
592
593     // Get the domain local module - useful for static init checks
594     PTR_DomainLocalModule   GetDomainLocalModule();
595
596     MethodTable *LoadEnclosingMethodTable(ClassLoadLevel targetLevel = CLASS_DEPENDENCIES_LOADED);
597
598     LPCWSTR GetPathForErrorMessages();
599
600     //-------------------------------------------------------------------
601     // COM INTEROP
602     //
603
604 #ifdef FEATURE_COMINTEROP
605     TypeHandle GetCoClassForInterface();
606
607 private:
608     TypeHandle SetupCoClassForInterface();
609
610 public:
611     DWORD IsComClassInterface();
612
613     // Retrieves the COM interface type.
614     CorIfaceAttr    GetComInterfaceType();
615     void SetComInterfaceType(CorIfaceAttr ItfType);
616
617     OBJECTHANDLE GetOHDelegate();
618     void SetOHDelegate (OBJECTHANDLE _ohDelegate);
619
620     CorClassIfaceAttr GetComClassInterfaceType();
621     TypeHandle GetDefItfForComClassItf();
622
623     void GetEventInterfaceInfo(MethodTable **ppSrcItfType, MethodTable **ppEvProvType);
624
625     BOOL            IsExtensibleRCW();
626
627     // Helper to get parent class skipping over COM class in
628     // the hierarchy
629     MethodTable* GetComPlusParentMethodTable();
630
631     DWORD IsComImport();
632
633     // class is a special COM event interface
634     int IsComEventItfType();
635
636     //-------------------------------------------------------------------
637     // Sparse VTables.   These require a SparseVTableMap in the EEClass in
638     // order to record how the CLR's vtable slots map across to COM
639     // Interop slots.
640     //
641     int IsSparseForCOMInterop();
642
643     // COM interop helpers
644     // accessors for m_pComData
645     ComCallWrapperTemplate *GetComCallWrapperTemplate();
646     BOOL                    SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate);
647 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
648     ClassFactoryBase       *GetComClassFactory();
649     BOOL                    SetComClassFactory(ClassFactoryBase *pFactory);
650 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
651
652     OBJECTREF GetObjCreateDelegate();
653     void SetObjCreateDelegate(OBJECTREF orDelegate);
654
655 private:
656     // This is for COM Interop backwards compatibility
657     BOOL InsertComInteropData(InteropMethodTableData *pData);
658     InteropMethodTableData *CreateComInteropData(AllocMemTracker *pamTracker);
659
660 public:
661     InteropMethodTableData *LookupComInteropData();
662     // This is the preferable entrypoint, as it will make sure that all
663     // parent MT's have their interop data created, and will create and
664     // add this MT's data if not available. The caller should make sure that
665     // an appropriate lock is taken to prevent duplicates.
666     // NOTE: The current caller of this is ComInterop, and it makes calls
667     // under its own lock to ensure not duplicates.
668     InteropMethodTableData *GetComInteropData();
669 #endif // !FEATURE_COMINTEROP
670
671     // class is a com object class
672     BOOL IsComObjectType()
673     {
674         LIMITED_METHOD_DAC_CONTRACT;
675         return GetFlag(enum_flag_ComObject);
676     }
677
678     // mark the class type as COM object class
679     void SetComObjectType();
680
681 #ifdef FEATURE_ICASTABLE
682     void SetICastable();
683 #endif
684
685     BOOL IsICastable(); // This type implements ICastable interface
686
687     void SetIDynamicInterfaceCastable();
688     BOOL IsIDynamicInterfaceCastable();
689
690     void SetIsTrackedReferenceWithFinalizer();
691     BOOL IsTrackedReferenceWithFinalizer();
692
693 #ifdef FEATURE_TYPEEQUIVALENCE
694     // mark the type as opted into type equivalence
695     void SetHasTypeEquivalence()
696     {
697         LIMITED_METHOD_CONTRACT;
698         SetFlag(enum_flag_HasTypeEquivalence);
699     }
700 #endif // FEATURE_TYPEEQUIVALENCE
701
702     // type has opted into type equivalence or is instantiated by/derived from a type that is
703     BOOL HasTypeEquivalence()
704     {
705         LIMITED_METHOD_CONTRACT;
706 #ifdef FEATURE_TYPEEQUIVALENCE
707         return GetFlag(enum_flag_HasTypeEquivalence);
708 #else
709         return FALSE;
710 #endif // FEATURE_TYPEEQUIVALENCE
711     }
712
713     //-------------------------------------------------------------------
714     // DYNAMIC ADDITION OF INTERFACES FOR COM INTEROP
715     //
716     // Support for dynamically added interfaces on extensible RCW's.
717
718 #ifdef FEATURE_COMINTEROP
719     PTR_InterfaceInfo GetDynamicallyAddedInterfaceMap();
720     unsigned GetNumDynamicallyAddedInterfaces();
721     BOOL FindDynamicallyAddedInterface(MethodTable *pInterface);
722     void AddDynamicInterface(MethodTable *pItfMT);
723
724     BOOL HasDynamicInterfaceMap()
725     {
726         LIMITED_METHOD_DAC_CONTRACT;
727
728         // currently all ComObjects except
729         // for __ComObject have dynamic Interface maps
730         return GetNumInterfaces() > 0 && IsComObjectType() && !ParentEquals(g_pObjectClass);
731     }
732 #endif // FEATURE_COMINTEROP
733
734 #ifndef DACCESS_COMPILE
735     VOID EnsureActive();
736     VOID EnsureInstanceActive();
737 #endif
738
739     CHECK CheckActivated();
740     CHECK CheckInstanceActivated();
741
742     //-------------------------------------------------------------------
743     // THE DEFAULT CONSTRUCTOR
744     //
745
746 public:
747     BOOL HasDefaultConstructor();
748     void SetHasDefaultConstructor();
749     WORD GetDefaultConstructorSlot();
750     MethodDesc *GetDefaultConstructor(BOOL forceBoxedEntryPoint = FALSE);
751
752     BOOL HasExplicitOrImplicitPublicDefaultConstructor();
753
754     //-------------------------------------------------------------------
755     // THE CLASS INITIALIZATION CONDITION
756     //  (and related DomainLocalModule storage)
757     //
758     // - populate the DomainLocalModule if needed
759     // - run the cctor
760     //
761
762 public:
763
764     // checks whether the class initialiser should be run on this class, and runs it if necessary
765     void CheckRunClassInitThrowing();
766
767     // checks whether or not the non-beforefieldinit class initializers have been run for all types in this type's
768     // inheritance hierarchy, and runs them if necessary. This simulates the behavior of running class constructors
769     // during object construction.
770     void CheckRunClassInitAsIfConstructingThrowing();
771
772 #if defined(TARGET_LOONGARCH64)
773     static bool IsLoongArch64OnlyOneField(MethodTable * pMT);
774     static int GetLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE clh);
775 #endif
776
777 #if defined(TARGET_RISCV64)
778     static bool IsRiscV64OnlyOneField(MethodTable * pMT);
779     static int GetRiscV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE clh);
780 #endif
781
782 #if defined(UNIX_AMD64_ABI_ITF)
783     // Builds the internal data structures and classifies struct eightbytes for Amd System V calling convention.
784     bool ClassifyEightBytes(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel, unsigned int startOffsetOfStruct, bool isNativeStruct, MethodTable** pByValueClassCache = NULL);
785     bool ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel, unsigned int startOffsetOfStruct, EEClassNativeLayoutInfo const* nativeLayoutInfo);
786 #endif // defined(UNIX_AMD64_ABI_ITF)
787
788     // Copy m_dwFlags from another method table
789     void CopyFlags(MethodTable * pOldMT)
790     {
791         LIMITED_METHOD_CONTRACT;
792         m_dwFlags = pOldMT->m_dwFlags;
793         m_wFlags2 = pOldMT->m_wFlags2;
794     }
795
796     // Init the m_dwFlags field for an array
797     void SetIsArray(CorElementType arrayType);
798
799     BOOL IsClassPreInited();
800
801     // mark the class as having its cctor run.
802 #ifndef DACCESS_COMPILE
803     void SetClassInited();
804     BOOL  IsClassInited();
805
806     BOOL IsInitError();
807     void SetClassInitError();
808 #endif
809
810     inline BOOL IsGlobalClass()
811     {
812         WRAPPER_NO_CONTRACT;
813         return (GetTypeDefRid() == RidFromToken(COR_GLOBAL_PARENT_TOKEN));
814     }
815
816     // uniquely identifes this type in the Domain table
817     DWORD GetClassIndex();
818
819 private:
820
821 #if defined(UNIX_AMD64_ABI_ITF)
822     void AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel) const;
823     // Builds the internal data structures and classifies struct eightbytes for Amd System V calling convention.
824     bool ClassifyEightBytesWithManagedLayout(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel, unsigned int startOffsetOfStruct, bool isNativeStruct, MethodTable** pByValueClassCache);
825 #endif // defined(UNIX_AMD64_ABI_ITF)
826
827     DWORD   GetClassIndexFromToken(mdTypeDef typeToken)
828     {
829         LIMITED_METHOD_CONTRACT;
830         return RidFromToken(typeToken) - 1;
831     }
832
833     // called from CheckRunClassInitThrowing().  The type wasn't marked as
834     // inited while we were there, so let's attempt to do the work.
835     void  DoRunClassInitThrowing();
836
837     BOOL RunClassInitEx(OBJECTREF *pThrowable);
838
839 public:
840     //-------------------------------------------------------------------
841     // THE CLASS CONSTRUCTOR
842     //
843
844     MethodDesc * GetClassConstructor();
845
846     BOOL HasClassConstructor();
847     void SetHasClassConstructor();
848     WORD GetClassConstructorSlot();
849
850     void GetSavedExtent(TADDR *ppStart, TADDR *ppEnd);
851
852     //-------------------------------------------------------------------
853     // Save/Fixup/Restore/NeedsRestore
854     //
855     // Restore this method table if it's not already restored
856     // This is done by forcing a class load which in turn calls the Restore method
857     // The pending list is required for restoring types that reference themselves through
858     // instantiations of the superclass or interfaces e.g. System.Int32 : IComparable<System.Int32>
859
860     void AllocateRegularStaticBoxes();
861     void AllocateRegularStaticBox(FieldDesc* pField, Object** boxedStaticHandle);
862     static OBJECTREF AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OBJECTHANDLE* pHandle = 0, bool canBeFrozen = false);
863
864     void CheckRestore();
865
866     inline BOOL HasUnrestoredTypeKey() const
867     {
868         LIMITED_METHOD_DAC_CONTRACT;
869
870         return (GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_UnrestoredTypeKey) != 0;
871     }
872
873     // Actually do the restore actions on the method table
874     void Restore();
875
876     void SetIsRestored();
877
878     inline BOOL IsRestored()
879     {
880         LIMITED_METHOD_DAC_CONTRACT;
881
882         return !(GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_Unrestored);
883     }
884
885     //-------------------------------------------------------------------
886     // LOAD LEVEL
887     //
888     // The load level of a method table is derived from various flag bits
889     // See classloadlevel.h for details of each level
890     //
891     // Level CLASS_LOADED (fully loaded) is special: a type only
892     // reaches this level once all of its dependent types are also at
893     // this level (generic arguments, parent, interfaces, etc).
894     // Fully loading a type to this level is done outside locks, hence the need for
895     // a single atomic action that sets the level.
896     //
897     inline void SetIsFullyLoaded()
898     {
899         CONTRACTL
900         {
901             THROWS;
902             GC_NOTRIGGER;
903             MODE_ANY;
904         }
905         CONTRACTL_END;
906
907         PRECONDITION(!HasApproxParent());
908         PRECONDITION(IsRestored());
909
910         InterlockedAnd((LONG*)&GetWriteableDataForWrite()->m_dwFlags, ~MethodTableWriteableData::enum_flag_IsNotFullyLoaded);
911     }
912
913     // Equivalent to GetLoadLevel() == CLASS_LOADED
914     inline BOOL IsFullyLoaded()
915     {
916         WRAPPER_NO_CONTRACT;
917
918         return (GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_IsNotFullyLoaded) == 0;
919     }
920
921     inline BOOL CanCompareBitsOrUseFastGetHashCode()
922     {
923         LIMITED_METHOD_CONTRACT;
924         return (GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_CanCompareBitsOrUseFastGetHashCode);
925     }
926
927     // If canCompare is true, this method ensure an atomic operation for setting
928     // enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode and enum_flag_CanCompareBitsOrUseFastGetHashCode flags.
929     inline void SetCanCompareBitsOrUseFastGetHashCode(BOOL canCompare)
930     {
931         WRAPPER_NO_CONTRACT
932         if (canCompare)
933         {
934             // Set checked and canCompare flags in one interlocked operation.
935             InterlockedOr((LONG*)&GetWriteableDataForWrite()->m_dwFlags,
936                 MethodTableWriteableData::enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode | MethodTableWriteableData::enum_flag_CanCompareBitsOrUseFastGetHashCode);
937         }
938         else
939         {
940             SetHasCheckedCanCompareBitsOrUseFastGetHashCode();
941         }
942     }
943
944     inline BOOL HasCheckedCanCompareBitsOrUseFastGetHashCode()
945     {
946         LIMITED_METHOD_CONTRACT;
947         return (GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode);
948     }
949
950     inline void SetHasCheckedCanCompareBitsOrUseFastGetHashCode()
951     {
952         WRAPPER_NO_CONTRACT;
953         InterlockedOr((LONG*)&GetWriteableDataForWrite()->m_dwFlags, MethodTableWriteableData::enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode);
954     }
955
956     inline void SetIsDependenciesLoaded()
957     {
958         CONTRACTL
959         {
960             THROWS;
961             GC_NOTRIGGER;
962             MODE_ANY;
963         }
964         CONTRACTL_END;
965
966         PRECONDITION(!HasApproxParent());
967         PRECONDITION(IsRestored());
968
969         InterlockedOr((LONG*)&GetWriteableDataForWrite()->m_dwFlags, MethodTableWriteableData::enum_flag_DependenciesLoaded);
970     }
971
972     inline ClassLoadLevel GetLoadLevel()
973     {
974         LIMITED_METHOD_DAC_CONTRACT;
975
976         DWORD dwFlags = GetWriteableData()->m_dwFlags;
977
978         if (dwFlags & MethodTableWriteableData::enum_flag_IsNotFullyLoaded)
979         {
980             if (dwFlags & MethodTableWriteableData::enum_flag_UnrestoredTypeKey)
981                 return CLASS_LOAD_UNRESTOREDTYPEKEY;
982
983             if (dwFlags & MethodTableWriteableData::enum_flag_Unrestored)
984                 return CLASS_LOAD_UNRESTORED;
985
986             if (dwFlags & MethodTableWriteableData::enum_flag_HasApproxParent)
987                 return CLASS_LOAD_APPROXPARENTS;
988
989             if (!(dwFlags & MethodTableWriteableData::enum_flag_DependenciesLoaded))
990                 return CLASS_LOAD_EXACTPARENTS;
991
992             return CLASS_DEPENDENCIES_LOADED;
993         }
994
995         return CLASS_LOADED;
996     }
997
998 #ifdef _DEBUG
999     CHECK CheckLoadLevel(ClassLoadLevel level)
1000     {
1001         LIMITED_METHOD_CONTRACT;
1002         return TypeHandle(this).CheckLoadLevel(level);
1003     }
1004 #endif
1005
1006
1007     void DoFullyLoad(Generics::RecursionGraph * const pVisited, const ClassLoadLevel level, DFLPendingList * const pPending, BOOL * const pfBailed,
1008                      const InstantiationContext * const pInstContext);
1009
1010     //-------------------------------------------------------------------
1011     // METHOD TABLES AS TYPE DESCRIPTORS
1012     //
1013     // A MethodTable can represeent a type such as "String" or an
1014     // instantiated type such as "List<String>".
1015     //
1016
1017     inline BOOL IsInterface()
1018     {
1019         LIMITED_METHOD_DAC_CONTRACT;
1020         return GetFlag(enum_flag_Category_Mask) == enum_flag_Category_Interface;
1021     }
1022
1023     void SetIsInterface()
1024     {
1025         LIMITED_METHOD_CONTRACT;
1026
1027         _ASSERTE(GetFlag(enum_flag_Category_Mask) == 0);
1028         SetFlag(enum_flag_Category_Interface);
1029     }
1030
1031     inline BOOL IsSealed();
1032
1033     inline BOOL IsAbstract();
1034
1035     BOOL IsExternallyVisible();
1036
1037     // Get the instantiation for this instantiated type e.g. for Dict<string,int>
1038     // this would be an array {string,int}
1039     // If not instantiated, return NULL
1040     Instantiation GetInstantiation();
1041
1042     // Get the instantiation for an instantiated type or a pointer to the
1043     // element type for an array
1044     Instantiation GetClassOrArrayInstantiation();
1045     Instantiation GetArrayInstantiation();
1046
1047     // Does this method table require that additional modules be loaded?
1048     inline BOOL HasModuleDependencies()
1049     {
1050         LIMITED_METHOD_CONTRACT;
1051         return GetFlag(enum_flag_HasModuleDependencies);
1052     }
1053
1054     inline void SetHasModuleDependencies()
1055     {
1056         SetFlag(enum_flag_HasModuleDependencies);
1057     }
1058
1059     inline BOOL IsIntrinsicType()
1060     {
1061         LIMITED_METHOD_DAC_CONTRACT;;
1062         return GetFlag(enum_flag_IsIntrinsicType);
1063     }
1064
1065     inline void SetIsIntrinsicType()
1066     {
1067         LIMITED_METHOD_DAC_CONTRACT;;
1068         SetFlag(enum_flag_IsIntrinsicType);
1069     }
1070
1071     // Is this a method table for a generic type instantiation, e.g. List<string>?
1072     inline BOOL HasInstantiation();
1073
1074     // Returns true for any class which is either itself a generic
1075     // instantiation or is derived from a generic
1076     // instantiation anywhere in it's class hierarchy,
1077     //
1078     // e.g. class D : C<int>
1079     // or class E : D, class D : C<int>
1080     //
1081     // Does not return true just because the class supports
1082     // an instantiated interface type.
1083     BOOL HasGenericClassInstantiationInHierarchy()
1084     {
1085         WRAPPER_NO_CONTRACT;
1086         return GetNumDicts() != 0;
1087     }
1088
1089     // Is this an instantiation of a generic class at its formal
1090     // type parameters ie. List<T> ?
1091     inline BOOL IsGenericTypeDefinition();
1092
1093     BOOL ContainsGenericMethodVariables();
1094
1095     // When creating an interface map, under some circumstances the
1096     // runtime will place the special marker type in the interface map instead
1097     // of the fully loaded type. This is to reduce the amount of type loading
1098     // performed at process startup.
1099     //
1100     // The current rule is that these interfaces can only appear
1101     // on valuetypes that are not shared generic, and that the special
1102     // marker type is the open generic type.
1103     //
1104     inline bool IsSpecialMarkerTypeForGenericCasting()
1105     {
1106         return IsGenericTypeDefinition();
1107     }
1108
1109     static const DWORD MaxGenericParametersForSpecialMarkerType = 8;
1110
1111     static BOOL ComputeContainsGenericVariables(Instantiation inst);
1112
1113     inline void SetContainsGenericVariables()
1114     {
1115         LIMITED_METHOD_CONTRACT;
1116         SetFlag(enum_flag_ContainsGenericVariables);
1117     }
1118
1119     inline void SetHasVariance()
1120     {
1121         LIMITED_METHOD_CONTRACT;
1122         SetFlag(enum_flag_HasVariance);
1123     }
1124
1125     inline BOOL HasVariance()
1126     {
1127         LIMITED_METHOD_CONTRACT;
1128         return GetFlag(enum_flag_HasVariance);
1129     }
1130
1131     // Is this something like List<T> or List<Stack<T>>?
1132     // List<Blah<T>> only exists for reflection and verification.
1133     inline DWORD ContainsGenericVariables(BOOL methodVarsOnly = FALSE)
1134     {
1135         WRAPPER_NO_CONTRACT;
1136         SUPPORTS_DAC;
1137         if (methodVarsOnly)
1138             return ContainsGenericMethodVariables();
1139         else
1140             return GetFlag(enum_flag_ContainsGenericVariables);
1141     }
1142
1143     BOOL IsByRefLike()
1144     {
1145         LIMITED_METHOD_DAC_CONTRACT;;
1146         return GetFlag(enum_flag_IsByRefLike);
1147     }
1148
1149     void SetIsByRefLike()
1150     {
1151         LIMITED_METHOD_CONTRACT;
1152         SetFlag(enum_flag_IsByRefLike);
1153     }
1154
1155     // class is a com object class
1156     Module* GetDefiningModuleForOpenType();
1157
1158     inline BOOL IsTypicalTypeDefinition()
1159     {
1160         LIMITED_METHOD_CONTRACT;
1161         return !HasInstantiation() || IsGenericTypeDefinition();
1162     }
1163
1164     BOOL HasSameTypeDefAs(MethodTable *pMT);
1165
1166     //-------------------------------------------------------------------
1167     // GENERICS & CODE SHARING
1168     //
1169
1170     BOOL IsSharedByGenericInstantiations();
1171
1172     // If this is a "representative" generic MT or a non-generic (regular) MT return true
1173     inline BOOL IsCanonicalMethodTable();
1174
1175     // Return the canonical representative MT amongst the set of MT's that share
1176     // code with the given MT because of generics.
1177     PTR_MethodTable GetCanonicalMethodTable();
1178
1179     //-------------------------------------------------------------------
1180     // Accessing methods by slot number
1181     //
1182     // Some of these functions are also currently used to get non-virtual
1183     // methods, relying on the assumption that they are contiguous.  This
1184     // is not true for non-virtual methods in generic instantiations, which
1185     // only live on the canonical method table.
1186
1187     enum
1188     {
1189         NO_SLOT = 0xffff // a unique slot number used to indicate "empty" for fields that record slot numbers
1190     };
1191
1192     PCODE GetSlot(UINT32 slotNumber)
1193     {
1194         WRAPPER_NO_CONTRACT;
1195         CONSISTENCY_CHECK(slotNumber < GetNumVtableSlots());
1196
1197         return *GetSlotPtrRaw(slotNumber);
1198     }
1199
1200     // Special-case for when we know that the slot number corresponds
1201     // to a virtual method.
1202     inline PCODE GetSlotForVirtual(UINT32 slotNum)
1203     {
1204         LIMITED_METHOD_CONTRACT;
1205
1206         CONSISTENCY_CHECK(slotNum < GetNumVirtuals());
1207         // Virtual slots live in chunks pointed to by vtable indirections
1208         return *(GetVtableIndirections()[GetIndexOfVtableIndirection(slotNum)] + GetIndexAfterVtableIndirection(slotNum));
1209     }
1210
1211     PTR_PCODE GetSlotPtrRaw(UINT32 slotNum)
1212     {
1213         WRAPPER_NO_CONTRACT;
1214         CONSISTENCY_CHECK(slotNum < GetNumVtableSlots());
1215
1216         if (slotNum < GetNumVirtuals())
1217         {
1218              // Virtual slots live in chunks pointed to by vtable indirections
1219             return GetVtableIndirections()[GetIndexOfVtableIndirection(slotNum)] + GetIndexAfterVtableIndirection(slotNum);
1220         }
1221         else if (HasSingleNonVirtualSlot())
1222         {
1223             // Non-virtual slots < GetNumVtableSlots live in a single chunk pointed to by an optional member,
1224             // except when there is only one in which case it lives in the optional member itself
1225             _ASSERTE(slotNum == GetNumVirtuals());
1226             return dac_cast<PTR_PCODE>(GetNonVirtualSlotsPtr());
1227         }
1228         else
1229         {
1230             // Non-virtual slots < GetNumVtableSlots live in a single chunk pointed to by an optional member
1231             _ASSERTE(HasNonVirtualSlotsArray());
1232             return GetNonVirtualSlotsArray() + (slotNum - GetNumVirtuals());
1233         }
1234     }
1235
1236     PTR_PCODE GetSlotPtr(UINT32 slotNum)
1237     {
1238         WRAPPER_NO_CONTRACT;
1239         return GetSlotPtrRaw(slotNum);
1240     }
1241
1242     void SetSlot(UINT32 slotNum, PCODE slotVal);
1243
1244     //-------------------------------------------------------------------
1245     // The VTABLE
1246     //
1247     // Rather than the traditional array of code pointers (or "slots") we use a two-level vtable in
1248     // which slots for virtual methods live in chunks.  Doing so allows the chunks to be shared among
1249     // method tables (the most common example being between parent and child classes where the child
1250     // does not override any method in the chunk).  This yields substantial space savings at the fixed
1251     // cost of one additional indirection for a virtual call.
1252     //
1253     // Note that none of this should be visible outside the implementation of MethodTable; all other
1254     // code continues to refer to a virtual method via the traditional slot number.  This is similar to
1255     // how we refer to non-virtual methods as having a slot number despite having long ago moved their
1256     // code pointers out of the vtable.
1257     //
1258     // Consider a class where GetNumVirtuals is 5 and (for the sake of the example) assume we break
1259     // the vtable into chunks of size 3.  The layout would be as follows:
1260     //
1261     //   pMT                       chunk 1                   chunk 2
1262     //   ------------------        ------------------        ------------------
1263     //   |                |        |      M1()      |        |      M4()      |
1264     //   |   fixed-size   |        ------------------        ------------------
1265     //   |   portion of   |        |      M2()      |        |      M5()      |
1266     //   |   MethodTable  |        ------------------        ------------------
1267     //   |                |        |      M3()      |
1268     //   ------------------        ------------------
1269     //   | ptr to chunk 1 |
1270     //   ------------------
1271     //   | ptr to chunk 2 |
1272     //   ------------------
1273     //
1274     // We refer to "ptr to chunk 1" and "ptr to chunk 2" as "indirection slots."
1275     //
1276     // The current chunking strategy is independent of class properties; all are of size 8.  Several
1277     // other strategies were tried, and the only one that has performed better empirically is to begin
1278     // with a single chunk of size 4 (matching the number of virtuals in System.Object) and then
1279     // continue with chunks of size 8.  However it was a small improvement and required the run-time
1280     // helpers listed below to be measurably slower.
1281     //
1282     // If you want to change this, you should only need to modify the first four functions below
1283     // along with any assembly helper that has taken a dependency on the layout.  Currently,
1284     // those consist of:
1285     //     JIT_IsInstanceOfInterface
1286     //     JIT_ChkCastInterface
1287     //     Transparent proxy stub
1288     //
1289     // This layout only applies to the virtual methods in a class (those with slot number below GetNumVirtuals).
1290     // Non-virtual methods that are in the vtable (those with slot numbers between GetNumVirtuals and
1291     // GetNumVtableSlots) are laid out in a single chunk pointed to by an optional member.
1292     // See GetSlotPtrRaw for more details.
1293
1294     #define VTABLE_SLOTS_PER_CHUNK 8
1295     #define VTABLE_SLOTS_PER_CHUNK_LOG2 3
1296
1297     typedef PCODE VTableIndir2_t;
1298     typedef DPTR(VTableIndir2_t) VTableIndir_t;
1299
1300     static DWORD GetIndexOfVtableIndirection(DWORD slotNum);
1301     static DWORD GetStartSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals);
1302     static DWORD GetEndSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals);
1303     static UINT32 GetIndexAfterVtableIndirection(UINT32 slotNum);
1304     static DWORD GetNumVtableIndirections(DWORD wNumVirtuals);
1305     DPTR(VTableIndir_t) GetVtableIndirections();
1306     DWORD GetNumVtableIndirections();
1307
1308     class VtableIndirectionSlotIterator
1309     {
1310         friend class MethodTable;
1311
1312     private:
1313         DPTR(VTableIndir_t) m_pSlot;
1314         DWORD m_i;
1315         DWORD m_count;
1316         PTR_MethodTable m_pMT;
1317
1318         VtableIndirectionSlotIterator(MethodTable *pMT);
1319         VtableIndirectionSlotIterator(MethodTable *pMT, DWORD index);
1320
1321     public:
1322         BOOL Next();
1323         BOOL Finished();
1324         DWORD GetIndex();
1325         DWORD GetOffsetFromMethodTable();
1326         DPTR(VTableIndir2_t) GetIndirectionSlot();
1327
1328 #ifndef DACCESS_COMPILE
1329         void SetIndirectionSlot(DPTR(VTableIndir2_t) pChunk);
1330 #endif
1331
1332         DWORD GetStartSlot();
1333         DWORD GetEndSlot();
1334         DWORD GetNumSlots();
1335         DWORD GetSize();
1336     };  // class VtableIndirectionSlotIterator
1337
1338     VtableIndirectionSlotIterator IterateVtableIndirectionSlots();
1339     VtableIndirectionSlotIterator IterateVtableIndirectionSlotsFrom(DWORD index);
1340
1341     inline BOOL HasNonVirtualSlots()
1342     {
1343         LIMITED_METHOD_DAC_CONTRACT;
1344         return GetFlag(enum_flag_HasNonVirtualSlots);
1345     }
1346
1347     inline BOOL HasSingleNonVirtualSlot()
1348     {
1349         LIMITED_METHOD_DAC_CONTRACT;
1350         return GetFlag(enum_flag_HasSingleNonVirtualSlot);
1351     }
1352
1353     inline BOOL HasNonVirtualSlotsArray()
1354     {
1355         LIMITED_METHOD_DAC_CONTRACT;
1356         return HasNonVirtualSlots() && !HasSingleNonVirtualSlot();
1357     }
1358
1359     TADDR GetNonVirtualSlotsPtr();
1360
1361     inline PTR_PCODE GetNonVirtualSlotsArray()
1362     {
1363         LIMITED_METHOD_DAC_CONTRACT;
1364         _ASSERTE(HasNonVirtualSlotsArray());
1365         return *dac_cast<PTR_PTR_PCODE>(GetNonVirtualSlotsPtr());
1366     }
1367
1368 #ifndef DACCESS_COMPILE
1369     inline void SetNonVirtualSlotsArray(PCODE *slots)
1370     {
1371         LIMITED_METHOD_CONTRACT;
1372         _ASSERTE(HasNonVirtualSlotsArray());
1373
1374         *(PCODE **)GetNonVirtualSlotsPtr() = slots;
1375     }
1376
1377     inline void SetHasSingleNonVirtualSlot()
1378     {
1379         LIMITED_METHOD_CONTRACT;
1380         SetFlag(enum_flag_HasSingleNonVirtualSlot);
1381     }
1382 #endif
1383
1384     inline unsigned GetNonVirtualSlotsArraySize()
1385     {
1386         LIMITED_METHOD_DAC_CONTRACT;
1387         return GetNumNonVirtualSlots() * sizeof(PCODE);
1388     }
1389
1390     inline WORD GetNumNonVirtualSlots();
1391
1392     inline BOOL HasVirtualStaticMethods() const;
1393     inline void SetHasVirtualStaticMethods();
1394
1395     void VerifyThatAllVirtualStaticMethodsAreImplemented();
1396
1397     inline WORD GetNumVirtuals()
1398     {
1399         LIMITED_METHOD_DAC_CONTRACT;
1400
1401         return m_wNumVirtuals;
1402     }
1403
1404     inline void SetNumVirtuals (WORD wNumVtableSlots)
1405     {
1406         LIMITED_METHOD_CONTRACT;
1407         m_wNumVirtuals = wNumVtableSlots;
1408     }
1409
1410     unsigned GetNumParentVirtuals()
1411     {
1412         LIMITED_METHOD_CONTRACT;
1413         if (IsInterface()) {
1414             return 0;
1415         }
1416         MethodTable *pMTParent = GetParentMethodTable();
1417         return pMTParent == NULL ? 0 : pMTParent->GetNumVirtuals();
1418     }
1419
1420     #define SIZEOF__MethodTable_ (0x10 + (6 INDEBUG(+1)) * TARGET_POINTER_SIZE)
1421
1422     static inline DWORD GetVtableOffset()
1423     {
1424         LIMITED_METHOD_DAC_CONTRACT;
1425
1426         return SIZEOF__MethodTable_;
1427     }
1428
1429     // Return total methods: virtual, static, and instance method slots.
1430     WORD GetNumMethods();
1431
1432     // Return number of slots in this methodtable. This is just an information about the layout of the methodtable, it should not be used
1433     // for functionality checks. Do not confuse with GetNumVirtuals()!
1434     WORD GetNumVtableSlots()
1435     {
1436         LIMITED_METHOD_DAC_CONTRACT;
1437         return GetNumVirtuals() + GetNumNonVirtualSlots();
1438     }
1439
1440     //-------------------------------------------------------------------
1441     // Slots <-> the MethodDesc associated with the slot.
1442     //
1443
1444     MethodDesc* GetMethodDescForSlot(DWORD slot);
1445
1446     static MethodDesc*  GetMethodDescForSlotAddress(PCODE addr, BOOL fSpeculative = FALSE);
1447
1448     PCODE GetRestoredSlot(DWORD slot);
1449
1450     // Returns MethodTable that GetRestoredSlot get its values from
1451     MethodTable * GetRestoredSlotMT(DWORD slot);
1452
1453     // Used to map methods on the same slot between instantiations.
1454     MethodDesc * GetParallelMethodDesc(MethodDesc * pDefMD);
1455
1456     //-------------------------------------------------------------------
1457     // BoxedEntryPoint MethodDescs.
1458     //
1459     // Virtual methods on structs have BoxedEntryPoint method descs in their vtable.
1460     // See also notes for MethodDesc::FindOrCreateAssociatedMethodDesc.  You should
1461     // probably be using that function if you need to map between unboxing
1462     // stubs and non-unboxing stubs.
1463
1464     MethodDesc* GetBoxedEntryPointMD(MethodDesc *pMD);
1465
1466     MethodDesc* GetUnboxedEntryPointMD(MethodDesc *pMD);
1467     MethodDesc* GetExistingUnboxedEntryPointMD(MethodDesc *pMD);
1468
1469     //-------------------------------------------------------------------
1470     // FIELD LAYOUT, OBJECT SIZE ETC.
1471     //
1472
1473     inline BOOL HasLayout();
1474
1475     inline EEClassLayoutInfo* GetLayoutInfo();
1476
1477     EEClassNativeLayoutInfo const* GetNativeLayoutInfo();
1478
1479     EEClassNativeLayoutInfo const* EnsureNativeLayoutInfoInitialized();
1480
1481     inline BOOL IsBlittable();
1482
1483     inline BOOL IsManagedSequential();
1484
1485     inline BOOL HasExplicitSize();
1486
1487     inline BOOL IsAutoLayoutOrHasAutoLayoutField();
1488
1489     // Only accurate on types which are not auto layout
1490     inline BOOL IsInt128OrHasInt128Fields();
1491
1492     UINT32 GetNativeSize();
1493
1494     DWORD           GetBaseSize()
1495     {
1496         LIMITED_METHOD_DAC_CONTRACT;
1497         return(m_BaseSize);
1498     }
1499
1500     void            SetBaseSize(DWORD baseSize)
1501     {
1502         LIMITED_METHOD_CONTRACT;
1503         m_BaseSize = baseSize;
1504     }
1505
1506     BOOL            IsStringOrArray() const
1507     {
1508         LIMITED_METHOD_DAC_CONTRACT;
1509         return HasComponentSize();
1510     }
1511
1512     BOOL IsString()
1513     {
1514         LIMITED_METHOD_DAC_CONTRACT;
1515         return HasComponentSize() && !IsArray() && RawGetComponentSize() == 2;
1516     }
1517
1518     BOOL            HasComponentSize() const
1519     {
1520         LIMITED_METHOD_DAC_CONTRACT;
1521         return GetFlag(enum_flag_HasComponentSize);
1522     }
1523
1524     // returns random combination of flags if this doesn't have a component size
1525     WORD            RawGetComponentSize()
1526     {
1527         LIMITED_METHOD_DAC_CONTRACT;
1528 #if BIGENDIAN
1529         return *((WORD*)&m_dwFlags + 1);
1530 #else // !BIGENDIAN
1531         return *(WORD*)&m_dwFlags;
1532 #endif // !BIGENDIAN
1533     }
1534
1535     // returns 0 if this doesn't have a component size
1536
1537     // The component size is actually 16-bit WORD, but this method is returning SIZE_T to ensure
1538     // that SIZE_T is used everywhere for object size computation. It is necessary to support
1539     // objects bigger than 2GB.
1540     SIZE_T          GetComponentSize()
1541     {
1542         LIMITED_METHOD_DAC_CONTRACT;
1543         return HasComponentSize() ? RawGetComponentSize() : 0;
1544     }
1545
1546     void SetComponentSize(WORD wComponentSize)
1547     {
1548         LIMITED_METHOD_CONTRACT;
1549         // it would be nice to assert here that this is either a string
1550         // or an array, but how do we know.
1551         //
1552         // it would also be nice to assert that the component size is > 0,
1553         // but that would not hold for array's of System.Void and generic type parameters
1554         SetFlag(enum_flag_HasComponentSize);
1555         m_dwFlags = (m_dwFlags & ~0xFFFF) | wComponentSize;
1556     }
1557
1558     inline WORD GetNumInstanceFields();
1559
1560     inline WORD GetNumStaticFields();
1561
1562     inline WORD GetNumThreadStaticFields();
1563
1564     // Note that for value types GetBaseSize returns the size of instance fields for
1565     // a boxed value, and GetNumInstanceFieldsBytes for an unboxed value.
1566     // We place methods like these on MethodTable primarily so we can choose to cache
1567     // the information within MethodTable, and so less code manipulates EEClass
1568     // objects directly, because doing so can lead to bugs related to generics.
1569     //
1570     // <TODO> Use m_wBaseSize whenever this is identical to GetNumInstanceFieldBytes.
1571     // We would need to reserve a flag for this. </TODO>
1572     //
1573     inline DWORD GetNumInstanceFieldBytes();
1574
1575     int GetFieldAlignmentRequirement();
1576
1577     inline WORD GetNumIntroducedInstanceFields();
1578
1579     // Note: This flag MUST be available even from an unrestored MethodTable - see GcScanRoots in siginfo.cpp.
1580     DWORD           ContainsPointers()
1581     {
1582         LIMITED_METHOD_CONTRACT;
1583         return GetFlag(enum_flag_ContainsPointers);
1584     }
1585
1586     BOOL            Collectible()
1587     {
1588         LIMITED_METHOD_CONTRACT;
1589 #ifdef FEATURE_COLLECTIBLE_TYPES
1590         return GetFlag(enum_flag_Collectible);
1591 #else
1592         return FALSE;
1593 #endif
1594     }
1595
1596     BOOL            ContainsPointersOrCollectible()
1597     {
1598         LIMITED_METHOD_CONTRACT;
1599         return GetFlag(enum_flag_ContainsPointers) || GetFlag(enum_flag_Collectible);
1600     }
1601
1602     OBJECTHANDLE    GetLoaderAllocatorObjectHandle();
1603     NOINLINE BYTE *GetLoaderAllocatorObjectForGC();
1604
1605     BOOL            IsNotTightlyPacked();
1606
1607     BOOL            IsAllGCPointers();
1608
1609     void SetContainsPointers()
1610     {
1611         LIMITED_METHOD_CONTRACT;
1612         SetFlag(enum_flag_ContainsPointers);
1613     }
1614
1615 #ifdef FEATURE_64BIT_ALIGNMENT
1616     inline bool RequiresAlign8()
1617     {
1618         LIMITED_METHOD_DAC_CONTRACT;
1619         return !!GetFlag(enum_flag_RequiresAlign8);
1620     }
1621
1622     inline void SetRequiresAlign8()
1623     {
1624         LIMITED_METHOD_CONTRACT;
1625         SetFlag(enum_flag_RequiresAlign8);
1626     }
1627 #endif // FEATURE_64BIT_ALIGNMENT
1628
1629     //-------------------------------------------------------------------
1630     // FIELD DESCRIPTORS
1631     //
1632     // Most of this API still lives on EEClass.
1633     //
1634     // ************************************ WARNING *************
1635     // **   !!!!INSTANCE FIELDDESCS ARE REPRESENTATIVES!!!!!   **
1636     // ** THEY ARE SHARED BY COMPATIBLE GENERIC INSTANTIATIONS **
1637     // ************************************ WARNING *************
1638
1639     // This goes straight to the EEClass
1640     // Careful about using this method. If it's possible that fields may have been added via EnC, then
1641     // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1642     PTR_FieldDesc GetApproxFieldDescListRaw();
1643
1644     // This returns a type-exact FieldDesc for a static field, but may still return a representative
1645     // for a non-static field.
1646     PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1647
1648     DWORD GetIndexForFieldDesc(FieldDesc *pField);
1649
1650     inline bool HasPreciseInitCctors()
1651     {
1652         LIMITED_METHOD_CONTRACT;
1653         return !!GetFlag(enum_flag_HasPreciseInitCctors);
1654     }
1655
1656     inline void SetHasPreciseInitCctors()
1657     {
1658         LIMITED_METHOD_CONTRACT;
1659         SetFlag(enum_flag_HasPreciseInitCctors);
1660     }
1661
1662 #if defined(FEATURE_HFA)
1663     inline bool IsHFA()
1664     {
1665         LIMITED_METHOD_CONTRACT;
1666         return !!GetFlag(enum_flag_IsHFA);
1667     }
1668
1669     inline void SetIsHFA()
1670     {
1671         LIMITED_METHOD_CONTRACT;
1672         SetFlag(enum_flag_IsHFA);
1673     }
1674 #else // !FEATURE_HFA
1675     bool IsHFA();
1676 #endif // FEATURE_HFA
1677
1678     // Returns the size in bytes of this type if it is a HW vector type; 0 otherwise.
1679     int GetVectorSize();
1680
1681     // Get the HFA type. This is supported both with FEATURE_HFA, in which case it
1682     // depends on the cached bit on the class, or without, in which case it is recomputed
1683     // for each invocation.
1684     CorInfoHFAElemType GetHFAType();
1685     // The managed and unmanaged HFA type can differ for types with layout. The following two methods return the unmanaged HFA type.
1686     bool IsNativeHFA();
1687     CorInfoHFAElemType GetNativeHFAType();
1688
1689 #ifdef UNIX_AMD64_ABI
1690     inline bool IsRegPassedStruct()
1691     {
1692         LIMITED_METHOD_CONTRACT;
1693         return !!GetFlag(enum_flag_IsRegStructPassed);
1694     }
1695
1696     inline void SetRegPassedStruct()
1697     {
1698         LIMITED_METHOD_CONTRACT;
1699         SetFlag(enum_flag_IsRegStructPassed);
1700     }
1701 #else
1702     inline bool IsRegPassedStruct()
1703     {
1704         return false;
1705     }
1706 #endif
1707
1708 #ifdef FEATURE_64BIT_ALIGNMENT
1709     // Returns true iff the native view of this type requires 64-bit alignment.
1710     bool NativeRequiresAlign8();
1711 #endif // FEATURE_64BIT_ALIGNMENT
1712
1713     //-------------------------------------------------------------------
1714     // PARENT INTERFACES
1715     //
1716     unsigned GetNumInterfaces()
1717     {
1718         LIMITED_METHOD_DAC_CONTRACT;
1719         return m_wNumInterfaces;
1720     }
1721
1722     //-------------------------------------------------------------------
1723     // CASTING
1724     //
1725     BOOL CanCastToInterface(MethodTable *pTargetMT, TypeHandlePairList *pVisited = NULL);
1726     BOOL CanCastToClass(MethodTable *pTargetMT, TypeHandlePairList *pVisited = NULL);
1727     BOOL CanCastTo(MethodTable* pTargetMT, TypeHandlePairList *pVisited);
1728     BOOL ArraySupportsBizarreInterface(MethodTable* pInterfaceMT, TypeHandlePairList* pVisited);
1729     BOOL ArrayIsInstanceOf(MethodTable* pTargetMT, TypeHandlePairList* pVisited);
1730
1731     BOOL CanCastByVarianceToInterfaceOrDelegate(MethodTable* pTargetMT, TypeHandlePairList* pVisited, MethodTable* pMTInterfaceMapOwner = NULL);
1732
1733     // The inline part of equivalence check.
1734 #ifndef DACCESS_COMPILE
1735     FORCEINLINE BOOL IsEquivalentTo(MethodTable *pOtherMT COMMA_INDEBUG(TypeHandlePairList *pVisited = NULL));
1736
1737 #ifdef FEATURE_TYPEEQUIVALENCE
1738     // This method is public so that TypeHandle has direct access to it
1739     BOOL IsEquivalentTo_Worker(MethodTable *pOtherMT COMMA_INDEBUG(TypeHandlePairList *pVisited));      // out-of-line part, SO tolerant
1740 private:
1741     BOOL IsEquivalentTo_WorkerInner(MethodTable *pOtherMT COMMA_INDEBUG(TypeHandlePairList *pVisited)); // out-of-line part, SO intolerant
1742 #endif // FEATURE_TYPEEQUIVALENCE
1743 #endif
1744
1745 public:
1746     //-------------------------------------------------------------------
1747     // THE METHOD TABLE PARENT (SUPERCLASS/BASE CLASS)
1748     //
1749     BOOL HasApproxParent()
1750     {
1751         LIMITED_METHOD_DAC_CONTRACT;
1752         return (GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_HasApproxParent) != 0;
1753     }
1754     inline void SetHasExactParent()
1755     {
1756         WRAPPER_NO_CONTRACT;
1757         InterlockedAnd((LONG*)&GetWriteableDataForWrite()->m_dwFlags, ~MethodTableWriteableData::enum_flag_HasApproxParent);
1758     }
1759
1760
1761     // Caller must know that the parent method table is not an encoded fixup
1762     inline PTR_MethodTable GetParentMethodTable()
1763     {
1764         LIMITED_METHOD_DAC_CONTRACT;
1765
1766         PRECONDITION(IsParentMethodTablePointerValid());
1767         return m_pParentMethodTable;
1768     }
1769
1770 #ifndef DACCESS_COMPILE
1771     inline MethodTable ** GetParentMethodTableValuePtr()
1772     {
1773         LIMITED_METHOD_CONTRACT;
1774         return &m_pParentMethodTable;
1775     }
1776 #endif // !DACCESS_COMPILE
1777
1778     // Is the parent method table pointer equal to the given argument?
1779     BOOL ParentEquals(PTR_MethodTable pMT)
1780     {
1781         LIMITED_METHOD_DAC_CONTRACT;
1782         PRECONDITION(IsParentMethodTablePointerValid());
1783         return GetParentMethodTable() == pMT;
1784     }
1785
1786 #ifdef _DEBUG
1787     BOOL IsParentMethodTablePointerValid();
1788 #endif
1789
1790 #ifndef DACCESS_COMPILE
1791     void SetParentMethodTable (MethodTable *pParentMethodTable)
1792     {
1793         LIMITED_METHOD_CONTRACT;
1794         m_pParentMethodTable = pParentMethodTable;
1795 #ifdef _DEBUG
1796         GetWriteableDataForWrite()->SetParentMethodTablePointerValid();
1797 #endif
1798     }
1799 #endif // !DACCESS_COMPILE
1800     MethodTable * GetMethodTableMatchingParentClass(MethodTable * pWhichParent);
1801     Instantiation GetInstantiationOfParentClass(MethodTable *pWhichParent);
1802
1803     //-------------------------------------------------------------------
1804     // THE  EEClass (Possibly shared between instantiations!).
1805     //
1806     // Note that it is not generally the case that GetClass.GetMethodTable() == t.
1807
1808     PTR_EEClass GetClass();
1809
1810     PTR_EEClass GetClassWithPossibleAV();
1811
1812     BOOL ValidateWithPossibleAV();
1813
1814     BOOL IsClassPointerValid();
1815
1816     static UINT32 GetOffsetOfFlags()
1817     {
1818         LIMITED_METHOD_CONTRACT;
1819         return offsetof(MethodTable, m_dwFlags);
1820     }
1821
1822     static UINT32 GetIfArrayThenSzArrayFlag()
1823     {
1824         LIMITED_METHOD_CONTRACT;
1825         return enum_flag_Category_IfArrayThenSzArray;
1826     }
1827
1828     //-------------------------------------------------------------------
1829     // CONSTRUCTION
1830     //
1831     // Do not call the following at any time except when creating a method table.
1832     // One day we will have proper constructors for method tables and all these
1833     // will disappear.
1834 #ifndef DACCESS_COMPILE
1835     inline void SetClass(EEClass *pClass)
1836     {
1837         LIMITED_METHOD_CONTRACT;
1838         m_pEEClass = pClass;
1839     }
1840
1841     inline void SetCanonicalMethodTable(MethodTable * pMT)
1842     {
1843         m_pCanonMT = (TADDR)pMT | MethodTable::UNION_METHODTABLE;
1844     }
1845 #endif
1846
1847     inline void SetHasInstantiation(BOOL fTypicalInstantiation, BOOL fSharedByGenericInstantiations);
1848
1849     //-------------------------------------------------------------------
1850     // INTERFACE IMPLEMENTATION
1851     //
1852  public:
1853     // Faster force-inlined version of ImplementsInterface
1854     BOOL ImplementsInterfaceInline(MethodTable *pInterface);
1855
1856     BOOL ImplementsInterface(MethodTable *pInterface);
1857     BOOL ImplementsEquivalentInterface(MethodTable *pInterface);
1858
1859     MethodDesc *GetMethodDescForInterfaceMethod(TypeHandle ownerType, MethodDesc *pInterfaceMD, BOOL throwOnConflict);
1860     MethodDesc *GetMethodDescForInterfaceMethod(MethodDesc *pInterfaceMD, BOOL throwOnConflict); // You can only use this one for non-generic interfaces
1861
1862     //-------------------------------------------------------------------
1863     // INTERFACE MAP.
1864     //
1865
1866     inline PTR_InterfaceInfo GetInterfaceMap();
1867
1868 #ifndef DACCESS_COMPILE
1869     void SetInterfaceMap(WORD wNumInterfaces, InterfaceInfo_t* iMap);
1870 #endif
1871
1872     inline int HasInterfaceMap()
1873     {
1874         LIMITED_METHOD_DAC_CONTRACT;
1875         return (m_wNumInterfaces != 0);
1876     }
1877
1878     // Where possible, use this iterator over the interface map instead of accessing the map directly
1879     // That way we can easily change the implementation of the map
1880     class InterfaceMapIterator
1881     {
1882         friend class MethodTable;
1883
1884     private:
1885         PTR_InterfaceInfo m_pMap;
1886         DWORD m_i;
1887         DWORD m_count;
1888
1889         InterfaceMapIterator(MethodTable *pMT)
1890           : m_pMap(pMT->GetInterfaceMap()),
1891             m_i((DWORD) -1),
1892             m_count(pMT->GetNumInterfaces())
1893         {
1894             WRAPPER_NO_CONTRACT;
1895         }
1896
1897         InterfaceMapIterator(MethodTable *pMT, DWORD index)
1898           : m_pMap(pMT->GetInterfaceMap() + index),
1899             m_i(index),
1900             m_count(pMT->GetNumInterfaces())
1901         {
1902             WRAPPER_NO_CONTRACT;
1903             CONSISTENCY_CHECK(index >= 0 && index < m_count);
1904         }
1905
1906     public:
1907         InterfaceInfo_t* GetInterfaceInfo()
1908         {
1909             LIMITED_METHOD_CONTRACT;
1910             return m_pMap;
1911         }
1912
1913         // Move to the next item in the map, returning TRUE if an item
1914         // exists or FALSE if we've run off the end
1915         inline BOOL Next()
1916         {
1917             LIMITED_METHOD_CONTRACT;
1918             PRECONDITION(!Finished());
1919             if (m_i != (DWORD) -1)
1920                 m_pMap++;
1921             return (++m_i < m_count);
1922         }
1923
1924         // Have we iterated over all of the items?
1925         BOOL Finished()
1926         {
1927             return (m_i == m_count);
1928         }
1929
1930 #ifndef DACCESS_COMPILE
1931         // Get the interface at the current position. This GetInterfaceMethod
1932         // will ensure that the exact correct instantiation of the interface
1933         // is found, even if the MethodTable in the interface map is the generic
1934         // approximation
1935         PTR_MethodTable GetInterface(MethodTable* pMTOwner, ClassLoadLevel loadLevel = CLASS_LOADED);
1936 #endif
1937
1938         // Get the interface at the current position, with whatever its normal load level is
1939         inline PTR_MethodTable GetInterfaceApprox()
1940         {
1941             CONTRACT(PTR_MethodTable)
1942             {
1943                 GC_NOTRIGGER;
1944                 NOTHROW;
1945                 SUPPORTS_DAC;
1946                 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
1947                 POSTCONDITION(CheckPointer(RETVAL));
1948             }
1949             CONTRACT_END;
1950
1951             RETURN (m_pMap->GetMethodTable());
1952         }
1953
1954         inline bool CurrentInterfaceMatches(MethodTable* pMTOwner, MethodTable* pMT)
1955         {
1956             CONTRACT(bool)
1957             {
1958                 GC_NOTRIGGER;
1959                 NOTHROW;
1960                 SUPPORTS_DAC;
1961                 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
1962             }
1963             CONTRACT_END;
1964
1965             MethodTable *pCurrentMethodTable = m_pMap->GetMethodTable();
1966
1967             bool exactMatch = pCurrentMethodTable == pMT;
1968             if (!exactMatch)
1969             {
1970                 if (pCurrentMethodTable->HasSameTypeDefAs(pMT) &&
1971                     pMT->HasInstantiation() &&
1972                     pCurrentMethodTable->IsSpecialMarkerTypeForGenericCasting() &&
1973                     !pMTOwner->ContainsGenericVariables() &&
1974                     pMT->GetInstantiation().ContainsAllOneType(pMTOwner))
1975                 {
1976                     exactMatch = true;
1977 #ifndef DACCESS_COMPILE
1978                     // We match exactly, and have an actual pMT loaded. Insert
1979                     // the searched for interface if it is fully loaded, so that
1980                     // future checks are more efficient
1981                     if (pMT->IsFullyLoaded())
1982                         SetInterface(pMT);
1983 #endif
1984                 }
1985             }
1986
1987             RETURN (exactMatch);
1988         }
1989
1990         inline bool HasSameTypeDefAs(MethodTable* pMT)
1991         {
1992             CONTRACT(bool)
1993             {
1994                 GC_NOTRIGGER;
1995                 NOTHROW;
1996                 SUPPORTS_DAC;
1997                 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
1998             }
1999             CONTRACT_END;
2000
2001             RETURN (m_pMap->GetMethodTable()->HasSameTypeDefAs(pMT));
2002         }
2003
2004 #ifndef DACCESS_COMPILE
2005         void SetInterface(MethodTable *pMT)
2006         {
2007             WRAPPER_NO_CONTRACT;
2008             m_pMap->SetMethodTable(pMT);
2009         }
2010 #endif
2011
2012         DWORD GetIndex()
2013         {
2014             LIMITED_METHOD_CONTRACT;
2015             return m_i;
2016         }
2017     };  // class InterfaceMapIterator
2018
2019     // Create a new iterator over the interface map
2020     // The iterator starts just before the first item in the map
2021     InterfaceMapIterator IterateInterfaceMap()
2022     {
2023         WRAPPER_NO_CONTRACT;
2024         return InterfaceMapIterator(this);
2025     }
2026
2027     // Create a new iterator over the interface map, starting at the index specified
2028     InterfaceMapIterator IterateInterfaceMapFrom(DWORD index)
2029     {
2030         WRAPPER_NO_CONTRACT;
2031         return InterfaceMapIterator(this, index);
2032     }
2033
2034     //-------------------------------------------------------------------
2035     // ADDITIONAL INTERFACE MAP DATA
2036     //
2037
2038     // We store extra info (flag bits) for interfaces implemented on this MethodTable in a separate optional
2039     // location for better data density (if we put them in the interface map directly data alignment could
2040     // have us using 32 or even 64 bits to represent a single boolean value). Currently the only flag we
2041     // persist is IsDeclaredOnClass (was the interface explicitly declared by this class).
2042
2043     // Currently we always store extra info whenever we have an interface map (in the future you could imagine
2044     // this being limited to those scenarios in which at least one of the interfaces has a non-default value
2045     // for a flag).
2046     inline BOOL HasExtraInterfaceInfo()
2047     {
2048         SUPPORTS_DAC;
2049         return HasInterfaceMap();
2050     }
2051
2052     // Count of interfaces that can have their extra info stored inline in the optional data structure itself
2053     // (once the interface count exceeds this limit the optional data slot will instead point to a buffer with
2054     // the information).
2055     enum { kInlinedInterfaceInfoThreshold = sizeof(TADDR) * 8 };
2056
2057     // Calculate how many bytes of storage will be required to track additional information for interfaces.
2058     // This will be zero if there are no interfaces, but can also be zero for small numbers of interfaces as
2059     // well, and callers should be ready to handle this.
2060     static SIZE_T GetExtraInterfaceInfoSize(DWORD cInterfaces);
2061
2062     // Called after GetExtraInterfaceInfoSize above to setup a new MethodTable with the additional memory to
2063     // track extra interface info. If there are a non-zero number of interfaces implemented on this class but
2064     // GetExtraInterfaceInfoSize() returned zero, this call must still be made (with a NULL argument).
2065     void InitializeExtraInterfaceInfo(PVOID pInfo);
2066
2067 #ifdef DACCESS_COMPILE
2068     void EnumMemoryRegionsForExtraInterfaceInfo();
2069 #endif // DACCESS_COMPILE
2070
2071     // For the given interface in the map (specified via map index) mark the interface as declared explicitly
2072     // on this class. This is not legal for dynamically added interfaces (as used by RCWs).
2073     void SetInterfaceDeclaredOnClass(DWORD index);
2074
2075     // For the given interface in the map (specified via map index) return true if the interface was declared
2076     // explicitly on this class.
2077     bool IsInterfaceDeclaredOnClass(DWORD index);
2078
2079     //-------------------------------------------------------------------
2080     // VIRTUAL/INTERFACE CALL RESOLUTION
2081     //
2082     // These should probably go in method.hpp since they don't have
2083     // much to do with method tables per se.
2084     //
2085
2086     // get the method desc given the interface method desc
2087     static MethodDesc *GetMethodDescForInterfaceMethodAndServer(TypeHandle ownerType, MethodDesc *pItfMD, OBJECTREF *pServer);
2088
2089 #ifdef FEATURE_COMINTEROP
2090     // get the method desc given the interface method desc on a COM implemented server (if fNullOk is set then NULL is an allowable return value)
2091     MethodDesc *GetMethodDescForComInterfaceMethod(MethodDesc *pItfMD, bool fNullOk);
2092 #endif // FEATURE_COMINTEROP
2093
2094     // Resolve virtual static interface method pInterfaceMD on this type.
2095     //
2096     // Specify allowNullResult to return NULL instead of throwing if the there is no implementation
2097     // Specify verifyImplemented to verify that there is a match, but do not actually return a final usable MethodDesc
2098     // Specify allowVariantMatches to permit generic interface variance
2099     // Specify uniqueResolution to store the flag saying whether the resolution was unambiguous;
2100     // when NULL, throw an AmbiguousResolutionException upon hitting ambiguous SVM resolution.
2101     // The 'level' parameter specifies the load level for the class containing the resolved MethodDesc.
2102     MethodDesc *ResolveVirtualStaticMethod(
2103         MethodTable* pInterfaceType,
2104         MethodDesc* pInterfaceMD,
2105         ResolveVirtualStaticMethodFlags resolveVirtualStaticMethodFlags,
2106         BOOL *uniqueResolution = NULL,
2107         ClassLoadLevel level = CLASS_LOADED);
2108
2109     // Try a partial resolve of the constraint call, up to generic code sharing.
2110     //
2111     // Note that this will not necessarily resolve the call exactly, since we might be compiling
2112     // shared generic code - it may just resolve it to a candidate suitable for
2113     // JIT compilation, and require a runtime lookup for the actual code pointer
2114     // to call.
2115     //
2116     // Return NULL if the call could not be resolved, e.g. because it is invoked
2117     // on a type that inherits the implementation of the method from System.Object
2118     // or System.ValueType.
2119     //
2120     // Always returns an unboxed entry point with a uniform calling convention.
2121     MethodDesc * TryResolveConstraintMethodApprox(
2122         TypeHandle   ownerType,
2123         MethodDesc * pMD,
2124         BOOL *       pfForceUseRuntimeLookup = NULL);
2125
2126     //-------------------------------------------------------------------
2127     // CONTRACT IMPLEMENTATIONS
2128     //
2129
2130     inline BOOL HasDispatchMap()
2131     {
2132         WRAPPER_NO_CONTRACT;
2133         return GetDispatchMap() != NULL;
2134     }
2135
2136     PTR_DispatchMap GetDispatchMap();
2137
2138     inline BOOL HasDispatchMapSlot()
2139     {
2140         LIMITED_METHOD_DAC_CONTRACT;
2141         return GetFlag(enum_flag_HasDispatchMapSlot);
2142     }
2143
2144 #ifndef DACCESS_COMPILE
2145     void SetDispatchMap(DispatchMap *pDispatchMap)
2146     {
2147         LIMITED_METHOD_CONTRACT;
2148         _ASSERTE(HasDispatchMapSlot());
2149
2150         TADDR pSlot = GetMultipurposeSlotPtr(enum_flag_HasDispatchMapSlot, c_DispatchMapSlotOffsets);
2151         *(DispatchMap **)pSlot = pDispatchMap;
2152     }
2153 #endif // !DACCESS_COMPILE
2154
2155 protected:
2156     BOOL FindEncodedMapDispatchEntry(UINT32 typeID,
2157                                      UINT32 slotNumber,
2158                                      DispatchMapEntry *pEntry);
2159
2160     BOOL FindIntroducedImplementationTableDispatchEntry(UINT32 slotNumber,
2161                                                         DispatchMapEntry *pEntry,
2162                                                         BOOL fVirtualMethodsOnly);
2163
2164     BOOL FindDispatchEntryForCurrentType(UINT32 typeID,
2165                                          UINT32 slotNumber,
2166                                          DispatchMapEntry *pEntry);
2167
2168     BOOL FindDispatchEntry(UINT32 typeID,
2169                            UINT32 slotNumber,
2170                            DispatchMapEntry *pEntry);
2171
2172 private:
2173     BOOL FindDispatchImpl(
2174         UINT32         typeID,
2175         UINT32         slotNumber,
2176         DispatchSlot * pImplSlot,
2177         BOOL           throwOnConflict);
2178
2179 public:
2180 #ifndef DACCESS_COMPILE
2181     BOOL FindDefaultInterfaceImplementation(
2182         MethodDesc *pInterfaceMD,
2183         MethodTable *pObjectMT,
2184         MethodDesc **ppDefaultMethod,
2185         FindDefaultInterfaceImplementationFlags findDefaultImplementationFlags,
2186         ClassLoadLevel level = CLASS_LOADED);
2187 #endif // DACCESS_COMPILE
2188
2189     DispatchSlot FindDispatchSlot(UINT32 typeID, UINT32 slotNumber, BOOL throwOnConflict);
2190
2191     // You must use the second of these two if there is any chance the pMD is a method
2192     // on a generic interface such as IComparable<T> (which it normally can be).  The
2193     // ownerType is used to provide an exact qualification in the case the pMD is
2194     // a shared method descriptor.
2195     DispatchSlot FindDispatchSlotForInterfaceMD(MethodDesc *pMD, BOOL throwOnConflict);
2196     DispatchSlot FindDispatchSlotForInterfaceMD(TypeHandle ownerType, MethodDesc *pMD, BOOL throwOnConflict);
2197
2198     MethodDesc *ReverseInterfaceMDLookup(UINT32 slotNumber);
2199
2200     // Lookup, does not assign if not already done.
2201     UINT32 LookupTypeID();
2202     // Lookup, will assign ID if not already done.
2203     UINT32 GetTypeID();
2204
2205
2206     // Will return either the dispatch map type. May trigger type loader in order to get
2207     // exact result.
2208     MethodTable *LookupDispatchMapType(DispatchMapTypeID typeID);
2209     bool DispatchMapTypeMatchesMethodTable(DispatchMapTypeID typeID, MethodTable* pMT);
2210
2211     MethodDesc *GetIntroducingMethodDesc(DWORD slotNumber);
2212
2213     // Determines whether all methods in the given interface have their final implementing
2214     // slot in a parent class. I.e. if this returns TRUE, it is trivial (no VSD lookup) to
2215     // dispatch pItfMT methods on this class if one knows how to dispatch them on pParentMT.
2216     BOOL ImplementsInterfaceWithSameSlotsAsParent(MethodTable *pItfMT, MethodTable *pParentMT);
2217
2218     // Determines whether all methods in the given interface have their final implementation
2219     // in a parent class. I.e. if this returns TRUE, this class behaves the same as pParentMT
2220     // when it comes to dispatching pItfMT methods.
2221     BOOL HasSameInterfaceImplementationAsParent(MethodTable *pItfMT, MethodTable *pParentMT);
2222
2223     // Try to resolve a given static virtual method override on this type. Return nullptr
2224     // when not found.
2225     MethodDesc *TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, ResolveVirtualStaticMethodFlags resolveVirtualStaticMethodFlags, ClassLoadLevel level);
2226
2227 public:
2228     static MethodDesc *MapMethodDeclToMethodImpl(MethodDesc *pMDDecl);
2229
2230     //-------------------------------------------------------------------
2231     // FINALIZATION SEMANTICS
2232     //
2233
2234     DWORD  CannotUseSuperFastHelper()
2235     {
2236         WRAPPER_NO_CONTRACT;
2237         return HasFinalizer();
2238     }
2239
2240     void SetHasFinalizer()
2241     {
2242         LIMITED_METHOD_CONTRACT;
2243         SetFlag(enum_flag_HasFinalizer);
2244     }
2245
2246     void SetHasCriticalFinalizer()
2247     {
2248         LIMITED_METHOD_CONTRACT;
2249         SetFlag(enum_flag_HasCriticalFinalizer);
2250     }
2251     // Does this class have non-trivial finalization requirements?
2252     DWORD HasFinalizer()
2253     {
2254         LIMITED_METHOD_DAC_CONTRACT;
2255         return GetFlag(enum_flag_HasFinalizer);
2256     }
2257     // Must this class be finalized during a rude appdomain unload, and
2258     // must it's finalizer run in a different order from normal finalizers?
2259     DWORD HasCriticalFinalizer() const
2260     {
2261         LIMITED_METHOD_CONTRACT;
2262         return GetFlag(enum_flag_HasCriticalFinalizer);
2263     }
2264
2265     //-------------------------------------------------------------------
2266     // STATIC FIELDS
2267     //
2268
2269     DWORD  GetOffsetOfFirstStaticHandle();
2270     DWORD  GetOffsetOfFirstStaticMT();
2271
2272 #ifndef DACCESS_COMPILE
2273     inline PTR_BYTE GetNonGCStaticsBasePointer();
2274     inline PTR_BYTE GetGCStaticsBasePointer();
2275     inline PTR_BYTE GetNonGCThreadStaticsBasePointer();
2276     inline PTR_BYTE GetGCThreadStaticsBasePointer();
2277     inline PTR_BYTE GetGCThreadStaticsBaseHandle();
2278 #endif //!DACCESS_COMPILE
2279
2280     inline PTR_BYTE GetNonGCThreadStaticsBasePointer(PTR_Thread pThread);
2281     inline PTR_BYTE GetGCThreadStaticsBasePointer(PTR_Thread pThread);
2282
2283     inline DWORD IsDynamicStatics()
2284     {
2285         LIMITED_METHOD_DAC_CONTRACT;
2286         return !TestFlagWithMask(enum_flag_StaticsMask, enum_flag_StaticsMask_NonDynamic);
2287     }
2288
2289     inline void SetDynamicStatics(BOOL fGeneric)
2290     {
2291         LIMITED_METHOD_CONTRACT;
2292         SetFlag(fGeneric ? enum_flag_StaticsMask_Generics : enum_flag_StaticsMask_Dynamic);
2293     }
2294
2295     inline void SetHasBoxedRegularStatics()
2296     {
2297         LIMITED_METHOD_CONTRACT;
2298         SetFlag(enum_flag_HasBoxedRegularStatics);
2299     }
2300
2301     inline DWORD HasBoxedRegularStatics()
2302     {
2303         LIMITED_METHOD_CONTRACT;
2304         return GetFlag(enum_flag_HasBoxedRegularStatics);
2305     }
2306
2307     DWORD HasFixedAddressVTStatics();
2308
2309     // Indicates if the MethodTable only contains abstract methods
2310     BOOL HasOnlyAbstractMethods();
2311
2312     //-------------------------------------------------------------------
2313     // PER-INSTANTIATION STATICS INFO
2314     //
2315
2316
2317     void SetupGenericsStaticsInfo(FieldDesc* pStaticFieldDescs);
2318
2319     BOOL HasGenericsStaticsInfo()
2320     {
2321         LIMITED_METHOD_DAC_CONTRACT;
2322         return GetFlag(enum_flag_StaticsMask_Generics);
2323     }
2324
2325     PTR_FieldDesc GetGenericsStaticFieldDescs()
2326     {
2327         WRAPPER_NO_CONTRACT;
2328         _ASSERTE(HasGenericsStaticsInfo());
2329         return GetGenericsStaticsInfo()->m_pFieldDescs;
2330     }
2331
2332     BOOL HasCrossModuleGenericStaticsInfo()
2333     {
2334         LIMITED_METHOD_DAC_CONTRACT;
2335         return TestFlagWithMask(enum_flag_StaticsMask, enum_flag_StaticsMask_CrossModuleGenerics);
2336     }
2337
2338     PTR_Module GetGenericsStaticsModuleAndID(DWORD * pID);
2339
2340     WORD GetNumHandleRegularStatics();
2341
2342     WORD GetNumBoxedRegularStatics ();
2343     WORD GetNumBoxedThreadStatics ();
2344
2345     //-------------------------------------------------------------------
2346     // DYNAMIC ID
2347     //
2348
2349     // Used for generics and reflection emit in memory
2350     DWORD GetModuleDynamicEntryID();
2351     Module* GetModuleForStatics();
2352
2353     //-------------------------------------------------------------------
2354     // GENERICS DICT INFO
2355     //
2356
2357     // Number of generic arguments, whether this is a method table for
2358     // a generic type instantiation, e.g. List<string> or the "generic" MethodTable
2359     // e.g. for List.
2360     inline DWORD GetNumGenericArgs()
2361     {
2362         LIMITED_METHOD_DAC_CONTRACT;
2363         if (HasInstantiation())
2364             return (DWORD) (GetGenericsDictInfo()->m_wNumTyPars);
2365         else
2366             return 0;
2367     }
2368
2369     inline DWORD GetNumDicts()
2370     {
2371         LIMITED_METHOD_DAC_CONTRACT;
2372         if (HasPerInstInfo())
2373         {
2374             PTR_GenericsDictInfo  pDictInfo = GetGenericsDictInfo();
2375             return (DWORD) (pDictInfo->m_wNumDicts);
2376         }
2377         else
2378             return 0;
2379     }
2380
2381     //-------------------------------------------------------------------
2382     // OBJECTS
2383     //
2384
2385     OBJECTREF Allocate();
2386
2387     // This flavor of Allocate is more efficient, but can only be used
2388     // if IsRestored(), CheckInstanceActivated(), IsClassInited() are known to be true.
2389     // A sufficient condition is that another instance of the exact same type already
2390     // exists in the same appdomain. It's currently called only from Delegate.Combine
2391     // via COMDelegate::InternalAllocLike.
2392     OBJECTREF AllocateNoChecks();
2393
2394     OBJECTREF Box(void* data);
2395     OBJECTREF FastBox(void** data);
2396 #ifndef DACCESS_COMPILE
2397     BOOL UnBoxInto(void *dest, OBJECTREF src);
2398     void UnBoxIntoUnchecked(void *dest, OBJECTREF src);
2399 #endif
2400
2401 #ifdef _DEBUG
2402     // Used for debugging class layout. Dumps to the debug console
2403     // when debug is true.
2404     void DebugDumpVtable(LPCUTF8 szClassName, BOOL fDebug);
2405     void Debug_DumpInterfaceMap(LPCSTR szInterfaceMapPrefix);
2406     void Debug_DumpDispatchMap();
2407     void DebugDumpFieldLayout(LPCUTF8 pszClassName, BOOL debug);
2408     void DebugRecursivelyDumpInstanceFields(LPCUTF8 pszClassName, BOOL debug);
2409     void DebugDumpGCDesc(LPCUTF8 pszClassName, BOOL debug);
2410 #endif //_DEBUG
2411
2412     inline BOOL IsAgileAndFinalizable()
2413     {
2414         LIMITED_METHOD_CONTRACT;
2415         // Right now, System.Thread is the only cases of this.
2416         // Things should stay this way - please don't change without talking to EE team.
2417         return this == g_pThreadClass;
2418     }
2419
2420
2421     //-------------------------------------------------------------------
2422     // ENUMS, DELEGATES, VALUE TYPES, ARRAYS
2423     //
2424     // #KindsOfElementTypes
2425     // GetInternalCorElementType() retrieves the internal representation of the type. It's not always
2426     // appropriate to use this. For example, we treat enums as their underlying type or some structs are
2427     // optimized to be ints. To get the signature type or the verifier type (same as signature except for
2428     // enums are normalized to the primitive type that underlies them), use the APIs in Typehandle.h
2429     //
2430     //   * code:TypeHandle.GetSignatureCorElementType()
2431     //   * code:TypeHandle.GetVerifierCorElementType()
2432     //   * code:TypeHandle.GetInternalCorElementType()
2433     CorElementType GetInternalCorElementType();
2434     void SetInternalCorElementType(CorElementType _NormType);
2435
2436     // See code:TypeHandle::GetVerifierCorElementType for description
2437     CorElementType GetVerifierCorElementType();
2438
2439     // See code:TypeHandle::GetSignatureCorElementType for description
2440     CorElementType GetSignatureCorElementType();
2441
2442     // A true primitive is one who's GetVerifierCorElementType() ==
2443     //      ELEMENT_TYPE_I,
2444     //      ELEMENT_TYPE_I4,
2445     //      ELEMENT_TYPE_TYPEDBYREF etc.
2446     // Note that GetIntenalCorElementType might return these same values for some additional
2447     // types such as Enums and some structs.
2448     BOOL IsTruePrimitive();
2449     void SetIsTruePrimitive();
2450
2451     // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
2452     inline BOOL IsDelegate()
2453     {
2454         LIMITED_METHOD_DAC_CONTRACT;
2455         // We do not allow single cast delegates anymore, just check for multicast delegate
2456         _ASSERTE(g_pMulticastDelegateClass);
2457         return ParentEquals(g_pMulticastDelegateClass);
2458     }
2459
2460     // Is this System.Object?
2461     inline BOOL IsObjectClass()
2462     {
2463         LIMITED_METHOD_CONTRACT;
2464         _ASSERTE(g_pObjectClass);
2465         return (this == g_pObjectClass);
2466     }
2467
2468     // Is this System.ValueType?
2469     inline DWORD IsValueTypeClass()
2470     {
2471         LIMITED_METHOD_CONTRACT;
2472         _ASSERTE(g_pValueTypeClass);
2473         return (this == g_pValueTypeClass);
2474     }
2475
2476     // Is this value type? Returns false for System.ValueType and System.Enum.
2477     inline BOOL IsValueType();
2478
2479     // Is this enum? Returns false for System.Enum.
2480     inline BOOL IsEnum();
2481
2482     // Is this array? Returns false for System.Array.
2483     inline BOOL IsArray()
2484     {
2485         LIMITED_METHOD_DAC_CONTRACT;
2486         return GetFlag(enum_flag_Category_Array_Mask) == enum_flag_Category_Array;
2487     }
2488     inline BOOL IsMultiDimArray()
2489     {
2490         LIMITED_METHOD_DAC_CONTRACT;
2491         PRECONDITION(IsArray());
2492         return !GetFlag(enum_flag_Category_IfArrayThenSzArray);
2493     }
2494
2495     // Returns true if this type is Nullable<T> for some T.
2496     inline BOOL IsNullable()
2497     {
2498         LIMITED_METHOD_DAC_CONTRACT;
2499         return GetFlag(enum_flag_Category_Mask) == enum_flag_Category_Nullable;
2500     }
2501
2502     inline void SetIsNullable()
2503     {
2504         LIMITED_METHOD_CONTRACT;
2505         _ASSERTE(GetFlag(enum_flag_Category_Mask) == enum_flag_Category_ValueType);
2506         SetFlag(enum_flag_Category_Nullable);
2507     }
2508
2509     // The following methods are only valid for the method tables for array types.
2510     CorElementType GetArrayElementType();
2511     DWORD GetRank();
2512
2513     TypeHandle GetArrayElementTypeHandle()
2514     {
2515         LIMITED_METHOD_DAC_CONTRACT;
2516         _ASSERTE (IsArray());
2517         return TypeHandle::FromTAddr(m_ElementTypeHnd);
2518     }
2519
2520     void SetArrayElementTypeHandle(TypeHandle th)
2521     {
2522         LIMITED_METHOD_DAC_CONTRACT;
2523         m_ElementTypeHnd = th.AsTAddr();
2524     }
2525
2526     TypeHandle * GetArrayElementTypeHandlePtr()
2527     {
2528         LIMITED_METHOD_CONTRACT;
2529         return (TypeHandle *)&m_ElementTypeHnd;
2530     }
2531
2532     static inline DWORD GetOffsetOfArrayElementTypeHandle()
2533     {
2534         LIMITED_METHOD_CONTRACT;
2535         return offsetof(MethodTable, m_ElementTypeHnd);
2536     }
2537
2538     //-------------------------------------------------------------------
2539     // UNDERLYING METADATA
2540     //
2541
2542
2543     // Get the RID/token for the metadata for the corresponding type declaration
2544     unsigned GetTypeDefRid();
2545
2546     inline mdTypeDef GetCl()
2547     {
2548         LIMITED_METHOD_CONTRACT;
2549         return TokenFromRid(GetTypeDefRid(), mdtTypeDef);
2550     }
2551
2552     void SetCl(mdTypeDef token);
2553
2554 #ifdef _DEBUG
2555 // Make this smaller in debug builds to exercise the overflow codepath
2556 #define METHODTABLE_TOKEN_OVERFLOW 0xFFF
2557 #else
2558 #define METHODTABLE_TOKEN_OVERFLOW 0xFFFF
2559 #endif
2560
2561     BOOL HasTokenOverflow()
2562     {
2563         LIMITED_METHOD_CONTRACT;
2564         return m_wToken == METHODTABLE_TOKEN_OVERFLOW;
2565     }
2566
2567     // Get the MD Import for the metadata for the corresponding type declaration
2568     IMDInternalImport* GetMDImport();
2569
2570     HRESULT GetCustomAttribute(WellKnownAttribute attribute,
2571                                const void  **ppData,
2572                                ULONG *pcbData);
2573
2574     mdTypeDef GetEnclosingCl();
2575
2576     CorNativeLinkType GetCharSet();
2577
2578 #ifdef DACCESS_COMPILE
2579     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
2580 #endif
2581
2582     //-------------------------------------------------------------------
2583     // DICTIONARIES FOR GENERIC INSTANTIATIONS
2584     //
2585     // The PerInstInfo pointer is a pointer to per-instantiation pointer table,
2586     // each entry of which points to an instantiation "dictionary"
2587     // for an instantiated type; the last pointer points to a
2588     // dictionary which is specific to this method table, previous
2589     // entries point to dictionaries in superclasses. Instantiated interfaces and structs
2590     // have just single dictionary (no inheritance).
2591     //
2592     // GetNumDicts() gives the number of dictionaries.
2593     //
2594     //@nice GENERICS: instead of a separate table of pointers, put the pointers
2595     // in the vtable itself. Advantages:
2596     // * Time: we save an indirection as we don't need to go through PerInstInfo first.
2597     // * Space: no need for PerInstInfo (1 word)
2598     // Problem is that lots of code assumes that the vtable is filled
2599     // uniformly with pointers to MethodDesc stubs.
2600     //
2601     // The dictionary for the method table is just an array of handles for
2602     // type parameters in the following cases:
2603     // * instantiated interfaces (no code)
2604     // * instantiated types whose code is not shared
2605     // Otherwise, it starts with the type parameters and then has a fixed
2606     // number of slots for handles (types & methods)
2607     // that are filled in lazily at run-time. Finally there is a "spill-bucket"
2608     // pointer used when the dictionary gets filled.
2609     // In summary:
2610     //    typar_1              type handle for first type parameter
2611     //    ...
2612     //    typar_n              type handle for last type parameter
2613     //    slot_1               slot for first run-time handle (initially null)
2614     //    ...
2615     //    slot_m               slot for last run-time handle (initially null)
2616     //    next_bucket          pointer to spill bucket (possibly null)
2617     // The spill bucket contains just run-time handle slots.
2618     //   (Alternative: continue chaining buckets.
2619     //    Advantage: no need to deallocate when growing dictionaries.
2620     //    Disadvantage: more indirections required at run-time.)
2621     //
2622     // The layout of dictionaries is determined by GetClass()->GetDictionaryLayout()
2623     // Thus the layout can vary between incompatible instantiations. This is sometimes useful because individual type
2624     // parameters may or may not be shared. For example, consider a two parameter class Dict<K,D>. In instantiations shared with
2625     // Dict<double,string> any reference to K is known at JIT-compile-time (it's double) but any token containing D
2626     // must have a dictionary entry. On the other hand, for instantiations shared with Dict<string,double> the opposite holds.
2627     //
2628
2629     typedef PTR_Dictionary PerInstInfoElem_t;
2630     typedef DPTR(PerInstInfoElem_t) PerInstInfo_t;
2631
2632     // Return a pointer to the per-instantiation information. See field itself for comments.
2633     DPTR(PerInstInfoElem_t) GetPerInstInfo()
2634     {
2635         LIMITED_METHOD_DAC_CONTRACT;
2636         _ASSERTE(HasPerInstInfo());
2637         return m_pPerInstInfo;
2638     }
2639     BOOL HasPerInstInfo()
2640     {
2641         LIMITED_METHOD_DAC_CONTRACT;
2642         return GetFlag(enum_flag_HasPerInstInfo) && !IsArray();
2643     }
2644 #ifndef DACCESS_COMPILE
2645     static inline DWORD GetOffsetOfPerInstInfo()
2646     {
2647         LIMITED_METHOD_CONTRACT;
2648         return offsetof(MethodTable, m_pPerInstInfo);
2649     }
2650     void SetPerInstInfo(PerInstInfoElem_t *pPerInstInfo)
2651     {
2652         LIMITED_METHOD_CONTRACT;
2653         m_pPerInstInfo = pPerInstInfo;
2654     }
2655     void SetDictInfo(WORD numDicts, WORD numTyPars)
2656     {
2657         WRAPPER_NO_CONTRACT;
2658         GenericsDictInfo* pInfo = GetGenericsDictInfo();
2659         pInfo->m_wNumDicts  = numDicts;
2660         pInfo->m_wNumTyPars = numTyPars;
2661     }
2662 #endif // !DACCESS_COMPILE
2663     PTR_GenericsDictInfo GetGenericsDictInfo()
2664     {
2665         LIMITED_METHOD_DAC_CONTRACT;
2666         // GenericsDictInfo is stored at negative offset of the dictionary
2667         return dac_cast<PTR_GenericsDictInfo>(GetPerInstInfo()) - 1;
2668     }
2669
2670     // Get a pointer to the dictionary for this instantiated type
2671     // (The instantiation is stored in the initial slots of the dictionary)
2672     // If not instantiated, return NULL
2673     PTR_Dictionary GetDictionary();
2674
2675     // Return a substitution suitbale for interpreting
2676     // the metadata in parent class, assuming we already have a subst.
2677     // suitable for interpreting the current class.
2678     //
2679     // If, for example, the definition for the current class is
2680     //   D<T> : C<List<T>, T[] >
2681     // then this (for C<!0,!1>) will be
2682     //   0 --> List<T>
2683     //   1 --> T[]
2684     // added to the chain of substitutions.
2685     //
2686     // Subsequently, if the definition for C is
2687     //   C<T, U> : B< Dictionary<T, U> >
2688     // then the next subst (for B<!0>) will be
2689     //   0 --> Dictionary< List<T>, T[] >
2690
2691     Substitution GetSubstitutionForParent(const Substitution *pSubst);
2692
2693     inline DWORD GetAttrClass();
2694
2695     inline BOOL HasFieldsWhichMustBeInited();
2696
2697     //-------------------------------------------------------------------
2698     // THE EXPOSED CLASS OBJECT
2699     //
2700     /*
2701      * m_ExposedClassObject is a RuntimeType instance for this class.  But
2702      * do NOT use it for Arrays or remoted objects!  All arrays of objects
2703      * share the same MethodTable/EEClass.
2704      * @GENERICS: this is per-instantiation data
2705      */
2706     // There are two version of GetManagedClassObject.  The GetManagedClassObject()
2707     //  method will get the class object.  If it doesn't exist it will be created.
2708     //  GetManagedClassObjectIfExists() will return null if the Type object doesn't exist.
2709     OBJECTREF GetManagedClassObject();
2710     OBJECTREF GetManagedClassObjectIfExists();
2711
2712
2713     // ------------------------------------------------------------------
2714     // Private part of MethodTable
2715     // ------------------------------------------------------------------
2716
2717 #ifndef DACCESS_COMPILE
2718     inline void SetWriteableData(PTR_MethodTableWriteableData pMTWriteableData)
2719     {
2720         LIMITED_METHOD_CONTRACT;
2721         _ASSERTE(pMTWriteableData);
2722         m_pWriteableData = pMTWriteableData;
2723     }
2724 #endif
2725
2726     inline PTR_Const_MethodTableWriteableData GetWriteableData() const
2727     {
2728         LIMITED_METHOD_DAC_CONTRACT;
2729         return MethodTable::m_pWriteableData;
2730     }
2731
2732     inline PTR_MethodTableWriteableData GetWriteableDataForWrite()
2733     {
2734         LIMITED_METHOD_DAC_CONTRACT;
2735         return MethodTable::m_pWriteableData;
2736     }
2737
2738     //-------------------------------------------------------------------
2739     // The GUID Info
2740     // Used by COM interop to get GUIDs (IIDs and CLSIDs)
2741
2742     // Get and cache the GUID for this interface/class
2743     HRESULT GetGuidNoThrow(GUID *pGuid, BOOL bGenerateIfNotFound, BOOL bClassic = TRUE);
2744
2745     // Get and cache the GUID for this interface/class
2746     void    GetGuid(GUID *pGuid, BOOL bGenerateIfNotFound, BOOL bClassic = TRUE);
2747
2748     // Convenience method - determine if the interface/class has a guid specified (even if not yet cached)
2749     BOOL HasExplicitGuid();
2750
2751 public :
2752     // Helper routines for the GetFullyQualifiedNameForClass macros defined at the top of class.h.
2753     // You probably should not use these functions directly.
2754     SString &_GetFullyQualifiedNameForClassNestedAware(SString &ssBuf);
2755     SString &_GetFullyQualifiedNameForClass(SString &ssBuf);
2756     LPCUTF8 GetFullyQualifiedNameInfo(LPCUTF8 *ppszNamespace);
2757
2758 private:
2759     template<typename RedirectFunctor> SString &_GetFullyQualifiedNameForClassNestedAwareInternal(SString &ssBuf);
2760
2761 public :
2762     //-------------------------------------------------------------------
2763     // Debug Info
2764     //
2765
2766
2767 #ifdef _DEBUG
2768     inline LPCUTF8 GetDebugClassName()
2769     {
2770         LIMITED_METHOD_CONTRACT;
2771         return debug_m_szClassName;
2772     }
2773     inline void SetDebugClassName(LPCUTF8 name)
2774     {
2775         LIMITED_METHOD_CONTRACT;
2776         debug_m_szClassName = name;
2777     }
2778
2779     // Was the type created with injected duplicates?
2780     // TRUE means that we tried to inject duplicates (not that we found one to inject).
2781     inline BOOL Debug_HasInjectedInterfaceDuplicates() const
2782     {
2783         LIMITED_METHOD_CONTRACT;
2784         return (GetWriteableData()->m_dwFlags & MethodTableWriteableData::enum_flag_HasInjectedInterfaceDuplicates) != 0;
2785     }
2786     inline void Debug_SetHasInjectedInterfaceDuplicates()
2787     {
2788         LIMITED_METHOD_CONTRACT;
2789         GetWriteableDataForWrite()->m_dwFlags |= MethodTableWriteableData::enum_flag_HasInjectedInterfaceDuplicates;
2790     }
2791 #endif // _DEBUG
2792
2793
2794 #ifndef DACCESS_COMPILE
2795 public:
2796     //--------------------------------------------------------------------------------------
2797     class MethodData
2798     {
2799       public:
2800         inline ULONG AddRef()
2801             { LIMITED_METHOD_CONTRACT; return (ULONG) InterlockedIncrement((LONG*)&m_cRef); }
2802
2803         ULONG Release();
2804
2805         // Since all methods that return a MethodData already AddRef'd, we do NOT
2806         // want to AddRef when putting a holder around it. We only want to release it.
2807         static void HolderAcquire(MethodData *pEntry)
2808             { LIMITED_METHOD_CONTRACT; return; }
2809         static void HolderRelease(MethodData *pEntry)
2810             { WRAPPER_NO_CONTRACT; if (pEntry != NULL) pEntry->Release(); }
2811
2812       protected:
2813         ULONG m_cRef;
2814         MethodTable *const m_pImplMT;
2815         MethodTable *const m_pDeclMT;
2816
2817       public:
2818         MethodData(MethodTable *implMT, MethodTable *declMT) : m_cRef(1), m_pImplMT(implMT), m_pDeclMT(declMT) { LIMITED_METHOD_CONTRACT; }
2819         virtual ~MethodData() { LIMITED_METHOD_CONTRACT; }
2820
2821         virtual MethodData  *GetDeclMethodData() = 0;
2822         MethodTable *GetDeclMethodTable() { return m_pDeclMT; }
2823         virtual MethodDesc  *GetDeclMethodDesc(UINT32 slotNumber) = 0;
2824
2825         virtual MethodData  *GetImplMethodData() = 0;
2826         MethodTable *GetImplMethodTable() { return m_pImplMT; }
2827         virtual DispatchSlot GetImplSlot(UINT32 slotNumber) = 0;
2828         // Returns INVALID_SLOT_NUMBER if no implementation exists.
2829         virtual UINT32       GetImplSlotNumber(UINT32 slotNumber) = 0;
2830         virtual MethodDesc  *GetImplMethodDesc(UINT32 slotNumber) = 0;
2831         virtual void InvalidateCachedVirtualSlot(UINT32 slotNumber) = 0;
2832
2833         virtual UINT32 GetNumVirtuals() = 0;
2834         virtual UINT32 GetNumMethods() = 0;
2835
2836         virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber) = 0;
2837
2838       protected:
2839         static const UINT32 INVALID_SLOT_NUMBER = UINT32_MAX;
2840
2841         // This is used when building the data
2842         struct MethodDataEntry
2843         {
2844           private:
2845             static const UINT32 INVALID_CHAIN_AND_INDEX = (UINT32)(-1);
2846             static const UINT16 INVALID_IMPL_SLOT_NUM = (UINT16)(-1);
2847
2848             // This contains both the chain delta and the table index. The
2849             // reason that they are combined is that we need atomic update
2850             // of both, and it is convenient that both are on UINT16 in size.
2851             UINT32           m_chainDeltaAndTableIndex;
2852             UINT16           m_implSlotNum;     // For virtually remapped slots
2853             DispatchSlot     m_slot;            // The entry in the DispatchImplTable
2854             MethodDesc      *m_pMD;             // The MethodDesc for this slot
2855
2856           public:
2857             inline MethodDataEntry() : m_slot(NULL)
2858                 { WRAPPER_NO_CONTRACT; Init(); }
2859
2860             inline void Init()
2861             {
2862                 LIMITED_METHOD_CONTRACT;
2863                 m_chainDeltaAndTableIndex = INVALID_CHAIN_AND_INDEX;
2864                 m_implSlotNum = INVALID_IMPL_SLOT_NUM;
2865                 m_slot = NULL;
2866                 m_pMD = NULL;
2867             }
2868
2869             inline BOOL IsDeclInit()
2870                 { LIMITED_METHOD_CONTRACT; return m_chainDeltaAndTableIndex != INVALID_CHAIN_AND_INDEX; }
2871             inline BOOL IsImplInit()
2872                 { LIMITED_METHOD_CONTRACT; return m_implSlotNum != INVALID_IMPL_SLOT_NUM; }
2873
2874             inline void SetDeclData(UINT32 chainDelta, UINT32 tableIndex)
2875                 { LIMITED_METHOD_CONTRACT; m_chainDeltaAndTableIndex = ((((UINT16) chainDelta) << 16) | ((UINT16) tableIndex)); }
2876             inline UINT32 GetChainDelta()
2877                 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(IsDeclInit()); return m_chainDeltaAndTableIndex >> 16; }
2878             inline UINT32 GetTableIndex()
2879                 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(IsDeclInit()); return (m_chainDeltaAndTableIndex & (UINT32)UINT16_MAX); }
2880
2881             inline void SetImplData(UINT32 implSlotNum)
2882                 { LIMITED_METHOD_CONTRACT; m_implSlotNum = (UINT16) implSlotNum; }
2883             inline UINT32 GetImplSlotNum()
2884                 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(IsImplInit()); return m_implSlotNum; }
2885
2886             inline void SetSlot(DispatchSlot slot)
2887                 { LIMITED_METHOD_CONTRACT; m_slot = slot; }
2888             inline DispatchSlot GetSlot()
2889                 { LIMITED_METHOD_CONTRACT; return m_slot; }
2890
2891             inline void SetMethodDesc(MethodDesc *pMD)
2892                 { LIMITED_METHOD_CONTRACT; m_pMD = pMD; }
2893             inline MethodDesc *GetMethodDesc()
2894                 { LIMITED_METHOD_CONTRACT; return m_pMD; }
2895
2896         };
2897
2898         static void ProcessMap(
2899             const DispatchMapTypeID * rgTypeIDs,
2900             UINT32                    cTypeIDs,
2901             MethodTable *             pMT,
2902             UINT32                    cCurrentChainDepth,
2903             MethodDataEntry *         rgWorkingData,
2904             size_t                    cWorkingData);
2905     };  // class MethodData
2906
2907     typedef ::Holder < MethodData *, MethodData::HolderAcquire, MethodData::HolderRelease > MethodDataHolder;
2908     typedef ::Wrapper < MethodData *, MethodData::HolderAcquire, MethodData::HolderRelease > MethodDataWrapper;
2909
2910 protected:
2911     //--------------------------------------------------------------------------------------
2912     class MethodDataObject final : public MethodData
2913     {
2914       public:
2915         // Static method that returns the amount of memory to allocate for a particular type.
2916         static UINT32 GetObjectSize(MethodTable *pMT);
2917
2918         // Constructor. Make sure you have allocated enough memory using GetObjectSize.
2919         inline MethodDataObject(MethodTable *pMT) : MethodData(pMT, pMT)
2920             { WRAPPER_NO_CONTRACT; Init(NULL); }
2921
2922         inline MethodDataObject(MethodTable *pMT, MethodData *pParentData) : MethodData(pMT, pMT)
2923             { WRAPPER_NO_CONTRACT; Init(pParentData); }
2924
2925         virtual ~MethodDataObject() { LIMITED_METHOD_CONTRACT; }
2926
2927         virtual MethodData  *GetDeclMethodData()
2928             { LIMITED_METHOD_CONTRACT; return this; }
2929         virtual MethodDesc *GetDeclMethodDesc(UINT32 slotNumber);
2930
2931         virtual MethodData  *GetImplMethodData()
2932             { LIMITED_METHOD_CONTRACT; return this; }
2933         virtual DispatchSlot GetImplSlot(UINT32 slotNumber);
2934         virtual UINT32       GetImplSlotNumber(UINT32 slotNumber);
2935         virtual MethodDesc  *GetImplMethodDesc(UINT32 slotNumber);
2936         virtual void InvalidateCachedVirtualSlot(UINT32 slotNumber);
2937
2938         virtual UINT32 GetNumVirtuals()
2939             { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetNumVirtuals(); }
2940         virtual UINT32 GetNumMethods()
2941             { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetCanonicalMethodTable()->GetNumMethods(); }
2942
2943         virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber);
2944
2945       protected:
2946         void Init(MethodData *pParentData);
2947
2948         BOOL PopulateNextLevel();
2949
2950         // This is used in staged map decoding - it indicates which type we will next decode.
2951         UINT32       m_iNextChainDepth;
2952         static const UINT32 MAX_CHAIN_DEPTH = UINT32_MAX;
2953
2954         BOOL m_containsMethodImpl;
2955
2956         // NOTE: Use of these APIs are unlocked and may appear to be erroneous. However, since calls
2957         //       to ProcessMap will result in identical values being placed in the MethodDataObjectEntry
2958         //       array, it it is not a problem if there is a race, since one thread may just end up
2959         //       doing some duplicate work.
2960
2961         inline UINT32 GetNextChainDepth()
2962         { LIMITED_METHOD_CONTRACT; return VolatileLoad(&m_iNextChainDepth); }
2963
2964         inline void SetNextChainDepth(UINT32 iDepth)
2965         {
2966             LIMITED_METHOD_CONTRACT;
2967             if (GetNextChainDepth() < iDepth) {
2968                 VolatileStore(&m_iNextChainDepth, iDepth);
2969             }
2970         }
2971
2972         // This is used when building the data
2973         struct MethodDataObjectEntry
2974         {
2975           private:
2976             MethodDesc *m_pMDDecl;
2977             MethodDesc *m_pMDImpl;
2978
2979           public:
2980             inline MethodDataObjectEntry() : m_pMDDecl(NULL), m_pMDImpl(NULL) {}
2981
2982             inline void SetDeclMethodDesc(MethodDesc *pMD)
2983                 { LIMITED_METHOD_CONTRACT; m_pMDDecl = pMD; }
2984             inline MethodDesc *GetDeclMethodDesc()
2985                 { LIMITED_METHOD_CONTRACT; return m_pMDDecl; }
2986             inline void SetImplMethodDesc(MethodDesc *pMD)
2987                 { LIMITED_METHOD_CONTRACT; m_pMDImpl = pMD; }
2988             inline MethodDesc *GetImplMethodDesc()
2989                 { LIMITED_METHOD_CONTRACT; return m_pMDImpl; }
2990         };
2991
2992
2993         inline MethodDataObjectEntry *GetEntryData()
2994             { LIMITED_METHOD_CONTRACT; return &m_rgEntries[0]; }
2995
2996         inline MethodDataObjectEntry *GetEntry(UINT32 i)
2997             { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(i < GetNumMethods()); return GetEntryData() + i; }
2998
2999         void FillEntryDataForAncestor(MethodTable *pMT);
3000
3001         //
3002         // At the end of this object is an array
3003         //
3004         MethodDataObjectEntry m_rgEntries[0];
3005
3006       public:
3007         struct TargetMethodTable
3008         {
3009             MethodTable* pMT;
3010         };
3011
3012         static void* operator new(size_t size, TargetMethodTable targetMT)
3013         {
3014             _ASSERTE(size <= GetObjectSize(targetMT.pMT));
3015             return ::operator new(GetObjectSize(targetMT.pMT));
3016         }
3017         static void* operator new(size_t size) = delete;
3018     };  // class MethodDataObject
3019
3020     //--------------------------------------------------------------------------------------
3021     class MethodDataInterface : public MethodData
3022     {
3023       public:
3024         // Static method that returns the amount of memory to allocate for a particular type.
3025         static UINT32 GetObjectSize(MethodTable *pMT)
3026             { LIMITED_METHOD_CONTRACT; return sizeof(MethodDataInterface); }
3027
3028         // Constructor. Make sure you have allocated enough memory using GetObjectSize.
3029         MethodDataInterface(MethodTable *pMT) : MethodData(pMT, pMT)
3030         {
3031             LIMITED_METHOD_CONTRACT;
3032             CONSISTENCY_CHECK(CheckPointer(pMT));
3033             CONSISTENCY_CHECK(pMT->IsInterface());
3034         }
3035         virtual ~MethodDataInterface()
3036             { LIMITED_METHOD_CONTRACT; }
3037
3038         //
3039         // Decl data
3040         //
3041         virtual MethodData  *GetDeclMethodData()
3042             { LIMITED_METHOD_CONTRACT; return this; }
3043         virtual MethodDesc *GetDeclMethodDesc(UINT32 slotNumber);
3044
3045         //
3046         // Impl data
3047         //
3048         virtual MethodData  *GetImplMethodData()
3049             { LIMITED_METHOD_CONTRACT; return this; }
3050         virtual DispatchSlot GetImplSlot(UINT32 slotNumber)
3051             { WRAPPER_NO_CONTRACT; return DispatchSlot(m_pDeclMT->GetRestoredSlot(slotNumber)); }
3052         virtual UINT32       GetImplSlotNumber(UINT32 slotNumber)
3053             { LIMITED_METHOD_CONTRACT; return slotNumber; }
3054         virtual MethodDesc  *GetImplMethodDesc(UINT32 slotNumber);
3055         virtual void InvalidateCachedVirtualSlot(UINT32 slotNumber);
3056
3057         //
3058         // Slot count data
3059         //
3060         virtual UINT32 GetNumVirtuals()
3061             { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetNumVirtuals(); }
3062         virtual UINT32 GetNumMethods()
3063             { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetNumMethods(); }
3064
3065         virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber)
3066             { LIMITED_METHOD_CONTRACT; }
3067
3068     };  // class MethodDataInterface
3069
3070     //--------------------------------------------------------------------------------------
3071     class MethodDataInterfaceImpl final : public MethodData
3072     {
3073       public:
3074         // Object construction-related methods
3075         static UINT32 GetObjectSize(MethodTable *pMTDecl);
3076
3077         MethodDataInterfaceImpl(
3078             const DispatchMapTypeID * rgDeclTypeIDs,
3079             UINT32                    cDeclTypeIDs,
3080             MethodData *              pDecl,
3081             MethodData *              pImpl);
3082         virtual ~MethodDataInterfaceImpl();
3083
3084         // Decl-related methods
3085         virtual MethodData  *GetDeclMethodData()
3086             { LIMITED_METHOD_CONTRACT; return m_pDecl; }
3087         virtual MethodTable *GetDeclMethodTable()
3088             { WRAPPER_NO_CONTRACT; return m_pDecl->GetDeclMethodTable(); }
3089         virtual MethodDesc  *GetDeclMethodDesc(UINT32 slotNumber)
3090             { WRAPPER_NO_CONTRACT; return m_pDecl->GetDeclMethodDesc(slotNumber); }
3091
3092         // Impl-related methods
3093         virtual MethodData  *GetImplMethodData()
3094             { LIMITED_METHOD_CONTRACT; return m_pImpl; }
3095         virtual MethodTable *GetImplMethodTable()
3096             { WRAPPER_NO_CONTRACT; return m_pImpl->GetImplMethodTable(); }
3097         virtual DispatchSlot GetImplSlot(UINT32 slotNumber);
3098         virtual UINT32       GetImplSlotNumber(UINT32 slotNumber);
3099         virtual MethodDesc  *GetImplMethodDesc(UINT32 slotNumber);
3100         virtual void InvalidateCachedVirtualSlot(UINT32 slotNumber);
3101
3102         virtual UINT32 GetNumVirtuals()
3103             { WRAPPER_NO_CONTRACT; return m_pDecl->GetNumVirtuals(); }
3104         virtual UINT32 GetNumMethods()
3105             { WRAPPER_NO_CONTRACT; return m_pDecl->GetNumVirtuals(); }
3106
3107         virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber)
3108             { LIMITED_METHOD_CONTRACT; }
3109
3110       protected:
3111         UINT32 MapToImplSlotNumber(UINT32 slotNumber);
3112
3113         BOOL PopulateNextLevel();
3114         void Init(
3115             const DispatchMapTypeID * rgDeclTypeIDs,
3116             UINT32                    cDeclTypeIDs,
3117             MethodData *              pDecl,
3118             MethodData *              pImpl);
3119
3120         MethodData *m_pDecl;
3121         MethodData *m_pImpl;
3122
3123         // This is used in staged map decoding - it indicates which type(s) we will find.
3124         const DispatchMapTypeID * m_rgDeclTypeIDs;
3125         UINT32                    m_cDeclTypeIDs;
3126         UINT32                    m_iNextChainDepth;
3127         static const UINT32       MAX_CHAIN_DEPTH = UINT32_MAX;
3128
3129         inline UINT32 GetNextChainDepth()
3130         { LIMITED_METHOD_CONTRACT; return VolatileLoad(&m_iNextChainDepth); }
3131
3132         inline void SetNextChainDepth(UINT32 iDepth)
3133         {
3134             LIMITED_METHOD_CONTRACT;
3135             if (GetNextChainDepth() < iDepth) {
3136                 VolatileStore(&m_iNextChainDepth, iDepth);
3137             }
3138         }
3139
3140         //
3141         // At the end of this object is an array, so you cannot derive from this class.
3142         //
3143
3144         inline MethodDataEntry *GetEntryData()
3145             { LIMITED_METHOD_CONTRACT; return &m_rgEntries[0]; }
3146
3147         inline MethodDataEntry *GetEntry(UINT32 i)
3148             { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(i < GetNumMethods()); return GetEntryData() + i; }
3149
3150         MethodDataEntry m_rgEntries[0];
3151
3152       public:
3153         struct TargetMethodTable
3154         {
3155             MethodTable* pMT;
3156         };
3157
3158         static void* operator new(size_t size, TargetMethodTable targetMT)
3159         {
3160             _ASSERTE(size <= GetObjectSize(targetMT.pMT));
3161             return ::operator new(GetObjectSize(targetMT.pMT));
3162         }
3163         static void* operator new(size_t size) = delete;
3164     };  // class MethodDataInterfaceImpl
3165
3166     //--------------------------------------------------------------------------------------
3167     static MethodDataCache *s_pMethodDataCache;
3168     static BOOL             s_fUseParentMethodData;
3169     static BOOL             s_fUseMethodDataCache;
3170
3171 public:
3172     static void AllowMethodDataCaching()
3173         { WRAPPER_NO_CONTRACT; CheckInitMethodDataCache(); s_fUseMethodDataCache = TRUE; }
3174     static void ClearMethodDataCache();
3175     static void AllowParentMethodDataCopy()
3176         { LIMITED_METHOD_CONTRACT; s_fUseParentMethodData = TRUE; }
3177     // NOTE: The fCanCache argument determines if the resulting MethodData object can
3178     //       be added to the global MethodDataCache. This is used when requesting a
3179     //       MethodData object for a type currently being built.
3180     static MethodData *GetMethodData(MethodTable *pMT, BOOL fCanCache = TRUE);
3181     static MethodData *GetMethodData(MethodTable *pMTDecl, MethodTable *pMTImpl, BOOL fCanCache = TRUE);
3182     // This method is used by BuildMethodTable because the exact interface has not yet been loaded.
3183     // NOTE: This method does not cache the resulting MethodData object in the global MethodDataCache.
3184     static MethodData * GetMethodData(
3185         const DispatchMapTypeID * rgDeclTypeIDs,
3186         UINT32                    cDeclTypeIDs,
3187         MethodTable *             pMTDecl,
3188         MethodTable *             pMTImpl);
3189
3190     void CopySlotFrom(UINT32 slotNumber, MethodDataWrapper &hSourceMTData, MethodTable *pSourceMT);
3191
3192 protected:
3193     static void CheckInitMethodDataCache();
3194     static MethodData *FindParentMethodDataHelper(MethodTable *pMT);
3195     static MethodData *FindMethodDataHelper(MethodTable *pMTDecl, MethodTable *pMTImpl);
3196     static MethodData *GetMethodDataHelper(MethodTable *pMTDecl, MethodTable *pMTImpl, BOOL fCanCache);
3197     // NOTE: This method does not cache the resulting MethodData object in the global MethodDataCache.
3198     static MethodData * GetMethodDataHelper(
3199         const DispatchMapTypeID * rgDeclTypeIDs,
3200         UINT32                    cDeclTypeIDs,
3201         MethodTable *             pMTDecl,
3202         MethodTable *             pMTImpl);
3203
3204 public:
3205     //--------------------------------------------------------------------------------------
3206     class MethodIterator
3207     {
3208     public:
3209         MethodIterator(MethodTable *pMT);
3210         MethodIterator(MethodTable *pMTDecl, MethodTable *pMTImpl);
3211         MethodIterator(MethodData *pMethodData);
3212         MethodIterator(const MethodIterator &it);
3213         inline ~MethodIterator() { WRAPPER_NO_CONTRACT; m_pMethodData->Release(); }
3214         INT32 GetNumMethods() const;
3215         inline BOOL IsValid() const;
3216         inline BOOL MoveTo(UINT32 idx);
3217         inline BOOL Prev();
3218         inline BOOL Next();
3219         inline void MoveToBegin();
3220         inline void MoveToEnd();
3221         inline UINT32 GetSlotNumber() const;
3222         inline UINT32 GetImplSlotNumber() const;
3223         inline BOOL IsVirtual() const;
3224         inline UINT32 GetNumVirtuals() const;
3225         inline DispatchSlot GetTarget() const;
3226
3227         // Can be called only if IsValid()=TRUE
3228         inline MethodDesc *GetMethodDesc() const;
3229         inline MethodDesc *GetDeclMethodDesc() const;
3230
3231     protected:
3232         void Init(MethodTable *pMTDecl, MethodTable *pMTImpl);
3233
3234         MethodData         *m_pMethodData;
3235         INT32               m_iCur;           // Current logical slot index
3236         INT32               m_iMethods;
3237     };  // class MethodIterator
3238 #endif // !DACCESS_COMPILE
3239
3240     //--------------------------------------------------------------------------------------
3241     // This iterator lets you walk over all the method bodies introduced by this type.
3242     // This includes new static methods, new non-virtual methods, and any overrides
3243     // of the parent's virtual methods. It does not include virtual method implementations
3244     // provided by the parent
3245
3246     class IntroducedMethodIterator
3247     {
3248     public:
3249         IntroducedMethodIterator(MethodTable *pMT, BOOL restrictToCanonicalTypes = TRUE);
3250         inline BOOL IsValid() const;
3251         BOOL Next();
3252
3253         // Can be called only if IsValid()=TRUE
3254         inline MethodDesc *GetMethodDesc() const;
3255
3256         // Static worker methods of the iterator. These are meant to be used
3257         // by RuntimeTypeHandle::GetFirstIntroducedMethod and RuntimeTypeHandle::GetNextIntroducedMethod
3258         // only to expose this iterator to managed code.
3259         static MethodDesc * GetFirst(MethodTable * pMT);
3260         static MethodDesc * GetNext(MethodDesc * pMD);
3261
3262     protected:
3263         MethodDesc      *m_pMethodDesc;     // Current method desc
3264
3265         // Cached info about current method desc
3266         MethodDescChunk *m_pChunk;
3267         TADDR            m_pChunkEnd;
3268
3269         void SetChunk(MethodDescChunk * pChunk);
3270     };  // class IntroducedMethodIterator
3271
3272     //-------------------------------------------------------------------
3273     // INSTANCE MEMBER VARIABLES
3274     //
3275
3276 #ifdef DACCESS_COMPILE
3277 public:
3278 #else
3279 private:
3280 #endif
3281     enum WFLAGS_LOW_ENUM
3282     {
3283         // AS YOU ADD NEW FLAGS PLEASE CONSIDER WHETHER Generics::NewInstantiation NEEDS
3284         // TO BE UPDATED IN ORDER TO ENSURE THAT METHODTABLES DUPLICATED FOR GENERIC INSTANTIATIONS
3285         // CARRY THE CORECT FLAGS.
3286         //
3287
3288         // We are overloading the low 2 bytes of m_dwFlags to be a component size for Strings
3289         // and Arrays and some set of flags which we can be assured are of a specified state
3290         // for Strings / Arrays, currently these will be a bunch of generics flags which don't
3291         // apply to Strings / Arrays.
3292
3293         enum_flag_UNUSED_ComponentSize_1    = 0x00000001,
3294
3295         enum_flag_StaticsMask               = 0x00000006,
3296         enum_flag_StaticsMask_NonDynamic    = 0x00000000,
3297         enum_flag_StaticsMask_Dynamic       = 0x00000002,   // dynamic statics (EnC, reflection.emit)
3298         enum_flag_StaticsMask_Generics      = 0x00000004,   // generics statics
3299         enum_flag_StaticsMask_CrossModuleGenerics       = 0x00000006, // cross module generics statics (NGen)
3300         enum_flag_StaticsMask_IfGenericsThenCrossModule = 0x00000002, // helper constant to get rid of unnecessary check
3301
3302         enum_flag_NotInPZM                  = 0x00000008,   // True if this type is not in its PreferredZapModule
3303
3304         enum_flag_GenericsMask              = 0x00000030,
3305         enum_flag_GenericsMask_NonGeneric   = 0x00000000,   // no instantiation
3306         enum_flag_GenericsMask_GenericInst  = 0x00000010,   // regular instantiation, e.g. List<String>
3307         enum_flag_GenericsMask_SharedInst   = 0x00000020,   // shared instantiation, e.g. List<__Canon> or List<MyValueType<__Canon>>
3308         enum_flag_GenericsMask_TypicalInst  = 0x00000030,   // the type instantiated at its formal parameters, e.g. List<T>
3309
3310         enum_flag_HasVariance               = 0x00000100,   // This is an instantiated type some of whose type parameters are co- or contra-variant
3311
3312         enum_flag_HasDefaultCtor            = 0x00000200,
3313         enum_flag_HasPreciseInitCctors      = 0x00000400,   // Do we need to run class constructors at allocation time? (Not perf important, could be moved to EEClass
3314
3315 #if defined(FEATURE_HFA)
3316 #if defined(UNIX_AMD64_ABI)
3317 #error "Can't define both FEATURE_HFA and UNIX_AMD64_ABI"
3318 #endif
3319         enum_flag_IsHFA                     = 0x00000800,   // This type is an HFA (Homogeneous Floating-point Aggregate)
3320 #endif // FEATURE_HFA
3321
3322 #if defined(UNIX_AMD64_ABI)
3323 #if defined(FEATURE_HFA)
3324 #error "Can't define both FEATURE_HFA and UNIX_AMD64_ABI"
3325 #endif
3326         enum_flag_IsRegStructPassed         = 0x00000800,   // This type is a System V register passed struct.
3327 #endif // UNIX_AMD64_ABI
3328
3329         enum_flag_IsByRefLike               = 0x00001000,
3330
3331         // In a perfect world we would fill these flags using other flags that we already have
3332         // which have a constant value for something which has a component size.
3333         enum_flag_UNUSED_ComponentSize_5    = 0x00002000,
3334         enum_flag_UNUSED_ComponentSize_6    = 0x00004000,
3335         enum_flag_UNUSED_ComponentSize_7    = 0x00008000,
3336
3337 #define SET_FALSE(flag)     ((flag) & 0)
3338 #define SET_TRUE(flag)      ((flag) & 0xffff)
3339
3340         // IMPORTANT! IMPORTANT! IMPORTANT!
3341         //
3342         // As you change the flags in WFLAGS_LOW_ENUM you also need to change this
3343         // to be up to date to reflect the default values of those flags for the
3344         // case where this MethodTable is for a String or Array
3345         enum_flag_StringArrayValues = SET_TRUE(enum_flag_StaticsMask_NonDynamic) |
3346                                       SET_FALSE(enum_flag_NotInPZM) |
3347                                       SET_TRUE(enum_flag_GenericsMask_NonGeneric) |
3348                                       SET_FALSE(enum_flag_HasVariance) |
3349                                       SET_FALSE(enum_flag_HasDefaultCtor) |
3350                                       SET_FALSE(enum_flag_HasPreciseInitCctors),
3351
3352     };  // enum WFLAGS_LOW_ENUM
3353
3354     enum WFLAGS_HIGH_ENUM
3355     {
3356         // DO NOT use flags that have bits set in the low 2 bytes.
3357         // These flags are DWORD sized so that our atomic masking
3358         // operations can operate on the entire 4-byte aligned DWORD
3359         // instead of the logical non-aligned WORD of flags.  The
3360         // low WORD of flags is reserved for the component size.
3361
3362         // The following bits describe mutually exclusive locations of the type
3363         // in the type hierarchy.
3364         enum_flag_Category_Mask             = 0x000F0000,
3365
3366         enum_flag_Category_Class            = 0x00000000,
3367         enum_flag_Category_Unused_1         = 0x00010000,
3368         enum_flag_Category_Unused_2         = 0x00020000,
3369         enum_flag_Category_Unused_3         = 0x00030000,
3370
3371         enum_flag_Category_ValueType        = 0x00040000,
3372         enum_flag_Category_ValueType_Mask   = 0x000C0000,
3373         enum_flag_Category_Nullable         = 0x00050000, // sub-category of ValueType
3374         enum_flag_Category_PrimitiveValueType=0x00060000, // sub-category of ValueType, Enum or primitive value type
3375         enum_flag_Category_TruePrimitive    = 0x00070000, // sub-category of ValueType, Primitive (ELEMENT_TYPE_I, etc.)
3376
3377         enum_flag_Category_Array            = 0x00080000,
3378         enum_flag_Category_Array_Mask       = 0x000C0000,
3379         // enum_flag_Category_IfArrayThenUnused                 = 0x00010000, // sub-category of Array
3380         enum_flag_Category_IfArrayThenSzArray                   = 0x00020000, // sub-category of Array
3381
3382         enum_flag_Category_Interface        = 0x000C0000,
3383         enum_flag_Category_Unused_4         = 0x000D0000,
3384         enum_flag_Category_Unused_5         = 0x000E0000,
3385         enum_flag_Category_Unused_6         = 0x000F0000,
3386
3387         enum_flag_Category_ElementTypeMask  = 0x000E0000, // bits that matter for element type mask
3388
3389
3390         enum_flag_HasFinalizer                = 0x00100000, // instances require finalization
3391
3392         enum_flag_IDynamicInterfaceCastable   = 0x00200000, // class implements IDynamicInterfaceCastable interface
3393
3394         enum_flag_ICastable                   = 0x00400000, // class implements ICastable interface
3395
3396         enum_flag_Unused_1                    = 0x00800000,
3397
3398         enum_flag_ContainsPointers            = 0x01000000,
3399
3400         enum_flag_HasTypeEquivalence          = 0x02000000, // can be equivalent to another type
3401
3402         enum_flag_IsTrackedReferenceWithFinalizer   = 0x04000000,
3403
3404         enum_flag_HasCriticalFinalizer        = 0x08000000, // finalizer must be run on Appdomain Unload
3405         enum_flag_Collectible                 = 0x10000000,
3406         enum_flag_ContainsGenericVariables    = 0x20000000,   // we cache this flag to help detect these efficiently and
3407                                                               // to detect this condition when restoring
3408
3409         enum_flag_ComObject                   = 0x40000000, // class is a com object
3410
3411         enum_flag_HasComponentSize            = 0x80000000,   // This is set if component size is used for flags.
3412
3413         // Types that require non-trivial interface cast have this bit set in the category
3414         enum_flag_NonTrivialInterfaceCast   =  enum_flag_Category_Array
3415                                              | enum_flag_ComObject
3416                                              | enum_flag_ICastable
3417                                              | enum_flag_IDynamicInterfaceCastable
3418                                              | enum_flag_Category_ValueType
3419
3420     };  // enum WFLAGS_HIGH_ENUM
3421
3422 // NIDump needs to be able to see these flags
3423 // TODO: figure out how to make these private
3424 #if defined(DACCESS_COMPILE)
3425 public:
3426 #else
3427 private:
3428 #endif
3429     enum WFLAGS2_ENUM
3430     {
3431         // AS YOU ADD NEW FLAGS PLEASE CONSIDER WHETHER Generics::NewInstantiation NEEDS
3432         // TO BE UPDATED IN ORDER TO ENSURE THAT METHODTABLES DUPLICATED FOR GENERIC INSTANTIATIONS
3433         // CARRY THE CORECT FLAGS.
3434
3435         // The following bits describe usage of optional slots. They have to stay
3436         // together because of we index using them into offset arrays.
3437         enum_flag_MultipurposeSlotsMask     = 0x001F,
3438         enum_flag_HasPerInstInfo            = 0x0001,
3439         enum_flag_HasInterfaceMap           = 0x0002,
3440         enum_flag_HasDispatchMapSlot        = 0x0004,
3441         enum_flag_HasNonVirtualSlots        = 0x0008,
3442         enum_flag_HasModuleOverride         = 0x0010,
3443
3444         // unused                           = 0x0020,
3445         // unused                           = 0x0040,
3446
3447         enum_flag_HasModuleDependencies     = 0x0080,
3448
3449         enum_flag_IsIntrinsicType           = 0x0100,
3450
3451         // unused                           = 0x0200,
3452
3453         enum_flag_HasCctor                  = 0x0400,
3454         enum_flag_HasVirtualStaticMethods   = 0x0800,
3455
3456 #ifdef FEATURE_64BIT_ALIGNMENT
3457         enum_flag_RequiresAlign8            = 0x1000, // Type requires 8-byte alignment (only set on platforms that require this and don't get it implicitly)
3458 #endif
3459
3460         enum_flag_HasBoxedRegularStatics    = 0x2000, // GetNumBoxedRegularStatics() != 0
3461
3462         enum_flag_HasSingleNonVirtualSlot   = 0x4000,
3463
3464         // unused                           = 0x8000,
3465     };  // enum WFLAGS2_ENUM
3466
3467     __forceinline void ClearFlag(WFLAGS_LOW_ENUM flag)
3468     {
3469         _ASSERTE(!IsStringOrArray());
3470         m_dwFlags &= ~flag;
3471     }
3472     __forceinline void SetFlag(WFLAGS_LOW_ENUM flag)
3473     {
3474         _ASSERTE(!IsStringOrArray());
3475         m_dwFlags |= flag;
3476     }
3477     __forceinline DWORD GetFlag(WFLAGS_LOW_ENUM flag) const
3478     {
3479         SUPPORTS_DAC;
3480         return (IsStringOrArray() ? (enum_flag_StringArrayValues & flag) : (m_dwFlags & flag));
3481     }
3482     __forceinline BOOL TestFlagWithMask(WFLAGS_LOW_ENUM mask, WFLAGS_LOW_ENUM flag) const
3483     {
3484         LIMITED_METHOD_DAC_CONTRACT;
3485         return (IsStringOrArray() ? (((DWORD)enum_flag_StringArrayValues & (DWORD)mask) == (DWORD)flag) :
3486             ((m_dwFlags & (DWORD)mask) == (DWORD)flag));
3487     }
3488
3489     __forceinline void ClearFlag(WFLAGS_HIGH_ENUM flag)
3490     {
3491         m_dwFlags &= ~flag;
3492     }
3493     __forceinline void SetFlag(WFLAGS_HIGH_ENUM flag)
3494     {
3495         m_dwFlags |= flag;
3496     }
3497     __forceinline DWORD GetFlag(WFLAGS_HIGH_ENUM flag) const
3498     {
3499         LIMITED_METHOD_DAC_CONTRACT;
3500         return m_dwFlags & flag;
3501     }
3502     __forceinline BOOL TestFlagWithMask(WFLAGS_HIGH_ENUM mask, WFLAGS_HIGH_ENUM flag) const
3503     {
3504         LIMITED_METHOD_DAC_CONTRACT;
3505         return ((m_dwFlags & (DWORD)mask) == (DWORD)flag);
3506     }
3507
3508     __forceinline void ClearFlag(WFLAGS2_ENUM flag)
3509     {
3510         m_wFlags2 &= ~flag;
3511     }
3512     __forceinline void SetFlag(WFLAGS2_ENUM flag)
3513     {
3514         m_wFlags2 |= flag;
3515     }
3516     __forceinline DWORD GetFlag(WFLAGS2_ENUM flag) const
3517     {
3518         LIMITED_METHOD_DAC_CONTRACT;
3519         return m_wFlags2 & flag;
3520     }
3521     __forceinline BOOL TestFlagWithMask(WFLAGS2_ENUM mask, WFLAGS2_ENUM flag) const
3522     {
3523         return (m_wFlags2 & (DWORD)mask) == (DWORD)flag;
3524     }
3525
3526 private:
3527     // Low WORD is component size for array and string types (HasComponentSize() returns true).
3528     // Used for flags otherwise.
3529     DWORD           m_dwFlags;
3530
3531     // Base size of instance of this class when allocated on the heap
3532     DWORD           m_BaseSize;
3533
3534     // See WFLAGS2_ENUM for values.
3535     WORD            m_wFlags2;
3536
3537     // Class token if it fits into 16-bits. If this is (WORD)-1, the class token is stored in the TokenOverflow optional member.
3538     WORD            m_wToken;
3539
3540     // <NICE> In the normal cases we shouldn't need a full word for each of these </NICE>
3541     WORD            m_wNumVirtuals;
3542     WORD            m_wNumInterfaces;
3543
3544 #ifdef _DEBUG
3545     LPCUTF8         debug_m_szClassName;
3546 #endif //_DEBUG
3547
3548     PTR_MethodTable m_pParentMethodTable;
3549
3550     PTR_Module      m_pLoaderModule;
3551
3552     PTR_MethodTableWriteableData m_pWriteableData;
3553
3554     // The value of lowest two bits describe what the union contains
3555     enum LowBits {
3556         UNION_EECLASS      = 0,    //  0 - pointer to EEClass. This MethodTable is the canonical method table.
3557         UNION_METHODTABLE  = 1,    //  1 - pointer to canonical MethodTable.
3558     };
3559     static const TADDR UNION_MASK = 1;
3560
3561     union {
3562         DPTR(EEClass) m_pEEClass;
3563         TADDR m_pCanonMT;
3564     };
3565
3566     __forceinline static LowBits union_getLowBits(TADDR pCanonMT)
3567     {
3568         LIMITED_METHOD_DAC_CONTRACT;
3569         return LowBits(pCanonMT & UNION_MASK);
3570     }
3571     __forceinline static TADDR   union_getPointer(TADDR pCanonMT)
3572     {
3573         LIMITED_METHOD_DAC_CONTRACT;
3574         return (pCanonMT & ~UNION_MASK);
3575     }
3576
3577     // m_pPerInstInfo and m_pInterfaceMap have to be at fixed offsets because of performance sensitive
3578     // JITed code and JIT helpers. However, they are frequently not present. The space is used by other
3579     // multipurpose slots on first come first served basis if the fixed ones are not present. The other
3580     // multipurpose are DispatchMapSlot, NonVirtualSlots, ModuleOverride (see enum_flag_MultipurposeSlotsMask).
3581     // The multipurpose slots that do not fit are stored after vtable slots.
3582
3583     union
3584     {
3585         PerInstInfo_t m_pPerInstInfo;
3586         TADDR         m_ElementTypeHnd;
3587         TADDR         m_pMultipurposeSlot1;
3588     };
3589     public:
3590     union
3591     {
3592         PTR_InterfaceInfo   m_pInterfaceMap;
3593         TADDR               m_pMultipurposeSlot2;
3594     };
3595
3596     // VTable and Non-Virtual slots go here
3597
3598     // Overflow multipurpose slots go here
3599
3600     // Optional Members go here
3601     //    See above for the list of optional members
3602
3603     // Generic dictionary pointers go here
3604
3605     // Interface map goes here
3606
3607     // Generic instantiation+dictionary goes here
3608
3609 private:
3610
3611     // disallow direct creation
3612     void *operator new(size_t dummy);
3613     void operator delete(void *pData);
3614     MethodTable();
3615
3616     // Optional members.  These are used for fields in the data structure where
3617     // the fields are (a) known when MT is created and (b) there is a default
3618     // value for the field in the common case.  That is, they are normally used
3619     // for data that is only relevant to a small number of method tables.
3620
3621     // Optional members and multipurpose slots have similar purpose, but they differ in details:
3622     // - Multipurpose slots can only accommodate pointer sized structures right now. It is non-trivial
3623     //   to add new ones, the access is faster.
3624     // - Optional members can accommodate structures of any size. It is trivial to add new ones,
3625     //   the access is slower.
3626
3627     // The following macro will automatically create GetXXX accessors for the optional members.
3628 #define METHODTABLE_OPTIONAL_MEMBERS() \
3629     /*                          NAME                    TYPE                            GETTER                     */ \
3630     /* Accessing this member efficiently is currently performance critical for static field accesses               */ \
3631     /* in generic classes, so place it early in the list. */                                                          \
3632     METHODTABLE_OPTIONAL_MEMBER(GenericsStaticsInfo,    GenericsStaticsInfo,            GetGenericsStaticsInfo      ) \
3633     /* Accessed during x-domain transition only, so place it late in the list. */                                     \
3634     METHODTABLE_REMOTING_OPTIONAL_MEMBERS()                                                                           \
3635     /* Accessed during certain generic type load operations only, so low priority */                                  \
3636     METHODTABLE_OPTIONAL_MEMBER(ExtraInterfaceInfo,     TADDR,                          GetExtraInterfaceInfoPtr    ) \
3637     /* TypeDef token for assemblies with more than 64k types. Never happens in real world. */                         \
3638     METHODTABLE_OPTIONAL_MEMBER(TokenOverflow,          TADDR,                          GetTokenOverflowPtr         ) \
3639
3640 #define METHODTABLE_REMOTING_OPTIONAL_MEMBERS()
3641
3642     enum OptionalMemberId
3643     {
3644 #undef METHODTABLE_OPTIONAL_MEMBER
3645 #define METHODTABLE_OPTIONAL_MEMBER(NAME, TYPE, GETTER) OptionalMember_##NAME,
3646         METHODTABLE_OPTIONAL_MEMBERS()
3647         OptionalMember_Count,
3648
3649         OptionalMember_First = OptionalMember_GenericsStaticsInfo,
3650     };
3651
3652     FORCEINLINE DWORD GetOffsetOfOptionalMember(OptionalMemberId id);
3653
3654 public:
3655
3656     //
3657     // Public accessor helpers for the optional members of MethodTable
3658     //
3659
3660 #undef METHODTABLE_OPTIONAL_MEMBER
3661 #define METHODTABLE_OPTIONAL_MEMBER(NAME, TYPE, GETTER) \
3662     inline DPTR(TYPE) GETTER() \
3663     { \
3664         LIMITED_METHOD_CONTRACT; \
3665         _ASSERTE(Has##NAME()); \
3666         return dac_cast<DPTR(TYPE)>(dac_cast<TADDR>(this) + GetOffsetOfOptionalMember(OptionalMember_##NAME)); \
3667     }
3668
3669     METHODTABLE_OPTIONAL_MEMBERS()
3670
3671 private:
3672     inline DWORD GetStartOffsetOfOptionalMembers()
3673     {
3674         WRAPPER_NO_CONTRACT;
3675         return GetOffsetOfOptionalMember(OptionalMember_First);
3676     }
3677
3678     inline DWORD GetEndOffsetOfOptionalMembers()
3679     {
3680         WRAPPER_NO_CONTRACT;
3681         return GetOffsetOfOptionalMember(OptionalMember_Count);
3682     }
3683
3684     inline static DWORD GetOptionalMembersAllocationSize(
3685                                                   DWORD dwMultipurposeSlotsMask,
3686                                                   BOOL needsGenericsStaticsInfo,
3687                                                   BOOL needsTokenOverflow);
3688     inline DWORD GetOptionalMembersSize();
3689
3690     // The PerInstInfo is a (possibly empty) array of pointers to
3691     // Instantiations/Dictionaries. This array comes after the optional members.
3692     inline DWORD GetPerInstInfoSize();
3693
3694     // This is the size of the interface map chunk in the method table.
3695     // If the MethodTable has a dynamic interface map then the size includes the pointer
3696     // that stores the extra info for that map.
3697     // The interface map itself comes after the PerInstInfo (if any)
3698     inline DWORD GetInterfaceMapSize();
3699
3700     // The instantiation/dictionary comes at the end of the MethodTable after
3701     // the interface map. This is the total number of bytes used by the dictionary.
3702     // The pSlotSize argument is used to return the size occupied by slots (not including
3703     // the optional back pointer used when expanding dictionaries).
3704     inline DWORD GetInstAndDictSize(DWORD *pSlotSize);
3705
3706 private:
3707     // Helper template to compute the offsets at compile time
3708     template<int mask>
3709     struct MultipurposeSlotOffset;
3710
3711     static const BYTE c_DispatchMapSlotOffsets[];
3712     static const BYTE c_NonVirtualSlotsOffsets[];
3713     static const BYTE c_ModuleOverrideOffsets[];
3714
3715     static const BYTE c_OptionalMembersStartOffsets[]; // total sizes of optional slots
3716
3717     TADDR GetMultipurposeSlotPtr(WFLAGS2_ENUM flag, const BYTE * offsets);
3718
3719     void SetMultipurposeSlotsMask(DWORD dwMask)
3720     {
3721         LIMITED_METHOD_CONTRACT;
3722         _ASSERTE((m_wFlags2 & enum_flag_MultipurposeSlotsMask) == 0);
3723         m_wFlags2 |= (WORD)dwMask;
3724     }
3725
3726     BOOL HasModuleOverride()
3727     {
3728         LIMITED_METHOD_DAC_CONTRACT;
3729         return GetFlag(enum_flag_HasModuleOverride);
3730     }
3731
3732     DPTR(PTR_Module) GetModuleOverridePtr()
3733     {
3734         LIMITED_METHOD_DAC_CONTRACT;
3735         return dac_cast<DPTR(PTR_Module)>(GetMultipurposeSlotPtr(enum_flag_HasModuleOverride, c_ModuleOverrideOffsets));
3736     }
3737
3738     void SetModule(Module * pModule);
3739
3740 public:
3741
3742     BOOL Validate ();
3743 };  // class MethodTable
3744
3745 #ifndef CROSSBITNESS_COMPILE
3746 static_assert_no_msg(sizeof(MethodTable) == SIZEOF__MethodTable_);
3747 #endif
3748 #if defined(FEATURE_TYPEEQUIVALENCE) && !defined(DACCESS_COMPILE)
3749 WORD GetEquivalentMethodSlot(MethodTable * pOldMT, MethodTable * pNewMT, WORD wMTslot, BOOL *pfFound);
3750 #endif // defined(FEATURE_TYPEEQUIVALENCE) && !defined(DACCESS_COMPILE)
3751
3752 MethodTable* CreateMinimalMethodTable(Module* pContainingModule,
3753                                       LoaderHeap* pCreationHeap,
3754                                       AllocMemTracker* pamTracker);
3755
3756 #endif // !_METHODTABLE_H_