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.
19 // NOTE: Even though EEClass is considered to contain cold data (relative to MethodTable), these data
20 // structures *are* touched (especially during startup as part of soft-binding). As a result, and given the
21 // number of EEClasses allocated for large assemblies, the size of this structure can have a direct impact on
22 // performance, especially startup performance.
24 // Given that the data itself is touched infrequently, we can trade off space reduction against cpu-usage to
25 // good effect here. A fair amount of work has gone into reducing the size of each EEClass instance (see
26 // EEClassOptionalFields and EEClassPackedFields) at the expense of somewhat more convoluted runtime access.
28 // Please consider this (and measure the impact of your changes against startup scenarios) before adding
29 // fields to EEClass or otherwise increasing its size.
31 // ============================================================================
39 #include "eecontract.h"
46 #include "objecthandle.h"
49 #ifdef FEATURE_COMINTEROP
50 #include "stdinterfaces.h"
54 #include "typehandle.h"
55 #include "perfcounters.h"
56 #include "methodtable.h"
59 #include "iterator_util.h"
61 #ifdef FEATURE_COMINTEROP
62 #include "..\md\winmd\inc\adapter.h"
64 #include "packedfields.inl"
66 #define IBCLOG(x) g_IBCLogger.##x
68 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
73 #define MAX_LOG2_PRIMITIVE_FIELD_SIZE 3
75 #define MAX_PRIMITIVE_FIELD_SIZE (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
78 * Forward declarations
82 class ArrayMethodDesc;
85 class DictionaryLayout;
86 class DomainLocalBlock;
87 class FCallMethodDesc;
92 struct LayoutRawFieldInfo;
95 class MethodDescChunk;
98 struct ModuleCtorInfo;
104 class StackingAllocator;
105 class AllocMemTracker;
106 class InteropMethodTableSlotDataMap;
107 class LoadingEntry_LockHolder;
108 class DispatchMapBuilder;
109 class LoaderAllocator;
110 class ComCallWrapperTemplate;
112 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
115 //---------------------------------------------------------------------------------
116 // Fields in an explicit-layout class present varying degrees of risk depending
117 // on how they overlap.
119 // Each level is a superset of the lower (in numerical value) level - i.e.
120 // all kVerifiable fields are also kLegal, but not vice-versa.
121 //---------------------------------------------------------------------------------
122 class ExplicitFieldTrust
127 // Note: order is important here - each guarantee also implicitly guarantees all promises
128 // made by values lower in number.
130 // What's guaranteed. What the loader does.
131 //----- ----------------------- -------------------------------
132 kNone = 0, // no guarantees at all - Type refuses to load at all.
133 kLegal = 1, // guarantees no objref <-> scalar overlap and no unaligned objref - Type loads but field access won't verify
134 kVerifiable = 2, // guarantees no objref <-> objref overlap and all guarantees above - Type loads and field access will verify
135 kNonOverLayed = 3, // guarantees no overlap at all and all guarantees above - Type loads, field access verifies and Equals() may be optimized if structure is tightly packed
137 kMaxTrust = kNonOverLayed,
142 //----------------------------------------------------------------------------------------------
143 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
144 // into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
145 // class. This abstraction enforces the rule that the overall class is only as trustworthy as
146 // the least trustworthy field.
147 //----------------------------------------------------------------------------------------------
148 class ExplicitClassTrust : private ExplicitFieldTrust
153 LIMITED_METHOD_CONTRACT;
154 m_trust = kMaxTrust; // Yes, we start out with maximal trust. This reflects that explicit layout structures with no fields do represent no risk.
157 VOID AddField(TrustLevel fieldTrust)
159 LIMITED_METHOD_CONTRACT;
160 m_trust = min(m_trust, fieldTrust);
165 LIMITED_METHOD_CONTRACT;
166 return m_trust >= kLegal;
171 LIMITED_METHOD_CONTRACT;
172 return m_trust >= kVerifiable;
175 BOOL IsNonOverLayed()
177 LIMITED_METHOD_CONTRACT;
178 return m_trust >= kNonOverLayed;
181 TrustLevel GetTrustLevel()
183 LIMITED_METHOD_CONTRACT;
191 //----------------------------------------------------------------------------------------------
192 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
193 // into this function, this class will collect trust information about individual fields to be later
194 // aggregated into the overall class level.
196 // This abstraction enforces the rule that all fields are presumed guilty until explicitly declared
197 // safe by calling SetTrust(). If you fail to call SetTrust before leaving the block, the destructor
198 // will automatically cause the entire class to be declared illegal (and you will get an assert
199 // telling you to fix this bug.)
200 //----------------------------------------------------------------------------------------------
201 class ExplicitFieldTrustHolder : private ExplicitFieldTrust
204 ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
206 LIMITED_METHOD_CONTRACT;
207 m_pExplicitClassTrust = pExplicitClassTrust;
209 m_trustDeclared = FALSE;
211 m_fieldTrust = kNone;
214 VOID SetTrust(TrustLevel fieldTrust)
216 LIMITED_METHOD_CONTRACT;
218 _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
219 _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
222 m_trustDeclared = TRUE;
224 m_fieldTrust = fieldTrust;
227 ~ExplicitFieldTrustHolder()
229 LIMITED_METHOD_CONTRACT;
230 // If no SetTrust() was ever called, we will default to kNone (i.e. declare the entire type
231 // illegal.) It'd be nice to assert here but since this case can be legitimately reached
232 // on exception unwind, we cannot.
233 m_pExplicitClassTrust->AddField(m_fieldTrust);
238 ExplicitClassTrust* m_pExplicitClassTrust;
239 TrustLevel m_fieldTrust;
241 BOOL m_trustDeclared; // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
245 //*******************************************************************************
246 // Enumerator to traverse the interface declarations of a type, automatically building
247 // a substitution chain on the stack.
248 class InterfaceImplEnum
251 HENUMInternalHolder hEnumInterfaceImpl;
252 const Substitution *m_pSubstChain;
253 Substitution m_CurrSubst;
256 InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
257 : hEnumInterfaceImpl(pModule->GetMDImport())
261 hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
262 m_pSubstChain = pSubstChain;
266 // S_OK ... if has next (TRUE)
267 // S_FALSE ... if does not have next (FALSE)
274 if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
279 IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
280 m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
283 const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
284 mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
287 #ifdef FEATURE_COMINTEROP
289 // Class used to map MethodTable slot numbers to COM vtable slots numbers
290 // (either for calling a classic COM component or for constructing a classic COM
291 // vtable via which COM components can call managed classes). This structure is
292 // embedded in the EEClass but the mapping list itself is only allocated if the
293 // COM vtable is sparse.
296 class SparseVTableMap
299 #ifdef DACCESS_COMPILE
300 friend class NativeImageDumper;
306 // First run through MT slots calling RecordGap wherever a gap in VT slots
308 void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
310 // Then call FinalizeMapping to create the actual mapping list.
311 void FinalizeMapping(WORD TotalMTSlots);
313 // Map MT to VT slot.
314 WORD LookupVTSlot(WORD MTSlot);
316 // Retrieve the number of slots in the vtable (both empty and full).
317 WORD GetNumVTableSlots();
319 const void* GetMapList()
321 LIMITED_METHOD_CONTRACT;
322 return (void*)m_MapList;
325 #ifdef FEATURE_PREJIT
326 // Methods to persist structure
327 void Save(DataImage *image);
328 void Fixup(DataImage *image);
329 #endif // FEATURE_PREJIT
333 enum { MapGrow = 4 };
337 WORD m_Start; // Starting MT slot number
338 WORD m_Span; // # of consecutive slots that map linearly
339 WORD m_MapTo; // Starting VT slot number
342 Entry *m_MapList; // Pointer to array of Entry structures
343 WORD m_MapEntries; // Number of entries in above
344 WORD m_Allocated; // Number of entries allocated
346 WORD m_LastUsed; // Index of last entry used in successful lookup
348 WORD m_VTSlot; // Current VT slot number, used during list build
349 WORD m_MTSlot; // Current MT slot number, used during list build
351 void AllocOrExpand(); // Allocate or expand the mapping list for a new entry
353 #endif // FEATURE_COMINTEROP
355 //=======================================================================
356 // Adjunct to the EEClass structure for classes w/ layout
357 //=======================================================================
358 class EEClassLayoutInfo
360 static VOID CollectLayoutFieldMetadataThrowing(
361 mdTypeDef cl, // cl of the NStruct being loaded
362 BYTE packingSize, // packing size (from @dll.struct)
363 BYTE nlType, // nltype (from @dll.struct)
364 #ifdef FEATURE_COMINTEROP
365 BOOL isWinRT, // Is the type a WinRT type
366 #endif // FEATURE_COMINTEROP
367 BOOL fExplicitOffsets, // explicit offsets?
368 MethodTable *pParentMT, // the loaded superclass
369 ULONG cMembers, // total number of members (methods + fields)
370 HENUMInternal *phEnumField, // enumerator for field
371 Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
372 const SigTypeContext *pTypeContext, // Type parameters for NStruct being loaded
373 EEClassLayoutInfo *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
374 LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in. Needs room for cMember+1 elements
375 LoaderAllocator * pAllocator,
376 AllocMemTracker *pamTracker
380 friend class ClassLoader;
381 friend class EEClass;
382 friend class MethodTableBuilder;
383 #ifdef DACCESS_COMPILE
384 friend class NativeImageDumper;
388 // size (in bytes) of fixed portion of NStruct.
389 UINT32 m_cbNativeSize;
390 UINT32 m_cbManagedSize;
393 // 1,2,4 or 8: this is equal to the largest of the alignment requirements
394 // of each of the EEClass's members. If the NStruct extends another NStruct,
395 // the base NStruct is treated as the first member for the purpose of
397 BYTE m_LargestAlignmentRequirementOfAllMembers;
399 // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
400 // for the managed layout.
401 BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
405 // TRUE if the GC layout of the class is bit-for-bit identical
406 // to its unmanaged counterpart (i.e. no internal reference fields,
407 // no ansi-unicode char conversions required, etc.) Used to
408 // optimize marshaling.
410 // Post V1.0 addition: Is this type also sequential in managed memory?
411 e_MANAGED_SEQUENTIAL = 0x02,
412 // When a sequential/explicit type has no fields, it is conceptually
413 // zero-sized, but actually is 1 byte in length. This holds onto this
414 // fact and allows us to revert the 1 byte of padding when another
415 // explicit type inherits from this type.
417 // The size of the struct is explicitly specified in the meta-data.
418 e_HAS_EXPLICIT_SIZE = 0x08,
419 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
421 #error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
422 #endif // FEATURE_HFA
423 e_NATIVE_PASS_IN_REGISTERS = 0x10, // Flag wheter a native struct is passed in registers.
424 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
426 // HFA type of the unmanaged layout
434 // Packing size in bytes (1, 2, 4, 8 etc.)
435 BYTE m_cbPackingSize;
437 // # of fields that are of the calltime-marshal variety.
440 // An array of FieldMarshaler data blocks, used to drive call-time
441 // marshaling of NStruct reference parameters. The number of elements
442 // equals m_numCTMFields.
443 FieldMarshaler *m_pFieldMarshalers;
447 BOOL GetNativeSize() const
449 LIMITED_METHOD_CONTRACT;
450 return m_cbNativeSize;
453 UINT32 GetManagedSize() const
455 LIMITED_METHOD_CONTRACT;
456 return m_cbManagedSize;
460 BYTE GetLargestAlignmentRequirementOfAllMembers() const
462 LIMITED_METHOD_CONTRACT;
463 return m_LargestAlignmentRequirementOfAllMembers;
466 UINT GetNumCTMFields() const
468 LIMITED_METHOD_CONTRACT;
469 return m_numCTMFields;
472 FieldMarshaler *GetFieldMarshalers() const
474 LIMITED_METHOD_CONTRACT;
475 return m_pFieldMarshalers;
478 BOOL IsBlittable() const
480 LIMITED_METHOD_CONTRACT;
481 return (m_bFlags & e_BLITTABLE) == e_BLITTABLE;
484 BOOL IsManagedSequential() const
486 LIMITED_METHOD_CONTRACT;
487 return (m_bFlags & e_MANAGED_SEQUENTIAL) == e_MANAGED_SEQUENTIAL;
490 // If true, this says that the type was originally zero-sized
491 // and the native size was bumped up to one for similar behaviour
492 // to C++ structs. However, it is necessary to keep track of this
493 // so that we can ignore the one byte padding if other types derive
494 // from this type, that we can
495 BOOL IsZeroSized() const
497 LIMITED_METHOD_CONTRACT;
498 return (m_bFlags & e_ZERO_SIZED) == e_ZERO_SIZED;
501 BOOL HasExplicitSize() const
503 LIMITED_METHOD_CONTRACT;
504 return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE;
507 DWORD GetPackingSize() const
509 LIMITED_METHOD_CONTRACT;
510 return m_cbPackingSize;
513 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
514 bool IsNativeStructPassedInRegisters()
516 LIMITED_METHOD_CONTRACT;
517 return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
519 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
524 LIMITED_METHOD_CONTRACT;
525 return (m_bFlags & (e_R4_HFA | e_R8_HFA)) != 0;
528 CorElementType GetNativeHFAType()
530 LIMITED_METHOD_CONTRACT;
532 return (m_bFlags & e_R4_HFA) ? ELEMENT_TYPE_R4 : ELEMENT_TYPE_R8;
533 return ELEMENT_TYPE_END;
538 void SetIsBlittable(BOOL isBlittable)
540 LIMITED_METHOD_CONTRACT;
541 m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
542 : (m_bFlags & ~e_BLITTABLE);
545 void SetIsManagedSequential(BOOL isManagedSequential)
547 LIMITED_METHOD_CONTRACT;
548 m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
549 : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
552 void SetIsZeroSized(BOOL isZeroSized)
554 LIMITED_METHOD_CONTRACT;
555 m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
556 : (m_bFlags & ~e_ZERO_SIZED);
559 void SetHasExplicitSize(BOOL hasExplicitSize)
561 LIMITED_METHOD_CONTRACT;
562 m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
563 : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
567 void SetNativeHFAType(CorElementType hfaType)
569 LIMITED_METHOD_CONTRACT;
570 m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA;
573 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
574 void SetNativeStructPassedInRegisters()
576 LIMITED_METHOD_CONTRACT;
577 m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
579 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
586 // This structure is used only when the classloader is building the interface map. Before the class
587 // is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
588 // for this class/interface by the metadata - inherited interfaces will not be present if they are
589 // not specifically declared.
591 // This structure is destroyed after resolving has completed.
595 // The interface method table; for instantiated interfaces, this is the generic interface
596 MethodTable *m_pMethodTable;
597 } BuildingInterfaceInfo_t;
601 // We should not need to touch anything in here once the classes are all loaded, unless we
602 // are doing reflection. Try to avoid paging this data structure in.
605 // Size of hash bitmap for method names
606 #define METHOD_HASH_BYTES 8
608 // Hash table size - prime number
609 #define METHOD_HASH_BITS 61
612 // These are some macros for forming fully qualified class names for a class.
613 // These are abstracted so that we can decide later if a max length for a
614 // class name is acceptable.
616 // It doesn't make any sense not to have a small but usually quite capable
617 // stack buffer to build class names into. Most class names that I can think
618 // of would fit in 128 characters, and that's a pretty small amount of stack
619 // to use in exchange for not having to new and delete the memory.
620 #define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4)
622 #define DefineFullyQualifiedNameForClass() \
623 ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
624 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
626 #define DefineFullyQualifiedNameForClassOnStack() \
627 ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
628 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
630 #define DefineFullyQualifiedNameForClassW() \
631 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
633 #define DefineFullyQualifiedNameForClassWOnStack() \
634 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
636 #define GetFullyQualifiedNameForClassNestedAware(pClass) \
637 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
639 #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
640 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
642 #define GetFullyQualifiedNameForClass(pClass) \
643 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
645 #define GetFullyQualifiedNameForClassW(pClass) \
646 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
648 #define GetFullyQualifiedNameForClassW_WinRT(pClass) \
649 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
651 #define GetFullyQualifiedNameForClass_WinRT(pClass) \
652 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
654 // Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to
655 // save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached
656 // via the m_rpOptionalFields field EEClass (use the GetOptionalFields() accessor rather than the field
658 class EEClassOptionalFields
660 // All fields here are intentionally private. Use the corresponding accessor on EEClass instead (this
661 // makes it easier to add and remove fields from the optional section in the future). We make exceptions
662 // for MethodTableBuilder and NativeImageDumper, which need raw field-level access.
663 friend class EEClass;
664 friend class MethodTableBuilder;
665 #ifdef DACCESS_COMPILE
666 friend class NativeImageDumper;
670 // GENERICS RELATED FIELDS.
673 // If IsSharedByGenericInstantiations(), layout of handle dictionary for generic type
674 // (the last dictionary pointed to from PerInstInfo). Otherwise NULL.
675 PTR_DictionaryLayout m_pDictLayout;
677 // Variance info for each type parameter (gpNonVariant, gpCovariant, or gpContravariant)
678 // If NULL, this type has no type parameters that are co/contravariant
679 RelativePointer<PTR_BYTE> m_pVarianceInfo;
682 // COM RELATED FIELDS.
685 #ifdef FEATURE_COMINTEROP
686 SparseVTableMap *m_pSparseVTableMap;
688 TypeHandle m_pCoClassForIntf; // @TODO: Coclass for an interface
690 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
691 // Points to activation information if the type is an activatable COM/WinRT class.
692 ClassFactoryBase *m_pClassFactory;
693 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
695 WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
697 #endif // FEATURE_COMINTEROP
703 #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
704 DWORD m_cbModuleDynamicID;
706 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
707 // Number of eightBytes in the following arrays
708 int m_numberEightBytes;
709 // Classification of the eightBytes
710 SystemVClassificationType m_eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
711 // Size of data the eightBytes
712 unsigned int m_eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
713 #endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
715 // Set default values for optional fields.
718 PTR_BYTE GetVarianceInfo()
720 LIMITED_METHOD_DAC_CONTRACT;
722 return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
725 typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
728 // Another mechanism used to reduce the size of the average EEClass instance is the notion of packed fields.
729 // This is based on the observation that EEClass has a large number of integer fields that typically contain
730 // small values and that are fixed once class layout has completed. We can compact these fields by discarding
731 // the leading zero bits (and for small values there'll be a lot of these) and packing the significant data
732 // into compact bitfields. This is a dynamic operation (the exact packing used depends on the exact data
733 // stored in the fields).
735 // The PackedDWORDFields<> class (defined in PackedFields.inl) encapsulates this. It takes one template
736 // parameter, the number of fields to pack, and provides operations to get and set those fields until we're
737 // happy with the values, at which point it will compact them for us.
739 // The packed fields themselves are stored at the end of the EEClass instance (or the LayoutEEClass or the
740 // DelegateEEClass etc.) so we can take advantage of the variable sized nature of the fields. We gain nothing for
741 // runtime allocated EEClasses (we have to allocate a maximally sized structure for the packed fields because
742 // we can't tell at the beginning of EEClass layout what the field values will be). But in the ngen scenario
743 // we can compact the fields just prior to saving and only store the portion of the EEClass that is relvant,
744 // helping us with our goal of packing all the EEClass instances together as tightly as possible.
746 // Since each packed field is now accessed via an array-like index, we give each of those indices a name with
747 // the enum below to make the code more readable.
752 EEClass_Field_NumInstanceFields = 0,
753 EEClass_Field_NumMethods,
754 EEClass_Field_NumStaticFields,
755 EEClass_Field_NumHandleStatics,
756 EEClass_Field_NumBoxedStatics,
757 EEClass_Field_NonGCStaticFieldBytes,
758 EEClass_Field_NumThreadStaticFields,
759 EEClass_Field_NumHandleThreadStatics,
760 EEClass_Field_NumBoxedThreadStatics,
761 EEClass_Field_NonGCThreadStaticFieldBytes,
762 EEClass_Field_NumNonVirtualSlots,
766 typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
767 typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
770 // For most types there is a one-to-one mapping between MethodTable* and EEClass*
771 // However this is not the case for instantiated types where code and representation
772 // are shared between compatible instantiations (e.g. List<string> and List<object>)
773 // Then a single EEClass structure is shared between multiple MethodTable structures
774 // Uninstantiated generic types (e.g. List) have their own EEClass and MethodTable,
775 // used (a) as a representative for the generic type itself, (b) for static fields and
776 // methods, which aren't present in the instantiations, and (c) to hold some information
777 // (e.g. formal instantiations of superclass and implemented interfaces) that is common
778 // to all instantiations and isn't stored in the EEClass structures for instantiated types
781 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
783 // A word about EEClass vs. MethodTable
784 // ------------------------------------
786 // At compile-time, we are happy to touch both MethodTable and EEClass. However,
787 // at runtime we want to restrict ourselves to the MethodTable. This is critical
788 // for common code paths, where we want to keep the EEClass out of our working
789 // set. For uncommon code paths, like throwing exceptions or strange Contexts
790 // issues, it's okay to access the EEClass.
792 // To this end, the TypeHandle (CLASS_HANDLE) abstraction is now based on the
793 // MethodTable pointer instead of the EEClass pointer. If you are writing a
794 // runtime helper that calls GetClass() to access the associated EEClass, please
795 // stop to wonder if you are making a mistake.
797 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
800 // An code:EEClass is a representation of the part of a managed type that is not used very frequently (it is
801 // cold), and thus is segregated from the hot portion (which lives in code:MethodTable). As noted above an
802 // it is also the case that EEClass is SHARED among all instantiations of a generic type, so anything that
803 // is specific to a paritcular type can not live off the EEClass.
805 // From here you can get to
806 // code:MethodTable - The representation of the hot portion of a type.
807 // code:MethodDesc - The representation of a method
808 // code:FieldDesc - The representation of a field.
810 // EEClasses hold the following important fields
811 // * code:EEClass.m_pMethodTable - Points a MethodTable associated with
812 // * code:EEClass.m_pChunks - a list of code:MethodDescChunk which is simply a list of code:MethodDesc
813 // which represent the methods.
814 // * code:EEClass.m_pFieldDescList - a list of fields in the type.
816 class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
818 /************************************
820 ************************************/
821 // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
822 // USE ACCESSORS TO READ/WRITE private field members
824 // To access bmt stuff
825 friend class MethodTable;
826 friend class MethodTableBuilder;
827 friend class FieldDesc;
828 friend class CheckAsmOffsets;
829 friend class ClrDataAccess;
830 #ifdef DACCESS_COMPILE
831 friend class NativeImageDumper;
834 /************************************
835 * PUBLIC INSTANCE METHODS
836 ************************************/
841 LIMITED_METHOD_CONTRACT;
842 return IsTdSealed(m_dwAttrClass);
845 inline DWORD IsInterface()
848 return IsTdInterface(m_dwAttrClass);
851 inline DWORD IsAbstract()
854 return IsTdAbstract(m_dwAttrClass);
857 BOOL HasExplicitFieldOffsetLayout()
860 return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
863 BOOL HasSequentialLayout()
866 return IsTdSequentialLayout(GetAttrClass());
868 BOOL IsSerializable()
871 return IsTdSerializable(GetAttrClass());
873 BOOL IsBeforeFieldInit()
876 return IsTdBeforeFieldInit(GetAttrClass());
879 DWORD GetProtection()
882 return (m_dwAttrClass & tdVisibilityMask);
885 // class is blittable
888 #ifndef DACCESS_COMPILE
889 void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
890 void Destruct(MethodTable * pMT);
892 static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
893 #endif // !DACCESS_COMPILE
896 // Add a new method to an already loaded type for EnC
897 static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
899 // Add a new field to an already loaded type for EnC
900 static HRESULT AddField(MethodTable * pMT, mdFieldDef fieldDesc, EnCFieldDesc **pAddedField);
901 static VOID FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdFieldDef fieldDef);
902 #endif // EnC_SUPPORTED
904 inline DWORD IsComImport()
907 return IsTdImport(m_dwAttrClass);
910 #ifdef FEATURE_PREJIT
913 void Save(DataImage *image, MethodTable *pMT);
914 void Fixup(DataImage *image, MethodTable *pMT);
915 #endif // FEATURE_PREJIT
917 EEClassLayoutInfo *GetLayoutInfo();
919 #ifdef DACCESS_COMPILE
920 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
923 static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
925 /************************************
926 * INSTANCE MEMBER VARIABLES
927 ************************************/
930 inline LPCUTF8 GetDebugClassName ()
932 LIMITED_METHOD_CONTRACT;
933 return m_szDebugClassName;
935 inline void SetDebugClassName (LPCUTF8 szDebugClassName)
937 LIMITED_METHOD_CONTRACT;
938 m_szDebugClassName = szDebugClassName;
942 * Controls debugging breaks and output if a method class
943 * is mentioned in the registry ("BreakOnClassBuild")
944 * Method layout within this class can cause a debug
945 * break by setting "BreakOnMethodName". Not accessible
951 #ifdef FEATURE_COMINTEROP
953 * Used to map MethodTable slots to VTable slots
955 inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
957 LIMITED_METHOD_CONTRACT;
958 return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
960 inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
962 LIMITED_METHOD_CONTRACT;
963 _ASSERTE(HasOptionalFields());
964 GetOptionalFields()->m_pSparseVTableMap = map;
966 #endif // FEATURE_COMINTEROP
970 * Maintain back pointer to statcally hot portion of EEClass.
971 * For an EEClass representing multiple instantiations of a generic type, this is the method table
972 * for the first instantiation requested and is the only one containing entries for non-virtual instance methods
973 * (i.e. non-vtable entries).
976 // Note that EEClass structures may be shared between generic instantiations
977 // (see IsSharedByGenericInstantiations). In these cases EEClass::GetMethodTable
978 // will return the method table pointer corresponding to the "canonical"
979 // instantiation, as defined in typehandle.h.
981 inline PTR_MethodTable GetMethodTable()
983 LIMITED_METHOD_CONTRACT;
986 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
989 // DO NOT ADD ANY ASSERTS TO THIS METHOD.
990 // DO NOT USE THIS METHOD.
991 // Yes folks, for better or worse the debugger pokes supposed object addresses
992 // to try to see if objects are valid, possibly firing an AccessViolation or worse,
993 // and then catches the AV and reports a failure to the debug client. This makes
994 // the debugger slightly more robust should any corrupted object references appear
995 // in a session. Thus it is "correct" behaviour for this to AV when used with
996 // an invalid object pointer, and incorrect behaviour for it to
998 inline PTR_MethodTable GetMethodTableWithPossibleAV()
1000 CANNOT_HAVE_CONTRACT;
1003 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1006 #ifndef DACCESS_COMPILE
1007 inline void SetMethodTable(MethodTable* pMT)
1009 LIMITED_METHOD_CONTRACT;
1010 m_pMethodTable.SetValueMaybeNull(pMT);
1012 #endif // !DACCESS_COMPILE
1015 * Number of fields in the class, including inherited fields.
1016 * Does not include fields added from EnC.
1018 inline WORD GetNumInstanceFields()
1020 LIMITED_METHOD_CONTRACT;
1022 return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1025 inline void SetNumInstanceFields (WORD wNumInstanceFields)
1027 LIMITED_METHOD_CONTRACT;
1028 SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1032 * Number of static fields declared in this class.
1033 * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1035 inline WORD GetNumStaticFields()
1037 LIMITED_METHOD_CONTRACT;
1039 return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1041 inline void SetNumStaticFields (WORD wNumStaticFields)
1043 LIMITED_METHOD_CONTRACT;
1044 SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1047 inline WORD GetNumThreadStaticFields()
1049 LIMITED_METHOD_CONTRACT;
1051 return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1054 inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1056 LIMITED_METHOD_CONTRACT;
1057 SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1060 // Statics are stored in a big chunk inside the module
1062 inline DWORD GetModuleDynamicID()
1064 LIMITED_METHOD_CONTRACT;
1066 return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1069 inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1071 LIMITED_METHOD_CONTRACT;
1072 _ASSERTE(HasOptionalFields());
1073 GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
1077 * Difference between the InterfaceMap ptr and Vtable in the
1078 * MethodTable used to indicate the number of static bytes
1079 * Now interfaceMap ptr can be optional hence we store it here
1081 inline DWORD GetNonGCRegularStaticFieldBytes()
1083 LIMITED_METHOD_CONTRACT;
1084 return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1086 inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1088 LIMITED_METHOD_CONTRACT;
1089 SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1092 inline DWORD GetNonGCThreadStaticFieldBytes()
1094 LIMITED_METHOD_CONTRACT;
1095 return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1097 inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1099 LIMITED_METHOD_CONTRACT;
1100 SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1103 inline WORD GetNumNonVirtualSlots()
1105 LIMITED_METHOD_CONTRACT;
1106 return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1108 inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1110 LIMITED_METHOD_CONTRACT;
1111 SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1114 inline BOOL IsEquivalentType()
1116 LIMITED_METHOD_CONTRACT;
1117 return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1120 #ifdef FEATURE_COMINTEROP
1121 inline void SetIsEquivalentType()
1123 LIMITED_METHOD_CONTRACT;
1124 m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1129 * Number of static handles allocated
1131 inline WORD GetNumHandleRegularStatics ()
1133 LIMITED_METHOD_CONTRACT;
1134 return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1136 inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1138 LIMITED_METHOD_CONTRACT;
1139 SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1143 * Number of static handles allocated for ThreadStatics
1145 inline WORD GetNumHandleThreadStatics ()
1147 LIMITED_METHOD_CONTRACT;
1148 return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1150 inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1152 LIMITED_METHOD_CONTRACT;
1153 SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1157 * Number of boxed statics allocated
1159 inline WORD GetNumBoxedRegularStatics ()
1161 LIMITED_METHOD_CONTRACT;
1162 return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1164 inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1166 LIMITED_METHOD_CONTRACT;
1167 SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1171 * Number of boxed statics allocated for ThreadStatics
1173 inline WORD GetNumBoxedThreadStatics ()
1175 LIMITED_METHOD_CONTRACT;
1176 return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1178 inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1180 LIMITED_METHOD_CONTRACT;
1181 SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
1185 * Number of bytes to subract from code:MethodTable::GetBaseSize() to get the actual number of bytes
1186 * of instance fields stored in the object on the GC heap.
1188 inline DWORD GetBaseSizePadding()
1190 LIMITED_METHOD_DAC_CONTRACT;
1191 return m_cbBaseSizePadding;
1193 inline void SetBaseSizePadding(DWORD dwPadding)
1195 LIMITED_METHOD_CONTRACT;
1196 _ASSERTE(FitsIn<BYTE>(dwPadding));
1197 m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1200 inline DWORD GetUnboxedNumInstanceFieldBytes()
1202 DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1204 _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1210 * Pointer to a list of FieldDescs declared in this class
1211 * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1214 #ifdef FEATURE_PREJIT
1215 static DWORD FieldDescListSize(MethodTable * pMT);
1218 inline PTR_FieldDesc GetFieldDescList()
1220 LIMITED_METHOD_DAC_CONTRACT;
1221 // Careful about using this method. If it's possible that fields may have been added via EnC, then
1222 // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1223 return m_pFieldDescList.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList));
1226 PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1228 #ifndef DACCESS_COMPILE
1229 inline void SetFieldDescList (FieldDesc* pFieldDescList)
1231 LIMITED_METHOD_CONTRACT;
1232 m_pFieldDescList.SetValue(pFieldDescList);
1234 #endif // !DACCESS_COMPILE
1236 inline WORD GetNumMethods()
1238 LIMITED_METHOD_DAC_CONTRACT;
1239 return (WORD)GetPackableField(EEClass_Field_NumMethods);
1241 inline void SetNumMethods (WORD wNumMethods)
1243 LIMITED_METHOD_CONTRACT;
1244 SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1248 * Cached metadata for this class (GetTypeDefProps)
1250 inline DWORD GetAttrClass()
1252 LIMITED_METHOD_CONTRACT;
1253 return m_dwAttrClass;
1255 inline void SetAttrClass (DWORD dwAttrClass)
1257 LIMITED_METHOD_CONTRACT;
1258 m_dwAttrClass = dwAttrClass;
1262 #ifdef FEATURE_COMINTEROP
1263 inline DWORD IsComClassInterface()
1265 LIMITED_METHOD_CONTRACT;
1266 return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1268 inline VOID SetIsComClassInterface()
1270 LIMITED_METHOD_CONTRACT;
1271 m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1273 inline void SetComEventItfType()
1275 LIMITED_METHOD_CONTRACT;
1276 _ASSERTE(IsInterface());
1277 m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1279 // class is a special COM event interface
1280 inline BOOL IsComEventItfType()
1282 LIMITED_METHOD_CONTRACT;
1283 return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1285 #endif // FEATURE_COMINTEROP
1288 inline DWORD IsDestroyed()
1290 LIMITED_METHOD_CONTRACT;
1291 return (m_wAuxFlags & AUXFLAG_DESTROYED);
1295 inline BOOL IsCritical()
1297 LIMITED_METHOD_CONTRACT;
1298 _ASSERTE(HasCriticalTransparentInfo());
1299 return (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) != VMFLAG_TRANSPARENCY_TRANSPARENT
1300 && !IsAllTransparent();
1303 inline BOOL IsTreatAsSafe()
1305 LIMITED_METHOD_CONTRACT;
1306 _ASSERTE(HasCriticalTransparentInfo());
1307 return (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) == VMFLAG_TRANSPARENCY_ALLCRITICAL_TAS ||
1308 (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) == VMFLAG_TRANSPARENCY_TAS_NOTCRITICAL
1312 inline BOOL IsAllTransparent()
1314 LIMITED_METHOD_CONTRACT;
1315 _ASSERTE(HasCriticalTransparentInfo());
1316 return (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) == VMFLAG_TRANSPARENCY_ALL_TRANSPARENT;
1319 inline BOOL IsAllCritical()
1321 LIMITED_METHOD_CONTRACT;
1322 _ASSERTE(HasCriticalTransparentInfo());
1323 return (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) == VMFLAG_TRANSPARENCY_ALLCRITICAL
1324 || (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) == VMFLAG_TRANSPARENCY_ALLCRITICAL_TAS;
1327 inline BOOL HasCriticalTransparentInfo()
1329 LIMITED_METHOD_CONTRACT;
1330 return (m_VMFlags & VMFLAG_TRANSPARENCY_MASK) != VMFLAG_TRANSPARENCY_UNKNOWN;
1333 void SetCriticalTransparentInfo(
1334 BOOL fIsTreatAsSafe,
1335 BOOL fIsAllTransparent,
1336 BOOL fIsAllCritical)
1338 WRAPPER_NO_CONTRACT;
1340 // TAS wihtout critical doesn't make sense - although it was allowed in the v2 desktop model,
1341 // so we need to allow it for compatibility reasons on the desktop.
1342 _ASSERTE(!fIsTreatAsSafe || fIsAllCritical);
1344 //if nothing is set, then we're transparent.
1345 unsigned flags = VMFLAG_TRANSPARENCY_TRANSPARENT;
1347 if (fIsAllTransparent)
1349 flags = VMFLAG_TRANSPARENCY_ALL_TRANSPARENT;
1351 else if (fIsAllCritical)
1353 flags = fIsTreatAsSafe ? VMFLAG_TRANSPARENCY_ALLCRITICAL_TAS :
1354 VMFLAG_TRANSPARENCY_ALLCRITICAL;
1358 flags = fIsTreatAsSafe ? VMFLAG_TRANSPARENCY_TAS_NOTCRITICAL :
1359 VMFLAG_TRANSPARENCY_TRANSPARENT;
1362 FastInterlockOr(EnsureWritablePages(&m_VMFlags), flags);
1364 _ASSERTE(HasCriticalTransparentInfo());
1366 inline DWORD IsUnsafeValueClass()
1368 LIMITED_METHOD_CONTRACT;
1369 return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1374 inline void SetUnsafeValueClass()
1376 LIMITED_METHOD_CONTRACT;
1377 m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1381 inline BOOL HasNoGuid()
1383 LIMITED_METHOD_CONTRACT;
1384 return (m_VMFlags & VMFLAG_NO_GUID);
1386 inline void SetHasNoGuid()
1388 WRAPPER_NO_CONTRACT;
1389 FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1394 inline void SetDoesNotHaveSuppressUnmanagedCodeAccessAttr()
1396 WRAPPER_NO_CONTRACT;
1397 FastInterlockOr(EnsureWritablePages(&m_VMFlags),VMFLAG_NOSUPPRESSUNMGDCODEACCESS);
1400 inline BOOL HasSuppressUnmanagedCodeAccessAttr()
1402 LIMITED_METHOD_CONTRACT;
1403 return !(m_VMFlags & VMFLAG_NOSUPPRESSUNMGDCODEACCESS);
1406 inline BOOL HasRemotingProxyAttribute()
1408 LIMITED_METHOD_CONTRACT;
1409 return m_VMFlags & VMFLAG_REMOTING_PROXY_ATTRIBUTE;
1411 inline void SetHasRemotingProxyAttribute()
1413 LIMITED_METHOD_CONTRACT;
1414 m_VMFlags |= (DWORD)VMFLAG_REMOTING_PROXY_ATTRIBUTE;
1416 inline BOOL IsAlign8Candidate()
1418 LIMITED_METHOD_CONTRACT;
1419 return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1421 inline void SetAlign8Candidate()
1423 LIMITED_METHOD_CONTRACT;
1424 m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1427 inline void SetDestroyed()
1429 LIMITED_METHOD_CONTRACT;
1430 m_wAuxFlags |= AUXFLAG_DESTROYED;
1433 inline void SetHasFixedAddressVTStatics()
1435 LIMITED_METHOD_CONTRACT;
1436 m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1438 #ifdef FEATURE_COMINTEROP
1439 void SetSparseForCOMInterop()
1441 LIMITED_METHOD_CONTRACT;
1442 m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1444 inline void SetProjectedFromWinRT()
1446 LIMITED_METHOD_CONTRACT;
1447 m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1449 inline void SetExportedToWinRT()
1451 LIMITED_METHOD_CONTRACT;
1452 m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1454 inline void SetMarshalingType(UINT32 mType)
1456 LIMITED_METHOD_CONTRACT;
1457 _ASSERTE(mType !=0);
1458 _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1461 case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1463 case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1465 case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1468 _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1471 #endif // FEATURE_COMINTEROP
1472 inline void SetHasLayout()
1474 LIMITED_METHOD_CONTRACT;
1475 m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT; //modified before the class is published
1477 inline void SetHasOverLayedFields()
1479 LIMITED_METHOD_CONTRACT;
1480 m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1482 inline void SetIsNested()
1484 LIMITED_METHOD_CONTRACT;
1485 m_VMFlags |= VMFLAG_ISNESTED;
1488 #ifdef FEATURE_READYTORUN
1489 inline BOOL HasLayoutDependsOnOtherModules()
1491 LIMITED_METHOD_CONTRACT;
1492 return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1495 inline void SetHasLayoutDependsOnOtherModules()
1497 LIMITED_METHOD_CONTRACT;
1498 m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1502 // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1503 inline BOOL IsDelegate()
1505 LIMITED_METHOD_CONTRACT;
1506 return m_VMFlags & VMFLAG_DELEGATE;
1508 inline void SetIsDelegate()
1510 LIMITED_METHOD_CONTRACT;
1511 m_VMFlags |= VMFLAG_DELEGATE;
1514 // This is only applicable to interfaces. This method does not
1515 // provide correct information for non-interface types.
1516 DWORD SomeMethodsRequireInheritanceCheck();
1517 void SetSomeMethodsRequireInheritanceCheck();
1519 BOOL HasFixedAddressVTStatics()
1521 LIMITED_METHOD_CONTRACT;
1522 return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1524 #ifdef FEATURE_COMINTEROP
1525 BOOL IsSparseForCOMInterop()
1527 LIMITED_METHOD_CONTRACT;
1528 return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1530 BOOL IsProjectedFromWinRT()
1532 LIMITED_METHOD_DAC_CONTRACT;
1533 return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1535 BOOL IsExportedToWinRT()
1537 LIMITED_METHOD_CONTRACT;
1538 return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1540 BOOL IsMarshalingTypeSet()
1542 LIMITED_METHOD_CONTRACT;
1543 return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1545 BOOL IsMarshalingTypeFreeThreaded()
1547 LIMITED_METHOD_CONTRACT;
1548 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1550 BOOL IsMarshalingTypeInhibit()
1552 LIMITED_METHOD_CONTRACT;
1553 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1555 BOOL IsMarshalingTypeStandard()
1557 LIMITED_METHOD_CONTRACT;
1558 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1560 #endif // FEATURE_COMINTEROP
1563 LIMITED_METHOD_CONTRACT;
1564 return m_VMFlags & VMFLAG_HASLAYOUT;
1566 BOOL HasOverLayedField()
1568 LIMITED_METHOD_CONTRACT;
1569 return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1573 LIMITED_METHOD_CONTRACT;
1574 return m_VMFlags & VMFLAG_ISNESTED;
1576 BOOL HasFieldsWhichMustBeInited()
1578 LIMITED_METHOD_CONTRACT;
1579 return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1581 void SetHasFieldsWhichMustBeInited()
1583 LIMITED_METHOD_CONTRACT;
1584 m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1586 void SetCannotBeBlittedByObjectCloner()
1590 DWORD HasNonPublicFields()
1592 LIMITED_METHOD_CONTRACT;
1593 return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1595 void SetHasNonPublicFields()
1597 LIMITED_METHOD_CONTRACT;
1598 m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1600 DWORD IsNotTightlyPacked()
1602 LIMITED_METHOD_CONTRACT;
1603 return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1605 void SetIsNotTightlyPacked()
1607 LIMITED_METHOD_CONTRACT;
1608 m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1610 DWORD ContainsMethodImpls()
1612 LIMITED_METHOD_CONTRACT;
1613 return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1615 void SetContainsMethodImpls()
1617 LIMITED_METHOD_CONTRACT;
1618 m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1622 BOOL IsManagedSequential();
1624 BOOL HasExplicitSize();
1626 static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1629 * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1632 // This is what would be used in the calling convention for this type.
1633 CorElementType GetInternalCorElementType()
1635 LIMITED_METHOD_DAC_CONTRACT;
1637 return CorElementType(m_NormType);
1639 void SetInternalCorElementType (CorElementType _NormType)
1641 LIMITED_METHOD_CONTRACT;
1642 m_NormType = static_cast<BYTE>(_NormType);
1646 * Chain of MethodDesc chunks for the MethodTable
1649 inline PTR_MethodDescChunk GetChunks();
1651 #ifndef DACCESS_COMPILE
1652 inline void SetChunks (MethodDescChunk* pChunks)
1654 LIMITED_METHOD_CONTRACT;
1655 m_pChunks.SetValueMaybeNull(pChunks);
1657 #endif // !DACCESS_COMPILE
1658 void AddChunk (MethodDescChunk* pNewChunk);
1660 void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1662 inline PTR_GuidInfo GetGuidInfo()
1664 LIMITED_METHOD_DAC_CONTRACT;
1666 return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1669 inline void SetGuidInfo(GuidInfo* pGuidInfo)
1671 WRAPPER_NO_CONTRACT;
1672 #ifndef DACCESS_COMPILE
1673 EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1674 #endif // DACCESS_COMPILE
1677 // Cached class level reliability contract info, see ConstrainedExecutionRegion.cpp for details.
1678 DWORD GetReliabilityContract();
1681 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
1682 // Get number of eightbytes used by a struct passed in registers.
1683 inline int GetNumberEightBytes()
1685 LIMITED_METHOD_CONTRACT;
1686 _ASSERTE(HasOptionalFields());
1687 return GetOptionalFields()->m_numberEightBytes;
1690 // Get eightbyte classification for the eightbyte with the specified index.
1691 inline SystemVClassificationType GetEightByteClassification(int index)
1693 LIMITED_METHOD_CONTRACT;
1694 _ASSERTE(HasOptionalFields());
1695 return GetOptionalFields()->m_eightByteClassifications[index];
1698 // Get size of the data in the eightbyte with the specified index.
1699 inline unsigned int GetEightByteSize(int index)
1701 LIMITED_METHOD_CONTRACT;
1702 _ASSERTE(HasOptionalFields());
1703 return GetOptionalFields()->m_eightByteSizes[index];
1706 // Set the eightByte classification
1707 inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1709 LIMITED_METHOD_CONTRACT;
1710 _ASSERTE(HasOptionalFields());
1711 GetOptionalFields()->m_numberEightBytes = eightByteCount;
1712 for (int i = 0; i < eightByteCount; i++)
1714 GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1715 GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1718 #endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
1720 #ifdef FEATURE_COMINTEROP
1721 inline TypeHandle GetCoClassForInterface()
1723 LIMITED_METHOD_CONTRACT;
1724 _ASSERTE(HasOptionalFields());
1725 return GetOptionalFields()->m_pCoClassForIntf;
1728 inline void SetCoClassForInterface(TypeHandle th)
1730 WRAPPER_NO_CONTRACT;
1731 _ASSERTE(HasOptionalFields());
1732 *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1735 inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1737 LIMITED_METHOD_CONTRACT;
1738 return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1739 : WinMDAdapter::RedirectedTypeIndex_Invalid;
1742 inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1744 LIMITED_METHOD_CONTRACT;
1745 _ASSERTE(HasOptionalFields());
1746 _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1747 GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1749 #endif // FEATURE_COMINTEROP
1751 inline UINT32 GetNativeSize()
1753 LIMITED_METHOD_DAC_CONTRACT;
1754 return m_cbNativeSize;
1756 static UINT32 GetOffsetOfNativeSize()
1758 LIMITED_METHOD_CONTRACT;
1759 return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1761 void SetNativeSize(UINT32 nativeSize)
1763 LIMITED_METHOD_CONTRACT;
1764 m_cbNativeSize = nativeSize;
1766 #ifdef FEATURE_COMINTEROP
1767 OBJECTHANDLE GetOHDelegate()
1769 LIMITED_METHOD_CONTRACT;
1770 return m_ohDelegate;
1772 void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1774 LIMITED_METHOD_CONTRACT;
1775 m_ohDelegate = _ohDelegate;
1777 // Set the COM interface type.
1778 CorIfaceAttr GetComInterfaceType()
1780 LIMITED_METHOD_CONTRACT;
1781 return m_ComInterfaceType;
1784 void SetComInterfaceType(CorIfaceAttr ItfType)
1786 WRAPPER_NO_CONTRACT;
1787 _ASSERTE(IsInterface());
1788 EnsureWritablePages(this);
1789 m_ComInterfaceType = ItfType;
1792 inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1794 LIMITED_METHOD_CONTRACT;
1795 return m_pccwTemplate;
1797 inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1799 WRAPPER_NO_CONTRACT;
1800 return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1803 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1804 inline ClassFactoryBase *GetComClassFactory()
1806 LIMITED_METHOD_CONTRACT;
1807 return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1809 inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1811 WRAPPER_NO_CONTRACT;
1812 _ASSERTE(HasOptionalFields());
1813 return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1815 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1816 #endif // FEATURE_COMINTEROP
1820 PTR_DictionaryLayout GetDictionaryLayout()
1823 WRAPPER_NO_CONTRACT;
1824 return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1827 void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1830 WRAPPER_NO_CONTRACT;
1831 _ASSERTE(HasOptionalFields());
1832 GetOptionalFields()->m_pDictLayout = pLayout;
1835 #ifndef DACCESS_COMPILE
1836 static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1838 LIMITED_METHOD_CONTRACT;
1839 if (pbVarianceInfo == NULL)
1840 return gpNonVariant;
1842 return (CorGenericParamAttr) (pbVarianceInfo[i]);
1845 CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1847 WRAPPER_NO_CONTRACT;
1848 return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1851 BYTE* GetVarianceInfo()
1853 LIMITED_METHOD_CONTRACT;
1854 return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1857 void SetVarianceInfo(BYTE *pVarianceInfo)
1859 LIMITED_METHOD_CONTRACT;
1860 _ASSERTE(HasOptionalFields());
1861 GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1863 #endif // !DACCESS_COMPILE
1865 // Check that a signature blob uses type parameters correctly
1866 // in accordance with the variance annotations specified by this class
1867 // The position parameter indicates the variance of the context we're in
1868 // (result type is gpCovariant, argument types are gpContravariant, deeper in a signature
1869 // we might be gpNonvariant e.g. in a pointer type or non-variant generic type)
1872 DWORD numGenericArgs,
1873 BYTE *pVarianceInfo,
1876 CorGenericParamAttr position);
1878 #if defined(CHECK_APP_DOMAIN_LEAKS) || defined(_DEBUG)
1881 AUXFLAG_APP_DOMAIN_AGILE = 0x00000001,
1882 AUXFLAG_CHECK_APP_DOMAIN_AGILE = 0x00000002,
1883 AUXFLAG_APP_DOMAIN_AGILITY_DONE = 0x00000004,
1884 AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1887 inline DWORD GetAuxFlagsRaw()
1889 LIMITED_METHOD_CONTRACT;
1892 inline DWORD* GetAuxFlagsPtr()
1894 LIMITED_METHOD_CONTRACT;
1895 return (DWORD*)(&m_wAuxFlags);
1897 inline void SetAuxFlags(DWORD flag)
1899 LIMITED_METHOD_CONTRACT;
1900 m_wAuxFlags |= (WORD)flag;
1903 // This flag is set (in a checked build only?) for classes whose
1904 // instances are always app domain agile. This can
1905 // be either because of type system guarantees or because
1906 // the class is explicitly marked.
1907 inline BOOL IsAppDomainAgile()
1909 LIMITED_METHOD_CONTRACT;
1910 return (m_wAuxFlags & AUXFLAG_APP_DOMAIN_AGILE);
1912 inline void SetAppDomainAgile()
1914 LIMITED_METHOD_CONTRACT;
1915 m_wAuxFlags |= AUXFLAG_APP_DOMAIN_AGILE;
1917 // This flag is set in a checked build for classes whose
1918 // instances may be marked app domain agile, but agility
1919 // isn't guaranteed by type safety. The JIT will compile
1920 // in extra checks to field assignment on some fields
1922 inline BOOL IsCheckAppDomainAgile()
1924 LIMITED_METHOD_CONTRACT;
1925 return (m_wAuxFlags & AUXFLAG_CHECK_APP_DOMAIN_AGILE);
1928 inline void SetCheckAppDomainAgile()
1930 LIMITED_METHOD_CONTRACT;
1931 m_wAuxFlags |= AUXFLAG_CHECK_APP_DOMAIN_AGILE;
1934 // This flag is set in a checked build to indicate that the
1935 // appdomain agility for a class had been set. This is used
1936 // for debugging purposes to make sure that we don't allocate
1937 // an object before the agility is set.
1938 inline BOOL IsAppDomainAgilityDone()
1940 LIMITED_METHOD_CONTRACT;
1941 return (m_wAuxFlags & AUXFLAG_APP_DOMAIN_AGILITY_DONE);
1943 inline void SetAppDomainAgilityDone()
1945 LIMITED_METHOD_CONTRACT;
1946 m_wAuxFlags |= AUXFLAG_APP_DOMAIN_AGILITY_DONE;
1949 // This predicate checks whether or not the class is "naturally"
1950 // app domain agile - that is:
1951 // (1) it is in the system domain
1952 // (2) all the fields are app domain agile
1953 // (3) it has no finalizer
1955 // Or, this also returns true for a proxy type which is allowed
1956 // to have cross app domain refs.
1958 inline BOOL IsTypesafeAppDomainAgile()
1960 LIMITED_METHOD_CONTRACT;
1961 return IsAppDomainAgile() && !IsCheckAppDomainAgile();
1964 // This predictate tests whether any instances are allowed
1965 // to be app domain agile.
1967 inline BOOL IsNeverAppDomainAgile()
1969 LIMITED_METHOD_CONTRACT;
1970 return !IsAppDomainAgile() && !IsCheckAppDomainAgile();
1972 static void SetAppDomainAgileAttribute(MethodTable * pMT);
1974 static void GetPredefinedAgility(Module *pModule, mdTypeDef td, BOOL *pfIsAgile, BOOL *pfIsCheckAgile);
1975 #endif // defined(CHECK_APP_DOMAIN_LEAKS) || defined(_DEBUG)
1977 //-------------------------------------------------------------
1978 // CONCRETE DATA LAYOUT
1980 // Although accessed far less frequently than MethodTables, EEClasses are still
1981 // pulled into working set, especially at startup. This has motivated several space
1982 // optimizations in field layout where each is balanced against the need to access
1983 // a particular field efficiently.
1985 // Currently, the following strategy is used:
1987 // - Any field that has a default value for the vast majority of EEClass instances
1988 // should be stored in the EEClassOptionalFields (see header comment)
1990 // - Any field that is nearly always a small positive integer and is infrequently
1991 // accessed should be in the EEClassPackedFields (see header comment)
1993 // If none of these categories apply - such as for always-meaningful pointer members or
1994 // sets of flags - a full field is used. Please avoid adding such members if possible.
1995 //-------------------------------------------------------------
1997 // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1999 // Flags for m_VMFlags
2004 #ifdef FEATURE_READYTORUN
2005 VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
2007 VMFLAG_DELEGATE = 0x00000002,
2011 //Flag | All Transparent | Critical | All Critical | TreatAsSafe
2012 //TRANSPARENT | 0 | 0 | 0 | 0
2013 //ALL_TRANSPARENT | 1 | 0 | 0 | 0
2014 //CRITICAL | 0 | 1 | 0 | 0
2015 //TAS_CRITICAL | 0 | 1 | 0 | 1
2016 //ALLCRITICAL | 0 | 0 | 1 | 0
2017 //ALLCRITICAL_TAS | 0 | 0 | 1 | 1
2018 //TAS_NOTCRITICAL | 0 | 0 | 0 | 1
2021 //On CoreCLR TAS implies Critical and "All Critical" and "Critical" are the same thing.
2024 //Flag | All Transparent | Critical | TreatAsSafe
2025 //TRANSPARENT | 0 | 0 | 0
2026 //ALL_TRANSPARENT | 1 | 0 | 0
2027 //CRITICAL | 0 | 1 | 0
2028 //TAS_CRITICAL | 0 | 1 | 1
2029 VMFLAG_TRANSPARENCY_MASK = 0x0000001c,
2030 VMFLAG_TRANSPARENCY_UNKNOWN = 0x00000000,
2031 VMFLAG_TRANSPARENCY_TRANSPARENT = 0x00000004,
2032 VMFLAG_TRANSPARENCY_ALL_TRANSPARENT = 0x00000008,
2033 VMFLAG_TRANSPARENCY_CRITICAL = 0x0000000c,
2034 VMFLAG_TRANSPARENCY_CRITICAL_TAS = 0x00000010,
2035 VMFLAG_TRANSPARENCY_ALLCRITICAL = 0x00000014,
2036 VMFLAG_TRANSPARENCY_ALLCRITICAL_TAS = 0x00000018,
2037 VMFLAG_TRANSPARENCY_TAS_NOTCRITICAL = 0x0000001c,
2039 VMFLAG_FIXED_ADDRESS_VT_STATICS = 0x00000020, // Value type Statics in this class will be pinned
2040 VMFLAG_HASLAYOUT = 0x00000040,
2041 VMFLAG_ISNESTED = 0x00000080,
2043 VMFLAG_IS_EQUIVALENT_TYPE = 0x00000200,
2045 // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
2046 VMFLAG_HASOVERLAYEDFIELDS = 0x00000400,
2048 // Set this if this class or its parent have instance fields which
2049 // must be explicitly inited in a constructor (e.g. pointers of any
2050 // kind, gc or native).
2052 // Currently this is used by the verifier when verifying value classes
2053 // - it's ok to use uninitialised value classes if there are no
2054 // pointer fields in them.
2055 VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED = 0x00000800,
2057 VMFLAG_UNSAFEVALUETYPE = 0x00001000,
2059 VMFLAG_BESTFITMAPPING_INITED = 0x00002000, // VMFLAG_BESTFITMAPPING and VMFLAG_THROWONUNMAPPABLECHAR are valid only if this is set
2060 VMFLAG_BESTFITMAPPING = 0x00004000, // BestFitMappingAttribute.Value
2061 VMFLAG_THROWONUNMAPPABLECHAR = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar
2063 VMFLAG_NOSUPPRESSUNMGDCODEACCESS = 0x00010000,
2064 VMFLAG_NO_GUID = 0x00020000,
2065 VMFLAG_HASNONPUBLICFIELDS = 0x00040000,
2066 VMFLAG_REMOTING_PROXY_ATTRIBUTE = 0x00080000,
2067 VMFLAG_CONTAINS_STACK_PTR = 0x00100000,
2068 VMFLAG_PREFER_ALIGN8 = 0x00200000, // Would like to have 8-byte alignment
2069 VMFLAG_METHODS_REQUIRE_INHERITANCE_CHECKS = 0x00400000,
2071 #ifdef FEATURE_COMINTEROP
2072 VMFLAG_SPARSE_FOR_COMINTEROP = 0x00800000,
2073 // interfaces may have a coclass attribute
2074 VMFLAG_HASCOCLASSATTRIB = 0x01000000,
2075 VMFLAG_COMEVENTITFMASK = 0x02000000, // class is a special COM event interface
2076 VMFLAG_PROJECTED_FROM_WINRT = 0x04000000,
2077 VMFLAG_EXPORTED_TO_WINRT = 0x08000000,
2078 #endif // FEATURE_COMINTEROP
2080 // This one indicates that the fields of the valuetype are
2081 // not tightly packed and is used to check whether we can
2082 // do bit-equality on value types to implement ValueType::Equals.
2083 // It is not valid for classes, and only matters if ContainsPointer
2085 VMFLAG_NOT_TIGHTLY_PACKED = 0x10000000,
2087 // True if methoddesc on this class have any real (non-interface) methodimpls
2088 VMFLAG_CONTAINS_METHODIMPLS = 0x20000000,
2090 #ifdef FEATURE_COMINTEROP
2091 VMFLAG_MARSHALINGTYPE_MASK = 0xc0000000,
2093 VMFLAG_MARSHALINGTYPE_INHIBIT = 0x40000000,
2094 VMFLAG_MARSHALINGTYPE_FREETHREADED = 0x80000000,
2095 VMFLAG_MARSHALINGTYPE_STANDARD = 0xc0000000,
2100 // C_ASSERTs in Jitinterface.cpp need this to be public to check the offset.
2101 // Put it first so the offset rarely changes, which just reduces the number of times we have to fiddle
2103 RelativePointer<PTR_GuidInfo> m_pGuidInfo; // The cached guid information for interfaces.
2107 LPCUTF8 m_szDebugClassName;
2108 BOOL m_fDebuggingClass;
2112 // Layout rest of fields below from largest to smallest to lessen the chance of wasting bytes with
2113 // compiler injected padding (especially with the difference between pointers and DWORDs on 64-bit).
2114 RelativePointer<PTR_EEClassOptionalFields> m_rpOptionalFields;
2116 // TODO: Remove this field. It is only used by SOS and object validation for stress.
2117 RelativePointer<PTR_MethodTable> m_pMethodTable;
2119 RelativePointer<PTR_FieldDesc> m_pFieldDescList;
2120 RelativePointer<PTR_MethodDescChunk> m_pChunks;
2124 // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
2125 UINT32 m_cbNativeSize; // size of fixed portion in bytes
2127 #ifdef FEATURE_COMINTEROP
2128 // For COM+ wrapper objects that extend an unmanaged class, this field
2129 // may contain a delegate to be called to allocate the aggregated
2130 // unmanaged class (instead of using CoCreateInstance).
2131 OBJECTHANDLE m_ohDelegate;
2133 // For interfaces this contains the COM interface type.
2134 CorIfaceAttr m_ComInterfaceType;
2135 #endif // FEATURE_COMINTEROP
2138 #ifdef FEATURE_COMINTEROP
2139 ComCallWrapperTemplate *m_pccwTemplate; // points to interop data structures used when this type is exposed to COM
2140 #endif // FEATURE_COMINTEROP
2142 DWORD m_dwAttrClass;
2146 * We maintain some auxillary flags in DEBUG or CHECK_APP_DOMAIN_LEAKS builds,
2147 * this frees up some bits in m_wVMFlags
2149 #if defined(CHECK_APP_DOMAIN_LEAKS) || defined(_DEBUG)
2153 // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
2154 // structure packing.
2156 BYTE m_fFieldsArePacked; // TRUE iff fields pointed to by GetPackedFields() are in packed state
2157 BYTE m_cbFixedEEClassFields; // Count of bytes of normal fields of this instance (EEClass,
2158 // LayoutEEClass etc.). Doesn't count bytes of "packed" fields
2159 BYTE m_cbBaseSizePadding; // How many bytes of padding are included in BaseSize
2162 // EEClass optional field support. Whether a particular EEClass instance has optional fields is determined
2163 // at class load time. The entire EEClassOptionalFields structure is allocated if the EEClass has need of
2164 // one or more optional fields.
2166 #ifndef DACCESS_COMPILE
2167 void AttachOptionalFields(EEClassOptionalFields *pFields)
2169 LIMITED_METHOD_CONTRACT;
2170 _ASSERTE(m_rpOptionalFields.IsNull());
2172 m_rpOptionalFields.SetValue(pFields);
2174 #endif // !DACCESS_COMPILE
2176 bool HasOptionalFields()
2178 LIMITED_METHOD_DAC_CONTRACT;
2179 return !m_rpOptionalFields.IsNull();
2182 PTR_EEClassOptionalFields GetOptionalFields()
2184 LIMITED_METHOD_DAC_CONTRACT;
2185 return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
2190 // Support for packed fields.
2193 // Get pointer to the packed fields structure attached to this instance.
2194 PTR_EEClassPackedFields GetPackedFields();
2196 // Get the value of the given field. Works regardless of whether the field is currently in its packed or
2198 DWORD GetPackableField(EEClassFieldId eField);
2200 // Set the value of the given field. The field *must* be in the unpacked state for this to be legal (in
2201 // practice all packable fields must be initialized during class construction and from then on remain
2203 void SetPackableField(EEClassFieldId eField, DWORD dwValue);
2205 //-------------------------------------------------------------
2206 // END CONCRETE DATA LAYOUT
2207 //-------------------------------------------------------------
2211 /************************************
2213 ************************************/
2215 #ifndef DACCESS_COMPILE
2217 * Constructor: prevent any other class from doing a new()
2219 EEClass(DWORD cbFixedEEClassFields);
2222 * Destructor: prevent any other class from deleting
2226 LIMITED_METHOD_CONTRACT;
2228 #endif // !DACCESS_COMPILE
2232 // --------------------------------------------------------------------------------------------
2233 template <typename Data>
2234 class FixedCapacityStackingAllocatedUTF8StringHash
2240 HashEntry * m_pNext; // Next item with same bucketed hash value
2241 DWORD m_dwHashValue; // Hash value
2242 LPCUTF8 m_pKey; // String key
2243 Data m_data; // Data
2246 HashEntry ** m_pBuckets; // Pointer to first entry for each bucket
2247 DWORD m_dwNumBuckets;
2248 BYTE * m_pMemory; // Current pointer into preallocated memory for entries
2249 BYTE * m_pMemoryStart; // Start pointer of pre-allocated memory fo entries
2251 INDEBUG(BYTE * m_pDebugEndMemory;)
2253 FixedCapacityStackingAllocatedUTF8StringHash()
2254 : m_pMemoryStart(NULL)
2255 { LIMITED_METHOD_CONTRACT; }
2260 { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2266 StackingAllocator * pAllocator);
2268 // Insert new entry at head of list
2274 // Return the first matching entry in the list, or NULL if there is no such entry
2279 // Return the next matching entry in the list, or NULL if there is no such entry.
2282 HashEntry * pEntry);
2286 //---------------------------------------------------------------------------------------
2288 class LayoutEEClass : public EEClass
2291 EEClassLayoutInfo m_LayoutInfo;
2293 #ifndef DACCESS_COMPILE
2294 LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2296 LIMITED_METHOD_CONTRACT;
2298 FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2301 #endif // !DACCESS_COMPILE
2304 class UMThunkMarshInfo;
2306 #ifdef FEATURE_COMINTEROP
2307 struct ComPlusCallInfo;
2308 #endif // FEATURE_COMINTEROP
2310 class DelegateEEClass : public EEClass
2313 PTR_Stub m_pStaticCallStub;
2314 PTR_Stub m_pInstRetBuffCallStub;
2315 RelativePointer<PTR_MethodDesc> m_pInvokeMethod;
2316 PTR_Stub m_pMultiCastInvokeStub;
2317 PTR_Stub m_pSecureDelegateInvokeStub;
2318 UMThunkMarshInfo* m_pUMThunkMarshInfo;
2319 RelativePointer<PTR_MethodDesc> m_pBeginInvokeMethod;
2320 RelativePointer<PTR_MethodDesc> m_pEndInvokeMethod;
2321 Volatile<PCODE> m_pMarshalStub;
2323 #ifdef FEATURE_COMINTEROP
2324 ComPlusCallInfo *m_pComPlusCallInfo;
2325 #endif // FEATURE_COMINTEROP
2328 // Ngened IL stub MethodDescs. Fixed up, wrapped with code:Stub, and installed to
2329 // m_pMarshalStub (forward) or m_pUMThunkMarshInfo (reverse) when first needed.
2331 MethodDesc* m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2332 MethodDesc* m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2334 PTR_MethodDesc GetInvokeMethod()
2336 return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2339 PTR_MethodDesc GetBeginInvokeMethod()
2341 return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2344 PTR_MethodDesc GetEndInvokeMethod()
2346 return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2349 #ifndef DACCESS_COMPILE
2350 DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2352 LIMITED_METHOD_CONTRACT;
2353 // Note: Memory allocated on loader heap is zero filled
2356 // We need a LoaderHeap that lives at least as long as the DelegateEEClass, but ideally no longer
2357 LoaderHeap *GetStubHeap();
2358 #endif // !DACCESS_COMPILE
2363 typedef DPTR(ArrayClass) PTR_ArrayClass;
2366 // Dynamically generated array class structure
2367 class ArrayClass : public EEClass
2369 #ifdef FEATURE_PREJIT
2370 friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2373 friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2375 #ifndef DACCESS_COMPILE
2376 ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2378 friend class NativeImageDumper;
2383 unsigned char m_rank;
2384 CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd
2388 LIMITED_METHOD_CONTRACT;
2392 void SetRank (unsigned Rank) {
2393 LIMITED_METHOD_CONTRACT;
2394 // The only code path calling this function is code:ClassLoader::CreateTypeHandleForTypeKey, which has
2395 // checked the rank already. Assert that the rank is less than MAX_RANK and that it fits in one byte.
2396 _ASSERTE((Rank <= MAX_RANK) && (Rank <= (unsigned char)(-1)));
2397 m_rank = (unsigned char)Rank;
2400 CorElementType GetArrayElementType() {
2401 LIMITED_METHOD_CONTRACT;
2402 return m_ElementType;
2404 void SetArrayElementType(CorElementType ElementType) {
2405 LIMITED_METHOD_CONTRACT;
2406 m_ElementType = ElementType;
2410 // Allocate a new MethodDesc for the methods we add to this class
2411 void InitArrayMethodDesc(
2412 ArrayMethodDesc* pNewMD,
2413 PCCOR_SIGNATURE pShortSig,
2416 LoaderAllocator *pLoaderAllocator,
2417 AllocMemTracker *pamTracker);
2419 // Generate a short sig for an array accessor
2420 VOID GenerateArrayAccessorCallSig(DWORD dwRank,
2421 DWORD dwFuncType, // Load, store, or <init>
2422 PCCOR_SIGNATURE *ppSig, // Generated signature
2423 DWORD * pcSig, // Generated signature size
2424 LoaderAllocator *pLoaderAllocator,
2425 AllocMemTracker *pamTracker
2426 #ifdef FEATURE_ARRAYSTUB_AS_IL
2434 inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2436 LIMITED_METHOD_CONTRACT;
2437 _ASSERTE(HasLayout());
2438 return &((LayoutEEClass *) this)->m_LayoutInfo;
2441 inline BOOL EEClass::IsBlittable()
2443 LIMITED_METHOD_CONTRACT;
2445 // Either we have an opaque bunch of bytes, or we have some fields that are
2446 // all isomorphic and explicitly layed out.
2447 return (HasLayout() && GetLayoutInfo()->IsBlittable());
2450 inline BOOL EEClass::IsManagedSequential()
2452 LIMITED_METHOD_CONTRACT;
2453 return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2456 inline BOOL EEClass::HasExplicitSize()
2458 LIMITED_METHOD_CONTRACT;
2459 return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2462 //==========================================================================
2463 // These routines manage the prestub (a bootstrapping stub that all
2464 // FunctionDesc's are initialized with.)
2465 //==========================================================================
2466 VOID InitPreStubManager();
2468 EXTERN_C void STDCALL ThePreStub();
2470 inline PCODE GetPreStubEntryPoint()
2472 return GetEEFuncEntryPoint(ThePreStub);
2475 #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2477 EXTERN_C void STDCALL ThePreStubCompactARM();
2479 inline PCODE GetPreStubCompactARMEntryPoint()
2481 return GetEEFuncEntryPoint(ThePreStubCompactARM);
2484 #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2486 PCODE TheUMThunkPreStub();
2488 PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
2492 // workaround: These classification bits need cleanup bad: for now, this gets around
2493 // IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
2494 #define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
2497 // The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
2498 // methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
2501 #define METH_NAME_CACHE_SIZE 5
2502 #define MAX_MISSES 3
2504 #ifdef EnC_SUPPORTED
2506 struct EnCAddedFieldElement;
2508 #endif // EnC_SUPPORTED
2511 // --------------------------------------------------------------------------------------------
2512 // For generic instantiations the FieldDescs stored for instance
2513 // fields are approximate, not exact, i.e. they are representatives owned by
2514 // canonical instantiation and they do not carry exact type information.
2515 // This will not include EnC related fields. (See EncApproxFieldDescIterator for that)
2516 class ApproxFieldDescIterator
2520 PTR_FieldDesc m_pFieldDescList;
2526 INSTANCE_FIELDS = 0x1,
2527 STATIC_FIELDS = 0x2,
2528 ALL_FIELDS = (INSTANCE_FIELDS | STATIC_FIELDS)
2530 ApproxFieldDescIterator();
2531 ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2534 Init(pMT, iteratorType);
2536 void Init(MethodTable *pMT, int iteratorType);
2537 PTR_FieldDesc Next();
2539 int GetIteratorType() {
2540 LIMITED_METHOD_CONTRACT;
2542 return m_iteratorType;
2546 LIMITED_METHOD_CONTRACT;
2547 return m_totalFields;
2549 int CountRemaining() {
2550 LIMITED_METHOD_CONTRACT;
2552 return m_totalFields - m_currField - 1;
2557 // DeepFieldDescIterator iterates over the entire
2558 // set of fields available to a class, inherited or
2562 class DeepFieldDescIterator
2565 ApproxFieldDescIterator m_fieldIter;
2568 MethodTable* m_classes[16];
2569 int m_deepTotalFields;
2570 bool m_lastNextFromParentClass;
2575 DeepFieldDescIterator()
2577 LIMITED_METHOD_CONTRACT;
2581 m_deepTotalFields = 0;
2582 m_lastNextFromParentClass = false;
2584 DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2585 bool includeParents = true)
2587 WRAPPER_NO_CONTRACT;
2589 Init(pMT, iteratorType, includeParents);
2591 void Init(MethodTable* pMT, int iteratorType,
2592 bool includeParents = true);
2596 bool Skip(int numSkip);
2600 LIMITED_METHOD_CONTRACT;
2601 return m_deepTotalFields;
2603 bool IsFieldFromParentClass()
2605 LIMITED_METHOD_CONTRACT;
2606 return m_lastNextFromParentClass;