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