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