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.
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.
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.
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.
23 // ============================================================================
31 #include "eecontract.h"
39 #ifdef FEATURE_COMINTEROP
40 #include "stdinterfaces.h"
44 #include "typehandle.h"
45 #include "methodtable.h"
48 #include "iterator_util.h"
50 #ifdef FEATURE_COMINTEROP
51 #include "..\md\winmd\inc\adapter.h"
53 #include "packedfields.inl"
55 #define IBCLOG(x) g_IBCLogger.##x
57 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
62 #define MAX_LOG2_PRIMITIVE_FIELD_SIZE 3
64 #define MAX_PRIMITIVE_FIELD_SIZE (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
67 * Forward declarations
71 class ArrayMethodDesc;
74 class DictionaryLayout;
75 class FCallMethodDesc;
80 struct LayoutRawFieldInfo;
83 class MethodDescChunk;
86 struct ModuleCtorInfo;
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;
101 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
102 typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
105 //---------------------------------------------------------------------------------
106 // Fields in an explicit-layout class present varying degrees of risk depending
107 // on how they overlap.
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
117 // Note: order is important here - each guarantee also implicitly guarantees all promises
118 // made by values lower in number.
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
127 kMaxTrust = kNonOverLayed,
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
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.
147 VOID AddField(TrustLevel fieldTrust)
149 LIMITED_METHOD_CONTRACT;
150 m_trust = min(m_trust, fieldTrust);
155 LIMITED_METHOD_CONTRACT;
156 return m_trust >= kLegal;
161 LIMITED_METHOD_CONTRACT;
162 return m_trust >= kVerifiable;
165 BOOL IsNonOverLayed()
167 LIMITED_METHOD_CONTRACT;
168 return m_trust >= kNonOverLayed;
171 TrustLevel GetTrustLevel()
173 LIMITED_METHOD_CONTRACT;
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.
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
194 ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
196 LIMITED_METHOD_CONTRACT;
197 m_pExplicitClassTrust = pExplicitClassTrust;
199 m_trustDeclared = FALSE;
201 m_fieldTrust = kNone;
204 VOID SetTrust(TrustLevel fieldTrust)
206 LIMITED_METHOD_CONTRACT;
208 _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
209 _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
212 m_trustDeclared = TRUE;
214 m_fieldTrust = fieldTrust;
217 ~ExplicitFieldTrustHolder()
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);
228 ExplicitClassTrust* m_pExplicitClassTrust;
229 TrustLevel m_fieldTrust;
231 BOOL m_trustDeclared; // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
235 //*******************************************************************************
236 // Enumerator to traverse the interface declarations of a type, automatically building
237 // a substitution chain on the stack.
238 class InterfaceImplEnum
241 HENUMInternalHolder hEnumInterfaceImpl;
242 const Substitution *m_pSubstChain;
243 Substitution m_CurrSubst;
246 InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
247 : hEnumInterfaceImpl(pModule->GetMDImport())
251 hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
252 m_pSubstChain = pSubstChain;
256 // S_OK ... if has next (TRUE)
257 // S_FALSE ... if does not have next (FALSE)
264 if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
269 IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
270 m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
273 const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
274 mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
277 #ifdef FEATURE_COMINTEROP
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.
286 class SparseVTableMap
289 #ifdef DACCESS_COMPILE
290 friend class NativeImageDumper;
296 // First run through MT slots calling RecordGap wherever a gap in VT slots
298 void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
300 // Then call FinalizeMapping to create the actual mapping list.
301 void FinalizeMapping(WORD TotalMTSlots);
303 // Map MT to VT slot.
304 WORD LookupVTSlot(WORD MTSlot);
306 // Retrieve the number of slots in the vtable (both empty and full).
307 WORD GetNumVTableSlots();
309 const void* GetMapList()
311 LIMITED_METHOD_CONTRACT;
312 return (void*)m_MapList;
315 #ifdef FEATURE_PREJIT
316 // Methods to persist structure
317 void Save(DataImage *image);
318 void Fixup(DataImage *image);
319 #endif // FEATURE_PREJIT
323 enum { MapGrow = 4 };
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
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
336 WORD m_LastUsed; // Index of last entry used in successful lookup
338 WORD m_VTSlot; // Current VT slot number, used during list build
339 WORD m_MTSlot; // Current MT slot number, used during list build
341 void AllocOrExpand(); // Allocate or expand the mapping list for a new entry
343 #endif // FEATURE_COMINTEROP
345 //=======================================================================
346 // Adjunct to the EEClass structure for classes w/ layout
347 //=======================================================================
348 class EEClassLayoutInfo
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
369 friend class ClassLoader;
370 friend class EEClass;
371 friend class MethodTableBuilder;
372 #ifdef DACCESS_COMPILE
373 friend class NativeImageDumper;
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
396 static void SetOffsetsAndSortFields(
397 IMDInternalImport* pInternalImport,
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.
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,
414 BYTE parentAlignmentRequirement,
415 BOOL calculatingNativeLayout,
416 EEClassLayoutInfo* pEEClassLayoutInfoOut // A pointer to a caller-allocated EEClassLayoutInfo that we are filling in.
419 // size (in bytes) of fixed portion of NStruct.
420 UINT32 m_cbNativeSize;
421 UINT32 m_cbManagedSize;
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
428 BYTE m_LargestAlignmentRequirementOfAllMembers;
430 // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
431 // for the managed layout.
432 BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
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.
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.
448 // The size of the struct is explicitly specified in the meta-data.
449 e_HAS_EXPLICIT_SIZE = 0x08,
450 #ifdef UNIX_AMD64_ABI
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
457 // HFA type of the unmanaged layout
458 // Note that these are not flags, they are discrete values.
462 e_HFATypeFlags = 0x30,
468 // Packing size in bytes (1, 2, 4, 8 etc.)
469 BYTE m_cbPackingSize;
471 // # of fields that are of the calltime-marshal variety.
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;
481 BOOL GetNativeSize() const
483 LIMITED_METHOD_CONTRACT;
484 return m_cbNativeSize;
487 UINT32 GetManagedSize() const
489 LIMITED_METHOD_CONTRACT;
490 return m_cbManagedSize;
494 BYTE GetLargestAlignmentRequirementOfAllMembers() const
496 LIMITED_METHOD_CONTRACT;
497 return m_LargestAlignmentRequirementOfAllMembers;
500 UINT GetNumCTMFields() const
502 LIMITED_METHOD_CONTRACT;
503 return m_numCTMFields;
506 PTR_FieldMarshaler GetFieldMarshalers() const
508 LIMITED_METHOD_CONTRACT;
509 return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
512 #ifndef DACCESS_COMPILE
513 void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
515 LIMITED_METHOD_CONTRACT;
516 m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
518 #endif // DACCESS_COMPILE
520 BOOL IsBlittable() const
522 LIMITED_METHOD_CONTRACT;
523 return (m_bFlags & e_BLITTABLE) == e_BLITTABLE;
526 BOOL IsManagedSequential() const
528 LIMITED_METHOD_CONTRACT;
529 return (m_bFlags & e_MANAGED_SEQUENTIAL) == e_MANAGED_SEQUENTIAL;
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
539 LIMITED_METHOD_CONTRACT;
540 return (m_bFlags & e_ZERO_SIZED) == e_ZERO_SIZED;
543 BOOL HasExplicitSize() const
545 LIMITED_METHOD_CONTRACT;
546 return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE;
549 DWORD GetPackingSize() const
551 LIMITED_METHOD_CONTRACT;
552 return m_cbPackingSize;
555 #ifdef UNIX_AMD64_ABI
556 bool IsNativeStructPassedInRegisters()
558 LIMITED_METHOD_CONTRACT;
559 return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
562 bool IsNativeStructPassedInRegisters()
566 #endif // UNIX_AMD64_ABI
568 CorElementType GetNativeHFATypeRaw();
572 LIMITED_METHOD_CONTRACT;
573 return (m_bFlags & e_HFATypeFlags) != 0;
576 CorElementType GetNativeHFAType()
578 LIMITED_METHOD_CONTRACT;
579 switch (m_bFlags & e_HFATypeFlags)
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;
587 #else // !FEATURE_HFA
590 return GetNativeHFATypeRaw() != ELEMENT_TYPE_END;
592 CorElementType GetNativeHFAType()
594 return GetNativeHFATypeRaw();
596 #endif // !FEATURE_HFA
599 void SetIsBlittable(BOOL isBlittable)
601 LIMITED_METHOD_CONTRACT;
602 m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
603 : (m_bFlags & ~e_BLITTABLE);
606 void SetIsManagedSequential(BOOL isManagedSequential)
608 LIMITED_METHOD_CONTRACT;
609 m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
610 : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
613 void SetIsZeroSized(BOOL isZeroSized)
615 LIMITED_METHOD_CONTRACT;
616 m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
617 : (m_bFlags & ~e_ZERO_SIZED);
620 void SetHasExplicitSize(BOOL hasExplicitSize)
622 LIMITED_METHOD_CONTRACT;
623 m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
624 : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
628 void SetNativeHFAType(CorElementType hfaType)
630 LIMITED_METHOD_CONTRACT;
631 // We should call this at most once.
632 _ASSERTE((m_bFlags & e_HFATypeFlags) == 0);
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");
642 #ifdef UNIX_AMD64_ABI
643 void SetNativeStructPassedInRegisters()
645 LIMITED_METHOD_CONTRACT;
646 m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
648 #endif // UNIX_AMD64_ABI
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.
660 // This structure is destroyed after resolving has completed.
664 // The interface method table; for instantiated interfaces, this is the generic interface
665 MethodTable *m_pMethodTable;
666 } BuildingInterfaceInfo_t;
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.
674 // Size of hash bitmap for method names
675 #define METHOD_HASH_BYTES 8
677 // Hash table size - prime number
678 #define METHOD_HASH_BITS 61
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.
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)
691 #define DefineFullyQualifiedNameForClass() \
692 ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
693 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
695 #define DefineFullyQualifiedNameForClassOnStack() \
696 ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
697 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
699 #define DefineFullyQualifiedNameForClassW() \
700 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
702 #define DefineFullyQualifiedNameForClassWOnStack() \
703 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
705 #define GetFullyQualifiedNameForClassNestedAware(pClass) \
706 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
708 #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
709 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
711 #define GetFullyQualifiedNameForClass(pClass) \
712 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
714 #define GetFullyQualifiedNameForClassW(pClass) \
715 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
717 #define GetFullyQualifiedNameForClassW_WinRT(pClass) \
718 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
720 #define GetFullyQualifiedNameForClass_WinRT(pClass) \
721 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
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
727 class EEClassOptionalFields
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;
739 // GENERICS RELATED FIELDS.
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;
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;
751 // COM RELATED FIELDS.
754 #ifdef FEATURE_COMINTEROP
755 SparseVTableMap *m_pSparseVTableMap;
757 TypeHandle m_pCoClassForIntf; // @TODO: Coclass for an interface
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
764 WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
766 #endif // FEATURE_COMINTEROP
772 #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
773 DWORD m_cbModuleDynamicID;
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
784 // Set default values for optional fields.
787 PTR_BYTE GetVarianceInfo()
789 LIMITED_METHOD_DAC_CONTRACT;
791 return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
794 typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
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).
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.
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.
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.
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,
835 typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
836 typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
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
850 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
852 // A word about EEClass vs. MethodTable
853 // ------------------------------------
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.
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.
866 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
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.
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.
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.
885 class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
887 /************************************
889 ************************************/
890 // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
891 // USE ACCESSORS TO READ/WRITE private field members
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;
903 /************************************
904 * PUBLIC INSTANCE METHODS
905 ************************************/
910 LIMITED_METHOD_CONTRACT;
911 return IsTdSealed(m_dwAttrClass);
914 inline DWORD IsInterface()
917 return IsTdInterface(m_dwAttrClass);
920 inline DWORD IsAbstract()
923 return IsTdAbstract(m_dwAttrClass);
926 BOOL HasExplicitFieldOffsetLayout()
929 return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
932 BOOL HasSequentialLayout()
935 return IsTdSequentialLayout(GetAttrClass());
937 BOOL IsBeforeFieldInit()
940 return IsTdBeforeFieldInit(GetAttrClass());
943 DWORD GetProtection()
946 return (m_dwAttrClass & tdVisibilityMask);
949 // class is blittable
952 #ifndef DACCESS_COMPILE
953 void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
954 void Destruct(MethodTable * pMT);
956 static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
957 #endif // !DACCESS_COMPILE
960 // Add a new method to an already loaded type for EnC
961 static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
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
968 inline DWORD IsComImport()
971 return IsTdImport(m_dwAttrClass);
974 #ifdef FEATURE_PREJIT
977 void Save(DataImage *image, MethodTable *pMT);
978 void Fixup(DataImage *image, MethodTable *pMT);
979 #endif // FEATURE_PREJIT
981 EEClassLayoutInfo *GetLayoutInfo();
983 #ifdef DACCESS_COMPILE
984 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
987 static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
989 /************************************
990 * INSTANCE MEMBER VARIABLES
991 ************************************/
994 inline LPCUTF8 GetDebugClassName ()
996 LIMITED_METHOD_CONTRACT;
997 return m_szDebugClassName;
999 inline void SetDebugClassName (LPCUTF8 szDebugClassName)
1001 LIMITED_METHOD_CONTRACT;
1002 m_szDebugClassName = szDebugClassName;
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.
1015 #ifdef FEATURE_COMINTEROP
1017 * Used to map MethodTable slots to VTable slots
1019 inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
1021 LIMITED_METHOD_CONTRACT;
1022 return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
1024 inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
1026 LIMITED_METHOD_CONTRACT;
1027 _ASSERTE(HasOptionalFields());
1028 GetOptionalFields()->m_pSparseVTableMap = map;
1030 #endif // FEATURE_COMINTEROP
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).
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.
1045 inline PTR_MethodTable GetMethodTable()
1047 LIMITED_METHOD_CONTRACT;
1050 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
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
1062 inline PTR_MethodTable GetMethodTableWithPossibleAV()
1064 CANNOT_HAVE_CONTRACT;
1067 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1070 #ifndef DACCESS_COMPILE
1071 inline void SetMethodTable(MethodTable* pMT)
1073 LIMITED_METHOD_CONTRACT;
1074 m_pMethodTable.SetValueMaybeNull(pMT);
1076 #endif // !DACCESS_COMPILE
1079 * Number of fields in the class, including inherited fields.
1080 * Does not include fields added from EnC.
1082 inline WORD GetNumInstanceFields()
1084 LIMITED_METHOD_CONTRACT;
1086 return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1089 inline void SetNumInstanceFields (WORD wNumInstanceFields)
1091 LIMITED_METHOD_CONTRACT;
1092 SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1096 * Number of static fields declared in this class.
1097 * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1099 inline WORD GetNumStaticFields()
1101 LIMITED_METHOD_CONTRACT;
1103 return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1105 inline void SetNumStaticFields (WORD wNumStaticFields)
1107 LIMITED_METHOD_CONTRACT;
1108 SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1111 inline WORD GetNumThreadStaticFields()
1113 LIMITED_METHOD_CONTRACT;
1115 return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1118 inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1120 LIMITED_METHOD_CONTRACT;
1121 SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1124 // Statics are stored in a big chunk inside the module
1126 inline DWORD GetModuleDynamicID()
1128 LIMITED_METHOD_CONTRACT;
1130 return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1133 inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1135 LIMITED_METHOD_CONTRACT;
1136 _ASSERTE(HasOptionalFields());
1137 GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
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
1145 inline DWORD GetNonGCRegularStaticFieldBytes()
1147 LIMITED_METHOD_CONTRACT;
1148 return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1150 inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1152 LIMITED_METHOD_CONTRACT;
1153 SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1156 inline DWORD GetNonGCThreadStaticFieldBytes()
1158 LIMITED_METHOD_CONTRACT;
1159 return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1161 inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1163 LIMITED_METHOD_CONTRACT;
1164 SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1167 inline WORD GetNumNonVirtualSlots()
1169 LIMITED_METHOD_CONTRACT;
1170 return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1172 inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1174 LIMITED_METHOD_CONTRACT;
1175 SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1178 inline BOOL IsEquivalentType()
1180 LIMITED_METHOD_CONTRACT;
1181 return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1184 #ifdef FEATURE_TYPEEQUIVALENCE
1185 inline void SetIsEquivalentType()
1187 LIMITED_METHOD_CONTRACT;
1188 m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1190 #endif // FEATURE_TYPEEQUIVALENCE
1193 * Number of static handles allocated
1195 inline WORD GetNumHandleRegularStatics ()
1197 LIMITED_METHOD_CONTRACT;
1198 return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1200 inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1202 LIMITED_METHOD_CONTRACT;
1203 SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1207 * Number of static handles allocated for ThreadStatics
1209 inline WORD GetNumHandleThreadStatics ()
1211 LIMITED_METHOD_CONTRACT;
1212 return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1214 inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1216 LIMITED_METHOD_CONTRACT;
1217 SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1221 * Number of boxed statics allocated
1223 inline WORD GetNumBoxedRegularStatics ()
1225 LIMITED_METHOD_CONTRACT;
1226 return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1228 inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1230 LIMITED_METHOD_CONTRACT;
1231 SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1235 * Number of boxed statics allocated for ThreadStatics
1237 inline WORD GetNumBoxedThreadStatics ()
1239 LIMITED_METHOD_CONTRACT;
1240 return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1242 inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1244 LIMITED_METHOD_CONTRACT;
1245 SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
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.
1252 inline DWORD GetBaseSizePadding()
1254 LIMITED_METHOD_DAC_CONTRACT;
1255 return m_cbBaseSizePadding;
1257 inline void SetBaseSizePadding(DWORD dwPadding)
1259 LIMITED_METHOD_CONTRACT;
1260 _ASSERTE(FitsIn<BYTE>(dwPadding));
1261 m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1264 inline DWORD GetUnboxedNumInstanceFieldBytes()
1266 DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1268 _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1274 * Pointer to a list of FieldDescs declared in this class
1275 * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1278 #ifdef FEATURE_PREJIT
1279 static DWORD FieldDescListSize(MethodTable * pMT);
1282 inline PTR_FieldDesc GetFieldDescList()
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));
1290 PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1292 #ifndef DACCESS_COMPILE
1293 inline void SetFieldDescList (FieldDesc* pFieldDescList)
1295 LIMITED_METHOD_CONTRACT;
1296 m_pFieldDescList.SetValue(pFieldDescList);
1298 #endif // !DACCESS_COMPILE
1300 inline WORD GetNumMethods()
1302 LIMITED_METHOD_DAC_CONTRACT;
1303 return (WORD)GetPackableField(EEClass_Field_NumMethods);
1305 inline void SetNumMethods (WORD wNumMethods)
1307 LIMITED_METHOD_CONTRACT;
1308 SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1312 * Cached metadata for this class (GetTypeDefProps)
1314 inline DWORD GetAttrClass()
1316 LIMITED_METHOD_CONTRACT;
1317 return m_dwAttrClass;
1319 inline void SetAttrClass (DWORD dwAttrClass)
1321 LIMITED_METHOD_CONTRACT;
1322 m_dwAttrClass = dwAttrClass;
1326 #ifdef FEATURE_COMINTEROP
1327 inline DWORD IsComClassInterface()
1329 LIMITED_METHOD_CONTRACT;
1330 return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1332 inline VOID SetIsComClassInterface()
1334 LIMITED_METHOD_CONTRACT;
1335 m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1337 inline void SetComEventItfType()
1339 LIMITED_METHOD_CONTRACT;
1340 _ASSERTE(IsInterface());
1341 m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1343 // class is a special COM event interface
1344 inline BOOL IsComEventItfType()
1346 LIMITED_METHOD_CONTRACT;
1347 return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1349 #endif // FEATURE_COMINTEROP
1352 inline DWORD IsDestroyed()
1354 LIMITED_METHOD_CONTRACT;
1355 return (m_wAuxFlags & AUXFLAG_DESTROYED);
1359 inline DWORD IsUnsafeValueClass()
1361 LIMITED_METHOD_CONTRACT;
1362 return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1367 inline void SetUnsafeValueClass()
1369 LIMITED_METHOD_CONTRACT;
1370 m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1374 inline BOOL HasNoGuid()
1376 LIMITED_METHOD_CONTRACT;
1377 return (m_VMFlags & VMFLAG_NO_GUID);
1379 inline void SetHasNoGuid()
1381 WRAPPER_NO_CONTRACT;
1382 FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1386 inline BOOL IsAlign8Candidate()
1388 LIMITED_METHOD_CONTRACT;
1389 return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1391 inline void SetAlign8Candidate()
1393 LIMITED_METHOD_CONTRACT;
1394 m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1397 inline void SetDestroyed()
1399 LIMITED_METHOD_CONTRACT;
1400 m_wAuxFlags |= AUXFLAG_DESTROYED;
1403 inline void SetHasFixedAddressVTStatics()
1405 LIMITED_METHOD_CONTRACT;
1406 m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1408 void SetHasOnlyAbstractMethods()
1410 LIMITED_METHOD_CONTRACT;
1411 m_VMFlags |= (DWORD) VMFLAG_ONLY_ABSTRACT_METHODS;
1413 #ifdef FEATURE_COMINTEROP
1414 void SetSparseForCOMInterop()
1416 LIMITED_METHOD_CONTRACT;
1417 m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1419 inline void SetProjectedFromWinRT()
1421 LIMITED_METHOD_CONTRACT;
1422 m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1424 inline void SetExportedToWinRT()
1426 LIMITED_METHOD_CONTRACT;
1427 m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1429 inline void SetMarshalingType(UINT32 mType)
1431 LIMITED_METHOD_CONTRACT;
1432 _ASSERTE(mType !=0);
1433 _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1436 case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1438 case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1440 case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1443 _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1446 #endif // FEATURE_COMINTEROP
1447 inline void SetHasLayout()
1449 LIMITED_METHOD_CONTRACT;
1450 m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT; //modified before the class is published
1452 inline void SetHasOverLayedFields()
1454 LIMITED_METHOD_CONTRACT;
1455 m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1457 inline void SetIsNested()
1459 LIMITED_METHOD_CONTRACT;
1460 m_VMFlags |= VMFLAG_ISNESTED;
1463 #ifdef FEATURE_READYTORUN
1464 inline BOOL HasLayoutDependsOnOtherModules()
1466 LIMITED_METHOD_CONTRACT;
1467 return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1470 inline void SetHasLayoutDependsOnOtherModules()
1472 LIMITED_METHOD_CONTRACT;
1473 m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1477 // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1478 inline BOOL IsDelegate()
1480 LIMITED_METHOD_CONTRACT;
1481 return m_VMFlags & VMFLAG_DELEGATE;
1483 inline void SetIsDelegate()
1485 LIMITED_METHOD_CONTRACT;
1486 m_VMFlags |= VMFLAG_DELEGATE;
1489 BOOL HasFixedAddressVTStatics()
1491 LIMITED_METHOD_CONTRACT;
1492 return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1495 BOOL HasOnlyAbstractMethods()
1497 LIMITED_METHOD_CONTRACT;
1498 return m_VMFlags & VMFLAG_ONLY_ABSTRACT_METHODS;
1501 #ifdef FEATURE_COMINTEROP
1502 BOOL IsSparseForCOMInterop()
1504 LIMITED_METHOD_CONTRACT;
1505 return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1507 BOOL IsProjectedFromWinRT()
1509 LIMITED_METHOD_DAC_CONTRACT;
1510 return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1512 BOOL IsExportedToWinRT()
1514 LIMITED_METHOD_CONTRACT;
1515 return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1517 BOOL IsMarshalingTypeSet()
1519 LIMITED_METHOD_CONTRACT;
1520 return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1522 BOOL IsMarshalingTypeFreeThreaded()
1524 LIMITED_METHOD_CONTRACT;
1525 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1527 BOOL IsMarshalingTypeInhibit()
1529 LIMITED_METHOD_CONTRACT;
1530 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1532 BOOL IsMarshalingTypeStandard()
1534 LIMITED_METHOD_CONTRACT;
1535 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1537 #endif // FEATURE_COMINTEROP
1540 LIMITED_METHOD_CONTRACT;
1541 return m_VMFlags & VMFLAG_HASLAYOUT;
1543 BOOL HasOverLayedField()
1545 LIMITED_METHOD_CONTRACT;
1546 return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1550 LIMITED_METHOD_CONTRACT;
1551 return m_VMFlags & VMFLAG_ISNESTED;
1553 BOOL HasFieldsWhichMustBeInited()
1555 LIMITED_METHOD_CONTRACT;
1556 return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1558 void SetHasFieldsWhichMustBeInited()
1560 LIMITED_METHOD_CONTRACT;
1561 m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1563 void SetCannotBeBlittedByObjectCloner()
1567 DWORD HasNonPublicFields()
1569 LIMITED_METHOD_CONTRACT;
1570 return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1572 void SetHasNonPublicFields()
1574 LIMITED_METHOD_CONTRACT;
1575 m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1577 DWORD IsNotTightlyPacked()
1579 LIMITED_METHOD_CONTRACT;
1580 return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1582 void SetIsNotTightlyPacked()
1584 LIMITED_METHOD_CONTRACT;
1585 m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1587 DWORD ContainsMethodImpls()
1589 LIMITED_METHOD_CONTRACT;
1590 return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1592 void SetContainsMethodImpls()
1594 LIMITED_METHOD_CONTRACT;
1595 m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1599 BOOL IsManagedSequential();
1601 BOOL HasExplicitSize();
1603 static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1606 * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1609 // This is what would be used in the calling convention for this type.
1610 CorElementType GetInternalCorElementType()
1612 LIMITED_METHOD_DAC_CONTRACT;
1614 return CorElementType(m_NormType);
1616 void SetInternalCorElementType (CorElementType _NormType)
1618 LIMITED_METHOD_CONTRACT;
1619 m_NormType = static_cast<BYTE>(_NormType);
1623 * Chain of MethodDesc chunks for the MethodTable
1626 inline PTR_MethodDescChunk GetChunks();
1628 #ifndef DACCESS_COMPILE
1629 inline void SetChunks (MethodDescChunk* pChunks)
1631 LIMITED_METHOD_CONTRACT;
1632 m_pChunks.SetValueMaybeNull(pChunks);
1634 #endif // !DACCESS_COMPILE
1635 void AddChunk (MethodDescChunk* pNewChunk);
1637 void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1639 inline PTR_GuidInfo GetGuidInfo()
1641 LIMITED_METHOD_DAC_CONTRACT;
1643 return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1646 inline void SetGuidInfo(GuidInfo* pGuidInfo)
1648 WRAPPER_NO_CONTRACT;
1649 #ifndef DACCESS_COMPILE
1650 EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1651 #endif // DACCESS_COMPILE
1655 #if defined(UNIX_AMD64_ABI)
1656 // Get number of eightbytes used by a struct passed in registers.
1657 inline int GetNumberEightBytes()
1659 LIMITED_METHOD_CONTRACT;
1660 _ASSERTE(HasOptionalFields());
1661 return GetOptionalFields()->m_numberEightBytes;
1664 // Get eightbyte classification for the eightbyte with the specified index.
1665 inline SystemVClassificationType GetEightByteClassification(int index)
1667 LIMITED_METHOD_CONTRACT;
1668 _ASSERTE(HasOptionalFields());
1669 return GetOptionalFields()->m_eightByteClassifications[index];
1672 // Get size of the data in the eightbyte with the specified index.
1673 inline unsigned int GetEightByteSize(int index)
1675 LIMITED_METHOD_CONTRACT;
1676 _ASSERTE(HasOptionalFields());
1677 return GetOptionalFields()->m_eightByteSizes[index];
1680 // Set the eightByte classification
1681 inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1683 LIMITED_METHOD_CONTRACT;
1684 _ASSERTE(HasOptionalFields());
1685 GetOptionalFields()->m_numberEightBytes = eightByteCount;
1686 for (int i = 0; i < eightByteCount; i++)
1688 GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1689 GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1692 #endif // UNIX_AMD64_ABI
1694 #if defined(FEATURE_HFA)
1695 bool CheckForHFA(MethodTable ** pByValueClassCache);
1696 VOID CheckForNativeHFA();
1697 #else // !FEATURE_HFA
1699 #endif // FEATURE_HFA
1701 #ifdef FEATURE_COMINTEROP
1702 inline TypeHandle GetCoClassForInterface()
1704 LIMITED_METHOD_CONTRACT;
1705 _ASSERTE(HasOptionalFields());
1706 return GetOptionalFields()->m_pCoClassForIntf;
1709 inline void SetCoClassForInterface(TypeHandle th)
1711 WRAPPER_NO_CONTRACT;
1712 _ASSERTE(HasOptionalFields());
1713 *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1716 inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1718 LIMITED_METHOD_CONTRACT;
1719 return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1720 : WinMDAdapter::RedirectedTypeIndex_Invalid;
1723 inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1725 LIMITED_METHOD_CONTRACT;
1726 _ASSERTE(HasOptionalFields());
1727 _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1728 GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1730 #endif // FEATURE_COMINTEROP
1732 inline UINT32 GetNativeSize()
1734 LIMITED_METHOD_DAC_CONTRACT;
1735 return m_cbNativeSize;
1737 static UINT32 GetOffsetOfNativeSize()
1739 LIMITED_METHOD_CONTRACT;
1740 return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1742 void SetNativeSize(UINT32 nativeSize)
1744 LIMITED_METHOD_CONTRACT;
1745 m_cbNativeSize = nativeSize;
1747 #ifdef FEATURE_COMINTEROP
1748 OBJECTHANDLE GetOHDelegate()
1750 LIMITED_METHOD_CONTRACT;
1751 return m_ohDelegate;
1753 void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1755 LIMITED_METHOD_CONTRACT;
1756 m_ohDelegate = _ohDelegate;
1758 // Set the COM interface type.
1759 CorIfaceAttr GetComInterfaceType()
1761 LIMITED_METHOD_CONTRACT;
1762 return m_ComInterfaceType;
1765 void SetComInterfaceType(CorIfaceAttr ItfType)
1767 WRAPPER_NO_CONTRACT;
1768 _ASSERTE(IsInterface());
1769 EnsureWritablePages(this);
1770 m_ComInterfaceType = ItfType;
1773 inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1775 LIMITED_METHOD_CONTRACT;
1776 return m_pccwTemplate;
1778 inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1780 WRAPPER_NO_CONTRACT;
1781 return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1784 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1785 inline ClassFactoryBase *GetComClassFactory()
1787 LIMITED_METHOD_CONTRACT;
1788 return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1790 inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1792 WRAPPER_NO_CONTRACT;
1793 _ASSERTE(HasOptionalFields());
1794 return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1796 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1797 #endif // FEATURE_COMINTEROP
1801 PTR_DictionaryLayout GetDictionaryLayout()
1804 WRAPPER_NO_CONTRACT;
1805 return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1808 void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1811 WRAPPER_NO_CONTRACT;
1812 _ASSERTE(HasOptionalFields());
1813 GetOptionalFields()->m_pDictLayout = pLayout;
1816 #ifndef DACCESS_COMPILE
1817 static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1819 LIMITED_METHOD_CONTRACT;
1820 if (pbVarianceInfo == NULL)
1821 return gpNonVariant;
1823 return (CorGenericParamAttr) (pbVarianceInfo[i]);
1826 CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1828 WRAPPER_NO_CONTRACT;
1829 return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1832 BYTE* GetVarianceInfo()
1834 LIMITED_METHOD_CONTRACT;
1835 return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1838 void SetVarianceInfo(BYTE *pVarianceInfo)
1840 LIMITED_METHOD_CONTRACT;
1841 _ASSERTE(HasOptionalFields());
1842 GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1844 #endif // !DACCESS_COMPILE
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)
1853 DWORD numGenericArgs,
1854 BYTE *pVarianceInfo,
1857 CorGenericParamAttr position);
1862 AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1864 #endif // defined(_DEBUG)
1866 //-------------------------------------------------------------
1867 // CONCRETE DATA LAYOUT
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.
1874 // Currently, the following strategy is used:
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)
1879 // - Any field that is nearly always a small positive integer and is infrequently
1880 // accessed should be in the EEClassPackedFields (see header comment)
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 //-------------------------------------------------------------
1886 // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1888 // Flags for m_VMFlags
1893 #ifdef FEATURE_READYTORUN
1894 VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
1896 VMFLAG_DELEGATE = 0x00000002,
1898 // VMFLAG_UNUSED = 0x0000001c,
1900 VMFLAG_FIXED_ADDRESS_VT_STATICS = 0x00000020, // Value type Statics in this class will be pinned
1901 VMFLAG_HASLAYOUT = 0x00000040,
1902 VMFLAG_ISNESTED = 0x00000080,
1904 VMFLAG_IS_EQUIVALENT_TYPE = 0x00000200,
1906 // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
1907 VMFLAG_HASOVERLAYEDFIELDS = 0x00000400,
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).
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,
1918 VMFLAG_UNSAFEVALUETYPE = 0x00001000,
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
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
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
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
1946 VMFLAG_NOT_TIGHTLY_PACKED = 0x10000000,
1948 // True if methoddesc on this class have any real (non-interface) methodimpls
1949 VMFLAG_CONTAINS_METHODIMPLS = 0x20000000,
1951 #ifdef FEATURE_COMINTEROP
1952 VMFLAG_MARSHALINGTYPE_MASK = 0xc0000000,
1954 VMFLAG_MARSHALINGTYPE_INHIBIT = 0x40000000,
1955 VMFLAG_MARSHALINGTYPE_FREETHREADED = 0x80000000,
1956 VMFLAG_MARSHALINGTYPE_STANDARD = 0xc0000000,
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
1964 RelativePointer<PTR_GuidInfo> m_pGuidInfo; // The cached guid information for interfaces.
1968 LPCUTF8 m_szDebugClassName;
1969 BOOL m_fDebuggingClass;
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;
1977 // TODO: Remove this field. It is only used by SOS and object validation for stress.
1978 RelativePointer<PTR_MethodTable> m_pMethodTable;
1980 RelativePointer<PTR_FieldDesc> m_pFieldDescList;
1981 RelativePointer<PTR_MethodDescChunk> m_pChunks;
1985 // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
1986 UINT32 m_cbNativeSize; // size of fixed portion in bytes
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;
1994 // For interfaces this contains the COM interface type.
1995 CorIfaceAttr m_ComInterfaceType;
1996 #endif // FEATURE_COMINTEROP
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
2003 DWORD m_dwAttrClass;
2007 * We maintain some auxillary flags in DEBUG builds,
2008 * this frees up some bits in m_wVMFlags
2014 // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
2015 // structure packing.
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
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.
2027 #ifndef DACCESS_COMPILE
2028 void AttachOptionalFields(EEClassOptionalFields *pFields)
2030 LIMITED_METHOD_CONTRACT;
2031 _ASSERTE(m_rpOptionalFields.IsNull());
2033 m_rpOptionalFields.SetValue(pFields);
2035 #endif // !DACCESS_COMPILE
2037 bool HasOptionalFields()
2039 LIMITED_METHOD_DAC_CONTRACT;
2040 return !m_rpOptionalFields.IsNull();
2043 PTR_EEClassOptionalFields GetOptionalFields()
2045 LIMITED_METHOD_DAC_CONTRACT;
2046 return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
2051 // Support for packed fields.
2054 // Get pointer to the packed fields structure attached to this instance.
2055 PTR_EEClassPackedFields GetPackedFields();
2057 // Get the value of the given field. Works regardless of whether the field is currently in its packed or
2059 DWORD GetPackableField(EEClassFieldId eField);
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
2064 void SetPackableField(EEClassFieldId eField, DWORD dwValue);
2066 //-------------------------------------------------------------
2067 // END CONCRETE DATA LAYOUT
2068 //-------------------------------------------------------------
2072 /************************************
2074 ************************************/
2076 #ifndef DACCESS_COMPILE
2078 * Constructor: prevent any other class from doing a new()
2080 EEClass(DWORD cbFixedEEClassFields);
2083 * Destructor: prevent any other class from deleting
2087 LIMITED_METHOD_CONTRACT;
2089 #endif // !DACCESS_COMPILE
2093 // --------------------------------------------------------------------------------------------
2094 template <typename Data>
2095 class FixedCapacityStackingAllocatedUTF8StringHash
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
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
2112 INDEBUG(BYTE * m_pDebugEndMemory;)
2114 FixedCapacityStackingAllocatedUTF8StringHash()
2115 : m_pMemoryStart(NULL)
2116 { LIMITED_METHOD_CONTRACT; }
2121 { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2127 StackingAllocator * pAllocator);
2129 // Insert new entry at head of list
2135 // Return the first matching entry in the list, or NULL if there is no such entry
2140 // Return the next matching entry in the list, or NULL if there is no such entry.
2143 HashEntry * pEntry);
2147 //---------------------------------------------------------------------------------------
2149 class LayoutEEClass : public EEClass
2152 EEClassLayoutInfo m_LayoutInfo;
2154 #ifndef DACCESS_COMPILE
2155 LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2157 LIMITED_METHOD_CONTRACT;
2159 FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2162 #endif // !DACCESS_COMPILE
2165 class UMThunkMarshInfo;
2167 #ifdef FEATURE_COMINTEROP
2168 struct ComPlusCallInfo;
2169 #endif // FEATURE_COMINTEROP
2171 class DelegateEEClass : public EEClass
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;
2184 #ifdef FEATURE_COMINTEROP
2185 ComPlusCallInfo *m_pComPlusCallInfo;
2186 #endif // FEATURE_COMINTEROP
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.
2192 MethodDesc* m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2193 MethodDesc* m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2195 PTR_MethodDesc GetInvokeMethod()
2197 return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2200 PTR_MethodDesc GetBeginInvokeMethod()
2202 return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2205 PTR_MethodDesc GetEndInvokeMethod()
2207 return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2210 #ifndef DACCESS_COMPILE
2211 DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2213 LIMITED_METHOD_CONTRACT;
2214 // Note: Memory allocated on loader heap is zero filled
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
2224 typedef DPTR(ArrayClass) PTR_ArrayClass;
2227 // Dynamically generated array class structure
2228 class ArrayClass : public EEClass
2230 #ifdef FEATURE_PREJIT
2231 friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2234 friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2236 #ifndef DACCESS_COMPILE
2237 ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2239 friend class NativeImageDumper;
2244 unsigned char m_rank;
2245 CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd
2249 LIMITED_METHOD_CONTRACT;
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;
2261 CorElementType GetArrayElementType() {
2262 LIMITED_METHOD_CONTRACT;
2263 return m_ElementType;
2265 void SetArrayElementType(CorElementType ElementType) {
2266 LIMITED_METHOD_CONTRACT;
2267 m_ElementType = ElementType;
2271 // Allocate a new MethodDesc for the methods we add to this class
2272 void InitArrayMethodDesc(
2273 ArrayMethodDesc* pNewMD,
2274 PCCOR_SIGNATURE pShortSig,
2277 LoaderAllocator *pLoaderAllocator,
2278 AllocMemTracker *pamTracker);
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
2295 inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2297 LIMITED_METHOD_CONTRACT;
2298 _ASSERTE(HasLayout());
2299 return &((LayoutEEClass *) this)->m_LayoutInfo;
2302 inline BOOL EEClass::IsBlittable()
2304 LIMITED_METHOD_CONTRACT;
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());
2311 inline BOOL EEClass::IsManagedSequential()
2313 LIMITED_METHOD_CONTRACT;
2314 return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2317 inline BOOL EEClass::HasExplicitSize()
2319 LIMITED_METHOD_CONTRACT;
2320 return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2323 //==========================================================================
2324 // These routines manage the prestub (a bootstrapping stub that all
2325 // FunctionDesc's are initialized with.)
2326 //==========================================================================
2327 VOID InitPreStubManager();
2329 EXTERN_C void STDCALL ThePreStub();
2331 inline PCODE GetPreStubEntryPoint()
2333 return GetEEFuncEntryPoint(ThePreStub);
2336 #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2338 EXTERN_C void STDCALL ThePreStubCompactARM();
2340 inline PCODE GetPreStubCompactARMEntryPoint()
2342 return GetEEFuncEntryPoint(ThePreStubCompactARM);
2345 #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2347 PCODE TheUMThunkPreStub();
2349 PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
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) )
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).
2362 #define METH_NAME_CACHE_SIZE 5
2363 #define MAX_MISSES 3
2365 #ifdef EnC_SUPPORTED
2367 struct EnCAddedFieldElement;
2369 #endif // EnC_SUPPORTED
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
2381 PTR_FieldDesc m_pFieldDescList;
2387 INSTANCE_FIELDS = 0x1,
2388 STATIC_FIELDS = 0x2,
2389 ALL_FIELDS = (INSTANCE_FIELDS | STATIC_FIELDS)
2391 ApproxFieldDescIterator();
2392 ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2395 Init(pMT, iteratorType);
2397 void Init(MethodTable *pMT, int iteratorType);
2398 PTR_FieldDesc Next();
2400 int GetIteratorType() {
2401 LIMITED_METHOD_CONTRACT;
2403 return m_iteratorType;
2407 LIMITED_METHOD_CONTRACT;
2408 return m_totalFields;
2410 int CountRemaining() {
2411 LIMITED_METHOD_CONTRACT;
2413 return m_totalFields - m_currField - 1;
2418 // DeepFieldDescIterator iterates over the entire
2419 // set of fields available to a class, inherited or
2423 class DeepFieldDescIterator
2426 ApproxFieldDescIterator m_fieldIter;
2429 MethodTable* m_classes[16];
2430 int m_deepTotalFields;
2431 bool m_lastNextFromParentClass;
2436 DeepFieldDescIterator()
2438 LIMITED_METHOD_CONTRACT;
2442 m_deepTotalFields = 0;
2443 m_lastNextFromParentClass = false;
2445 DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2446 bool includeParents = true)
2448 WRAPPER_NO_CONTRACT;
2450 Init(pMT, iteratorType, includeParents);
2452 void Init(MethodTable* pMT, int iteratorType,
2453 bool includeParents = true);
2457 bool Skip(int numSkip);
2461 LIMITED_METHOD_CONTRACT;
2462 return m_deepTotalFields;
2464 bool IsFieldFromParentClass()
2466 LIMITED_METHOD_CONTRACT;
2467 return m_lastNextFromParentClass;