Merge pull request #18379 from acmyu/disasm
[platform/upstream/coreclr.git] / src / vm / class.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 // ==--==
6 //
7 // File: CLASS.H
8 //
9
10 //
11 // NOTE: Even though EEClass is considered to contain cold data (relative to MethodTable), these data
12 // structures *are* touched (especially during startup as part of soft-binding). As a result, and given the
13 // number of EEClasses allocated for large assemblies, the size of this structure can have a direct impact on
14 // performance, especially startup performance.
15 //
16 // Given that the data itself is touched infrequently, we can trade off space reduction against cpu-usage to
17 // good effect here. A fair amount of work has gone into reducing the size of each EEClass instance (see
18 // EEClassOptionalFields and EEClassPackedFields) at the expense of somewhat more convoluted runtime access.
19 //
20 // Please consider this (and measure the impact of your changes against startup scenarios) before adding
21 // fields to EEClass or otherwise increasing its size.
22 //
23 // ============================================================================
24
25 #ifndef CLASS_H
26 #define CLASS_H
27
28 /*
29  *  Include Files
30  */
31 #include "eecontract.h"
32 #include "argslot.h"
33 #include "vars.hpp"
34 #include "cor.h"
35 #include "clrex.h"
36 #include "hash.h"
37 #include "crst.h"
38 #include "cgensys.h"
39 #include "declsec.h"
40 #ifdef FEATURE_COMINTEROP
41 #include "stdinterfaces.h"
42 #endif
43 #include "slist.h"
44 #include "spinlock.h"
45 #include "typehandle.h"
46 #include "perfcounters.h"
47 #include "methodtable.h"
48 #include "eeconfig.h"
49 #include "typectxt.h"
50 #include "iterator_util.h"
51
52 #ifdef FEATURE_COMINTEROP
53 #include "..\md\winmd\inc\adapter.h"
54 #endif
55 #include "packedfields.inl"
56 #include "array.h"
57 #define IBCLOG(x) g_IBCLogger.##x
58
59 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
60
61 /*
62  *  Macro definitions
63  */
64 #define MAX_LOG2_PRIMITIVE_FIELD_SIZE   3
65
66 #define MAX_PRIMITIVE_FIELD_SIZE        (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
67
68 /*
69  *  Forward declarations
70  */
71 class   AppDomain;
72 class   ArrayClass;
73 class   ArrayMethodDesc;
74 class   Assembly;
75 class   ClassLoader;
76 class   DictionaryLayout;
77 class   DomainLocalBlock;
78 class   FCallMethodDesc;
79 class   EEClass;
80 class   EnCFieldDesc;
81 class   FieldDesc;
82 class   FieldMarshaler;
83 struct  LayoutRawFieldInfo;
84 class   MetaSig;
85 class   MethodDesc;
86 class   MethodDescChunk;
87 class   MethodTable;
88 class   Module;
89 struct  ModuleCtorInfo;
90 class   Object;
91 class   Stub;
92 class   Substitution;
93 class   SystemDomain;
94 class   TypeHandle;
95 class   StackingAllocator;
96 class   AllocMemTracker;
97 class   InteropMethodTableSlotDataMap;
98 class LoadingEntry_LockHolder;
99 class   DispatchMapBuilder;
100 class LoaderAllocator;
101 class ComCallWrapperTemplate;
102
103 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
104 typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
105
106
107 //---------------------------------------------------------------------------------
108 // Fields in an explicit-layout class present varying degrees of risk depending
109 // on how they overlap.
110 //
111 // Each level is a superset of the lower (in numerical value) level - i.e.
112 // all kVerifiable fields are also kLegal, but not vice-versa.
113 //---------------------------------------------------------------------------------
114 class ExplicitFieldTrust
115 {
116     public:
117         enum TrustLevel
118         {
119             // Note: order is important here - each guarantee also implicitly guarantees all promises
120             // made by values lower in number.
121
122             //                       What's guaranteed.                                                  What the loader does.
123             //-----                  -----------------------                                             -------------------------------
124             kNone         = 0,    // no guarantees at all                                              - Type refuses to load at all.
125             kLegal        = 1,    // guarantees no objref <-> scalar overlap and no unaligned objref   - Type loads but field access won't verify
126             kVerifiable   = 2,    // guarantees no objref <-> objref overlap and all guarantees above  - Type loads and field access will verify
127             kNonOverLayed = 3,    // guarantees no overlap at all and all guarantees above             - Type loads, field access verifies and Equals() may be optimized if structure is tightly packed
128
129             kMaxTrust     = kNonOverLayed,
130         };
131
132 };
133
134 //----------------------------------------------------------------------------------------------
135 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
136 // into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
137 // class. This abstraction enforces the rule that the overall class is only as trustworthy as
138 // the least trustworthy field.
139 //----------------------------------------------------------------------------------------------
140 class ExplicitClassTrust : private ExplicitFieldTrust
141 {
142     public:
143         ExplicitClassTrust()
144         {
145             LIMITED_METHOD_CONTRACT;
146             m_trust = kMaxTrust;   // Yes, we start out with maximal trust. This reflects that explicit layout structures with no fields do represent no risk.
147         }
148
149         VOID AddField(TrustLevel fieldTrust)
150         {
151             LIMITED_METHOD_CONTRACT;
152             m_trust = min(m_trust, fieldTrust);
153         }
154
155         BOOL IsLegal()
156         {
157             LIMITED_METHOD_CONTRACT;
158             return m_trust >= kLegal;
159         }
160
161         BOOL IsVerifiable()
162         {
163             LIMITED_METHOD_CONTRACT;
164             return m_trust >= kVerifiable;
165         }
166
167         BOOL IsNonOverLayed()
168         {
169             LIMITED_METHOD_CONTRACT;
170             return m_trust >= kNonOverLayed;
171         }
172
173         TrustLevel GetTrustLevel()
174         {
175             LIMITED_METHOD_CONTRACT;
176             return m_trust;
177         }
178
179     private:
180         TrustLevel      m_trust;
181 };
182
183 //----------------------------------------------------------------------------------------------
184 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
185 // into this function, this class will collect trust information about individual fields to be later
186 // aggregated into the overall class level.
187 //
188 // This abstraction enforces the rule that all fields are presumed guilty until explicitly declared
189 // safe by calling SetTrust(). If you fail to call SetTrust before leaving the block, the destructor
190 // will automatically cause the entire class to be declared illegal (and you will get an assert
191 // telling you to fix this bug.)
192 //----------------------------------------------------------------------------------------------
193 class ExplicitFieldTrustHolder : private ExplicitFieldTrust
194 {
195     public:
196         ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
197         {
198             LIMITED_METHOD_CONTRACT;
199             m_pExplicitClassTrust = pExplicitClassTrust;
200 #ifdef _DEBUG
201             m_trustDeclared       = FALSE;
202 #endif
203             m_fieldTrust          = kNone;
204         }
205
206         VOID SetTrust(TrustLevel fieldTrust)
207         {
208             LIMITED_METHOD_CONTRACT;
209
210             _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
211             _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
212
213 #ifdef _DEBUG
214             m_trustDeclared = TRUE;
215 #endif
216             m_fieldTrust = fieldTrust;
217         }
218
219         ~ExplicitFieldTrustHolder()
220         {
221             LIMITED_METHOD_CONTRACT;
222             // If no SetTrust() was ever called, we will default to kNone (i.e. declare the entire type
223             // illegal.) It'd be nice to assert here but since this case can be legitimately reached
224             // on exception unwind, we cannot.
225             m_pExplicitClassTrust->AddField(m_fieldTrust);
226         }
227
228
229     private:
230         ExplicitClassTrust* m_pExplicitClassTrust;
231         TrustLevel          m_fieldTrust;
232 #ifdef _DEBUG
233         BOOL                m_trustDeclared;                // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
234 #endif
235 };
236
237 //*******************************************************************************
238 // Enumerator to traverse the interface declarations of a type, automatically building
239 // a substitution chain on the stack.
240 class InterfaceImplEnum
241 {
242     Module* m_pModule;
243     HENUMInternalHolder   hEnumInterfaceImpl;
244     const Substitution *m_pSubstChain;
245     Substitution m_CurrSubst;
246     mdTypeDef m_CurrTok;
247 public:
248     InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
249         : hEnumInterfaceImpl(pModule->GetMDImport())
250     {
251         WRAPPER_NO_CONTRACT;
252         m_pModule = pModule;
253         hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
254         m_pSubstChain = pSubstChain;
255     }
256     
257     // Returns:
258     // S_OK ... if has next (TRUE)
259     // S_FALSE ... if does not have next (FALSE)
260     // error code.
261     HRESULT Next()
262     {
263         WRAPPER_NO_CONTRACT;
264         HRESULT hr;
265         mdInterfaceImpl ii;
266         if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
267         {
268             return S_FALSE;
269         }
270         
271         IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
272         m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
273         return S_OK;
274     }
275     const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
276     mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
277 };
278
279 #ifdef FEATURE_COMINTEROP
280 //
281 // Class used to map MethodTable slot numbers to COM vtable slots numbers
282 // (either for calling a classic COM component or for constructing a classic COM
283 // vtable via which COM components can call managed classes). This structure is
284 // embedded in the EEClass but the mapping list itself is only allocated if the
285 // COM vtable is sparse.
286 //
287
288 class SparseVTableMap
289 {
290 public:
291 #ifdef DACCESS_COMPILE
292     friend class NativeImageDumper;
293 #endif
294
295     SparseVTableMap();
296     ~SparseVTableMap();
297
298     // First run through MT slots calling RecordGap wherever a gap in VT slots
299     // occurs.
300     void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
301
302     // Then call FinalizeMapping to create the actual mapping list.
303     void FinalizeMapping(WORD TotalMTSlots);
304
305     // Map MT to VT slot.
306     WORD LookupVTSlot(WORD MTSlot);
307
308     // Retrieve the number of slots in the vtable (both empty and full).
309     WORD GetNumVTableSlots();
310
311     const void* GetMapList()
312     {
313         LIMITED_METHOD_CONTRACT;
314         return (void*)m_MapList;
315     }
316
317 #ifdef FEATURE_PREJIT
318     // Methods to persist structure
319     void Save(DataImage *image);
320     void Fixup(DataImage *image);
321 #endif // FEATURE_PREJIT
322
323 private:
324
325     enum { MapGrow = 4 };
326
327     struct Entry
328     {
329         WORD    m_Start;        // Starting MT slot number
330         WORD    m_Span;         // # of consecutive slots that map linearly
331         WORD    m_MapTo;        // Starting VT slot number
332     };
333
334     Entry      *m_MapList;      // Pointer to array of Entry structures
335     WORD        m_MapEntries;   // Number of entries in above
336     WORD        m_Allocated;    // Number of entries allocated
337
338     WORD        m_LastUsed;     // Index of last entry used in successful lookup
339
340     WORD        m_VTSlot;       // Current VT slot number, used during list build
341     WORD        m_MTSlot;       // Current MT slot number, used during list build
342
343     void AllocOrExpand();       // Allocate or expand the mapping list for a new entry
344 };
345 #endif // FEATURE_COMINTEROP
346
347 //=======================================================================
348 // Adjunct to the EEClass structure for classes w/ layout
349 //=======================================================================
350 class EEClassLayoutInfo
351 {
352     static VOID CollectLayoutFieldMetadataThrowing(
353        mdTypeDef cl,                // cl of the NStruct being loaded
354        BYTE packingSize,            // packing size (from @dll.struct)
355        BYTE nlType,                 // nltype (from @dll.struct)
356 #ifdef FEATURE_COMINTEROP
357        BOOL isWinRT,                // Is the type a WinRT type
358 #endif // FEATURE_COMINTEROP
359        BOOL fExplicitOffsets,       // explicit offsets?
360        MethodTable *pParentMT,       // the loaded superclass
361        ULONG cMembers,              // total number of members (methods + fields)
362        HENUMInternal *phEnumField,  // enumerator for field
363        Module* pModule,             // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
364        const SigTypeContext *pTypeContext,          // Type parameters for NStruct being loaded
365        EEClassLayoutInfo *pEEClassLayoutInfoOut,  // caller-allocated structure to fill in.
366        LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in.  Needs room for cMember+1 elements
367        LoaderAllocator * pAllocator,
368        AllocMemTracker    *pamTracker
369     );
370
371
372     friend class ClassLoader;
373     friend class EEClass;
374     friend class MethodTableBuilder;
375 #ifdef DACCESS_COMPILE
376     friend class NativeImageDumper;
377 #endif
378
379     private:
380         // size (in bytes) of fixed portion of NStruct.
381         UINT32      m_cbNativeSize;
382         UINT32      m_cbManagedSize;
383
384     public:
385         // 1,2,4 or 8: this is equal to the largest of the alignment requirements
386         // of each of the EEClass's members. If the NStruct extends another NStruct,
387         // the base NStruct is treated as the first member for the purpose of
388         // this calculation.
389         BYTE        m_LargestAlignmentRequirementOfAllMembers;
390
391         // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
392         // for the managed layout.
393         BYTE        m_ManagedLargestAlignmentRequirementOfAllMembers;
394
395     private:
396         enum {
397             // TRUE if the GC layout of the class is bit-for-bit identical
398             // to its unmanaged counterpart (i.e. no internal reference fields,
399             // no ansi-unicode char conversions required, etc.) Used to
400             // optimize marshaling.
401             e_BLITTABLE                 = 0x01,
402             // Post V1.0 addition: Is this type also sequential in managed memory?
403             e_MANAGED_SEQUENTIAL        = 0x02,
404             // When a sequential/explicit type has no fields, it is conceptually
405             // zero-sized, but actually is 1 byte in length. This holds onto this
406             // fact and allows us to revert the 1 byte of padding when another
407             // explicit type inherits from this type.
408             e_ZERO_SIZED                =   0x04,
409             // The size of the struct is explicitly specified in the meta-data.
410             e_HAS_EXPLICIT_SIZE         = 0x08,
411 #ifdef UNIX_AMD64_ABI
412 #ifdef FEATURE_HFA
413 #error Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time.
414 #endif // FEATURE_HFA
415             e_NATIVE_PASS_IN_REGISTERS  = 0x10, // Flag wheter a native struct is passed in registers.
416 #endif // UNIX_AMD64_ABI
417 #ifdef FEATURE_HFA
418             // HFA type of the unmanaged layout
419             e_R4_HFA                    = 0x10,
420             e_R8_HFA                    = 0x20,
421 #endif
422         };
423
424         BYTE        m_bFlags;
425
426         // Packing size in bytes (1, 2, 4, 8 etc.)
427         BYTE        m_cbPackingSize;
428
429         // # of fields that are of the calltime-marshal variety.
430         UINT        m_numCTMFields;
431
432         // An array of FieldMarshaler data blocks, used to drive call-time
433         // marshaling of NStruct reference parameters. The number of elements
434         // equals m_numCTMFields.
435         RelativePointer<PTR_FieldMarshaler> m_pFieldMarshalers;
436
437
438     public:
439         BOOL GetNativeSize() const
440         {
441             LIMITED_METHOD_CONTRACT;
442             return m_cbNativeSize;
443         }
444
445         UINT32 GetManagedSize() const
446         {
447             LIMITED_METHOD_CONTRACT;
448             return m_cbManagedSize;
449         }
450
451
452         BYTE GetLargestAlignmentRequirementOfAllMembers() const
453         {
454             LIMITED_METHOD_CONTRACT;
455             return m_LargestAlignmentRequirementOfAllMembers;
456         }
457
458         UINT GetNumCTMFields() const
459         {
460             LIMITED_METHOD_CONTRACT;
461             return m_numCTMFields;
462         }
463
464         PTR_FieldMarshaler GetFieldMarshalers() const
465         {
466             LIMITED_METHOD_CONTRACT;
467             return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
468         }
469
470 #ifndef DACCESS_COMPILE
471         void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
472         {
473             LIMITED_METHOD_CONTRACT;
474             m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
475         }
476 #endif // DACCESS_COMPILE
477
478         BOOL IsBlittable() const
479         {
480             LIMITED_METHOD_CONTRACT;
481             return (m_bFlags & e_BLITTABLE) == e_BLITTABLE;
482         }
483
484         BOOL IsManagedSequential() const
485         {
486             LIMITED_METHOD_CONTRACT;
487             return (m_bFlags & e_MANAGED_SEQUENTIAL) == e_MANAGED_SEQUENTIAL;
488         }
489
490         // If true, this says that the type was originally zero-sized
491         // and the native size was bumped up to one for similar behaviour
492         // to C++ structs. However, it is necessary to keep track of this
493         // so that we can ignore the one byte padding if other types derive
494         // from this type, that we can
495         BOOL IsZeroSized() const
496         {
497             LIMITED_METHOD_CONTRACT;
498             return (m_bFlags & e_ZERO_SIZED) == e_ZERO_SIZED;
499         }
500
501         BOOL HasExplicitSize() const
502         {
503             LIMITED_METHOD_CONTRACT;
504             return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE;
505         }        
506
507         DWORD GetPackingSize() const
508         {
509             LIMITED_METHOD_CONTRACT;
510             return m_cbPackingSize;
511         }
512
513 #ifdef UNIX_AMD64_ABI
514         bool IsNativeStructPassedInRegisters()
515         {
516             LIMITED_METHOD_CONTRACT;
517             return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
518         }
519 #endif // UNIX_AMD64_ABI
520
521         CorElementType GetNativeHFATypeRaw();
522 #ifdef FEATURE_HFA
523         bool IsNativeHFA()
524         {
525             LIMITED_METHOD_CONTRACT;
526             return (m_bFlags & (e_R4_HFA | e_R8_HFA)) != 0;
527         }
528
529         CorElementType GetNativeHFAType()
530         {
531             LIMITED_METHOD_CONTRACT;
532             if (IsNativeHFA())                      
533                 return (m_bFlags & e_R4_HFA) ? ELEMENT_TYPE_R4 : ELEMENT_TYPE_R8;
534             return ELEMENT_TYPE_END;
535         }
536 #else // !FEATURE_HFA
537         bool IsNativeHFA()
538         {
539             return GetNativeHFATypeRaw() != ELEMENT_TYPE_END;
540         }
541         CorElementType GetNativeHFAType()
542         {
543             return GetNativeHFATypeRaw();
544         }
545 #endif // !FEATURE_HFA
546
547     private:
548         void SetIsBlittable(BOOL isBlittable)
549         {
550             LIMITED_METHOD_CONTRACT;
551             m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
552                                    : (m_bFlags & ~e_BLITTABLE);
553         }
554
555         void SetIsManagedSequential(BOOL isManagedSequential)
556         {
557             LIMITED_METHOD_CONTRACT;
558             m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
559                                            : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
560         }
561
562         void SetIsZeroSized(BOOL isZeroSized)
563         {
564             LIMITED_METHOD_CONTRACT;
565             m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
566                                    : (m_bFlags & ~e_ZERO_SIZED);
567         }
568
569         void SetHasExplicitSize(BOOL hasExplicitSize)
570         {
571             LIMITED_METHOD_CONTRACT;
572             m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
573                                        : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
574         }
575
576 #ifdef FEATURE_HFA
577         void SetNativeHFAType(CorElementType hfaType)
578         {
579             LIMITED_METHOD_CONTRACT;
580             m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA;
581         }
582 #endif
583 #ifdef UNIX_AMD64_ABI
584         void SetNativeStructPassedInRegisters()
585         {
586             LIMITED_METHOD_CONTRACT;
587             m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
588         }
589 #endif // UNIX_AMD64_ABI
590
591 };
592
593
594
595 //
596 // This structure is used only when the classloader is building the interface map.  Before the class
597 // is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
598 // for this class/interface by the metadata - inherited interfaces will not be present if they are
599 // not specifically declared.
600 //
601 // This structure is destroyed after resolving has completed.
602 //
603 typedef struct
604 {
605     // The interface method table; for instantiated interfaces, this is the generic interface
606     MethodTable     *m_pMethodTable;
607 } BuildingInterfaceInfo_t;
608
609
610 //
611 // We should not need to touch anything in here once the classes are all loaded, unless we
612 // are doing reflection.  Try to avoid paging this data structure in.
613 //
614
615 // Size of hash bitmap for method names
616 #define METHOD_HASH_BYTES  8
617
618 // Hash table size - prime number
619 #define METHOD_HASH_BITS    61
620
621
622 // These are some macros for forming fully qualified class names for a class.
623 // These are abstracted so that we can decide later if a max length for a
624 // class name is acceptable.
625
626 // It doesn't make any sense not to have a small but usually quite capable
627 // stack buffer to build class names into. Most class names that I can think
628 // of would fit in 128 characters, and that's a pretty small amount of stack
629 // to use in exchange for not having to new and delete the memory.
630 #define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4)
631
632 #define DefineFullyQualifiedNameForClass() \
633     ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
634     InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
635
636 #define DefineFullyQualifiedNameForClassOnStack() \
637     ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
638     InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
639
640 #define DefineFullyQualifiedNameForClassW() \
641     InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
642
643 #define DefineFullyQualifiedNameForClassWOnStack() \
644     InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
645
646 #define GetFullyQualifiedNameForClassNestedAware(pClass) \
647     pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
648
649 #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
650     pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
651
652 #define GetFullyQualifiedNameForClass(pClass) \
653     pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
654
655 #define GetFullyQualifiedNameForClassW(pClass) \
656     pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
657
658 #define GetFullyQualifiedNameForClassW_WinRT(pClass) \
659     pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
660
661 #define GetFullyQualifiedNameForClass_WinRT(pClass) \
662     pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
663
664 // Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to
665 // save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached
666 // via the m_rpOptionalFields field EEClass (use the GetOptionalFields() accessor rather than the field
667 // itself).
668 class EEClassOptionalFields
669 {
670     // All fields here are intentionally private. Use the corresponding accessor on EEClass instead (this
671     // makes it easier to add and remove fields from the optional section in the future). We make exceptions
672     // for MethodTableBuilder and NativeImageDumper, which need raw field-level access.
673     friend class EEClass;
674     friend class MethodTableBuilder;
675 #ifdef DACCESS_COMPILE
676     friend class NativeImageDumper;
677 #endif
678
679     //
680     // GENERICS RELATED FIELDS. 
681     //
682
683     // If IsSharedByGenericInstantiations(), layout of handle dictionary for generic type 
684     // (the last dictionary pointed to from PerInstInfo). Otherwise NULL.
685     PTR_DictionaryLayout m_pDictLayout;
686
687     // Variance info for each type parameter (gpNonVariant, gpCovariant, or gpContravariant)
688     // If NULL, this type has no type parameters that are co/contravariant
689     RelativePointer<PTR_BYTE> m_pVarianceInfo;
690
691     //
692     // COM RELATED FIELDS.
693     //
694
695 #ifdef FEATURE_COMINTEROP
696     SparseVTableMap *m_pSparseVTableMap;
697
698     TypeHandle m_pCoClassForIntf;  // @TODO: Coclass for an interface
699
700 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
701     // Points to activation information if the type is an activatable COM/WinRT class.
702     ClassFactoryBase *m_pClassFactory;
703 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
704
705     WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
706
707 #endif // FEATURE_COMINTEROP
708
709     //
710     // MISC FIELDS
711     //
712
713     #define    MODULE_NON_DYNAMIC_STATICS      ((DWORD)-1)
714     DWORD m_cbModuleDynamicID;
715
716 #if defined(UNIX_AMD64_ABI)
717     // Number of eightBytes in the following arrays
718     int m_numberEightBytes; 
719     // Classification of the eightBytes
720     SystemVClassificationType m_eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
721     // Size of data the eightBytes
722     unsigned int m_eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
723 #endif // UNIX_AMD64_ABI
724
725     // Set default values for optional fields.
726     inline void Init();
727
728     PTR_BYTE GetVarianceInfo()
729     {
730         LIMITED_METHOD_DAC_CONTRACT;
731
732         return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
733     }
734 };
735 typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
736
737 //
738 // Another mechanism used to reduce the size of the average EEClass instance is the notion of packed fields.
739 // This is based on the observation that EEClass has a large number of integer fields that typically contain
740 // small values and that are fixed once class layout has completed. We can compact these fields by discarding
741 // the leading zero bits (and for small values there'll be a lot of these) and packing the significant data
742 // into compact bitfields. This is a dynamic operation (the exact packing used depends on the exact data
743 // stored in the fields).
744 //
745 // The PackedDWORDFields<> class (defined in PackedFields.inl) encapsulates this. It takes one template
746 // parameter, the number of fields to pack, and provides operations to get and set those fields until we're
747 // happy with the values, at which point it will compact them for us.
748 //
749 // The packed fields themselves are stored at the end of the EEClass instance (or the LayoutEEClass or the
750 // DelegateEEClass etc.) so we can take advantage of the variable sized nature of the fields. We gain nothing for
751 // runtime allocated EEClasses (we have to allocate a maximally sized structure for the packed fields because
752 // we can't tell at the beginning of EEClass layout what the field values will be). But in the ngen scenario
753 // we can compact the fields just prior to saving and only store the portion of the EEClass that is relvant,
754 // helping us with our goal of packing all the EEClass instances together as tightly as possible.
755 //
756 // Since each packed field is now accessed via an array-like index, we give each of those indices a name with
757 // the enum below to make the code more readable.
758 //
759
760 enum EEClassFieldId
761 {
762     EEClass_Field_NumInstanceFields = 0,
763     EEClass_Field_NumMethods,
764     EEClass_Field_NumStaticFields,
765     EEClass_Field_NumHandleStatics,
766     EEClass_Field_NumBoxedStatics,
767     EEClass_Field_NonGCStaticFieldBytes,
768     EEClass_Field_NumThreadStaticFields,
769     EEClass_Field_NumHandleThreadStatics,
770     EEClass_Field_NumBoxedThreadStatics,
771     EEClass_Field_NonGCThreadStaticFieldBytes,
772     EEClass_Field_NumNonVirtualSlots,
773     EEClass_Field_COUNT
774 };
775
776 typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
777 typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
778
779 //@GENERICS:
780 // For most types there is a one-to-one mapping between MethodTable* and EEClass*
781 // However this is not the case for instantiated types where code and representation
782 // are shared between compatible instantiations (e.g. List<string> and List<object>)
783 // Then a single EEClass structure is shared between multiple MethodTable structures
784 // Uninstantiated generic types (e.g. List) have their own EEClass and MethodTable,
785 // used (a) as a representative for the generic type itself, (b) for static fields and
786 // methods, which aren't present in the instantiations, and (c) to hold some information
787 // (e.g. formal instantiations of superclass and implemented interfaces) that is common
788 // to all instantiations and isn't stored in the EEClass structures for instantiated types
789 //
790 //
791 // **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE
792 //
793 // A word about EEClass vs. MethodTable
794 // ------------------------------------
795 //
796 // At compile-time, we are happy to touch both MethodTable and EEClass.  However,
797 // at runtime we want to restrict ourselves to the MethodTable.  This is critical
798 // for common code paths, where we want to keep the EEClass out of our working
799 // set.  For uncommon code paths, like throwing exceptions or strange Contexts
800 // issues, it's okay to access the EEClass.
801 //
802 // To this end, the TypeHandle (CLASS_HANDLE) abstraction is now based on the
803 // MethodTable pointer instead of the EEClass pointer.  If you are writing a
804 // runtime helper that calls GetClass() to access the associated EEClass, please
805 // stop to wonder if you are making a mistake.
806 //
807 // **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE  **  NOTE
808
809
810 // An code:EEClass is a representation of the part of a managed type that is not used very frequently (it is
811 // cold), and thus is segregated from the hot portion (which lives in code:MethodTable).  As noted above an
812 // it is also the case that EEClass is SHARED among all instantiations of a generic type, so anything that
813 // is specific to a paritcular type can not live off the EEClass.
814 // 
815 // From here you can get to 
816 //     code:MethodTable - The representation of the hot portion of a type.
817 //     code:MethodDesc - The representation of a method 
818 //     code:FieldDesc - The representation of a field. 
819 // 
820 // EEClasses hold the following important fields
821 //     * code:EEClass.m_pMethodTable - Points a MethodTable associated with 
822 //     * code:EEClass.m_pChunks - a list of code:MethodDescChunk which is simply a list of code:MethodDesc
823 //         which represent the methods.  
824 //     * code:EEClass.m_pFieldDescList - a list of fields in the type.  
825 // 
826 class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
827 {
828     /************************************
829      *  FRIEND FUNCTIONS
830      ************************************/
831     // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
832     // USE ACCESSORS TO READ/WRITE private field members
833
834     // To access bmt stuff
835     friend class MethodTable;
836     friend class MethodTableBuilder;
837     friend class FieldDesc;
838     friend class CheckAsmOffsets;
839     friend class ClrDataAccess;
840 #ifdef DACCESS_COMPILE
841     friend class NativeImageDumper;
842 #endif
843
844     /************************************
845      *  PUBLIC INSTANCE METHODS
846      ************************************/
847 public:
848
849     DWORD  IsSealed()
850     {
851         LIMITED_METHOD_CONTRACT;
852         return IsTdSealed(m_dwAttrClass);
853     }
854
855     inline DWORD IsInterface()
856     {
857         WRAPPER_NO_CONTRACT;
858         return IsTdInterface(m_dwAttrClass);
859     }
860
861     inline DWORD IsAbstract()
862     {
863         WRAPPER_NO_CONTRACT;
864         return IsTdAbstract(m_dwAttrClass);
865     }
866
867     BOOL HasExplicitFieldOffsetLayout()
868     {
869         WRAPPER_NO_CONTRACT;
870         return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
871     }
872
873     BOOL HasSequentialLayout()
874     {
875         WRAPPER_NO_CONTRACT;
876         return IsTdSequentialLayout(GetAttrClass());
877     }
878     BOOL IsSerializable()
879     {
880         WRAPPER_NO_CONTRACT;
881         return IsTdSerializable(GetAttrClass());
882     }
883     BOOL IsBeforeFieldInit()
884     {
885         WRAPPER_NO_CONTRACT;
886         return IsTdBeforeFieldInit(GetAttrClass());
887     }
888
889     DWORD GetProtection()
890     {
891         WRAPPER_NO_CONTRACT;
892         return (m_dwAttrClass & tdVisibilityMask);
893     }
894
895     // class is blittable
896     BOOL IsBlittable();
897
898 #ifndef DACCESS_COMPILE
899     void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
900     void Destruct(MethodTable * pMT);
901
902     static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
903 #endif // !DACCESS_COMPILE
904
905 #ifdef EnC_SUPPORTED
906     // Add a new method to an already loaded type for EnC
907     static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
908
909     // Add a new field to an already loaded type for EnC
910     static HRESULT AddField(MethodTable * pMT, mdFieldDef fieldDesc, EnCFieldDesc **pAddedField);
911     static VOID    FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdFieldDef fieldDef);
912 #endif // EnC_SUPPORTED
913
914     inline DWORD IsComImport()
915     {
916         WRAPPER_NO_CONTRACT;
917         return IsTdImport(m_dwAttrClass);
918     }
919
920 #ifdef FEATURE_PREJIT
921     DWORD GetSize();
922
923     void Save(DataImage *image, MethodTable *pMT);
924     void Fixup(DataImage *image, MethodTable *pMT);
925 #endif // FEATURE_PREJIT
926
927     EEClassLayoutInfo *GetLayoutInfo();
928
929 #ifdef DACCESS_COMPILE
930     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
931 #endif
932
933     static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
934
935     /************************************
936      *  INSTANCE MEMBER VARIABLES
937      ************************************/
938 #ifdef _DEBUG
939 public:
940     inline LPCUTF8 GetDebugClassName ()
941     {
942         LIMITED_METHOD_CONTRACT;
943         return m_szDebugClassName;
944     }
945     inline void SetDebugClassName (LPCUTF8 szDebugClassName)
946     {
947         LIMITED_METHOD_CONTRACT;
948         m_szDebugClassName = szDebugClassName;
949     }
950
951     /*
952      * Controls debugging breaks and output if a method class
953      * is mentioned in the registry ("BreakOnClassBuild")
954      * Method layout within this class can cause a debug
955      * break by setting "BreakOnMethodName". Not accessible
956      * outside the class.
957      */
958
959 #endif // _DEBUG
960
961 #ifdef FEATURE_COMINTEROP
962     /*
963      * Used to map MethodTable slots to VTable slots
964      */
965     inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
966     {
967         LIMITED_METHOD_CONTRACT;
968         return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
969     }
970     inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
971     {
972         LIMITED_METHOD_CONTRACT;
973         _ASSERTE(HasOptionalFields());
974         GetOptionalFields()->m_pSparseVTableMap = map;
975     }
976 #endif // FEATURE_COMINTEROP
977
978 public:
979     /*
980      * Maintain back pointer to statcally hot portion of EEClass.
981      * For an EEClass representing multiple instantiations of a generic type, this is the method table
982      * for the first instantiation requested and is the only one containing entries for non-virtual instance methods
983      * (i.e. non-vtable entries).
984      */
985
986     // Note that EEClass structures may be shared between generic instantiations
987     // (see IsSharedByGenericInstantiations).  In these cases  EEClass::GetMethodTable
988     // will return the method table pointer corresponding to the "canonical"
989     // instantiation, as defined in typehandle.h.
990     //
991     inline PTR_MethodTable GetMethodTable()
992     {
993         LIMITED_METHOD_CONTRACT;
994         SUPPORTS_DAC;
995
996         return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
997     }
998
999     // DO NOT ADD ANY ASSERTS TO THIS METHOD.
1000     // DO NOT USE THIS METHOD.
1001     // Yes folks, for better or worse the debugger pokes supposed object addresses
1002     // to try to see if objects are valid, possibly firing an AccessViolation or worse,
1003     // and then catches the AV and reports a failure to the debug client.  This makes
1004     // the debugger slightly more robust should any corrupted object references appear
1005     // in a session. Thus it is "correct" behaviour for this to AV when used with
1006     // an invalid object pointer, and incorrect behaviour for it to
1007     // assert.
1008     inline PTR_MethodTable GetMethodTableWithPossibleAV()
1009     {
1010         CANNOT_HAVE_CONTRACT;
1011         SUPPORTS_DAC;
1012
1013         return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1014     }
1015
1016 #ifndef DACCESS_COMPILE
1017     inline void SetMethodTable(MethodTable*  pMT)
1018     {
1019         LIMITED_METHOD_CONTRACT;
1020         m_pMethodTable.SetValueMaybeNull(pMT);
1021     }
1022 #endif // !DACCESS_COMPILE
1023
1024     /*
1025      * Number of fields in the class, including inherited fields.
1026      * Does not include fields added from EnC.
1027      */
1028     inline WORD GetNumInstanceFields()
1029     {
1030         LIMITED_METHOD_CONTRACT;
1031         SUPPORTS_DAC;
1032         return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1033     }
1034
1035     inline void SetNumInstanceFields (WORD wNumInstanceFields)
1036     {
1037         LIMITED_METHOD_CONTRACT;
1038         SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1039     }
1040
1041     /*
1042      * Number of static fields declared in this class.
1043      * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1044      */
1045     inline WORD GetNumStaticFields()
1046     {
1047         LIMITED_METHOD_CONTRACT;
1048         SUPPORTS_DAC;
1049         return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1050     }
1051     inline void SetNumStaticFields (WORD wNumStaticFields)
1052     {
1053         LIMITED_METHOD_CONTRACT;
1054         SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1055     }
1056
1057     inline WORD GetNumThreadStaticFields()
1058     {
1059         LIMITED_METHOD_CONTRACT;
1060         SUPPORTS_DAC;
1061         return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1062     }
1063
1064     inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1065     {
1066         LIMITED_METHOD_CONTRACT;
1067         SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1068     }
1069
1070     // Statics are stored in a big chunk inside the module
1071
1072     inline  DWORD GetModuleDynamicID()
1073     {
1074         LIMITED_METHOD_CONTRACT;
1075         SUPPORTS_DAC;
1076         return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1077     }
1078
1079     inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1080     {
1081         LIMITED_METHOD_CONTRACT;
1082         _ASSERTE(HasOptionalFields());
1083         GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
1084     }
1085
1086     /*
1087      * Difference between the InterfaceMap ptr and Vtable in the
1088      * MethodTable used to indicate the number of static bytes
1089      * Now interfaceMap ptr can be optional hence we store it here
1090      */
1091     inline DWORD GetNonGCRegularStaticFieldBytes()
1092     {
1093         LIMITED_METHOD_CONTRACT;
1094         return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1095     }
1096     inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1097     {
1098         LIMITED_METHOD_CONTRACT;
1099         SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1100     }
1101
1102     inline DWORD GetNonGCThreadStaticFieldBytes()
1103     {
1104         LIMITED_METHOD_CONTRACT;
1105         return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1106     }
1107     inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1108     {
1109         LIMITED_METHOD_CONTRACT;
1110         SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1111     }
1112
1113     inline WORD GetNumNonVirtualSlots()
1114     {
1115         LIMITED_METHOD_CONTRACT;
1116         return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1117     }
1118     inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1119     {
1120         LIMITED_METHOD_CONTRACT;
1121         SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1122     }
1123
1124     inline BOOL IsEquivalentType()
1125     {
1126         LIMITED_METHOD_CONTRACT;
1127         return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1128     }
1129
1130 #ifdef FEATURE_COMINTEROP
1131     inline void SetIsEquivalentType()
1132     {
1133         LIMITED_METHOD_CONTRACT;
1134         m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1135     }
1136 #endif
1137
1138     /*
1139      * Number of static handles allocated
1140      */
1141     inline WORD GetNumHandleRegularStatics ()
1142     {
1143         LIMITED_METHOD_CONTRACT;
1144         return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1145     }
1146     inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1147     {
1148         LIMITED_METHOD_CONTRACT;
1149         SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1150     }
1151
1152     /*
1153      * Number of static handles allocated for ThreadStatics
1154      */
1155     inline WORD GetNumHandleThreadStatics ()
1156     {
1157         LIMITED_METHOD_CONTRACT;
1158         return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1159     }
1160     inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1161     {
1162         LIMITED_METHOD_CONTRACT;
1163         SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1164     }
1165
1166     /*
1167      * Number of boxed statics allocated
1168      */
1169     inline WORD GetNumBoxedRegularStatics ()
1170     {
1171         LIMITED_METHOD_CONTRACT;
1172         return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1173     }
1174     inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1175     {
1176         LIMITED_METHOD_CONTRACT;
1177         SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1178     }
1179
1180     /*
1181      * Number of boxed statics allocated for ThreadStatics
1182      */
1183     inline WORD GetNumBoxedThreadStatics ()
1184     {
1185         LIMITED_METHOD_CONTRACT;
1186         return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1187     }
1188     inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1189     {
1190         LIMITED_METHOD_CONTRACT;
1191         SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
1192     }
1193
1194     /*
1195      * Number of bytes to subract from code:MethodTable::GetBaseSize() to get the actual number of bytes 
1196      * of instance fields stored in the object on the GC heap.
1197      */
1198     inline DWORD GetBaseSizePadding()
1199     {
1200         LIMITED_METHOD_DAC_CONTRACT;
1201         return m_cbBaseSizePadding;
1202     }
1203     inline void SetBaseSizePadding(DWORD dwPadding)
1204     {
1205         LIMITED_METHOD_CONTRACT;
1206         _ASSERTE(FitsIn<BYTE>(dwPadding));
1207         m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1208     }
1209
1210     inline DWORD GetUnboxedNumInstanceFieldBytes()
1211     {
1212         DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1213
1214         _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1215         return cbBoxedSize;
1216     }
1217
1218
1219     /*
1220      * Pointer to a list of FieldDescs declared in this class
1221      * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1222      * in this array
1223      */
1224 #ifdef FEATURE_PREJIT
1225     static DWORD FieldDescListSize(MethodTable * pMT);
1226 #endif
1227
1228     inline PTR_FieldDesc GetFieldDescList()
1229     {
1230         LIMITED_METHOD_DAC_CONTRACT;
1231         // Careful about using this method. If it's possible that fields may have been added via EnC, then
1232         // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1233         return m_pFieldDescList.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList));
1234     }
1235
1236     PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1237
1238 #ifndef DACCESS_COMPILE
1239     inline void SetFieldDescList (FieldDesc* pFieldDescList)
1240     {
1241         LIMITED_METHOD_CONTRACT;
1242         m_pFieldDescList.SetValue(pFieldDescList);
1243     }
1244 #endif // !DACCESS_COMPILE
1245
1246     inline WORD GetNumMethods()
1247     {
1248         LIMITED_METHOD_DAC_CONTRACT;
1249         return (WORD)GetPackableField(EEClass_Field_NumMethods);
1250     }
1251     inline void SetNumMethods (WORD wNumMethods)
1252     {
1253         LIMITED_METHOD_CONTRACT;
1254         SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1255     }
1256
1257     /*
1258      * Cached metadata for this class (GetTypeDefProps)
1259      */
1260     inline DWORD GetAttrClass()
1261     {
1262         LIMITED_METHOD_CONTRACT;
1263         return m_dwAttrClass;
1264     }
1265     inline void SetAttrClass (DWORD dwAttrClass)
1266     {
1267         LIMITED_METHOD_CONTRACT;
1268         m_dwAttrClass = dwAttrClass;
1269     }
1270
1271
1272 #ifdef FEATURE_COMINTEROP
1273     inline DWORD IsComClassInterface()
1274     {
1275         LIMITED_METHOD_CONTRACT;
1276         return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1277     }
1278     inline VOID SetIsComClassInterface()
1279     {
1280         LIMITED_METHOD_CONTRACT;
1281         m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1282     }
1283     inline void SetComEventItfType()
1284     {
1285         LIMITED_METHOD_CONTRACT;
1286         _ASSERTE(IsInterface());
1287         m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1288     }
1289     // class is a special COM event interface
1290     inline BOOL IsComEventItfType()
1291     {
1292         LIMITED_METHOD_CONTRACT;
1293         return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1294     }
1295 #endif // FEATURE_COMINTEROP
1296
1297 #ifdef _DEBUG
1298     inline DWORD IsDestroyed()
1299     {
1300         LIMITED_METHOD_CONTRACT;
1301         return (m_wAuxFlags & AUXFLAG_DESTROYED);
1302     }
1303 #endif
1304
1305     inline DWORD IsUnsafeValueClass()
1306     {
1307         LIMITED_METHOD_CONTRACT;
1308         return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1309     }
1310
1311     
1312 private:
1313     inline void SetUnsafeValueClass()
1314     {
1315         LIMITED_METHOD_CONTRACT;
1316         m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1317     }
1318     
1319 public:
1320     inline BOOL HasNoGuid()
1321     {
1322         LIMITED_METHOD_CONTRACT;
1323         return (m_VMFlags & VMFLAG_NO_GUID);
1324     }
1325     inline void SetHasNoGuid()
1326     {
1327         WRAPPER_NO_CONTRACT;
1328         FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1329     }
1330
1331 public:
1332     inline BOOL IsAlign8Candidate()
1333     {
1334         LIMITED_METHOD_CONTRACT;
1335         return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1336     }
1337     inline void SetAlign8Candidate()
1338     {
1339         LIMITED_METHOD_CONTRACT;
1340         m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1341     }
1342 #ifdef _DEBUG
1343     inline void SetDestroyed()
1344     {
1345         LIMITED_METHOD_CONTRACT;
1346         m_wAuxFlags |= AUXFLAG_DESTROYED;
1347     }
1348 #endif
1349     inline void SetHasFixedAddressVTStatics()
1350     {
1351         LIMITED_METHOD_CONTRACT;
1352         m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1353     }
1354 #ifdef FEATURE_COMINTEROP
1355     void SetSparseForCOMInterop()
1356     {
1357         LIMITED_METHOD_CONTRACT;
1358         m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1359     }
1360     inline void SetProjectedFromWinRT()
1361     {
1362         LIMITED_METHOD_CONTRACT;
1363         m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1364     }
1365     inline void SetExportedToWinRT()
1366     {
1367         LIMITED_METHOD_CONTRACT;
1368         m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1369     }
1370     inline void SetMarshalingType(UINT32 mType)
1371     {
1372         LIMITED_METHOD_CONTRACT;
1373         _ASSERTE(mType !=0);
1374         _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1375         switch(mType)
1376         {
1377         case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1378             break;
1379         case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1380             break;
1381         case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1382             break;
1383         default:
1384             _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1385         }
1386     }
1387 #endif // FEATURE_COMINTEROP
1388     inline void SetHasLayout()
1389     {
1390         LIMITED_METHOD_CONTRACT;
1391         m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT;  //modified before the class is published
1392     }
1393     inline void SetHasOverLayedFields()
1394     {
1395         LIMITED_METHOD_CONTRACT;
1396         m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1397     }
1398     inline void SetIsNested()
1399     {
1400         LIMITED_METHOD_CONTRACT;
1401         m_VMFlags |= VMFLAG_ISNESTED;
1402     }
1403
1404 #ifdef FEATURE_READYTORUN
1405     inline BOOL HasLayoutDependsOnOtherModules()
1406     {
1407         LIMITED_METHOD_CONTRACT;
1408         return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1409     }
1410
1411     inline void SetHasLayoutDependsOnOtherModules()
1412     {
1413         LIMITED_METHOD_CONTRACT;
1414         m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1415     }
1416 #endif
1417
1418     // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1419     inline BOOL IsDelegate()
1420     {
1421         LIMITED_METHOD_CONTRACT;
1422         return m_VMFlags & VMFLAG_DELEGATE;
1423     }
1424     inline void SetIsDelegate()
1425     {
1426         LIMITED_METHOD_CONTRACT;
1427         m_VMFlags |= VMFLAG_DELEGATE;
1428     }
1429
1430     BOOL HasFixedAddressVTStatics()
1431     {
1432         LIMITED_METHOD_CONTRACT;
1433         return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1434     }
1435 #ifdef FEATURE_COMINTEROP
1436     BOOL IsSparseForCOMInterop()
1437     {
1438         LIMITED_METHOD_CONTRACT;
1439         return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1440     }
1441     BOOL IsProjectedFromWinRT()
1442     {
1443         LIMITED_METHOD_DAC_CONTRACT;
1444         return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1445     }
1446     BOOL IsExportedToWinRT()
1447     {
1448         LIMITED_METHOD_CONTRACT;
1449         return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1450     }
1451     BOOL IsMarshalingTypeSet()
1452     {
1453         LIMITED_METHOD_CONTRACT;
1454         return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1455     }
1456     BOOL IsMarshalingTypeFreeThreaded()
1457     {
1458         LIMITED_METHOD_CONTRACT;
1459         return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1460     }
1461     BOOL IsMarshalingTypeInhibit()
1462     {
1463         LIMITED_METHOD_CONTRACT;
1464         return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1465     }
1466     BOOL IsMarshalingTypeStandard()
1467     {
1468         LIMITED_METHOD_CONTRACT;
1469         return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1470     }
1471 #endif // FEATURE_COMINTEROP
1472     BOOL HasLayout()
1473     {
1474         LIMITED_METHOD_CONTRACT;
1475         return m_VMFlags & VMFLAG_HASLAYOUT;
1476     }
1477     BOOL HasOverLayedField()
1478     {
1479         LIMITED_METHOD_CONTRACT;
1480         return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1481     }
1482     BOOL IsNested()
1483     {
1484         LIMITED_METHOD_CONTRACT;
1485         return m_VMFlags & VMFLAG_ISNESTED;
1486     }
1487     BOOL HasFieldsWhichMustBeInited()
1488     {
1489         LIMITED_METHOD_CONTRACT;
1490         return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1491     }
1492     void SetHasFieldsWhichMustBeInited()
1493     {
1494         LIMITED_METHOD_CONTRACT;
1495         m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1496     }
1497     void SetCannotBeBlittedByObjectCloner()
1498     {
1499         /* no op */
1500     }
1501     DWORD HasNonPublicFields()
1502     {
1503         LIMITED_METHOD_CONTRACT;
1504         return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1505     }
1506     void SetHasNonPublicFields()
1507     {
1508         LIMITED_METHOD_CONTRACT;
1509         m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1510     }
1511     DWORD IsNotTightlyPacked()
1512     {
1513         LIMITED_METHOD_CONTRACT;
1514         return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1515     }
1516     void SetIsNotTightlyPacked()
1517     {
1518         LIMITED_METHOD_CONTRACT;
1519         m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1520     }
1521     DWORD ContainsMethodImpls()
1522     {
1523         LIMITED_METHOD_CONTRACT;
1524         return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1525     }
1526     void SetContainsMethodImpls()
1527     {
1528         LIMITED_METHOD_CONTRACT;
1529         m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1530     }
1531
1532
1533     BOOL IsManagedSequential();
1534
1535     BOOL HasExplicitSize();
1536
1537     static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1538
1539     /*
1540      * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1541      */
1542 public:
1543     // This is what would be used in the calling convention for this type. 
1544     CorElementType  GetInternalCorElementType()
1545     {
1546         LIMITED_METHOD_DAC_CONTRACT;
1547
1548         return CorElementType(m_NormType);
1549     }
1550     void SetInternalCorElementType (CorElementType _NormType)
1551     {
1552         LIMITED_METHOD_CONTRACT;
1553         m_NormType = static_cast<BYTE>(_NormType);
1554     }
1555
1556     /*
1557      * Chain of MethodDesc chunks for the MethodTable
1558      */
1559 public:
1560     inline PTR_MethodDescChunk GetChunks();
1561
1562 #ifndef DACCESS_COMPILE
1563     inline void SetChunks (MethodDescChunk* pChunks)
1564     {
1565         LIMITED_METHOD_CONTRACT;
1566         m_pChunks.SetValueMaybeNull(pChunks);
1567     }
1568 #endif // !DACCESS_COMPILE
1569     void AddChunk (MethodDescChunk* pNewChunk);
1570
1571     void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1572
1573     inline PTR_GuidInfo GetGuidInfo()
1574     {
1575         LIMITED_METHOD_DAC_CONTRACT;
1576
1577         return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1578     }
1579
1580     inline void SetGuidInfo(GuidInfo* pGuidInfo)
1581     {
1582         WRAPPER_NO_CONTRACT;
1583         #ifndef DACCESS_COMPILE
1584         EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1585         #endif // DACCESS_COMPILE
1586     }
1587
1588     // Cached class level reliability contract info, see ConstrainedExecutionRegion.cpp for details.
1589     DWORD GetReliabilityContract();
1590
1591
1592 #if defined(UNIX_AMD64_ABI)
1593     // Get number of eightbytes used by a struct passed in registers.
1594     inline int GetNumberEightBytes()
1595     {
1596         LIMITED_METHOD_CONTRACT;
1597         _ASSERTE(HasOptionalFields());
1598         return GetOptionalFields()->m_numberEightBytes;
1599     }
1600
1601     // Get eightbyte classification for the eightbyte with the specified index.
1602     inline SystemVClassificationType GetEightByteClassification(int index)
1603     {
1604         LIMITED_METHOD_CONTRACT;
1605         _ASSERTE(HasOptionalFields());
1606         return GetOptionalFields()->m_eightByteClassifications[index];
1607     }
1608
1609     // Get size of the data in the eightbyte with the specified index.
1610     inline unsigned int GetEightByteSize(int index)
1611     {
1612         LIMITED_METHOD_CONTRACT;
1613         _ASSERTE(HasOptionalFields());
1614         return GetOptionalFields()->m_eightByteSizes[index];
1615     }
1616
1617     // Set the eightByte classification
1618     inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1619     {
1620         LIMITED_METHOD_CONTRACT;
1621         _ASSERTE(HasOptionalFields());
1622         GetOptionalFields()->m_numberEightBytes = eightByteCount;
1623         for (int i = 0; i < eightByteCount; i++)
1624         {
1625             GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1626             GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1627         }
1628     }
1629 #endif // UNIX_AMD64_ABI    
1630
1631 #if defined(FEATURE_HFA)
1632     bool CheckForHFA(MethodTable ** pByValueClassCache);
1633     VOID CheckForNativeHFA();
1634 #else // !FEATURE_HFA
1635     bool CheckForHFA();
1636 #endif // FEATURE_HFA
1637
1638 #ifdef FEATURE_COMINTEROP
1639     inline TypeHandle GetCoClassForInterface()
1640     {
1641         LIMITED_METHOD_CONTRACT;
1642         _ASSERTE(HasOptionalFields());
1643         return GetOptionalFields()->m_pCoClassForIntf;
1644     }
1645
1646     inline void SetCoClassForInterface(TypeHandle th)
1647     {
1648         WRAPPER_NO_CONTRACT;
1649         _ASSERTE(HasOptionalFields());
1650         *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1651     }
1652
1653     inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1654     {
1655         LIMITED_METHOD_CONTRACT;
1656         return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1657                                    : WinMDAdapter::RedirectedTypeIndex_Invalid;
1658     }
1659
1660     inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1661     {
1662         LIMITED_METHOD_CONTRACT;
1663         _ASSERTE(HasOptionalFields());
1664         _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1665         GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1666     }
1667 #endif // FEATURE_COMINTEROP
1668
1669     inline UINT32 GetNativeSize()
1670     {
1671         LIMITED_METHOD_DAC_CONTRACT;
1672         return m_cbNativeSize;
1673     }
1674     static UINT32 GetOffsetOfNativeSize()
1675     {
1676         LIMITED_METHOD_CONTRACT;
1677         return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1678     }
1679     void SetNativeSize(UINT32 nativeSize)
1680     {
1681         LIMITED_METHOD_CONTRACT;
1682         m_cbNativeSize = nativeSize;
1683     }
1684 #ifdef FEATURE_COMINTEROP
1685     OBJECTHANDLE GetOHDelegate()
1686     {
1687         LIMITED_METHOD_CONTRACT;
1688         return m_ohDelegate;
1689     }
1690     void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1691     {
1692         LIMITED_METHOD_CONTRACT;
1693         m_ohDelegate = _ohDelegate;
1694     }
1695     // Set the COM interface type.
1696     CorIfaceAttr GetComInterfaceType()
1697     {
1698         LIMITED_METHOD_CONTRACT;
1699         return m_ComInterfaceType;
1700     }
1701
1702     void SetComInterfaceType(CorIfaceAttr ItfType)
1703     {
1704         WRAPPER_NO_CONTRACT;
1705         _ASSERTE(IsInterface());
1706         EnsureWritablePages(this);
1707         m_ComInterfaceType = ItfType;
1708     }
1709
1710     inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1711     {
1712         LIMITED_METHOD_CONTRACT;
1713         return m_pccwTemplate;
1714     }
1715     inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1716     {
1717         WRAPPER_NO_CONTRACT;
1718         return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1719     }
1720
1721 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1722     inline ClassFactoryBase *GetComClassFactory()
1723     {
1724         LIMITED_METHOD_CONTRACT;
1725         return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1726     }
1727     inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1728     {
1729         WRAPPER_NO_CONTRACT;
1730         _ASSERTE(HasOptionalFields());
1731         return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1732     }
1733 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1734 #endif // FEATURE_COMINTEROP
1735
1736
1737 public:
1738     PTR_DictionaryLayout GetDictionaryLayout()
1739     {
1740         SUPPORTS_DAC;
1741         WRAPPER_NO_CONTRACT;
1742         return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1743     }
1744
1745     void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1746     {
1747         SUPPORTS_DAC;
1748         WRAPPER_NO_CONTRACT;
1749         _ASSERTE(HasOptionalFields());
1750         GetOptionalFields()->m_pDictLayout = pLayout;
1751     }
1752
1753 #ifndef DACCESS_COMPILE
1754     static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1755     {
1756         LIMITED_METHOD_CONTRACT;
1757         if (pbVarianceInfo == NULL)
1758             return gpNonVariant;
1759         else
1760             return (CorGenericParamAttr) (pbVarianceInfo[i]);
1761     }
1762
1763     CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1764     {
1765         WRAPPER_NO_CONTRACT;
1766         return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1767     }
1768
1769     BYTE* GetVarianceInfo()
1770     {
1771         LIMITED_METHOD_CONTRACT;
1772         return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1773     }
1774
1775     void SetVarianceInfo(BYTE *pVarianceInfo)
1776     {
1777         LIMITED_METHOD_CONTRACT;
1778         _ASSERTE(HasOptionalFields());
1779         GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1780     }
1781 #endif // !DACCESS_COMPILE
1782
1783     // Check that a signature blob uses type parameters correctly
1784     // in accordance with the variance annotations specified by this class
1785     // The position parameter indicates the variance of the context we're in
1786     // (result type is gpCovariant, argument types are gpContravariant, deeper in a signature
1787     // we might be gpNonvariant e.g. in a pointer type or non-variant generic type)
1788     static BOOL
1789     CheckVarianceInSig(
1790         DWORD numGenericArgs,
1791         BYTE *pVarianceInfo,
1792         Module * pModule,
1793         SigPointer sp,
1794         CorGenericParamAttr position);
1795
1796 #if defined(_DEBUG)
1797 public:
1798     enum{
1799         AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1800     };
1801 #endif // defined(_DEBUG)
1802
1803     //-------------------------------------------------------------
1804     // CONCRETE DATA LAYOUT
1805     //
1806     // Although accessed far less frequently than MethodTables, EEClasses are still
1807     // pulled into working set, especially at startup.  This has motivated several space
1808     // optimizations in field layout where each is balanced against the need to access
1809     // a particular field efficiently.
1810     //
1811     // Currently, the following strategy is used:
1812     //
1813     //     - Any field that has a default value for the vast majority of EEClass instances
1814     //       should be stored in the EEClassOptionalFields (see header comment)
1815     //
1816     //     - Any field that is nearly always a small positive integer and is infrequently
1817     //       accessed should be in the EEClassPackedFields (see header comment)
1818     //
1819     // If none of these categories apply - such as for always-meaningful pointer members or
1820     // sets of flags - a full field is used.  Please avoid adding such members if possible.
1821     //-------------------------------------------------------------
1822
1823     // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1824     //
1825     // Flags for m_VMFlags
1826     //
1827 public:
1828     enum
1829     {
1830 #ifdef FEATURE_READYTORUN
1831         VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
1832 #endif
1833         VMFLAG_DELEGATE                        = 0x00000002,
1834
1835         // VMFLAG_UNUSED                       = 0x0000001c,
1836
1837         VMFLAG_FIXED_ADDRESS_VT_STATICS        = 0x00000020, // Value type Statics in this class will be pinned
1838         VMFLAG_HASLAYOUT                       = 0x00000040,
1839         VMFLAG_ISNESTED                        = 0x00000080,
1840
1841         VMFLAG_IS_EQUIVALENT_TYPE              = 0x00000200,
1842
1843         //   OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
1844         VMFLAG_HASOVERLAYEDFIELDS              = 0x00000400,
1845         
1846         // Set this if this class or its parent have instance fields which
1847         // must be explicitly inited in a constructor (e.g. pointers of any
1848         // kind, gc or native).
1849         //
1850         // Currently this is used by the verifier when verifying value classes
1851         // - it's ok to use uninitialised value classes if there are no
1852         // pointer fields in them.
1853         VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED = 0x00000800,
1854
1855         VMFLAG_UNSAFEVALUETYPE                 = 0x00001000,
1856
1857         VMFLAG_BESTFITMAPPING_INITED           = 0x00002000, // VMFLAG_BESTFITMAPPING and VMFLAG_THROWONUNMAPPABLECHAR are valid only if this is set
1858         VMFLAG_BESTFITMAPPING                  = 0x00004000, // BestFitMappingAttribute.Value
1859         VMFLAG_THROWONUNMAPPABLECHAR           = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar
1860
1861         // unused                              = 0x00010000,
1862         VMFLAG_NO_GUID                         = 0x00020000,
1863         VMFLAG_HASNONPUBLICFIELDS              = 0x00040000,
1864         // unused                              = 0x00080000,
1865         VMFLAG_CONTAINS_STACK_PTR              = 0x00100000,
1866         VMFLAG_PREFER_ALIGN8                   = 0x00200000, // Would like to have 8-byte alignment
1867         // unused                              = 0x00400000,
1868
1869 #ifdef FEATURE_COMINTEROP
1870         VMFLAG_SPARSE_FOR_COMINTEROP           = 0x00800000,
1871         // interfaces may have a coclass attribute
1872         VMFLAG_HASCOCLASSATTRIB                = 0x01000000,
1873         VMFLAG_COMEVENTITFMASK                 = 0x02000000, // class is a special COM event interface
1874         VMFLAG_PROJECTED_FROM_WINRT            = 0x04000000,
1875         VMFLAG_EXPORTED_TO_WINRT               = 0x08000000,
1876 #endif // FEATURE_COMINTEROP
1877
1878         // This one indicates that the fields of the valuetype are 
1879         // not tightly packed and is used to check whether we can
1880         // do bit-equality on value types to implement ValueType::Equals.
1881         // It is not valid for classes, and only matters if ContainsPointer
1882         // is false.
1883         VMFLAG_NOT_TIGHTLY_PACKED              = 0x10000000,
1884
1885         // True if methoddesc on this class have any real (non-interface) methodimpls
1886         VMFLAG_CONTAINS_METHODIMPLS            = 0x20000000,
1887
1888 #ifdef FEATURE_COMINTEROP
1889         VMFLAG_MARSHALINGTYPE_MASK             = 0xc0000000,
1890
1891         VMFLAG_MARSHALINGTYPE_INHIBIT          = 0x40000000,
1892         VMFLAG_MARSHALINGTYPE_FREETHREADED     = 0x80000000,
1893         VMFLAG_MARSHALINGTYPE_STANDARD         = 0xc0000000,
1894 #endif
1895     };
1896
1897 public: 
1898     // C_ASSERTs in Jitinterface.cpp need this to be public to check the offset.
1899     // Put it first so the offset rarely changes, which just reduces the number of times we have to fiddle
1900     // with the offset.
1901     RelativePointer<PTR_GuidInfo> m_pGuidInfo;  // The cached guid information for interfaces.
1902
1903 #ifdef _DEBUG
1904 public:
1905     LPCUTF8 m_szDebugClassName;
1906     BOOL m_fDebuggingClass;
1907 #endif 
1908
1909 private: 
1910     // Layout rest of fields below from largest to smallest to lessen the chance of wasting bytes with
1911     // compiler injected padding (especially with the difference between pointers and DWORDs on 64-bit).
1912     RelativePointer<PTR_EEClassOptionalFields> m_rpOptionalFields;
1913
1914     // TODO: Remove this field. It is only used by SOS and object validation for stress.
1915     RelativePointer<PTR_MethodTable> m_pMethodTable;
1916
1917     RelativePointer<PTR_FieldDesc> m_pFieldDescList;
1918     RelativePointer<PTR_MethodDescChunk> m_pChunks;
1919
1920     union
1921     {
1922         // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
1923         UINT32          m_cbNativeSize; // size of fixed portion in bytes
1924
1925 #ifdef FEATURE_COMINTEROP
1926         // For COM+ wrapper objects that extend an unmanaged class, this field
1927         // may contain a delegate to be called to allocate the aggregated
1928         // unmanaged class (instead of using CoCreateInstance).
1929         OBJECTHANDLE    m_ohDelegate;
1930
1931         // For interfaces this contains the COM interface type.
1932         CorIfaceAttr    m_ComInterfaceType;
1933 #endif // FEATURE_COMINTEROP
1934     };
1935
1936 #ifdef FEATURE_COMINTEROP
1937     ComCallWrapperTemplate *m_pccwTemplate;   // points to interop data structures used when this type is exposed to COM
1938 #endif // FEATURE_COMINTEROP
1939
1940     DWORD m_dwAttrClass;
1941     DWORD m_VMFlags;
1942
1943     /*
1944      * We maintain some auxillary flags in DEBUG builds,
1945      * this frees up some bits in m_wVMFlags
1946      */
1947 #if defined(_DEBUG)
1948     WORD m_wAuxFlags;
1949 #endif
1950
1951     // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
1952     // structure packing.
1953     BYTE m_NormType;
1954     BYTE m_fFieldsArePacked;        // TRUE iff fields pointed to by GetPackedFields() are in packed state
1955     BYTE m_cbFixedEEClassFields;    // Count of bytes of normal fields of this instance (EEClass,
1956                                     // LayoutEEClass etc.). Doesn't count bytes of "packed" fields
1957     BYTE m_cbBaseSizePadding;       // How many bytes of padding are included in BaseSize
1958
1959 public:
1960     // EEClass optional field support. Whether a particular EEClass instance has optional fields is determined
1961     // at class load time. The entire EEClassOptionalFields structure is allocated if the EEClass has need of
1962     // one or more optional fields.
1963
1964 #ifndef DACCESS_COMPILE
1965     void AttachOptionalFields(EEClassOptionalFields *pFields)
1966     {
1967         LIMITED_METHOD_CONTRACT;
1968         _ASSERTE(m_rpOptionalFields.IsNull());
1969
1970         m_rpOptionalFields.SetValue(pFields);
1971     }
1972 #endif // !DACCESS_COMPILE
1973
1974     bool HasOptionalFields()
1975     {
1976         LIMITED_METHOD_DAC_CONTRACT;
1977         return !m_rpOptionalFields.IsNull();
1978     }
1979
1980     PTR_EEClassOptionalFields GetOptionalFields()
1981     {
1982         LIMITED_METHOD_DAC_CONTRACT;
1983         return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
1984     }
1985
1986 private:
1987     //
1988     // Support for packed fields.
1989     //
1990
1991     // Get pointer to the packed fields structure attached to this instance.
1992     PTR_EEClassPackedFields GetPackedFields();
1993
1994     // Get the value of the given field. Works regardless of whether the field is currently in its packed or
1995     // unpacked state.
1996     DWORD GetPackableField(EEClassFieldId eField);
1997
1998     // Set the value of the given field. The field *must* be in the unpacked state for this to be legal (in
1999     // practice all packable fields must be initialized during class construction and from then on remain
2000     // immutable).
2001     void SetPackableField(EEClassFieldId eField, DWORD dwValue);
2002
2003     //-------------------------------------------------------------
2004     // END CONCRETE DATA LAYOUT
2005     //-------------------------------------------------------------
2006
2007
2008
2009     /************************************
2010      *  PROTECTED METHODS
2011      ************************************/
2012 protected:
2013 #ifndef DACCESS_COMPILE
2014     /*
2015      * Constructor: prevent any other class from doing a new()
2016      */
2017     EEClass(DWORD cbFixedEEClassFields);
2018
2019     /*
2020      * Destructor: prevent any other class from deleting
2021      */
2022     ~EEClass()
2023     {
2024         LIMITED_METHOD_CONTRACT;
2025     }
2026 #endif // !DACCESS_COMPILE
2027
2028 };
2029
2030 // --------------------------------------------------------------------------------------------
2031 template <typename Data>
2032 class FixedCapacityStackingAllocatedUTF8StringHash
2033 {
2034 public:
2035     // Entry
2036     struct HashEntry
2037     {
2038         HashEntry *   m_pNext;        // Next item with same bucketed hash value
2039         DWORD         m_dwHashValue;  // Hash value
2040         LPCUTF8       m_pKey;         // String key
2041         Data          m_data;         // Data
2042     };
2043
2044     HashEntry **      m_pBuckets;       // Pointer to first entry for each bucket
2045     DWORD             m_dwNumBuckets;
2046     BYTE *            m_pMemory;        // Current pointer into preallocated memory for entries
2047     BYTE *            m_pMemoryStart;   // Start pointer of pre-allocated memory fo entries
2048
2049     INDEBUG(BYTE *    m_pDebugEndMemory;)
2050
2051     FixedCapacityStackingAllocatedUTF8StringHash()
2052         : m_pMemoryStart(NULL)
2053         { LIMITED_METHOD_CONTRACT; }
2054
2055     static DWORD
2056     GetHashCode(
2057         LPCUTF8 szString)
2058         { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2059
2060     // Throws on error
2061     void
2062     Init(
2063         DWORD               dwMaxEntries,
2064         StackingAllocator * pAllocator);
2065
2066     // Insert new entry at head of list
2067     void
2068     Insert(
2069         LPCUTF8         pszName,
2070         const Data &    data);
2071
2072     // Return the first matching entry in the list, or NULL if there is no such entry
2073     HashEntry *
2074     Lookup(
2075         LPCUTF8 pszName);
2076
2077     // Return the next matching entry in the list, or NULL if there is no such entry.
2078     HashEntry *
2079     FindNext(
2080         HashEntry * pEntry);
2081 };
2082
2083
2084 //---------------------------------------------------------------------------------------
2085 // 
2086 class LayoutEEClass : public EEClass
2087 {
2088 public:
2089     EEClassLayoutInfo m_LayoutInfo;
2090
2091 #ifndef DACCESS_COMPILE
2092     LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2093     {
2094         LIMITED_METHOD_CONTRACT;
2095 #ifdef _DEBUG
2096         FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2097 #endif
2098     }
2099 #endif // !DACCESS_COMPILE
2100 };
2101
2102 class UMThunkMarshInfo;
2103
2104 #ifdef FEATURE_COMINTEROP
2105 struct ComPlusCallInfo;
2106 #endif // FEATURE_COMINTEROP
2107
2108 class DelegateEEClass : public EEClass
2109 {
2110 public:
2111     PTR_Stub                         m_pStaticCallStub;
2112     PTR_Stub                         m_pInstRetBuffCallStub;
2113     RelativePointer<PTR_MethodDesc>  m_pInvokeMethod;
2114     PTR_Stub                         m_pMultiCastInvokeStub;
2115     PTR_Stub                         m_pSecureDelegateInvokeStub;
2116     UMThunkMarshInfo*                m_pUMThunkMarshInfo;
2117     RelativePointer<PTR_MethodDesc>  m_pBeginInvokeMethod;
2118     RelativePointer<PTR_MethodDesc>  m_pEndInvokeMethod;
2119     Volatile<PCODE>                  m_pMarshalStub;
2120
2121 #ifdef FEATURE_COMINTEROP
2122     ComPlusCallInfo *m_pComPlusCallInfo;
2123 #endif // FEATURE_COMINTEROP
2124
2125     //
2126     // Ngened IL stub MethodDescs. Fixed up, wrapped with code:Stub, and installed to
2127     // m_pMarshalStub (forward) or m_pUMThunkMarshInfo (reverse) when first needed.
2128     //
2129     MethodDesc*         m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2130     MethodDesc*         m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2131
2132     PTR_MethodDesc GetInvokeMethod()
2133     {
2134         return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2135     }
2136
2137     PTR_MethodDesc GetBeginInvokeMethod()
2138     {
2139         return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2140     }
2141
2142     PTR_MethodDesc GetEndInvokeMethod()
2143     {
2144         return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2145     }
2146
2147 #ifndef DACCESS_COMPILE
2148     DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2149     {
2150         LIMITED_METHOD_CONTRACT;
2151         // Note: Memory allocated on loader heap is zero filled
2152     }
2153
2154     // We need a LoaderHeap that lives at least as long as the DelegateEEClass, but ideally no longer
2155     LoaderHeap *GetStubHeap();
2156 #endif // !DACCESS_COMPILE
2157
2158 };
2159
2160
2161 typedef DPTR(ArrayClass) PTR_ArrayClass;
2162
2163
2164 // Dynamically generated array class structure
2165 class ArrayClass : public EEClass
2166 {
2167 #ifdef FEATURE_PREJIT
2168     friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2169 #endif
2170
2171     friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2172
2173 #ifndef DACCESS_COMPILE
2174     ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2175 #else
2176     friend class NativeImageDumper;
2177 #endif
2178
2179 private:
2180
2181     unsigned char   m_rank;
2182     CorElementType  m_ElementType;// Cache of element type in m_ElementTypeHnd
2183
2184 public:
2185     DWORD GetRank() {
2186         LIMITED_METHOD_CONTRACT;
2187         SUPPORTS_DAC;
2188         return m_rank;
2189     }
2190     void SetRank (unsigned Rank) {
2191         LIMITED_METHOD_CONTRACT;
2192         // The only code path calling this function is code:ClassLoader::CreateTypeHandleForTypeKey, which has
2193         // checked the rank already.  Assert that the rank is less than MAX_RANK and that it fits in one byte.
2194         _ASSERTE((Rank <= MAX_RANK) && (Rank <= (unsigned char)(-1)));
2195         m_rank = (unsigned char)Rank;
2196     }
2197
2198     CorElementType GetArrayElementType() {
2199         LIMITED_METHOD_CONTRACT;
2200         return m_ElementType;
2201     }
2202     void SetArrayElementType(CorElementType ElementType) {
2203         LIMITED_METHOD_CONTRACT;
2204         m_ElementType = ElementType;
2205     }
2206
2207
2208     // Allocate a new MethodDesc for the methods we add to this class
2209     void InitArrayMethodDesc(
2210         ArrayMethodDesc* pNewMD,
2211         PCCOR_SIGNATURE pShortSig,
2212         DWORD   cShortSig,
2213         DWORD   dwVtableSlot,
2214         LoaderAllocator *pLoaderAllocator,
2215         AllocMemTracker *pamTracker);
2216
2217     // Generate a short sig for an array accessor
2218     VOID GenerateArrayAccessorCallSig(DWORD   dwRank,
2219                                       DWORD   dwFuncType, // Load, store, or <init>
2220                                       PCCOR_SIGNATURE *ppSig, // Generated signature
2221                                       DWORD * pcSig,      // Generated signature size
2222                                       LoaderAllocator *pLoaderAllocator,
2223                                       AllocMemTracker *pamTracker
2224 #ifdef FEATURE_ARRAYSTUB_AS_IL
2225                                       ,BOOL fForStubAsIL
2226 #endif
2227     );
2228
2229
2230 };
2231
2232 inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2233 {
2234     LIMITED_METHOD_CONTRACT;
2235     _ASSERTE(HasLayout());
2236     return &((LayoutEEClass *) this)->m_LayoutInfo;
2237 }
2238
2239 inline BOOL EEClass::IsBlittable()
2240 {
2241     LIMITED_METHOD_CONTRACT;
2242
2243     // Either we have an opaque bunch of bytes, or we have some fields that are
2244     // all isomorphic and explicitly layed out.
2245     return (HasLayout() && GetLayoutInfo()->IsBlittable());
2246 }
2247
2248 inline BOOL EEClass::IsManagedSequential()
2249 {
2250     LIMITED_METHOD_CONTRACT;
2251     return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2252 }
2253
2254 inline BOOL EEClass::HasExplicitSize()
2255 {
2256     LIMITED_METHOD_CONTRACT;
2257     return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2258 }
2259
2260 //==========================================================================
2261 // These routines manage the prestub (a bootstrapping stub that all
2262 // FunctionDesc's are initialized with.)
2263 //==========================================================================
2264 VOID InitPreStubManager();
2265
2266 EXTERN_C void STDCALL ThePreStub();
2267
2268 inline PCODE GetPreStubEntryPoint()
2269 {
2270     return GetEEFuncEntryPoint(ThePreStub);
2271 }
2272
2273 #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2274
2275 EXTERN_C void STDCALL ThePreStubCompactARM();
2276
2277 inline PCODE GetPreStubCompactARMEntryPoint()
2278 {
2279     return GetEEFuncEntryPoint(ThePreStubCompactARM);
2280 }
2281
2282 #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2283
2284 PCODE TheUMThunkPreStub();
2285
2286 PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
2287
2288
2289
2290 // workaround: These classification bits need cleanup bad: for now, this gets around
2291 // IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
2292 #define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
2293
2294 //
2295 // The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
2296 // methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
2297 //
2298
2299 #define METH_NAME_CACHE_SIZE        5
2300 #define MAX_MISSES                  3
2301
2302 #ifdef EnC_SUPPORTED
2303
2304 struct EnCAddedFieldElement;
2305
2306 #endif // EnC_SUPPORTED
2307
2308
2309 // --------------------------------------------------------------------------------------------
2310 // For generic instantiations the FieldDescs stored for instance 
2311 // fields are approximate, not exact, i.e. they are representatives owned by 
2312 // canonical instantiation and they do not carry exact type information.
2313 // This will not include EnC related fields. (See EncApproxFieldDescIterator for that)
2314 class ApproxFieldDescIterator
2315 {
2316 private:
2317     int m_iteratorType;
2318     PTR_FieldDesc m_pFieldDescList;
2319     int m_currField;
2320     int m_totalFields;
2321
2322   public:
2323     enum IteratorType {
2324        INSTANCE_FIELDS = 0x1,
2325        STATIC_FIELDS   = 0x2,
2326        ALL_FIELDS      = (INSTANCE_FIELDS | STATIC_FIELDS)
2327     };
2328     ApproxFieldDescIterator();
2329     ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2330     {
2331         SUPPORTS_DAC;
2332         Init(pMT, iteratorType);
2333     }
2334     void Init(MethodTable *pMT, int iteratorType);
2335     PTR_FieldDesc Next();
2336
2337     int GetIteratorType() {
2338         LIMITED_METHOD_CONTRACT;
2339         SUPPORTS_DAC;
2340         return m_iteratorType;
2341     }
2342     
2343     int Count() {
2344         LIMITED_METHOD_CONTRACT;
2345         return m_totalFields;
2346     }
2347     int CountRemaining() {
2348         LIMITED_METHOD_CONTRACT;
2349         SUPPORTS_DAC;
2350         return m_totalFields - m_currField - 1;
2351     }
2352 };
2353
2354 //
2355 // DeepFieldDescIterator iterates over the entire
2356 // set of fields available to a class, inherited or
2357 // introduced.
2358 //
2359
2360 class DeepFieldDescIterator
2361 {
2362 private:
2363     ApproxFieldDescIterator m_fieldIter;
2364     int m_numClasses;
2365     int m_curClass;
2366     MethodTable* m_classes[16];
2367     int m_deepTotalFields;
2368     bool m_lastNextFromParentClass;
2369
2370     bool NextClass();
2371     
2372 public:
2373     DeepFieldDescIterator()
2374     {
2375         LIMITED_METHOD_CONTRACT;
2376         
2377         m_numClasses = 0;
2378         m_curClass = 0;
2379         m_deepTotalFields = 0;
2380         m_lastNextFromParentClass = false;
2381     }
2382     DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2383                           bool includeParents = true)
2384     {
2385         WRAPPER_NO_CONTRACT;
2386         
2387         Init(pMT, iteratorType, includeParents);
2388     }
2389     void Init(MethodTable* pMT, int iteratorType,
2390               bool includeParents = true);
2391     
2392     FieldDesc* Next();
2393
2394     bool Skip(int numSkip);
2395     
2396     int Count()
2397     {
2398         LIMITED_METHOD_CONTRACT;
2399         return m_deepTotalFields;
2400     }
2401     bool IsFieldFromParentClass()
2402     {
2403         LIMITED_METHOD_CONTRACT;
2404         return m_lastNextFromParentClass;
2405     }
2406 };
2407
2408 #endif // !CLASS_H