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