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"
40 #ifdef FEATURE_COMINTEROP
41 #include "stdinterfaces.h"
45 #include "typehandle.h"
46 #include "perfcounters.h"
47 #include "methodtable.h"
50 #include "iterator_util.h"
52 #ifdef FEATURE_COMINTEROP
53 #include "..\md\winmd\inc\adapter.h"
55 #include "packedfields.inl"
57 #define IBCLOG(x) g_IBCLogger.##x
59 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
64 #define MAX_LOG2_PRIMITIVE_FIELD_SIZE 3
66 #define MAX_PRIMITIVE_FIELD_SIZE (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
69 * Forward declarations
73 class ArrayMethodDesc;
76 class DictionaryLayout;
77 class DomainLocalBlock;
78 class FCallMethodDesc;
83 struct LayoutRawFieldInfo;
86 class MethodDescChunk;
89 struct ModuleCtorInfo;
95 class StackingAllocator;
96 class AllocMemTracker;
97 class InteropMethodTableSlotDataMap;
98 class LoadingEntry_LockHolder;
99 class DispatchMapBuilder;
100 class LoaderAllocator;
101 class ComCallWrapperTemplate;
103 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
104 typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
107 //---------------------------------------------------------------------------------
108 // Fields in an explicit-layout class present varying degrees of risk depending
109 // on how they overlap.
111 // Each level is a superset of the lower (in numerical value) level - i.e.
112 // all kVerifiable fields are also kLegal, but not vice-versa.
113 //---------------------------------------------------------------------------------
114 class ExplicitFieldTrust
119 // Note: order is important here - each guarantee also implicitly guarantees all promises
120 // made by values lower in number.
122 // What's guaranteed. What the loader does.
123 //----- ----------------------- -------------------------------
124 kNone = 0, // no guarantees at all - Type refuses to load at all.
125 kLegal = 1, // guarantees no objref <-> scalar overlap and no unaligned objref - Type loads but field access won't verify
126 kVerifiable = 2, // guarantees no objref <-> objref overlap and all guarantees above - Type loads and field access will verify
127 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
129 kMaxTrust = kNonOverLayed,
134 //----------------------------------------------------------------------------------------------
135 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
136 // into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
137 // class. This abstraction enforces the rule that the overall class is only as trustworthy as
138 // the least trustworthy field.
139 //----------------------------------------------------------------------------------------------
140 class ExplicitClassTrust : private ExplicitFieldTrust
145 LIMITED_METHOD_CONTRACT;
146 m_trust = kMaxTrust; // Yes, we start out with maximal trust. This reflects that explicit layout structures with no fields do represent no risk.
149 VOID AddField(TrustLevel fieldTrust)
151 LIMITED_METHOD_CONTRACT;
152 m_trust = min(m_trust, fieldTrust);
157 LIMITED_METHOD_CONTRACT;
158 return m_trust >= kLegal;
163 LIMITED_METHOD_CONTRACT;
164 return m_trust >= kVerifiable;
167 BOOL IsNonOverLayed()
169 LIMITED_METHOD_CONTRACT;
170 return m_trust >= kNonOverLayed;
173 TrustLevel GetTrustLevel()
175 LIMITED_METHOD_CONTRACT;
183 //----------------------------------------------------------------------------------------------
184 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
185 // into this function, this class will collect trust information about individual fields to be later
186 // aggregated into the overall class level.
188 // This abstraction enforces the rule that all fields are presumed guilty until explicitly declared
189 // safe by calling SetTrust(). If you fail to call SetTrust before leaving the block, the destructor
190 // will automatically cause the entire class to be declared illegal (and you will get an assert
191 // telling you to fix this bug.)
192 //----------------------------------------------------------------------------------------------
193 class ExplicitFieldTrustHolder : private ExplicitFieldTrust
196 ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
198 LIMITED_METHOD_CONTRACT;
199 m_pExplicitClassTrust = pExplicitClassTrust;
201 m_trustDeclared = FALSE;
203 m_fieldTrust = kNone;
206 VOID SetTrust(TrustLevel fieldTrust)
208 LIMITED_METHOD_CONTRACT;
210 _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
211 _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
214 m_trustDeclared = TRUE;
216 m_fieldTrust = fieldTrust;
219 ~ExplicitFieldTrustHolder()
221 LIMITED_METHOD_CONTRACT;
222 // If no SetTrust() was ever called, we will default to kNone (i.e. declare the entire type
223 // illegal.) It'd be nice to assert here but since this case can be legitimately reached
224 // on exception unwind, we cannot.
225 m_pExplicitClassTrust->AddField(m_fieldTrust);
230 ExplicitClassTrust* m_pExplicitClassTrust;
231 TrustLevel m_fieldTrust;
233 BOOL m_trustDeclared; // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
237 //*******************************************************************************
238 // Enumerator to traverse the interface declarations of a type, automatically building
239 // a substitution chain on the stack.
240 class InterfaceImplEnum
243 HENUMInternalHolder hEnumInterfaceImpl;
244 const Substitution *m_pSubstChain;
245 Substitution m_CurrSubst;
248 InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
249 : hEnumInterfaceImpl(pModule->GetMDImport())
253 hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
254 m_pSubstChain = pSubstChain;
258 // S_OK ... if has next (TRUE)
259 // S_FALSE ... if does not have next (FALSE)
266 if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
271 IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
272 m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
275 const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
276 mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
279 #ifdef FEATURE_COMINTEROP
281 // Class used to map MethodTable slot numbers to COM vtable slots numbers
282 // (either for calling a classic COM component or for constructing a classic COM
283 // vtable via which COM components can call managed classes). This structure is
284 // embedded in the EEClass but the mapping list itself is only allocated if the
285 // COM vtable is sparse.
288 class SparseVTableMap
291 #ifdef DACCESS_COMPILE
292 friend class NativeImageDumper;
298 // First run through MT slots calling RecordGap wherever a gap in VT slots
300 void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
302 // Then call FinalizeMapping to create the actual mapping list.
303 void FinalizeMapping(WORD TotalMTSlots);
305 // Map MT to VT slot.
306 WORD LookupVTSlot(WORD MTSlot);
308 // Retrieve the number of slots in the vtable (both empty and full).
309 WORD GetNumVTableSlots();
311 const void* GetMapList()
313 LIMITED_METHOD_CONTRACT;
314 return (void*)m_MapList;
317 #ifdef FEATURE_PREJIT
318 // Methods to persist structure
319 void Save(DataImage *image);
320 void Fixup(DataImage *image);
321 #endif // FEATURE_PREJIT
325 enum { MapGrow = 4 };
329 WORD m_Start; // Starting MT slot number
330 WORD m_Span; // # of consecutive slots that map linearly
331 WORD m_MapTo; // Starting VT slot number
334 Entry *m_MapList; // Pointer to array of Entry structures
335 WORD m_MapEntries; // Number of entries in above
336 WORD m_Allocated; // Number of entries allocated
338 WORD m_LastUsed; // Index of last entry used in successful lookup
340 WORD m_VTSlot; // Current VT slot number, used during list build
341 WORD m_MTSlot; // Current MT slot number, used during list build
343 void AllocOrExpand(); // Allocate or expand the mapping list for a new entry
345 #endif // FEATURE_COMINTEROP
347 //=======================================================================
348 // Adjunct to the EEClass structure for classes w/ layout
349 //=======================================================================
350 class EEClassLayoutInfo
352 static VOID CollectLayoutFieldMetadataThrowing(
353 mdTypeDef cl, // cl of the NStruct being loaded
354 BYTE packingSize, // packing size (from @dll.struct)
355 BYTE nlType, // nltype (from @dll.struct)
356 #ifdef FEATURE_COMINTEROP
357 BOOL isWinRT, // Is the type a WinRT type
358 #endif // FEATURE_COMINTEROP
359 BOOL fExplicitOffsets, // explicit offsets?
360 MethodTable *pParentMT, // the loaded superclass
361 ULONG cMembers, // total number of members (methods + fields)
362 HENUMInternal *phEnumField, // enumerator for field
363 Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
364 const SigTypeContext *pTypeContext, // Type parameters for NStruct being loaded
365 EEClassLayoutInfo *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
366 LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in. Needs room for cMember+1 elements
367 LoaderAllocator * pAllocator,
368 AllocMemTracker *pamTracker
372 friend class ClassLoader;
373 friend class EEClass;
374 friend class MethodTableBuilder;
375 #ifdef DACCESS_COMPILE
376 friend class NativeImageDumper;
380 // size (in bytes) of fixed portion of NStruct.
381 UINT32 m_cbNativeSize;
382 UINT32 m_cbManagedSize;
385 // 1,2,4 or 8: this is equal to the largest of the alignment requirements
386 // of each of the EEClass's members. If the NStruct extends another NStruct,
387 // the base NStruct is treated as the first member for the purpose of
389 BYTE m_LargestAlignmentRequirementOfAllMembers;
391 // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
392 // for the managed layout.
393 BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
397 // TRUE if the GC layout of the class is bit-for-bit identical
398 // to its unmanaged counterpart (i.e. no internal reference fields,
399 // no ansi-unicode char conversions required, etc.) Used to
400 // optimize marshaling.
402 // Post V1.0 addition: Is this type also sequential in managed memory?
403 e_MANAGED_SEQUENTIAL = 0x02,
404 // When a sequential/explicit type has no fields, it is conceptually
405 // zero-sized, but actually is 1 byte in length. This holds onto this
406 // fact and allows us to revert the 1 byte of padding when another
407 // explicit type inherits from this type.
409 // The size of the struct is explicitly specified in the meta-data.
410 e_HAS_EXPLICIT_SIZE = 0x08,
411 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
413 #error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
414 #endif // FEATURE_HFA
415 e_NATIVE_PASS_IN_REGISTERS = 0x10, // Flag wheter a native struct is passed in registers.
416 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
418 // HFA type of the unmanaged layout
426 // Packing size in bytes (1, 2, 4, 8 etc.)
427 BYTE m_cbPackingSize;
429 // # of fields that are of the calltime-marshal variety.
432 // An array of FieldMarshaler data blocks, used to drive call-time
433 // marshaling of NStruct reference parameters. The number of elements
434 // equals m_numCTMFields.
435 RelativePointer<PTR_FieldMarshaler> m_pFieldMarshalers;
439 BOOL GetNativeSize() const
441 LIMITED_METHOD_CONTRACT;
442 return m_cbNativeSize;
445 UINT32 GetManagedSize() const
447 LIMITED_METHOD_CONTRACT;
448 return m_cbManagedSize;
452 BYTE GetLargestAlignmentRequirementOfAllMembers() const
454 LIMITED_METHOD_CONTRACT;
455 return m_LargestAlignmentRequirementOfAllMembers;
458 UINT GetNumCTMFields() const
460 LIMITED_METHOD_CONTRACT;
461 return m_numCTMFields;
464 PTR_FieldMarshaler GetFieldMarshalers() const
466 LIMITED_METHOD_CONTRACT;
467 return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
470 #ifndef DACCESS_COMPILE
471 void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
473 LIMITED_METHOD_CONTRACT;
474 m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
476 #endif // DACCESS_COMPILE
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
521 CorElementType GetNativeHFATypeRaw();
525 LIMITED_METHOD_CONTRACT;
526 return (m_bFlags & (e_R4_HFA | e_R8_HFA)) != 0;
529 CorElementType GetNativeHFAType()
531 LIMITED_METHOD_CONTRACT;
533 return (m_bFlags & e_R4_HFA) ? ELEMENT_TYPE_R4 : ELEMENT_TYPE_R8;
534 return ELEMENT_TYPE_END;
536 #else // !FEATURE_HFA
539 return GetNativeHFATypeRaw() != ELEMENT_TYPE_END;
541 CorElementType GetNativeHFAType()
543 return GetNativeHFATypeRaw();
545 #endif // !FEATURE_HFA
548 void SetIsBlittable(BOOL isBlittable)
550 LIMITED_METHOD_CONTRACT;
551 m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
552 : (m_bFlags & ~e_BLITTABLE);
555 void SetIsManagedSequential(BOOL isManagedSequential)
557 LIMITED_METHOD_CONTRACT;
558 m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
559 : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
562 void SetIsZeroSized(BOOL isZeroSized)
564 LIMITED_METHOD_CONTRACT;
565 m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
566 : (m_bFlags & ~e_ZERO_SIZED);
569 void SetHasExplicitSize(BOOL hasExplicitSize)
571 LIMITED_METHOD_CONTRACT;
572 m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
573 : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
577 void SetNativeHFAType(CorElementType hfaType)
579 LIMITED_METHOD_CONTRACT;
580 m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA;
583 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
584 void SetNativeStructPassedInRegisters()
586 LIMITED_METHOD_CONTRACT;
587 m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
589 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
596 // This structure is used only when the classloader is building the interface map. Before the class
597 // is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
598 // for this class/interface by the metadata - inherited interfaces will not be present if they are
599 // not specifically declared.
601 // This structure is destroyed after resolving has completed.
605 // The interface method table; for instantiated interfaces, this is the generic interface
606 MethodTable *m_pMethodTable;
607 } BuildingInterfaceInfo_t;
611 // We should not need to touch anything in here once the classes are all loaded, unless we
612 // are doing reflection. Try to avoid paging this data structure in.
615 // Size of hash bitmap for method names
616 #define METHOD_HASH_BYTES 8
618 // Hash table size - prime number
619 #define METHOD_HASH_BITS 61
622 // These are some macros for forming fully qualified class names for a class.
623 // These are abstracted so that we can decide later if a max length for a
624 // class name is acceptable.
626 // It doesn't make any sense not to have a small but usually quite capable
627 // stack buffer to build class names into. Most class names that I can think
628 // of would fit in 128 characters, and that's a pretty small amount of stack
629 // to use in exchange for not having to new and delete the memory.
630 #define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4)
632 #define DefineFullyQualifiedNameForClass() \
633 ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
634 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
636 #define DefineFullyQualifiedNameForClassOnStack() \
637 ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
638 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
640 #define DefineFullyQualifiedNameForClassW() \
641 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
643 #define DefineFullyQualifiedNameForClassWOnStack() \
644 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
646 #define GetFullyQualifiedNameForClassNestedAware(pClass) \
647 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
649 #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
650 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
652 #define GetFullyQualifiedNameForClass(pClass) \
653 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
655 #define GetFullyQualifiedNameForClassW(pClass) \
656 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
658 #define GetFullyQualifiedNameForClassW_WinRT(pClass) \
659 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
661 #define GetFullyQualifiedNameForClass_WinRT(pClass) \
662 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
664 // Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to
665 // save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached
666 // via the m_rpOptionalFields field EEClass (use the GetOptionalFields() accessor rather than the field
668 class EEClassOptionalFields
670 // All fields here are intentionally private. Use the corresponding accessor on EEClass instead (this
671 // makes it easier to add and remove fields from the optional section in the future). We make exceptions
672 // for MethodTableBuilder and NativeImageDumper, which need raw field-level access.
673 friend class EEClass;
674 friend class MethodTableBuilder;
675 #ifdef DACCESS_COMPILE
676 friend class NativeImageDumper;
680 // GENERICS RELATED FIELDS.
683 // If IsSharedByGenericInstantiations(), layout of handle dictionary for generic type
684 // (the last dictionary pointed to from PerInstInfo). Otherwise NULL.
685 PTR_DictionaryLayout m_pDictLayout;
687 // Variance info for each type parameter (gpNonVariant, gpCovariant, or gpContravariant)
688 // If NULL, this type has no type parameters that are co/contravariant
689 RelativePointer<PTR_BYTE> m_pVarianceInfo;
692 // COM RELATED FIELDS.
695 #ifdef FEATURE_COMINTEROP
696 SparseVTableMap *m_pSparseVTableMap;
698 TypeHandle m_pCoClassForIntf; // @TODO: Coclass for an interface
700 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
701 // Points to activation information if the type is an activatable COM/WinRT class.
702 ClassFactoryBase *m_pClassFactory;
703 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
705 WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
707 #endif // FEATURE_COMINTEROP
713 #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
714 DWORD m_cbModuleDynamicID;
716 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
717 // Number of eightBytes in the following arrays
718 int m_numberEightBytes;
719 // Classification of the eightBytes
720 SystemVClassificationType m_eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
721 // Size of data the eightBytes
722 unsigned int m_eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
723 #endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
725 // Set default values for optional fields.
728 PTR_BYTE GetVarianceInfo()
730 LIMITED_METHOD_DAC_CONTRACT;
732 return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
735 typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
738 // Another mechanism used to reduce the size of the average EEClass instance is the notion of packed fields.
739 // This is based on the observation that EEClass has a large number of integer fields that typically contain
740 // small values and that are fixed once class layout has completed. We can compact these fields by discarding
741 // the leading zero bits (and for small values there'll be a lot of these) and packing the significant data
742 // into compact bitfields. This is a dynamic operation (the exact packing used depends on the exact data
743 // stored in the fields).
745 // The PackedDWORDFields<> class (defined in PackedFields.inl) encapsulates this. It takes one template
746 // parameter, the number of fields to pack, and provides operations to get and set those fields until we're
747 // happy with the values, at which point it will compact them for us.
749 // The packed fields themselves are stored at the end of the EEClass instance (or the LayoutEEClass or the
750 // DelegateEEClass etc.) so we can take advantage of the variable sized nature of the fields. We gain nothing for
751 // runtime allocated EEClasses (we have to allocate a maximally sized structure for the packed fields because
752 // we can't tell at the beginning of EEClass layout what the field values will be). But in the ngen scenario
753 // we can compact the fields just prior to saving and only store the portion of the EEClass that is relvant,
754 // helping us with our goal of packing all the EEClass instances together as tightly as possible.
756 // Since each packed field is now accessed via an array-like index, we give each of those indices a name with
757 // the enum below to make the code more readable.
762 EEClass_Field_NumInstanceFields = 0,
763 EEClass_Field_NumMethods,
764 EEClass_Field_NumStaticFields,
765 EEClass_Field_NumHandleStatics,
766 EEClass_Field_NumBoxedStatics,
767 EEClass_Field_NonGCStaticFieldBytes,
768 EEClass_Field_NumThreadStaticFields,
769 EEClass_Field_NumHandleThreadStatics,
770 EEClass_Field_NumBoxedThreadStatics,
771 EEClass_Field_NonGCThreadStaticFieldBytes,
772 EEClass_Field_NumNonVirtualSlots,
776 typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
777 typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
780 // For most types there is a one-to-one mapping between MethodTable* and EEClass*
781 // However this is not the case for instantiated types where code and representation
782 // are shared between compatible instantiations (e.g. List<string> and List<object>)
783 // Then a single EEClass structure is shared between multiple MethodTable structures
784 // Uninstantiated generic types (e.g. List) have their own EEClass and MethodTable,
785 // used (a) as a representative for the generic type itself, (b) for static fields and
786 // methods, which aren't present in the instantiations, and (c) to hold some information
787 // (e.g. formal instantiations of superclass and implemented interfaces) that is common
788 // to all instantiations and isn't stored in the EEClass structures for instantiated types
791 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
793 // A word about EEClass vs. MethodTable
794 // ------------------------------------
796 // At compile-time, we are happy to touch both MethodTable and EEClass. However,
797 // at runtime we want to restrict ourselves to the MethodTable. This is critical
798 // for common code paths, where we want to keep the EEClass out of our working
799 // set. For uncommon code paths, like throwing exceptions or strange Contexts
800 // issues, it's okay to access the EEClass.
802 // To this end, the TypeHandle (CLASS_HANDLE) abstraction is now based on the
803 // MethodTable pointer instead of the EEClass pointer. If you are writing a
804 // runtime helper that calls GetClass() to access the associated EEClass, please
805 // stop to wonder if you are making a mistake.
807 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
810 // An code:EEClass is a representation of the part of a managed type that is not used very frequently (it is
811 // cold), and thus is segregated from the hot portion (which lives in code:MethodTable). As noted above an
812 // it is also the case that EEClass is SHARED among all instantiations of a generic type, so anything that
813 // is specific to a paritcular type can not live off the EEClass.
815 // From here you can get to
816 // code:MethodTable - The representation of the hot portion of a type.
817 // code:MethodDesc - The representation of a method
818 // code:FieldDesc - The representation of a field.
820 // EEClasses hold the following important fields
821 // * code:EEClass.m_pMethodTable - Points a MethodTable associated with
822 // * code:EEClass.m_pChunks - a list of code:MethodDescChunk which is simply a list of code:MethodDesc
823 // which represent the methods.
824 // * code:EEClass.m_pFieldDescList - a list of fields in the type.
826 class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
828 /************************************
830 ************************************/
831 // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
832 // USE ACCESSORS TO READ/WRITE private field members
834 // To access bmt stuff
835 friend class MethodTable;
836 friend class MethodTableBuilder;
837 friend class FieldDesc;
838 friend class CheckAsmOffsets;
839 friend class ClrDataAccess;
840 #ifdef DACCESS_COMPILE
841 friend class NativeImageDumper;
844 /************************************
845 * PUBLIC INSTANCE METHODS
846 ************************************/
851 LIMITED_METHOD_CONTRACT;
852 return IsTdSealed(m_dwAttrClass);
855 inline DWORD IsInterface()
858 return IsTdInterface(m_dwAttrClass);
861 inline DWORD IsAbstract()
864 return IsTdAbstract(m_dwAttrClass);
867 BOOL HasExplicitFieldOffsetLayout()
870 return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
873 BOOL HasSequentialLayout()
876 return IsTdSequentialLayout(GetAttrClass());
878 BOOL IsSerializable()
881 return IsTdSerializable(GetAttrClass());
883 BOOL IsBeforeFieldInit()
886 return IsTdBeforeFieldInit(GetAttrClass());
889 DWORD GetProtection()
892 return (m_dwAttrClass & tdVisibilityMask);
895 // class is blittable
898 #ifndef DACCESS_COMPILE
899 void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
900 void Destruct(MethodTable * pMT);
902 static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
903 #endif // !DACCESS_COMPILE
906 // Add a new method to an already loaded type for EnC
907 static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
909 // Add a new field to an already loaded type for EnC
910 static HRESULT AddField(MethodTable * pMT, mdFieldDef fieldDesc, EnCFieldDesc **pAddedField);
911 static VOID FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdFieldDef fieldDef);
912 #endif // EnC_SUPPORTED
914 inline DWORD IsComImport()
917 return IsTdImport(m_dwAttrClass);
920 #ifdef FEATURE_PREJIT
923 void Save(DataImage *image, MethodTable *pMT);
924 void Fixup(DataImage *image, MethodTable *pMT);
925 #endif // FEATURE_PREJIT
927 EEClassLayoutInfo *GetLayoutInfo();
929 #ifdef DACCESS_COMPILE
930 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
933 static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
935 /************************************
936 * INSTANCE MEMBER VARIABLES
937 ************************************/
940 inline LPCUTF8 GetDebugClassName ()
942 LIMITED_METHOD_CONTRACT;
943 return m_szDebugClassName;
945 inline void SetDebugClassName (LPCUTF8 szDebugClassName)
947 LIMITED_METHOD_CONTRACT;
948 m_szDebugClassName = szDebugClassName;
952 * Controls debugging breaks and output if a method class
953 * is mentioned in the registry ("BreakOnClassBuild")
954 * Method layout within this class can cause a debug
955 * break by setting "BreakOnMethodName". Not accessible
961 #ifdef FEATURE_COMINTEROP
963 * Used to map MethodTable slots to VTable slots
965 inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
967 LIMITED_METHOD_CONTRACT;
968 return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
970 inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
972 LIMITED_METHOD_CONTRACT;
973 _ASSERTE(HasOptionalFields());
974 GetOptionalFields()->m_pSparseVTableMap = map;
976 #endif // FEATURE_COMINTEROP
980 * Maintain back pointer to statcally hot portion of EEClass.
981 * For an EEClass representing multiple instantiations of a generic type, this is the method table
982 * for the first instantiation requested and is the only one containing entries for non-virtual instance methods
983 * (i.e. non-vtable entries).
986 // Note that EEClass structures may be shared between generic instantiations
987 // (see IsSharedByGenericInstantiations). In these cases EEClass::GetMethodTable
988 // will return the method table pointer corresponding to the "canonical"
989 // instantiation, as defined in typehandle.h.
991 inline PTR_MethodTable GetMethodTable()
993 LIMITED_METHOD_CONTRACT;
996 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
999 // DO NOT ADD ANY ASSERTS TO THIS METHOD.
1000 // DO NOT USE THIS METHOD.
1001 // Yes folks, for better or worse the debugger pokes supposed object addresses
1002 // to try to see if objects are valid, possibly firing an AccessViolation or worse,
1003 // and then catches the AV and reports a failure to the debug client. This makes
1004 // the debugger slightly more robust should any corrupted object references appear
1005 // in a session. Thus it is "correct" behaviour for this to AV when used with
1006 // an invalid object pointer, and incorrect behaviour for it to
1008 inline PTR_MethodTable GetMethodTableWithPossibleAV()
1010 CANNOT_HAVE_CONTRACT;
1013 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1016 #ifndef DACCESS_COMPILE
1017 inline void SetMethodTable(MethodTable* pMT)
1019 LIMITED_METHOD_CONTRACT;
1020 m_pMethodTable.SetValueMaybeNull(pMT);
1022 #endif // !DACCESS_COMPILE
1025 * Number of fields in the class, including inherited fields.
1026 * Does not include fields added from EnC.
1028 inline WORD GetNumInstanceFields()
1030 LIMITED_METHOD_CONTRACT;
1032 return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1035 inline void SetNumInstanceFields (WORD wNumInstanceFields)
1037 LIMITED_METHOD_CONTRACT;
1038 SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1042 * Number of static fields declared in this class.
1043 * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1045 inline WORD GetNumStaticFields()
1047 LIMITED_METHOD_CONTRACT;
1049 return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1051 inline void SetNumStaticFields (WORD wNumStaticFields)
1053 LIMITED_METHOD_CONTRACT;
1054 SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1057 inline WORD GetNumThreadStaticFields()
1059 LIMITED_METHOD_CONTRACT;
1061 return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1064 inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1066 LIMITED_METHOD_CONTRACT;
1067 SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1070 // Statics are stored in a big chunk inside the module
1072 inline DWORD GetModuleDynamicID()
1074 LIMITED_METHOD_CONTRACT;
1076 return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1079 inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1081 LIMITED_METHOD_CONTRACT;
1082 _ASSERTE(HasOptionalFields());
1083 GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
1087 * Difference between the InterfaceMap ptr and Vtable in the
1088 * MethodTable used to indicate the number of static bytes
1089 * Now interfaceMap ptr can be optional hence we store it here
1091 inline DWORD GetNonGCRegularStaticFieldBytes()
1093 LIMITED_METHOD_CONTRACT;
1094 return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1096 inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1098 LIMITED_METHOD_CONTRACT;
1099 SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1102 inline DWORD GetNonGCThreadStaticFieldBytes()
1104 LIMITED_METHOD_CONTRACT;
1105 return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1107 inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1109 LIMITED_METHOD_CONTRACT;
1110 SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1113 inline WORD GetNumNonVirtualSlots()
1115 LIMITED_METHOD_CONTRACT;
1116 return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1118 inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1120 LIMITED_METHOD_CONTRACT;
1121 SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1124 inline BOOL IsEquivalentType()
1126 LIMITED_METHOD_CONTRACT;
1127 return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1130 #ifdef FEATURE_COMINTEROP
1131 inline void SetIsEquivalentType()
1133 LIMITED_METHOD_CONTRACT;
1134 m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1139 * Number of static handles allocated
1141 inline WORD GetNumHandleRegularStatics ()
1143 LIMITED_METHOD_CONTRACT;
1144 return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1146 inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1148 LIMITED_METHOD_CONTRACT;
1149 SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1153 * Number of static handles allocated for ThreadStatics
1155 inline WORD GetNumHandleThreadStatics ()
1157 LIMITED_METHOD_CONTRACT;
1158 return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1160 inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1162 LIMITED_METHOD_CONTRACT;
1163 SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1167 * Number of boxed statics allocated
1169 inline WORD GetNumBoxedRegularStatics ()
1171 LIMITED_METHOD_CONTRACT;
1172 return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1174 inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1176 LIMITED_METHOD_CONTRACT;
1177 SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1181 * Number of boxed statics allocated for ThreadStatics
1183 inline WORD GetNumBoxedThreadStatics ()
1185 LIMITED_METHOD_CONTRACT;
1186 return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1188 inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1190 LIMITED_METHOD_CONTRACT;
1191 SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
1195 * Number of bytes to subract from code:MethodTable::GetBaseSize() to get the actual number of bytes
1196 * of instance fields stored in the object on the GC heap.
1198 inline DWORD GetBaseSizePadding()
1200 LIMITED_METHOD_DAC_CONTRACT;
1201 return m_cbBaseSizePadding;
1203 inline void SetBaseSizePadding(DWORD dwPadding)
1205 LIMITED_METHOD_CONTRACT;
1206 _ASSERTE(FitsIn<BYTE>(dwPadding));
1207 m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1210 inline DWORD GetUnboxedNumInstanceFieldBytes()
1212 DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1214 _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1220 * Pointer to a list of FieldDescs declared in this class
1221 * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1224 #ifdef FEATURE_PREJIT
1225 static DWORD FieldDescListSize(MethodTable * pMT);
1228 inline PTR_FieldDesc GetFieldDescList()
1230 LIMITED_METHOD_DAC_CONTRACT;
1231 // Careful about using this method. If it's possible that fields may have been added via EnC, then
1232 // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1233 return m_pFieldDescList.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList));
1236 PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1238 #ifndef DACCESS_COMPILE
1239 inline void SetFieldDescList (FieldDesc* pFieldDescList)
1241 LIMITED_METHOD_CONTRACT;
1242 m_pFieldDescList.SetValue(pFieldDescList);
1244 #endif // !DACCESS_COMPILE
1246 inline WORD GetNumMethods()
1248 LIMITED_METHOD_DAC_CONTRACT;
1249 return (WORD)GetPackableField(EEClass_Field_NumMethods);
1251 inline void SetNumMethods (WORD wNumMethods)
1253 LIMITED_METHOD_CONTRACT;
1254 SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1258 * Cached metadata for this class (GetTypeDefProps)
1260 inline DWORD GetAttrClass()
1262 LIMITED_METHOD_CONTRACT;
1263 return m_dwAttrClass;
1265 inline void SetAttrClass (DWORD dwAttrClass)
1267 LIMITED_METHOD_CONTRACT;
1268 m_dwAttrClass = dwAttrClass;
1272 #ifdef FEATURE_COMINTEROP
1273 inline DWORD IsComClassInterface()
1275 LIMITED_METHOD_CONTRACT;
1276 return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1278 inline VOID SetIsComClassInterface()
1280 LIMITED_METHOD_CONTRACT;
1281 m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1283 inline void SetComEventItfType()
1285 LIMITED_METHOD_CONTRACT;
1286 _ASSERTE(IsInterface());
1287 m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1289 // class is a special COM event interface
1290 inline BOOL IsComEventItfType()
1292 LIMITED_METHOD_CONTRACT;
1293 return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1295 #endif // FEATURE_COMINTEROP
1298 inline DWORD IsDestroyed()
1300 LIMITED_METHOD_CONTRACT;
1301 return (m_wAuxFlags & AUXFLAG_DESTROYED);
1305 inline DWORD IsUnsafeValueClass()
1307 LIMITED_METHOD_CONTRACT;
1308 return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1313 inline void SetUnsafeValueClass()
1315 LIMITED_METHOD_CONTRACT;
1316 m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1320 inline BOOL HasNoGuid()
1322 LIMITED_METHOD_CONTRACT;
1323 return (m_VMFlags & VMFLAG_NO_GUID);
1325 inline void SetHasNoGuid()
1327 WRAPPER_NO_CONTRACT;
1328 FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1332 inline BOOL IsAlign8Candidate()
1334 LIMITED_METHOD_CONTRACT;
1335 return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1337 inline void SetAlign8Candidate()
1339 LIMITED_METHOD_CONTRACT;
1340 m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1343 inline void SetDestroyed()
1345 LIMITED_METHOD_CONTRACT;
1346 m_wAuxFlags |= AUXFLAG_DESTROYED;
1349 inline void SetHasFixedAddressVTStatics()
1351 LIMITED_METHOD_CONTRACT;
1352 m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1354 #ifdef FEATURE_COMINTEROP
1355 void SetSparseForCOMInterop()
1357 LIMITED_METHOD_CONTRACT;
1358 m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1360 inline void SetProjectedFromWinRT()
1362 LIMITED_METHOD_CONTRACT;
1363 m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1365 inline void SetExportedToWinRT()
1367 LIMITED_METHOD_CONTRACT;
1368 m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1370 inline void SetMarshalingType(UINT32 mType)
1372 LIMITED_METHOD_CONTRACT;
1373 _ASSERTE(mType !=0);
1374 _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1377 case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1379 case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1381 case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1384 _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1387 #endif // FEATURE_COMINTEROP
1388 inline void SetHasLayout()
1390 LIMITED_METHOD_CONTRACT;
1391 m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT; //modified before the class is published
1393 inline void SetHasOverLayedFields()
1395 LIMITED_METHOD_CONTRACT;
1396 m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1398 inline void SetIsNested()
1400 LIMITED_METHOD_CONTRACT;
1401 m_VMFlags |= VMFLAG_ISNESTED;
1404 #ifdef FEATURE_READYTORUN
1405 inline BOOL HasLayoutDependsOnOtherModules()
1407 LIMITED_METHOD_CONTRACT;
1408 return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1411 inline void SetHasLayoutDependsOnOtherModules()
1413 LIMITED_METHOD_CONTRACT;
1414 m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1418 // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1419 inline BOOL IsDelegate()
1421 LIMITED_METHOD_CONTRACT;
1422 return m_VMFlags & VMFLAG_DELEGATE;
1424 inline void SetIsDelegate()
1426 LIMITED_METHOD_CONTRACT;
1427 m_VMFlags |= VMFLAG_DELEGATE;
1430 BOOL HasFixedAddressVTStatics()
1432 LIMITED_METHOD_CONTRACT;
1433 return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1435 #ifdef FEATURE_COMINTEROP
1436 BOOL IsSparseForCOMInterop()
1438 LIMITED_METHOD_CONTRACT;
1439 return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1441 BOOL IsProjectedFromWinRT()
1443 LIMITED_METHOD_DAC_CONTRACT;
1444 return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1446 BOOL IsExportedToWinRT()
1448 LIMITED_METHOD_CONTRACT;
1449 return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1451 BOOL IsMarshalingTypeSet()
1453 LIMITED_METHOD_CONTRACT;
1454 return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1456 BOOL IsMarshalingTypeFreeThreaded()
1458 LIMITED_METHOD_CONTRACT;
1459 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1461 BOOL IsMarshalingTypeInhibit()
1463 LIMITED_METHOD_CONTRACT;
1464 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1466 BOOL IsMarshalingTypeStandard()
1468 LIMITED_METHOD_CONTRACT;
1469 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1471 #endif // FEATURE_COMINTEROP
1474 LIMITED_METHOD_CONTRACT;
1475 return m_VMFlags & VMFLAG_HASLAYOUT;
1477 BOOL HasOverLayedField()
1479 LIMITED_METHOD_CONTRACT;
1480 return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1484 LIMITED_METHOD_CONTRACT;
1485 return m_VMFlags & VMFLAG_ISNESTED;
1487 BOOL HasFieldsWhichMustBeInited()
1489 LIMITED_METHOD_CONTRACT;
1490 return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1492 void SetHasFieldsWhichMustBeInited()
1494 LIMITED_METHOD_CONTRACT;
1495 m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1497 void SetCannotBeBlittedByObjectCloner()
1501 DWORD HasNonPublicFields()
1503 LIMITED_METHOD_CONTRACT;
1504 return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1506 void SetHasNonPublicFields()
1508 LIMITED_METHOD_CONTRACT;
1509 m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1511 DWORD IsNotTightlyPacked()
1513 LIMITED_METHOD_CONTRACT;
1514 return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1516 void SetIsNotTightlyPacked()
1518 LIMITED_METHOD_CONTRACT;
1519 m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1521 DWORD ContainsMethodImpls()
1523 LIMITED_METHOD_CONTRACT;
1524 return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1526 void SetContainsMethodImpls()
1528 LIMITED_METHOD_CONTRACT;
1529 m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1533 BOOL IsManagedSequential();
1535 BOOL HasExplicitSize();
1537 static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1540 * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1543 // This is what would be used in the calling convention for this type.
1544 CorElementType GetInternalCorElementType()
1546 LIMITED_METHOD_DAC_CONTRACT;
1548 return CorElementType(m_NormType);
1550 void SetInternalCorElementType (CorElementType _NormType)
1552 LIMITED_METHOD_CONTRACT;
1553 m_NormType = static_cast<BYTE>(_NormType);
1557 * Chain of MethodDesc chunks for the MethodTable
1560 inline PTR_MethodDescChunk GetChunks();
1562 #ifndef DACCESS_COMPILE
1563 inline void SetChunks (MethodDescChunk* pChunks)
1565 LIMITED_METHOD_CONTRACT;
1566 m_pChunks.SetValueMaybeNull(pChunks);
1568 #endif // !DACCESS_COMPILE
1569 void AddChunk (MethodDescChunk* pNewChunk);
1571 void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1573 inline PTR_GuidInfo GetGuidInfo()
1575 LIMITED_METHOD_DAC_CONTRACT;
1577 return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1580 inline void SetGuidInfo(GuidInfo* pGuidInfo)
1582 WRAPPER_NO_CONTRACT;
1583 #ifndef DACCESS_COMPILE
1584 EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1585 #endif // DACCESS_COMPILE
1588 // Cached class level reliability contract info, see ConstrainedExecutionRegion.cpp for details.
1589 DWORD GetReliabilityContract();
1592 #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
1593 // Get number of eightbytes used by a struct passed in registers.
1594 inline int GetNumberEightBytes()
1596 LIMITED_METHOD_CONTRACT;
1597 _ASSERTE(HasOptionalFields());
1598 return GetOptionalFields()->m_numberEightBytes;
1601 // Get eightbyte classification for the eightbyte with the specified index.
1602 inline SystemVClassificationType GetEightByteClassification(int index)
1604 LIMITED_METHOD_CONTRACT;
1605 _ASSERTE(HasOptionalFields());
1606 return GetOptionalFields()->m_eightByteClassifications[index];
1609 // Get size of the data in the eightbyte with the specified index.
1610 inline unsigned int GetEightByteSize(int index)
1612 LIMITED_METHOD_CONTRACT;
1613 _ASSERTE(HasOptionalFields());
1614 return GetOptionalFields()->m_eightByteSizes[index];
1617 // Set the eightByte classification
1618 inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1620 LIMITED_METHOD_CONTRACT;
1621 _ASSERTE(HasOptionalFields());
1622 GetOptionalFields()->m_numberEightBytes = eightByteCount;
1623 for (int i = 0; i < eightByteCount; i++)
1625 GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1626 GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1629 #endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
1631 #if defined(FEATURE_HFA)
1632 bool CheckForHFA(MethodTable ** pByValueClassCache);
1633 VOID CheckForNativeHFA();
1634 #else // !FEATURE_HFA
1636 #endif // FEATURE_HFA
1638 #ifdef FEATURE_COMINTEROP
1639 inline TypeHandle GetCoClassForInterface()
1641 LIMITED_METHOD_CONTRACT;
1642 _ASSERTE(HasOptionalFields());
1643 return GetOptionalFields()->m_pCoClassForIntf;
1646 inline void SetCoClassForInterface(TypeHandle th)
1648 WRAPPER_NO_CONTRACT;
1649 _ASSERTE(HasOptionalFields());
1650 *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1653 inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1655 LIMITED_METHOD_CONTRACT;
1656 return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1657 : WinMDAdapter::RedirectedTypeIndex_Invalid;
1660 inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1662 LIMITED_METHOD_CONTRACT;
1663 _ASSERTE(HasOptionalFields());
1664 _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1665 GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1667 #endif // FEATURE_COMINTEROP
1669 inline UINT32 GetNativeSize()
1671 LIMITED_METHOD_DAC_CONTRACT;
1672 return m_cbNativeSize;
1674 static UINT32 GetOffsetOfNativeSize()
1676 LIMITED_METHOD_CONTRACT;
1677 return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1679 void SetNativeSize(UINT32 nativeSize)
1681 LIMITED_METHOD_CONTRACT;
1682 m_cbNativeSize = nativeSize;
1684 #ifdef FEATURE_COMINTEROP
1685 OBJECTHANDLE GetOHDelegate()
1687 LIMITED_METHOD_CONTRACT;
1688 return m_ohDelegate;
1690 void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1692 LIMITED_METHOD_CONTRACT;
1693 m_ohDelegate = _ohDelegate;
1695 // Set the COM interface type.
1696 CorIfaceAttr GetComInterfaceType()
1698 LIMITED_METHOD_CONTRACT;
1699 return m_ComInterfaceType;
1702 void SetComInterfaceType(CorIfaceAttr ItfType)
1704 WRAPPER_NO_CONTRACT;
1705 _ASSERTE(IsInterface());
1706 EnsureWritablePages(this);
1707 m_ComInterfaceType = ItfType;
1710 inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1712 LIMITED_METHOD_CONTRACT;
1713 return m_pccwTemplate;
1715 inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1717 WRAPPER_NO_CONTRACT;
1718 return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1721 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1722 inline ClassFactoryBase *GetComClassFactory()
1724 LIMITED_METHOD_CONTRACT;
1725 return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1727 inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1729 WRAPPER_NO_CONTRACT;
1730 _ASSERTE(HasOptionalFields());
1731 return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1733 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1734 #endif // FEATURE_COMINTEROP
1738 PTR_DictionaryLayout GetDictionaryLayout()
1741 WRAPPER_NO_CONTRACT;
1742 return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1745 void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1748 WRAPPER_NO_CONTRACT;
1749 _ASSERTE(HasOptionalFields());
1750 GetOptionalFields()->m_pDictLayout = pLayout;
1753 #ifndef DACCESS_COMPILE
1754 static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1756 LIMITED_METHOD_CONTRACT;
1757 if (pbVarianceInfo == NULL)
1758 return gpNonVariant;
1760 return (CorGenericParamAttr) (pbVarianceInfo[i]);
1763 CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1765 WRAPPER_NO_CONTRACT;
1766 return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1769 BYTE* GetVarianceInfo()
1771 LIMITED_METHOD_CONTRACT;
1772 return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1775 void SetVarianceInfo(BYTE *pVarianceInfo)
1777 LIMITED_METHOD_CONTRACT;
1778 _ASSERTE(HasOptionalFields());
1779 GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1781 #endif // !DACCESS_COMPILE
1783 // Check that a signature blob uses type parameters correctly
1784 // in accordance with the variance annotations specified by this class
1785 // The position parameter indicates the variance of the context we're in
1786 // (result type is gpCovariant, argument types are gpContravariant, deeper in a signature
1787 // we might be gpNonvariant e.g. in a pointer type or non-variant generic type)
1790 DWORD numGenericArgs,
1791 BYTE *pVarianceInfo,
1794 CorGenericParamAttr position);
1799 AUXFLAG_APP_DOMAIN_AGILE = 0x00000001,
1800 AUXFLAG_CHECK_APP_DOMAIN_AGILE = 0x00000002,
1801 AUXFLAG_APP_DOMAIN_AGILITY_DONE = 0x00000004,
1802 AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1805 inline DWORD GetAuxFlagsRaw()
1807 LIMITED_METHOD_CONTRACT;
1810 inline DWORD* GetAuxFlagsPtr()
1812 LIMITED_METHOD_CONTRACT;
1813 return (DWORD*)(&m_wAuxFlags);
1815 inline void SetAuxFlags(DWORD flag)
1817 LIMITED_METHOD_CONTRACT;
1818 m_wAuxFlags |= (WORD)flag;
1821 // This flag is set (in a checked build only?) for classes whose
1822 // instances are always app domain agile. This can
1823 // be either because of type system guarantees or because
1824 // the class is explicitly marked.
1825 inline BOOL IsAppDomainAgile()
1827 LIMITED_METHOD_CONTRACT;
1828 return (m_wAuxFlags & AUXFLAG_APP_DOMAIN_AGILE);
1830 inline void SetAppDomainAgile()
1832 LIMITED_METHOD_CONTRACT;
1833 m_wAuxFlags |= AUXFLAG_APP_DOMAIN_AGILE;
1835 // This flag is set in a checked build for classes whose
1836 // instances may be marked app domain agile, but agility
1837 // isn't guaranteed by type safety. The JIT will compile
1838 // in extra checks to field assignment on some fields
1840 inline BOOL IsCheckAppDomainAgile()
1842 LIMITED_METHOD_CONTRACT;
1843 return (m_wAuxFlags & AUXFLAG_CHECK_APP_DOMAIN_AGILE);
1846 inline void SetCheckAppDomainAgile()
1848 LIMITED_METHOD_CONTRACT;
1849 m_wAuxFlags |= AUXFLAG_CHECK_APP_DOMAIN_AGILE;
1852 // This flag is set in a checked build to indicate that the
1853 // appdomain agility for a class had been set. This is used
1854 // for debugging purposes to make sure that we don't allocate
1855 // an object before the agility is set.
1856 inline BOOL IsAppDomainAgilityDone()
1858 LIMITED_METHOD_CONTRACT;
1859 return (m_wAuxFlags & AUXFLAG_APP_DOMAIN_AGILITY_DONE);
1861 inline void SetAppDomainAgilityDone()
1863 LIMITED_METHOD_CONTRACT;
1864 m_wAuxFlags |= AUXFLAG_APP_DOMAIN_AGILITY_DONE;
1867 // This predicate checks whether or not the class is "naturally"
1868 // app domain agile - that is:
1869 // (1) it is in the system domain
1870 // (2) all the fields are app domain agile
1871 // (3) it has no finalizer
1873 // Or, this also returns true for a proxy type which is allowed
1874 // to have cross app domain refs.
1876 inline BOOL IsTypesafeAppDomainAgile()
1878 LIMITED_METHOD_CONTRACT;
1879 return IsAppDomainAgile() && !IsCheckAppDomainAgile();
1882 // This predictate tests whether any instances are allowed
1883 // to be app domain agile.
1885 inline BOOL IsNeverAppDomainAgile()
1887 LIMITED_METHOD_CONTRACT;
1888 return !IsAppDomainAgile() && !IsCheckAppDomainAgile();
1890 static void SetAppDomainAgileAttribute(MethodTable * pMT);
1892 static void GetPredefinedAgility(Module *pModule, mdTypeDef td, BOOL *pfIsAgile, BOOL *pfIsCheckAgile);
1893 #endif // defined(_DEBUG)
1895 //-------------------------------------------------------------
1896 // CONCRETE DATA LAYOUT
1898 // Although accessed far less frequently than MethodTables, EEClasses are still
1899 // pulled into working set, especially at startup. This has motivated several space
1900 // optimizations in field layout where each is balanced against the need to access
1901 // a particular field efficiently.
1903 // Currently, the following strategy is used:
1905 // - Any field that has a default value for the vast majority of EEClass instances
1906 // should be stored in the EEClassOptionalFields (see header comment)
1908 // - Any field that is nearly always a small positive integer and is infrequently
1909 // accessed should be in the EEClassPackedFields (see header comment)
1911 // If none of these categories apply - such as for always-meaningful pointer members or
1912 // sets of flags - a full field is used. Please avoid adding such members if possible.
1913 //-------------------------------------------------------------
1915 // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1917 // Flags for m_VMFlags
1922 #ifdef FEATURE_READYTORUN
1923 VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
1925 VMFLAG_DELEGATE = 0x00000002,
1927 // VMFLAG_UNUSED = 0x0000001c,
1929 VMFLAG_FIXED_ADDRESS_VT_STATICS = 0x00000020, // Value type Statics in this class will be pinned
1930 VMFLAG_HASLAYOUT = 0x00000040,
1931 VMFLAG_ISNESTED = 0x00000080,
1933 VMFLAG_IS_EQUIVALENT_TYPE = 0x00000200,
1935 // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
1936 VMFLAG_HASOVERLAYEDFIELDS = 0x00000400,
1938 // Set this if this class or its parent have instance fields which
1939 // must be explicitly inited in a constructor (e.g. pointers of any
1940 // kind, gc or native).
1942 // Currently this is used by the verifier when verifying value classes
1943 // - it's ok to use uninitialised value classes if there are no
1944 // pointer fields in them.
1945 VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED = 0x00000800,
1947 VMFLAG_UNSAFEVALUETYPE = 0x00001000,
1949 VMFLAG_BESTFITMAPPING_INITED = 0x00002000, // VMFLAG_BESTFITMAPPING and VMFLAG_THROWONUNMAPPABLECHAR are valid only if this is set
1950 VMFLAG_BESTFITMAPPING = 0x00004000, // BestFitMappingAttribute.Value
1951 VMFLAG_THROWONUNMAPPABLECHAR = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar
1953 // unused = 0x00010000,
1954 VMFLAG_NO_GUID = 0x00020000,
1955 VMFLAG_HASNONPUBLICFIELDS = 0x00040000,
1956 // unused = 0x00080000,
1957 VMFLAG_CONTAINS_STACK_PTR = 0x00100000,
1958 VMFLAG_PREFER_ALIGN8 = 0x00200000, // Would like to have 8-byte alignment
1959 // unused = 0x00400000,
1961 #ifdef FEATURE_COMINTEROP
1962 VMFLAG_SPARSE_FOR_COMINTEROP = 0x00800000,
1963 // interfaces may have a coclass attribute
1964 VMFLAG_HASCOCLASSATTRIB = 0x01000000,
1965 VMFLAG_COMEVENTITFMASK = 0x02000000, // class is a special COM event interface
1966 VMFLAG_PROJECTED_FROM_WINRT = 0x04000000,
1967 VMFLAG_EXPORTED_TO_WINRT = 0x08000000,
1968 #endif // FEATURE_COMINTEROP
1970 // This one indicates that the fields of the valuetype are
1971 // not tightly packed and is used to check whether we can
1972 // do bit-equality on value types to implement ValueType::Equals.
1973 // It is not valid for classes, and only matters if ContainsPointer
1975 VMFLAG_NOT_TIGHTLY_PACKED = 0x10000000,
1977 // True if methoddesc on this class have any real (non-interface) methodimpls
1978 VMFLAG_CONTAINS_METHODIMPLS = 0x20000000,
1980 #ifdef FEATURE_COMINTEROP
1981 VMFLAG_MARSHALINGTYPE_MASK = 0xc0000000,
1983 VMFLAG_MARSHALINGTYPE_INHIBIT = 0x40000000,
1984 VMFLAG_MARSHALINGTYPE_FREETHREADED = 0x80000000,
1985 VMFLAG_MARSHALINGTYPE_STANDARD = 0xc0000000,
1990 // C_ASSERTs in Jitinterface.cpp need this to be public to check the offset.
1991 // Put it first so the offset rarely changes, which just reduces the number of times we have to fiddle
1993 RelativePointer<PTR_GuidInfo> m_pGuidInfo; // The cached guid information for interfaces.
1997 LPCUTF8 m_szDebugClassName;
1998 BOOL m_fDebuggingClass;
2002 // Layout rest of fields below from largest to smallest to lessen the chance of wasting bytes with
2003 // compiler injected padding (especially with the difference between pointers and DWORDs on 64-bit).
2004 RelativePointer<PTR_EEClassOptionalFields> m_rpOptionalFields;
2006 // TODO: Remove this field. It is only used by SOS and object validation for stress.
2007 RelativePointer<PTR_MethodTable> m_pMethodTable;
2009 RelativePointer<PTR_FieldDesc> m_pFieldDescList;
2010 RelativePointer<PTR_MethodDescChunk> m_pChunks;
2014 // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
2015 UINT32 m_cbNativeSize; // size of fixed portion in bytes
2017 #ifdef FEATURE_COMINTEROP
2018 // For COM+ wrapper objects that extend an unmanaged class, this field
2019 // may contain a delegate to be called to allocate the aggregated
2020 // unmanaged class (instead of using CoCreateInstance).
2021 OBJECTHANDLE m_ohDelegate;
2023 // For interfaces this contains the COM interface type.
2024 CorIfaceAttr m_ComInterfaceType;
2025 #endif // FEATURE_COMINTEROP
2028 #ifdef FEATURE_COMINTEROP
2029 ComCallWrapperTemplate *m_pccwTemplate; // points to interop data structures used when this type is exposed to COM
2030 #endif // FEATURE_COMINTEROP
2032 DWORD m_dwAttrClass;
2036 * We maintain some auxillary flags in DEBUG builds,
2037 * this frees up some bits in m_wVMFlags
2043 // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
2044 // structure packing.
2046 BYTE m_fFieldsArePacked; // TRUE iff fields pointed to by GetPackedFields() are in packed state
2047 BYTE m_cbFixedEEClassFields; // Count of bytes of normal fields of this instance (EEClass,
2048 // LayoutEEClass etc.). Doesn't count bytes of "packed" fields
2049 BYTE m_cbBaseSizePadding; // How many bytes of padding are included in BaseSize
2052 // EEClass optional field support. Whether a particular EEClass instance has optional fields is determined
2053 // at class load time. The entire EEClassOptionalFields structure is allocated if the EEClass has need of
2054 // one or more optional fields.
2056 #ifndef DACCESS_COMPILE
2057 void AttachOptionalFields(EEClassOptionalFields *pFields)
2059 LIMITED_METHOD_CONTRACT;
2060 _ASSERTE(m_rpOptionalFields.IsNull());
2062 m_rpOptionalFields.SetValue(pFields);
2064 #endif // !DACCESS_COMPILE
2066 bool HasOptionalFields()
2068 LIMITED_METHOD_DAC_CONTRACT;
2069 return !m_rpOptionalFields.IsNull();
2072 PTR_EEClassOptionalFields GetOptionalFields()
2074 LIMITED_METHOD_DAC_CONTRACT;
2075 return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
2080 // Support for packed fields.
2083 // Get pointer to the packed fields structure attached to this instance.
2084 PTR_EEClassPackedFields GetPackedFields();
2086 // Get the value of the given field. Works regardless of whether the field is currently in its packed or
2088 DWORD GetPackableField(EEClassFieldId eField);
2090 // Set the value of the given field. The field *must* be in the unpacked state for this to be legal (in
2091 // practice all packable fields must be initialized during class construction and from then on remain
2093 void SetPackableField(EEClassFieldId eField, DWORD dwValue);
2095 //-------------------------------------------------------------
2096 // END CONCRETE DATA LAYOUT
2097 //-------------------------------------------------------------
2101 /************************************
2103 ************************************/
2105 #ifndef DACCESS_COMPILE
2107 * Constructor: prevent any other class from doing a new()
2109 EEClass(DWORD cbFixedEEClassFields);
2112 * Destructor: prevent any other class from deleting
2116 LIMITED_METHOD_CONTRACT;
2118 #endif // !DACCESS_COMPILE
2122 // --------------------------------------------------------------------------------------------
2123 template <typename Data>
2124 class FixedCapacityStackingAllocatedUTF8StringHash
2130 HashEntry * m_pNext; // Next item with same bucketed hash value
2131 DWORD m_dwHashValue; // Hash value
2132 LPCUTF8 m_pKey; // String key
2133 Data m_data; // Data
2136 HashEntry ** m_pBuckets; // Pointer to first entry for each bucket
2137 DWORD m_dwNumBuckets;
2138 BYTE * m_pMemory; // Current pointer into preallocated memory for entries
2139 BYTE * m_pMemoryStart; // Start pointer of pre-allocated memory fo entries
2141 INDEBUG(BYTE * m_pDebugEndMemory;)
2143 FixedCapacityStackingAllocatedUTF8StringHash()
2144 : m_pMemoryStart(NULL)
2145 { LIMITED_METHOD_CONTRACT; }
2150 { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2156 StackingAllocator * pAllocator);
2158 // Insert new entry at head of list
2164 // Return the first matching entry in the list, or NULL if there is no such entry
2169 // Return the next matching entry in the list, or NULL if there is no such entry.
2172 HashEntry * pEntry);
2176 //---------------------------------------------------------------------------------------
2178 class LayoutEEClass : public EEClass
2181 EEClassLayoutInfo m_LayoutInfo;
2183 #ifndef DACCESS_COMPILE
2184 LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2186 LIMITED_METHOD_CONTRACT;
2188 FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2191 #endif // !DACCESS_COMPILE
2194 class UMThunkMarshInfo;
2196 #ifdef FEATURE_COMINTEROP
2197 struct ComPlusCallInfo;
2198 #endif // FEATURE_COMINTEROP
2200 class DelegateEEClass : public EEClass
2203 PTR_Stub m_pStaticCallStub;
2204 PTR_Stub m_pInstRetBuffCallStub;
2205 RelativePointer<PTR_MethodDesc> m_pInvokeMethod;
2206 PTR_Stub m_pMultiCastInvokeStub;
2207 PTR_Stub m_pSecureDelegateInvokeStub;
2208 UMThunkMarshInfo* m_pUMThunkMarshInfo;
2209 RelativePointer<PTR_MethodDesc> m_pBeginInvokeMethod;
2210 RelativePointer<PTR_MethodDesc> m_pEndInvokeMethod;
2211 Volatile<PCODE> m_pMarshalStub;
2213 #ifdef FEATURE_COMINTEROP
2214 ComPlusCallInfo *m_pComPlusCallInfo;
2215 #endif // FEATURE_COMINTEROP
2218 // Ngened IL stub MethodDescs. Fixed up, wrapped with code:Stub, and installed to
2219 // m_pMarshalStub (forward) or m_pUMThunkMarshInfo (reverse) when first needed.
2221 MethodDesc* m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2222 MethodDesc* m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2224 PTR_MethodDesc GetInvokeMethod()
2226 return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2229 PTR_MethodDesc GetBeginInvokeMethod()
2231 return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2234 PTR_MethodDesc GetEndInvokeMethod()
2236 return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2239 #ifndef DACCESS_COMPILE
2240 DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2242 LIMITED_METHOD_CONTRACT;
2243 // Note: Memory allocated on loader heap is zero filled
2246 // We need a LoaderHeap that lives at least as long as the DelegateEEClass, but ideally no longer
2247 LoaderHeap *GetStubHeap();
2248 #endif // !DACCESS_COMPILE
2253 typedef DPTR(ArrayClass) PTR_ArrayClass;
2256 // Dynamically generated array class structure
2257 class ArrayClass : public EEClass
2259 #ifdef FEATURE_PREJIT
2260 friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2263 friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2265 #ifndef DACCESS_COMPILE
2266 ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2268 friend class NativeImageDumper;
2273 unsigned char m_rank;
2274 CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd
2278 LIMITED_METHOD_CONTRACT;
2282 void SetRank (unsigned Rank) {
2283 LIMITED_METHOD_CONTRACT;
2284 // The only code path calling this function is code:ClassLoader::CreateTypeHandleForTypeKey, which has
2285 // checked the rank already. Assert that the rank is less than MAX_RANK and that it fits in one byte.
2286 _ASSERTE((Rank <= MAX_RANK) && (Rank <= (unsigned char)(-1)));
2287 m_rank = (unsigned char)Rank;
2290 CorElementType GetArrayElementType() {
2291 LIMITED_METHOD_CONTRACT;
2292 return m_ElementType;
2294 void SetArrayElementType(CorElementType ElementType) {
2295 LIMITED_METHOD_CONTRACT;
2296 m_ElementType = ElementType;
2300 // Allocate a new MethodDesc for the methods we add to this class
2301 void InitArrayMethodDesc(
2302 ArrayMethodDesc* pNewMD,
2303 PCCOR_SIGNATURE pShortSig,
2306 LoaderAllocator *pLoaderAllocator,
2307 AllocMemTracker *pamTracker);
2309 // Generate a short sig for an array accessor
2310 VOID GenerateArrayAccessorCallSig(DWORD dwRank,
2311 DWORD dwFuncType, // Load, store, or <init>
2312 PCCOR_SIGNATURE *ppSig, // Generated signature
2313 DWORD * pcSig, // Generated signature size
2314 LoaderAllocator *pLoaderAllocator,
2315 AllocMemTracker *pamTracker
2316 #ifdef FEATURE_ARRAYSTUB_AS_IL
2324 inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2326 LIMITED_METHOD_CONTRACT;
2327 _ASSERTE(HasLayout());
2328 return &((LayoutEEClass *) this)->m_LayoutInfo;
2331 inline BOOL EEClass::IsBlittable()
2333 LIMITED_METHOD_CONTRACT;
2335 // Either we have an opaque bunch of bytes, or we have some fields that are
2336 // all isomorphic and explicitly layed out.
2337 return (HasLayout() && GetLayoutInfo()->IsBlittable());
2340 inline BOOL EEClass::IsManagedSequential()
2342 LIMITED_METHOD_CONTRACT;
2343 return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2346 inline BOOL EEClass::HasExplicitSize()
2348 LIMITED_METHOD_CONTRACT;
2349 return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2352 //==========================================================================
2353 // These routines manage the prestub (a bootstrapping stub that all
2354 // FunctionDesc's are initialized with.)
2355 //==========================================================================
2356 VOID InitPreStubManager();
2358 EXTERN_C void STDCALL ThePreStub();
2360 inline PCODE GetPreStubEntryPoint()
2362 return GetEEFuncEntryPoint(ThePreStub);
2365 #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2367 EXTERN_C void STDCALL ThePreStubCompactARM();
2369 inline PCODE GetPreStubCompactARMEntryPoint()
2371 return GetEEFuncEntryPoint(ThePreStubCompactARM);
2374 #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2376 PCODE TheUMThunkPreStub();
2378 PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
2382 // workaround: These classification bits need cleanup bad: for now, this gets around
2383 // IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
2384 #define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
2387 // The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
2388 // methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
2391 #define METH_NAME_CACHE_SIZE 5
2392 #define MAX_MISSES 3
2394 #ifdef EnC_SUPPORTED
2396 struct EnCAddedFieldElement;
2398 #endif // EnC_SUPPORTED
2401 // --------------------------------------------------------------------------------------------
2402 // For generic instantiations the FieldDescs stored for instance
2403 // fields are approximate, not exact, i.e. they are representatives owned by
2404 // canonical instantiation and they do not carry exact type information.
2405 // This will not include EnC related fields. (See EncApproxFieldDescIterator for that)
2406 class ApproxFieldDescIterator
2410 PTR_FieldDesc m_pFieldDescList;
2416 INSTANCE_FIELDS = 0x1,
2417 STATIC_FIELDS = 0x2,
2418 ALL_FIELDS = (INSTANCE_FIELDS | STATIC_FIELDS)
2420 ApproxFieldDescIterator();
2421 ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2424 Init(pMT, iteratorType);
2426 void Init(MethodTable *pMT, int iteratorType);
2427 PTR_FieldDesc Next();
2429 int GetIteratorType() {
2430 LIMITED_METHOD_CONTRACT;
2432 return m_iteratorType;
2436 LIMITED_METHOD_CONTRACT;
2437 return m_totalFields;
2439 int CountRemaining() {
2440 LIMITED_METHOD_CONTRACT;
2442 return m_totalFields - m_currField - 1;
2447 // DeepFieldDescIterator iterates over the entire
2448 // set of fields available to a class, inherited or
2452 class DeepFieldDescIterator
2455 ApproxFieldDescIterator m_fieldIter;
2458 MethodTable* m_classes[16];
2459 int m_deepTotalFields;
2460 bool m_lastNextFromParentClass;
2465 DeepFieldDescIterator()
2467 LIMITED_METHOD_CONTRACT;
2471 m_deepTotalFields = 0;
2472 m_lastNextFromParentClass = false;
2474 DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2475 bool includeParents = true)
2477 WRAPPER_NO_CONTRACT;
2479 Init(pMT, iteratorType, includeParents);
2481 void Init(MethodTable* pMT, int iteratorType,
2482 bool includeParents = true);
2486 bool Skip(int numSkip);
2490 LIMITED_METHOD_CONTRACT;
2491 return m_deepTotalFields;
2493 bool IsFieldFromParentClass()
2495 LIMITED_METHOD_CONTRACT;
2496 return m_lastNextFromParentClass;