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