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