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