1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
11 // NOTE: Even though EEClass is considered to contain cold data (relative to MethodTable), these data
12 // structures *are* touched (especially during startup as part of soft-binding). As a result, and given the
13 // number of EEClasses allocated for large assemblies, the size of this structure can have a direct impact on
14 // performance, especially startup performance.
16 // Given that the data itself is touched infrequently, we can trade off space reduction against cpu-usage to
17 // good effect here. A fair amount of work has gone into reducing the size of each EEClass instance (see
18 // EEClassOptionalFields and EEClassPackedFields) at the expense of somewhat more convoluted runtime access.
20 // Please consider this (and measure the impact of your changes against startup scenarios) before adding
21 // fields to EEClass or otherwise increasing its size.
23 // ============================================================================
31 #include "eecontract.h"
39 #ifdef FEATURE_COMINTEROP
40 #include "stdinterfaces.h"
44 #include "typehandle.h"
45 #include "methodtable.h"
48 #include "iterator_util.h"
50 #ifdef FEATURE_COMINTEROP
51 #include "..\md\winmd\inc\adapter.h"
53 #include "packedfields.inl"
55 #define IBCLOG(x) g_IBCLogger.##x
57 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
62 #define MAX_LOG2_PRIMITIVE_FIELD_SIZE 3
64 #define MAX_PRIMITIVE_FIELD_SIZE (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
67 * Forward declarations
71 class ArrayMethodDesc;
74 class DictionaryLayout;
75 class DomainLocalBlock;
76 class FCallMethodDesc;
81 struct LayoutRawFieldInfo;
84 class MethodDescChunk;
87 struct ModuleCtorInfo;
93 class StackingAllocator;
94 class AllocMemTracker;
95 class InteropMethodTableSlotDataMap;
96 class LoadingEntry_LockHolder;
97 class DispatchMapBuilder;
98 class LoaderAllocator;
99 class ComCallWrapperTemplate;
101 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
102 typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
105 //---------------------------------------------------------------------------------
106 // Fields in an explicit-layout class present varying degrees of risk depending
107 // on how they overlap.
109 // Each level is a superset of the lower (in numerical value) level - i.e.
110 // all kVerifiable fields are also kLegal, but not vice-versa.
111 //---------------------------------------------------------------------------------
112 class ExplicitFieldTrust
117 // Note: order is important here - each guarantee also implicitly guarantees all promises
118 // made by values lower in number.
120 // What's guaranteed. What the loader does.
121 //----- ----------------------- -------------------------------
122 kNone = 0, // no guarantees at all - Type refuses to load at all.
123 kLegal = 1, // guarantees no objref <-> scalar overlap and no unaligned objref - Type loads but field access won't verify
124 kVerifiable = 2, // guarantees no objref <-> objref overlap and all guarantees above - Type loads and field access will verify
125 kNonOverLayed = 3, // guarantees no overlap at all and all guarantees above - Type loads, field access verifies and Equals() may be optimized if structure is tightly packed
127 kMaxTrust = kNonOverLayed,
132 //----------------------------------------------------------------------------------------------
133 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
134 // into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
135 // class. This abstraction enforces the rule that the overall class is only as trustworthy as
136 // the least trustworthy field.
137 //----------------------------------------------------------------------------------------------
138 class ExplicitClassTrust : private ExplicitFieldTrust
143 LIMITED_METHOD_CONTRACT;
144 m_trust = kMaxTrust; // Yes, we start out with maximal trust. This reflects that explicit layout structures with no fields do represent no risk.
147 VOID AddField(TrustLevel fieldTrust)
149 LIMITED_METHOD_CONTRACT;
150 m_trust = min(m_trust, fieldTrust);
155 LIMITED_METHOD_CONTRACT;
156 return m_trust >= kLegal;
161 LIMITED_METHOD_CONTRACT;
162 return m_trust >= kVerifiable;
165 BOOL IsNonOverLayed()
167 LIMITED_METHOD_CONTRACT;
168 return m_trust >= kNonOverLayed;
171 TrustLevel GetTrustLevel()
173 LIMITED_METHOD_CONTRACT;
181 //----------------------------------------------------------------------------------------------
182 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
183 // into this function, this class will collect trust information about individual fields to be later
184 // aggregated into the overall class level.
186 // This abstraction enforces the rule that all fields are presumed guilty until explicitly declared
187 // safe by calling SetTrust(). If you fail to call SetTrust before leaving the block, the destructor
188 // will automatically cause the entire class to be declared illegal (and you will get an assert
189 // telling you to fix this bug.)
190 //----------------------------------------------------------------------------------------------
191 class ExplicitFieldTrustHolder : private ExplicitFieldTrust
194 ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
196 LIMITED_METHOD_CONTRACT;
197 m_pExplicitClassTrust = pExplicitClassTrust;
199 m_trustDeclared = FALSE;
201 m_fieldTrust = kNone;
204 VOID SetTrust(TrustLevel fieldTrust)
206 LIMITED_METHOD_CONTRACT;
208 _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
209 _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
212 m_trustDeclared = TRUE;
214 m_fieldTrust = fieldTrust;
217 ~ExplicitFieldTrustHolder()
219 LIMITED_METHOD_CONTRACT;
220 // If no SetTrust() was ever called, we will default to kNone (i.e. declare the entire type
221 // illegal.) It'd be nice to assert here but since this case can be legitimately reached
222 // on exception unwind, we cannot.
223 m_pExplicitClassTrust->AddField(m_fieldTrust);
228 ExplicitClassTrust* m_pExplicitClassTrust;
229 TrustLevel m_fieldTrust;
231 BOOL m_trustDeclared; // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
235 //*******************************************************************************
236 // Enumerator to traverse the interface declarations of a type, automatically building
237 // a substitution chain on the stack.
238 class InterfaceImplEnum
241 HENUMInternalHolder hEnumInterfaceImpl;
242 const Substitution *m_pSubstChain;
243 Substitution m_CurrSubst;
246 InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
247 : hEnumInterfaceImpl(pModule->GetMDImport())
251 hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
252 m_pSubstChain = pSubstChain;
256 // S_OK ... if has next (TRUE)
257 // S_FALSE ... if does not have next (FALSE)
264 if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
269 IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
270 m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
273 const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
274 mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
277 #ifdef FEATURE_COMINTEROP
279 // Class used to map MethodTable slot numbers to COM vtable slots numbers
280 // (either for calling a classic COM component or for constructing a classic COM
281 // vtable via which COM components can call managed classes). This structure is
282 // embedded in the EEClass but the mapping list itself is only allocated if the
283 // COM vtable is sparse.
286 class SparseVTableMap
289 #ifdef DACCESS_COMPILE
290 friend class NativeImageDumper;
296 // First run through MT slots calling RecordGap wherever a gap in VT slots
298 void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
300 // Then call FinalizeMapping to create the actual mapping list.
301 void FinalizeMapping(WORD TotalMTSlots);
303 // Map MT to VT slot.
304 WORD LookupVTSlot(WORD MTSlot);
306 // Retrieve the number of slots in the vtable (both empty and full).
307 WORD GetNumVTableSlots();
309 const void* GetMapList()
311 LIMITED_METHOD_CONTRACT;
312 return (void*)m_MapList;
315 #ifdef FEATURE_PREJIT
316 // Methods to persist structure
317 void Save(DataImage *image);
318 void Fixup(DataImage *image);
319 #endif // FEATURE_PREJIT
323 enum { MapGrow = 4 };
327 WORD m_Start; // Starting MT slot number
328 WORD m_Span; // # of consecutive slots that map linearly
329 WORD m_MapTo; // Starting VT slot number
332 Entry *m_MapList; // Pointer to array of Entry structures
333 WORD m_MapEntries; // Number of entries in above
334 WORD m_Allocated; // Number of entries allocated
336 WORD m_LastUsed; // Index of last entry used in successful lookup
338 WORD m_VTSlot; // Current VT slot number, used during list build
339 WORD m_MTSlot; // Current MT slot number, used during list build
341 void AllocOrExpand(); // Allocate or expand the mapping list for a new entry
343 #endif // FEATURE_COMINTEROP
345 //=======================================================================
346 // Adjunct to the EEClass structure for classes w/ layout
347 //=======================================================================
348 class EEClassLayoutInfo
350 static VOID CollectLayoutFieldMetadataThrowing(
351 mdTypeDef cl, // cl of the NStruct being loaded
352 BYTE packingSize, // packing size (from @dll.struct)
353 BYTE nlType, // nltype (from @dll.struct)
354 #ifdef FEATURE_COMINTEROP
355 BOOL isWinRT, // Is the type a WinRT type
356 #endif // FEATURE_COMINTEROP
357 BOOL fExplicitOffsets, // explicit offsets?
358 MethodTable *pParentMT, // the loaded superclass
359 ULONG cTotalFields, // total number of fields (instance and static)
360 HENUMInternal *phEnumField, // enumerator for field
361 Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
362 const SigTypeContext *pTypeContext, // Type parameters for NStruct being loaded
363 EEClassLayoutInfo *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
364 LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in. Needs room for cMember+1 elements
365 LoaderAllocator * pAllocator,
366 AllocMemTracker *pamTracker
370 friend class ClassLoader;
371 friend class EEClass;
372 friend class MethodTableBuilder;
373 #ifdef DACCESS_COMPILE
374 friend class NativeImageDumper;
378 // size (in bytes) of fixed portion of NStruct.
379 UINT32 m_cbNativeSize;
380 UINT32 m_cbManagedSize;
383 // 1,2,4 or 8: this is equal to the largest of the alignment requirements
384 // of each of the EEClass's members. If the NStruct extends another NStruct,
385 // the base NStruct is treated as the first member for the purpose of
387 BYTE m_LargestAlignmentRequirementOfAllMembers;
389 // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
390 // for the managed layout.
391 BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
395 // TRUE if the GC layout of the class is bit-for-bit identical
396 // to its unmanaged counterpart (i.e. no internal reference fields,
397 // no ansi-unicode char conversions required, etc.) Used to
398 // optimize marshaling.
400 // Post V1.0 addition: Is this type also sequential in managed memory?
401 e_MANAGED_SEQUENTIAL = 0x02,
402 // When a sequential/explicit type has no fields, it is conceptually
403 // zero-sized, but actually is 1 byte in length. This holds onto this
404 // fact and allows us to revert the 1 byte of padding when another
405 // explicit type inherits from this type.
407 // The size of the struct is explicitly specified in the meta-data.
408 e_HAS_EXPLICIT_SIZE = 0x08,
409 #ifdef UNIX_AMD64_ABI
411 #error "Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time."
412 #endif // FEATURE_HFA
413 e_NATIVE_PASS_IN_REGISTERS = 0x10, // Flag wheter a native struct is passed in registers.
414 #endif // UNIX_AMD64_ABI
416 // HFA type of the unmanaged layout
424 // Packing size in bytes (1, 2, 4, 8 etc.)
425 BYTE m_cbPackingSize;
427 // # of fields that are of the calltime-marshal variety.
430 // An array of FieldMarshaler data blocks, used to drive call-time
431 // marshaling of NStruct reference parameters. The number of elements
432 // equals m_numCTMFields.
433 RelativePointer<PTR_FieldMarshaler> m_pFieldMarshalers;
437 BOOL GetNativeSize() const
439 LIMITED_METHOD_CONTRACT;
440 return m_cbNativeSize;
443 UINT32 GetManagedSize() const
445 LIMITED_METHOD_CONTRACT;
446 return m_cbManagedSize;
450 BYTE GetLargestAlignmentRequirementOfAllMembers() const
452 LIMITED_METHOD_CONTRACT;
453 return m_LargestAlignmentRequirementOfAllMembers;
456 UINT GetNumCTMFields() const
458 LIMITED_METHOD_CONTRACT;
459 return m_numCTMFields;
462 PTR_FieldMarshaler GetFieldMarshalers() const
464 LIMITED_METHOD_CONTRACT;
465 return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
468 #ifndef DACCESS_COMPILE
469 void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
471 LIMITED_METHOD_CONTRACT;
472 m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
474 #endif // DACCESS_COMPILE
476 BOOL IsBlittable() const
478 LIMITED_METHOD_CONTRACT;
479 return (m_bFlags & e_BLITTABLE) == e_BLITTABLE;
482 BOOL IsManagedSequential() const
484 LIMITED_METHOD_CONTRACT;
485 return (m_bFlags & e_MANAGED_SEQUENTIAL) == e_MANAGED_SEQUENTIAL;
488 // If true, this says that the type was originally zero-sized
489 // and the native size was bumped up to one for similar behaviour
490 // to C++ structs. However, it is necessary to keep track of this
491 // so that we can ignore the one byte padding if other types derive
492 // from this type, that we can
493 BOOL IsZeroSized() const
495 LIMITED_METHOD_CONTRACT;
496 return (m_bFlags & e_ZERO_SIZED) == e_ZERO_SIZED;
499 BOOL HasExplicitSize() const
501 LIMITED_METHOD_CONTRACT;
502 return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE;
505 DWORD GetPackingSize() const
507 LIMITED_METHOD_CONTRACT;
508 return m_cbPackingSize;
511 #ifdef UNIX_AMD64_ABI
512 bool IsNativeStructPassedInRegisters()
514 LIMITED_METHOD_CONTRACT;
515 return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
518 bool IsNativeStructPassedInRegisters()
522 #endif // UNIX_AMD64_ABI
524 CorElementType GetNativeHFATypeRaw();
528 LIMITED_METHOD_CONTRACT;
529 return (m_bFlags & (e_R4_HFA | e_R8_HFA)) != 0;
532 CorElementType GetNativeHFAType()
534 LIMITED_METHOD_CONTRACT;
536 return (m_bFlags & e_R4_HFA) ? ELEMENT_TYPE_R4 : ELEMENT_TYPE_R8;
537 return ELEMENT_TYPE_END;
539 #else // !FEATURE_HFA
542 return GetNativeHFATypeRaw() != ELEMENT_TYPE_END;
544 CorElementType GetNativeHFAType()
546 return GetNativeHFATypeRaw();
548 #endif // !FEATURE_HFA
551 void SetIsBlittable(BOOL isBlittable)
553 LIMITED_METHOD_CONTRACT;
554 m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
555 : (m_bFlags & ~e_BLITTABLE);
558 void SetIsManagedSequential(BOOL isManagedSequential)
560 LIMITED_METHOD_CONTRACT;
561 m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
562 : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
565 void SetIsZeroSized(BOOL isZeroSized)
567 LIMITED_METHOD_CONTRACT;
568 m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
569 : (m_bFlags & ~e_ZERO_SIZED);
572 void SetHasExplicitSize(BOOL hasExplicitSize)
574 LIMITED_METHOD_CONTRACT;
575 m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
576 : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
580 void SetNativeHFAType(CorElementType hfaType)
582 LIMITED_METHOD_CONTRACT;
583 m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA;
586 #ifdef UNIX_AMD64_ABI
587 void SetNativeStructPassedInRegisters()
589 LIMITED_METHOD_CONTRACT;
590 m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
592 #endif // UNIX_AMD64_ABI
599 // This structure is used only when the classloader is building the interface map. Before the class
600 // is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
601 // for this class/interface by the metadata - inherited interfaces will not be present if they are
602 // not specifically declared.
604 // This structure is destroyed after resolving has completed.
608 // The interface method table; for instantiated interfaces, this is the generic interface
609 MethodTable *m_pMethodTable;
610 } BuildingInterfaceInfo_t;
614 // We should not need to touch anything in here once the classes are all loaded, unless we
615 // are doing reflection. Try to avoid paging this data structure in.
618 // Size of hash bitmap for method names
619 #define METHOD_HASH_BYTES 8
621 // Hash table size - prime number
622 #define METHOD_HASH_BITS 61
625 // These are some macros for forming fully qualified class names for a class.
626 // These are abstracted so that we can decide later if a max length for a
627 // class name is acceptable.
629 // It doesn't make any sense not to have a small but usually quite capable
630 // stack buffer to build class names into. Most class names that I can think
631 // of would fit in 128 characters, and that's a pretty small amount of stack
632 // to use in exchange for not having to new and delete the memory.
633 #define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4)
635 #define DefineFullyQualifiedNameForClass() \
636 ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
637 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
639 #define DefineFullyQualifiedNameForClassOnStack() \
640 ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
641 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
643 #define DefineFullyQualifiedNameForClassW() \
644 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
646 #define DefineFullyQualifiedNameForClassWOnStack() \
647 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
649 #define GetFullyQualifiedNameForClassNestedAware(pClass) \
650 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
652 #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
653 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
655 #define GetFullyQualifiedNameForClass(pClass) \
656 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
658 #define GetFullyQualifiedNameForClassW(pClass) \
659 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
661 #define GetFullyQualifiedNameForClassW_WinRT(pClass) \
662 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
664 #define GetFullyQualifiedNameForClass_WinRT(pClass) \
665 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
667 // Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to
668 // save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached
669 // via the m_rpOptionalFields field EEClass (use the GetOptionalFields() accessor rather than the field
671 class EEClassOptionalFields
673 // All fields here are intentionally private. Use the corresponding accessor on EEClass instead (this
674 // makes it easier to add and remove fields from the optional section in the future). We make exceptions
675 // for MethodTableBuilder and NativeImageDumper, which need raw field-level access.
676 friend class EEClass;
677 friend class MethodTableBuilder;
678 #ifdef DACCESS_COMPILE
679 friend class NativeImageDumper;
683 // GENERICS RELATED FIELDS.
686 // If IsSharedByGenericInstantiations(), layout of handle dictionary for generic type
687 // (the last dictionary pointed to from PerInstInfo). Otherwise NULL.
688 PTR_DictionaryLayout m_pDictLayout;
690 // Variance info for each type parameter (gpNonVariant, gpCovariant, or gpContravariant)
691 // If NULL, this type has no type parameters that are co/contravariant
692 RelativePointer<PTR_BYTE> m_pVarianceInfo;
695 // COM RELATED FIELDS.
698 #ifdef FEATURE_COMINTEROP
699 SparseVTableMap *m_pSparseVTableMap;
701 TypeHandle m_pCoClassForIntf; // @TODO: Coclass for an interface
703 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
704 // Points to activation information if the type is an activatable COM/WinRT class.
705 ClassFactoryBase *m_pClassFactory;
706 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
708 WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
710 #endif // FEATURE_COMINTEROP
716 #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
717 DWORD m_cbModuleDynamicID;
719 #if defined(UNIX_AMD64_ABI)
720 // Number of eightBytes in the following arrays
721 int m_numberEightBytes;
722 // Classification of the eightBytes
723 SystemVClassificationType m_eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
724 // Size of data the eightBytes
725 unsigned int m_eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
726 #endif // UNIX_AMD64_ABI
728 // Set default values for optional fields.
731 PTR_BYTE GetVarianceInfo()
733 LIMITED_METHOD_DAC_CONTRACT;
735 return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
738 typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
741 // Another mechanism used to reduce the size of the average EEClass instance is the notion of packed fields.
742 // This is based on the observation that EEClass has a large number of integer fields that typically contain
743 // small values and that are fixed once class layout has completed. We can compact these fields by discarding
744 // the leading zero bits (and for small values there'll be a lot of these) and packing the significant data
745 // into compact bitfields. This is a dynamic operation (the exact packing used depends on the exact data
746 // stored in the fields).
748 // The PackedDWORDFields<> class (defined in PackedFields.inl) encapsulates this. It takes one template
749 // parameter, the number of fields to pack, and provides operations to get and set those fields until we're
750 // happy with the values, at which point it will compact them for us.
752 // The packed fields themselves are stored at the end of the EEClass instance (or the LayoutEEClass or the
753 // DelegateEEClass etc.) so we can take advantage of the variable sized nature of the fields. We gain nothing for
754 // runtime allocated EEClasses (we have to allocate a maximally sized structure for the packed fields because
755 // we can't tell at the beginning of EEClass layout what the field values will be). But in the ngen scenario
756 // we can compact the fields just prior to saving and only store the portion of the EEClass that is relvant,
757 // helping us with our goal of packing all the EEClass instances together as tightly as possible.
759 // Since each packed field is now accessed via an array-like index, we give each of those indices a name with
760 // the enum below to make the code more readable.
765 EEClass_Field_NumInstanceFields = 0,
766 EEClass_Field_NumMethods,
767 EEClass_Field_NumStaticFields,
768 EEClass_Field_NumHandleStatics,
769 EEClass_Field_NumBoxedStatics,
770 EEClass_Field_NonGCStaticFieldBytes,
771 EEClass_Field_NumThreadStaticFields,
772 EEClass_Field_NumHandleThreadStatics,
773 EEClass_Field_NumBoxedThreadStatics,
774 EEClass_Field_NonGCThreadStaticFieldBytes,
775 EEClass_Field_NumNonVirtualSlots,
779 typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
780 typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
783 // For most types there is a one-to-one mapping between MethodTable* and EEClass*
784 // However this is not the case for instantiated types where code and representation
785 // are shared between compatible instantiations (e.g. List<string> and List<object>)
786 // Then a single EEClass structure is shared between multiple MethodTable structures
787 // Uninstantiated generic types (e.g. List) have their own EEClass and MethodTable,
788 // used (a) as a representative for the generic type itself, (b) for static fields and
789 // methods, which aren't present in the instantiations, and (c) to hold some information
790 // (e.g. formal instantiations of superclass and implemented interfaces) that is common
791 // to all instantiations and isn't stored in the EEClass structures for instantiated types
794 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
796 // A word about EEClass vs. MethodTable
797 // ------------------------------------
799 // At compile-time, we are happy to touch both MethodTable and EEClass. However,
800 // at runtime we want to restrict ourselves to the MethodTable. This is critical
801 // for common code paths, where we want to keep the EEClass out of our working
802 // set. For uncommon code paths, like throwing exceptions or strange Contexts
803 // issues, it's okay to access the EEClass.
805 // To this end, the TypeHandle (CLASS_HANDLE) abstraction is now based on the
806 // MethodTable pointer instead of the EEClass pointer. If you are writing a
807 // runtime helper that calls GetClass() to access the associated EEClass, please
808 // stop to wonder if you are making a mistake.
810 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
813 // An code:EEClass is a representation of the part of a managed type that is not used very frequently (it is
814 // cold), and thus is segregated from the hot portion (which lives in code:MethodTable). As noted above an
815 // it is also the case that EEClass is SHARED among all instantiations of a generic type, so anything that
816 // is specific to a paritcular type can not live off the EEClass.
818 // From here you can get to
819 // code:MethodTable - The representation of the hot portion of a type.
820 // code:MethodDesc - The representation of a method
821 // code:FieldDesc - The representation of a field.
823 // EEClasses hold the following important fields
824 // * code:EEClass.m_pMethodTable - Points a MethodTable associated with
825 // * code:EEClass.m_pChunks - a list of code:MethodDescChunk which is simply a list of code:MethodDesc
826 // which represent the methods.
827 // * code:EEClass.m_pFieldDescList - a list of fields in the type.
829 class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
831 /************************************
833 ************************************/
834 // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
835 // USE ACCESSORS TO READ/WRITE private field members
837 // To access bmt stuff
838 friend class MethodTable;
839 friend class MethodTableBuilder;
840 friend class FieldDesc;
841 friend class CheckAsmOffsets;
842 friend class ClrDataAccess;
843 #ifdef DACCESS_COMPILE
844 friend class NativeImageDumper;
847 /************************************
848 * PUBLIC INSTANCE METHODS
849 ************************************/
854 LIMITED_METHOD_CONTRACT;
855 return IsTdSealed(m_dwAttrClass);
858 inline DWORD IsInterface()
861 return IsTdInterface(m_dwAttrClass);
864 inline DWORD IsAbstract()
867 return IsTdAbstract(m_dwAttrClass);
870 BOOL HasExplicitFieldOffsetLayout()
873 return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
876 BOOL HasSequentialLayout()
879 return IsTdSequentialLayout(GetAttrClass());
881 BOOL IsBeforeFieldInit()
884 return IsTdBeforeFieldInit(GetAttrClass());
887 DWORD GetProtection()
890 return (m_dwAttrClass & tdVisibilityMask);
893 // class is blittable
896 #ifndef DACCESS_COMPILE
897 void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
898 void Destruct(MethodTable * pMT);
900 static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
901 #endif // !DACCESS_COMPILE
904 // Add a new method to an already loaded type for EnC
905 static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
907 // Add a new field to an already loaded type for EnC
908 static HRESULT AddField(MethodTable * pMT, mdFieldDef fieldDesc, EnCFieldDesc **pAddedField);
909 static VOID FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdFieldDef fieldDef);
910 #endif // EnC_SUPPORTED
912 inline DWORD IsComImport()
915 return IsTdImport(m_dwAttrClass);
918 #ifdef FEATURE_PREJIT
921 void Save(DataImage *image, MethodTable *pMT);
922 void Fixup(DataImage *image, MethodTable *pMT);
923 #endif // FEATURE_PREJIT
925 EEClassLayoutInfo *GetLayoutInfo();
927 #ifdef DACCESS_COMPILE
928 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
931 static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
933 /************************************
934 * INSTANCE MEMBER VARIABLES
935 ************************************/
938 inline LPCUTF8 GetDebugClassName ()
940 LIMITED_METHOD_CONTRACT;
941 return m_szDebugClassName;
943 inline void SetDebugClassName (LPCUTF8 szDebugClassName)
945 LIMITED_METHOD_CONTRACT;
946 m_szDebugClassName = szDebugClassName;
950 * Controls debugging breaks and output if a method class
951 * is mentioned in the registry ("BreakOnClassBuild")
952 * Method layout within this class can cause a debug
953 * break by setting "BreakOnMethodName". Not accessible
959 #ifdef FEATURE_COMINTEROP
961 * Used to map MethodTable slots to VTable slots
963 inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
965 LIMITED_METHOD_CONTRACT;
966 return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
968 inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
970 LIMITED_METHOD_CONTRACT;
971 _ASSERTE(HasOptionalFields());
972 GetOptionalFields()->m_pSparseVTableMap = map;
974 #endif // FEATURE_COMINTEROP
978 * Maintain back pointer to statcally hot portion of EEClass.
979 * For an EEClass representing multiple instantiations of a generic type, this is the method table
980 * for the first instantiation requested and is the only one containing entries for non-virtual instance methods
981 * (i.e. non-vtable entries).
984 // Note that EEClass structures may be shared between generic instantiations
985 // (see IsSharedByGenericInstantiations). In these cases EEClass::GetMethodTable
986 // will return the method table pointer corresponding to the "canonical"
987 // instantiation, as defined in typehandle.h.
989 inline PTR_MethodTable GetMethodTable()
991 LIMITED_METHOD_CONTRACT;
994 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
997 // DO NOT ADD ANY ASSERTS TO THIS METHOD.
998 // DO NOT USE THIS METHOD.
999 // Yes folks, for better or worse the debugger pokes supposed object addresses
1000 // to try to see if objects are valid, possibly firing an AccessViolation or worse,
1001 // and then catches the AV and reports a failure to the debug client. This makes
1002 // the debugger slightly more robust should any corrupted object references appear
1003 // in a session. Thus it is "correct" behaviour for this to AV when used with
1004 // an invalid object pointer, and incorrect behaviour for it to
1006 inline PTR_MethodTable GetMethodTableWithPossibleAV()
1008 CANNOT_HAVE_CONTRACT;
1011 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1014 #ifndef DACCESS_COMPILE
1015 inline void SetMethodTable(MethodTable* pMT)
1017 LIMITED_METHOD_CONTRACT;
1018 m_pMethodTable.SetValueMaybeNull(pMT);
1020 #endif // !DACCESS_COMPILE
1023 * Number of fields in the class, including inherited fields.
1024 * Does not include fields added from EnC.
1026 inline WORD GetNumInstanceFields()
1028 LIMITED_METHOD_CONTRACT;
1030 return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1033 inline void SetNumInstanceFields (WORD wNumInstanceFields)
1035 LIMITED_METHOD_CONTRACT;
1036 SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1040 * Number of static fields declared in this class.
1041 * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1043 inline WORD GetNumStaticFields()
1045 LIMITED_METHOD_CONTRACT;
1047 return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1049 inline void SetNumStaticFields (WORD wNumStaticFields)
1051 LIMITED_METHOD_CONTRACT;
1052 SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1055 inline WORD GetNumThreadStaticFields()
1057 LIMITED_METHOD_CONTRACT;
1059 return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1062 inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1064 LIMITED_METHOD_CONTRACT;
1065 SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1068 // Statics are stored in a big chunk inside the module
1070 inline DWORD GetModuleDynamicID()
1072 LIMITED_METHOD_CONTRACT;
1074 return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1077 inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1079 LIMITED_METHOD_CONTRACT;
1080 _ASSERTE(HasOptionalFields());
1081 GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
1085 * Difference between the InterfaceMap ptr and Vtable in the
1086 * MethodTable used to indicate the number of static bytes
1087 * Now interfaceMap ptr can be optional hence we store it here
1089 inline DWORD GetNonGCRegularStaticFieldBytes()
1091 LIMITED_METHOD_CONTRACT;
1092 return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1094 inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1096 LIMITED_METHOD_CONTRACT;
1097 SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1100 inline DWORD GetNonGCThreadStaticFieldBytes()
1102 LIMITED_METHOD_CONTRACT;
1103 return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1105 inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1107 LIMITED_METHOD_CONTRACT;
1108 SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1111 inline WORD GetNumNonVirtualSlots()
1113 LIMITED_METHOD_CONTRACT;
1114 return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1116 inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1118 LIMITED_METHOD_CONTRACT;
1119 SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1122 inline BOOL IsEquivalentType()
1124 LIMITED_METHOD_CONTRACT;
1125 return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1128 #ifdef FEATURE_TYPEEQUIVALENCE
1129 inline void SetIsEquivalentType()
1131 LIMITED_METHOD_CONTRACT;
1132 m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1134 #endif // FEATURE_TYPEEQUIVALENCE
1137 * Number of static handles allocated
1139 inline WORD GetNumHandleRegularStatics ()
1141 LIMITED_METHOD_CONTRACT;
1142 return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1144 inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1146 LIMITED_METHOD_CONTRACT;
1147 SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1151 * Number of static handles allocated for ThreadStatics
1153 inline WORD GetNumHandleThreadStatics ()
1155 LIMITED_METHOD_CONTRACT;
1156 return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1158 inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1160 LIMITED_METHOD_CONTRACT;
1161 SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1165 * Number of boxed statics allocated
1167 inline WORD GetNumBoxedRegularStatics ()
1169 LIMITED_METHOD_CONTRACT;
1170 return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1172 inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1174 LIMITED_METHOD_CONTRACT;
1175 SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1179 * Number of boxed statics allocated for ThreadStatics
1181 inline WORD GetNumBoxedThreadStatics ()
1183 LIMITED_METHOD_CONTRACT;
1184 return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1186 inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1188 LIMITED_METHOD_CONTRACT;
1189 SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
1193 * Number of bytes to subract from code:MethodTable::GetBaseSize() to get the actual number of bytes
1194 * of instance fields stored in the object on the GC heap.
1196 inline DWORD GetBaseSizePadding()
1198 LIMITED_METHOD_DAC_CONTRACT;
1199 return m_cbBaseSizePadding;
1201 inline void SetBaseSizePadding(DWORD dwPadding)
1203 LIMITED_METHOD_CONTRACT;
1204 _ASSERTE(FitsIn<BYTE>(dwPadding));
1205 m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1208 inline DWORD GetUnboxedNumInstanceFieldBytes()
1210 DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1212 _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1218 * Pointer to a list of FieldDescs declared in this class
1219 * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1222 #ifdef FEATURE_PREJIT
1223 static DWORD FieldDescListSize(MethodTable * pMT);
1226 inline PTR_FieldDesc GetFieldDescList()
1228 LIMITED_METHOD_DAC_CONTRACT;
1229 // Careful about using this method. If it's possible that fields may have been added via EnC, then
1230 // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1231 return m_pFieldDescList.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList));
1234 PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1236 #ifndef DACCESS_COMPILE
1237 inline void SetFieldDescList (FieldDesc* pFieldDescList)
1239 LIMITED_METHOD_CONTRACT;
1240 m_pFieldDescList.SetValue(pFieldDescList);
1242 #endif // !DACCESS_COMPILE
1244 inline WORD GetNumMethods()
1246 LIMITED_METHOD_DAC_CONTRACT;
1247 return (WORD)GetPackableField(EEClass_Field_NumMethods);
1249 inline void SetNumMethods (WORD wNumMethods)
1251 LIMITED_METHOD_CONTRACT;
1252 SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1256 * Cached metadata for this class (GetTypeDefProps)
1258 inline DWORD GetAttrClass()
1260 LIMITED_METHOD_CONTRACT;
1261 return m_dwAttrClass;
1263 inline void SetAttrClass (DWORD dwAttrClass)
1265 LIMITED_METHOD_CONTRACT;
1266 m_dwAttrClass = dwAttrClass;
1270 #ifdef FEATURE_COMINTEROP
1271 inline DWORD IsComClassInterface()
1273 LIMITED_METHOD_CONTRACT;
1274 return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1276 inline VOID SetIsComClassInterface()
1278 LIMITED_METHOD_CONTRACT;
1279 m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1281 inline void SetComEventItfType()
1283 LIMITED_METHOD_CONTRACT;
1284 _ASSERTE(IsInterface());
1285 m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1287 // class is a special COM event interface
1288 inline BOOL IsComEventItfType()
1290 LIMITED_METHOD_CONTRACT;
1291 return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1293 #endif // FEATURE_COMINTEROP
1296 inline DWORD IsDestroyed()
1298 LIMITED_METHOD_CONTRACT;
1299 return (m_wAuxFlags & AUXFLAG_DESTROYED);
1303 inline DWORD IsUnsafeValueClass()
1305 LIMITED_METHOD_CONTRACT;
1306 return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1311 inline void SetUnsafeValueClass()
1313 LIMITED_METHOD_CONTRACT;
1314 m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1318 inline BOOL HasNoGuid()
1320 LIMITED_METHOD_CONTRACT;
1321 return (m_VMFlags & VMFLAG_NO_GUID);
1323 inline void SetHasNoGuid()
1325 WRAPPER_NO_CONTRACT;
1326 FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1330 inline BOOL IsAlign8Candidate()
1332 LIMITED_METHOD_CONTRACT;
1333 return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1335 inline void SetAlign8Candidate()
1337 LIMITED_METHOD_CONTRACT;
1338 m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1341 inline void SetDestroyed()
1343 LIMITED_METHOD_CONTRACT;
1344 m_wAuxFlags |= AUXFLAG_DESTROYED;
1347 inline void SetHasFixedAddressVTStatics()
1349 LIMITED_METHOD_CONTRACT;
1350 m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1352 #ifdef FEATURE_COMINTEROP
1353 void SetSparseForCOMInterop()
1355 LIMITED_METHOD_CONTRACT;
1356 m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1358 inline void SetProjectedFromWinRT()
1360 LIMITED_METHOD_CONTRACT;
1361 m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1363 inline void SetExportedToWinRT()
1365 LIMITED_METHOD_CONTRACT;
1366 m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1368 inline void SetMarshalingType(UINT32 mType)
1370 LIMITED_METHOD_CONTRACT;
1371 _ASSERTE(mType !=0);
1372 _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1375 case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1377 case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1379 case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1382 _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1385 #endif // FEATURE_COMINTEROP
1386 inline void SetHasLayout()
1388 LIMITED_METHOD_CONTRACT;
1389 m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT; //modified before the class is published
1391 inline void SetHasOverLayedFields()
1393 LIMITED_METHOD_CONTRACT;
1394 m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1396 inline void SetIsNested()
1398 LIMITED_METHOD_CONTRACT;
1399 m_VMFlags |= VMFLAG_ISNESTED;
1402 #ifdef FEATURE_READYTORUN
1403 inline BOOL HasLayoutDependsOnOtherModules()
1405 LIMITED_METHOD_CONTRACT;
1406 return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1409 inline void SetHasLayoutDependsOnOtherModules()
1411 LIMITED_METHOD_CONTRACT;
1412 m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1416 // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1417 inline BOOL IsDelegate()
1419 LIMITED_METHOD_CONTRACT;
1420 return m_VMFlags & VMFLAG_DELEGATE;
1422 inline void SetIsDelegate()
1424 LIMITED_METHOD_CONTRACT;
1425 m_VMFlags |= VMFLAG_DELEGATE;
1428 BOOL HasFixedAddressVTStatics()
1430 LIMITED_METHOD_CONTRACT;
1431 return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1433 #ifdef FEATURE_COMINTEROP
1434 BOOL IsSparseForCOMInterop()
1436 LIMITED_METHOD_CONTRACT;
1437 return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1439 BOOL IsProjectedFromWinRT()
1441 LIMITED_METHOD_DAC_CONTRACT;
1442 return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1444 BOOL IsExportedToWinRT()
1446 LIMITED_METHOD_CONTRACT;
1447 return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1449 BOOL IsMarshalingTypeSet()
1451 LIMITED_METHOD_CONTRACT;
1452 return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1454 BOOL IsMarshalingTypeFreeThreaded()
1456 LIMITED_METHOD_CONTRACT;
1457 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1459 BOOL IsMarshalingTypeInhibit()
1461 LIMITED_METHOD_CONTRACT;
1462 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1464 BOOL IsMarshalingTypeStandard()
1466 LIMITED_METHOD_CONTRACT;
1467 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1469 #endif // FEATURE_COMINTEROP
1472 LIMITED_METHOD_CONTRACT;
1473 return m_VMFlags & VMFLAG_HASLAYOUT;
1475 BOOL HasOverLayedField()
1477 LIMITED_METHOD_CONTRACT;
1478 return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1482 LIMITED_METHOD_CONTRACT;
1483 return m_VMFlags & VMFLAG_ISNESTED;
1485 BOOL HasFieldsWhichMustBeInited()
1487 LIMITED_METHOD_CONTRACT;
1488 return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1490 void SetHasFieldsWhichMustBeInited()
1492 LIMITED_METHOD_CONTRACT;
1493 m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1495 void SetCannotBeBlittedByObjectCloner()
1499 DWORD HasNonPublicFields()
1501 LIMITED_METHOD_CONTRACT;
1502 return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1504 void SetHasNonPublicFields()
1506 LIMITED_METHOD_CONTRACT;
1507 m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1509 DWORD IsNotTightlyPacked()
1511 LIMITED_METHOD_CONTRACT;
1512 return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1514 void SetIsNotTightlyPacked()
1516 LIMITED_METHOD_CONTRACT;
1517 m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1519 DWORD ContainsMethodImpls()
1521 LIMITED_METHOD_CONTRACT;
1522 return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1524 void SetContainsMethodImpls()
1526 LIMITED_METHOD_CONTRACT;
1527 m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1531 BOOL IsManagedSequential();
1533 BOOL HasExplicitSize();
1535 static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1538 * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1541 // This is what would be used in the calling convention for this type.
1542 CorElementType GetInternalCorElementType()
1544 LIMITED_METHOD_DAC_CONTRACT;
1546 return CorElementType(m_NormType);
1548 void SetInternalCorElementType (CorElementType _NormType)
1550 LIMITED_METHOD_CONTRACT;
1551 m_NormType = static_cast<BYTE>(_NormType);
1555 * Chain of MethodDesc chunks for the MethodTable
1558 inline PTR_MethodDescChunk GetChunks();
1560 #ifndef DACCESS_COMPILE
1561 inline void SetChunks (MethodDescChunk* pChunks)
1563 LIMITED_METHOD_CONTRACT;
1564 m_pChunks.SetValueMaybeNull(pChunks);
1566 #endif // !DACCESS_COMPILE
1567 void AddChunk (MethodDescChunk* pNewChunk);
1569 void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1571 inline PTR_GuidInfo GetGuidInfo()
1573 LIMITED_METHOD_DAC_CONTRACT;
1575 return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1578 inline void SetGuidInfo(GuidInfo* pGuidInfo)
1580 WRAPPER_NO_CONTRACT;
1581 #ifndef DACCESS_COMPILE
1582 EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1583 #endif // DACCESS_COMPILE
1587 #if defined(UNIX_AMD64_ABI)
1588 // Get number of eightbytes used by a struct passed in registers.
1589 inline int GetNumberEightBytes()
1591 LIMITED_METHOD_CONTRACT;
1592 _ASSERTE(HasOptionalFields());
1593 return GetOptionalFields()->m_numberEightBytes;
1596 // Get eightbyte classification for the eightbyte with the specified index.
1597 inline SystemVClassificationType GetEightByteClassification(int index)
1599 LIMITED_METHOD_CONTRACT;
1600 _ASSERTE(HasOptionalFields());
1601 return GetOptionalFields()->m_eightByteClassifications[index];
1604 // Get size of the data in the eightbyte with the specified index.
1605 inline unsigned int GetEightByteSize(int index)
1607 LIMITED_METHOD_CONTRACT;
1608 _ASSERTE(HasOptionalFields());
1609 return GetOptionalFields()->m_eightByteSizes[index];
1612 // Set the eightByte classification
1613 inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1615 LIMITED_METHOD_CONTRACT;
1616 _ASSERTE(HasOptionalFields());
1617 GetOptionalFields()->m_numberEightBytes = eightByteCount;
1618 for (int i = 0; i < eightByteCount; i++)
1620 GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1621 GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1624 #endif // UNIX_AMD64_ABI
1626 #if defined(FEATURE_HFA)
1627 bool CheckForHFA(MethodTable ** pByValueClassCache);
1628 VOID CheckForNativeHFA();
1629 #else // !FEATURE_HFA
1631 #endif // FEATURE_HFA
1633 #ifdef FEATURE_COMINTEROP
1634 inline TypeHandle GetCoClassForInterface()
1636 LIMITED_METHOD_CONTRACT;
1637 _ASSERTE(HasOptionalFields());
1638 return GetOptionalFields()->m_pCoClassForIntf;
1641 inline void SetCoClassForInterface(TypeHandle th)
1643 WRAPPER_NO_CONTRACT;
1644 _ASSERTE(HasOptionalFields());
1645 *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1648 inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1650 LIMITED_METHOD_CONTRACT;
1651 return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1652 : WinMDAdapter::RedirectedTypeIndex_Invalid;
1655 inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1657 LIMITED_METHOD_CONTRACT;
1658 _ASSERTE(HasOptionalFields());
1659 _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1660 GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1662 #endif // FEATURE_COMINTEROP
1664 inline UINT32 GetNativeSize()
1666 LIMITED_METHOD_DAC_CONTRACT;
1667 return m_cbNativeSize;
1669 static UINT32 GetOffsetOfNativeSize()
1671 LIMITED_METHOD_CONTRACT;
1672 return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1674 void SetNativeSize(UINT32 nativeSize)
1676 LIMITED_METHOD_CONTRACT;
1677 m_cbNativeSize = nativeSize;
1679 #ifdef FEATURE_COMINTEROP
1680 OBJECTHANDLE GetOHDelegate()
1682 LIMITED_METHOD_CONTRACT;
1683 return m_ohDelegate;
1685 void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1687 LIMITED_METHOD_CONTRACT;
1688 m_ohDelegate = _ohDelegate;
1690 // Set the COM interface type.
1691 CorIfaceAttr GetComInterfaceType()
1693 LIMITED_METHOD_CONTRACT;
1694 return m_ComInterfaceType;
1697 void SetComInterfaceType(CorIfaceAttr ItfType)
1699 WRAPPER_NO_CONTRACT;
1700 _ASSERTE(IsInterface());
1701 EnsureWritablePages(this);
1702 m_ComInterfaceType = ItfType;
1705 inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1707 LIMITED_METHOD_CONTRACT;
1708 return m_pccwTemplate;
1710 inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1712 WRAPPER_NO_CONTRACT;
1713 return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1716 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1717 inline ClassFactoryBase *GetComClassFactory()
1719 LIMITED_METHOD_CONTRACT;
1720 return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1722 inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1724 WRAPPER_NO_CONTRACT;
1725 _ASSERTE(HasOptionalFields());
1726 return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1728 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1729 #endif // FEATURE_COMINTEROP
1733 PTR_DictionaryLayout GetDictionaryLayout()
1736 WRAPPER_NO_CONTRACT;
1737 return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1740 void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1743 WRAPPER_NO_CONTRACT;
1744 _ASSERTE(HasOptionalFields());
1745 GetOptionalFields()->m_pDictLayout = pLayout;
1748 #ifndef DACCESS_COMPILE
1749 static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1751 LIMITED_METHOD_CONTRACT;
1752 if (pbVarianceInfo == NULL)
1753 return gpNonVariant;
1755 return (CorGenericParamAttr) (pbVarianceInfo[i]);
1758 CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1760 WRAPPER_NO_CONTRACT;
1761 return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1764 BYTE* GetVarianceInfo()
1766 LIMITED_METHOD_CONTRACT;
1767 return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1770 void SetVarianceInfo(BYTE *pVarianceInfo)
1772 LIMITED_METHOD_CONTRACT;
1773 _ASSERTE(HasOptionalFields());
1774 GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1776 #endif // !DACCESS_COMPILE
1778 // Check that a signature blob uses type parameters correctly
1779 // in accordance with the variance annotations specified by this class
1780 // The position parameter indicates the variance of the context we're in
1781 // (result type is gpCovariant, argument types are gpContravariant, deeper in a signature
1782 // we might be gpNonvariant e.g. in a pointer type or non-variant generic type)
1785 DWORD numGenericArgs,
1786 BYTE *pVarianceInfo,
1789 CorGenericParamAttr position);
1794 AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1796 #endif // defined(_DEBUG)
1798 //-------------------------------------------------------------
1799 // CONCRETE DATA LAYOUT
1801 // Although accessed far less frequently than MethodTables, EEClasses are still
1802 // pulled into working set, especially at startup. This has motivated several space
1803 // optimizations in field layout where each is balanced against the need to access
1804 // a particular field efficiently.
1806 // Currently, the following strategy is used:
1808 // - Any field that has a default value for the vast majority of EEClass instances
1809 // should be stored in the EEClassOptionalFields (see header comment)
1811 // - Any field that is nearly always a small positive integer and is infrequently
1812 // accessed should be in the EEClassPackedFields (see header comment)
1814 // If none of these categories apply - such as for always-meaningful pointer members or
1815 // sets of flags - a full field is used. Please avoid adding such members if possible.
1816 //-------------------------------------------------------------
1818 // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1820 // Flags for m_VMFlags
1825 #ifdef FEATURE_READYTORUN
1826 VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
1828 VMFLAG_DELEGATE = 0x00000002,
1830 // VMFLAG_UNUSED = 0x0000001c,
1832 VMFLAG_FIXED_ADDRESS_VT_STATICS = 0x00000020, // Value type Statics in this class will be pinned
1833 VMFLAG_HASLAYOUT = 0x00000040,
1834 VMFLAG_ISNESTED = 0x00000080,
1836 VMFLAG_IS_EQUIVALENT_TYPE = 0x00000200,
1838 // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
1839 VMFLAG_HASOVERLAYEDFIELDS = 0x00000400,
1841 // Set this if this class or its parent have instance fields which
1842 // must be explicitly inited in a constructor (e.g. pointers of any
1843 // kind, gc or native).
1845 // Currently this is used by the verifier when verifying value classes
1846 // - it's ok to use uninitialised value classes if there are no
1847 // pointer fields in them.
1848 VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED = 0x00000800,
1850 VMFLAG_UNSAFEVALUETYPE = 0x00001000,
1852 VMFLAG_BESTFITMAPPING_INITED = 0x00002000, // VMFLAG_BESTFITMAPPING and VMFLAG_THROWONUNMAPPABLECHAR are valid only if this is set
1853 VMFLAG_BESTFITMAPPING = 0x00004000, // BestFitMappingAttribute.Value
1854 VMFLAG_THROWONUNMAPPABLECHAR = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar
1856 // unused = 0x00010000,
1857 VMFLAG_NO_GUID = 0x00020000,
1858 VMFLAG_HASNONPUBLICFIELDS = 0x00040000,
1859 // unused = 0x00080000,
1860 VMFLAG_CONTAINS_STACK_PTR = 0x00100000,
1861 VMFLAG_PREFER_ALIGN8 = 0x00200000, // Would like to have 8-byte alignment
1862 // unused = 0x00400000,
1864 #ifdef FEATURE_COMINTEROP
1865 VMFLAG_SPARSE_FOR_COMINTEROP = 0x00800000,
1866 // interfaces may have a coclass attribute
1867 VMFLAG_HASCOCLASSATTRIB = 0x01000000,
1868 VMFLAG_COMEVENTITFMASK = 0x02000000, // class is a special COM event interface
1869 VMFLAG_PROJECTED_FROM_WINRT = 0x04000000,
1870 VMFLAG_EXPORTED_TO_WINRT = 0x08000000,
1871 #endif // FEATURE_COMINTEROP
1873 // This one indicates that the fields of the valuetype are
1874 // not tightly packed and is used to check whether we can
1875 // do bit-equality on value types to implement ValueType::Equals.
1876 // It is not valid for classes, and only matters if ContainsPointer
1878 VMFLAG_NOT_TIGHTLY_PACKED = 0x10000000,
1880 // True if methoddesc on this class have any real (non-interface) methodimpls
1881 VMFLAG_CONTAINS_METHODIMPLS = 0x20000000,
1883 #ifdef FEATURE_COMINTEROP
1884 VMFLAG_MARSHALINGTYPE_MASK = 0xc0000000,
1886 VMFLAG_MARSHALINGTYPE_INHIBIT = 0x40000000,
1887 VMFLAG_MARSHALINGTYPE_FREETHREADED = 0x80000000,
1888 VMFLAG_MARSHALINGTYPE_STANDARD = 0xc0000000,
1893 // C_ASSERTs in Jitinterface.cpp need this to be public to check the offset.
1894 // Put it first so the offset rarely changes, which just reduces the number of times we have to fiddle
1896 RelativePointer<PTR_GuidInfo> m_pGuidInfo; // The cached guid information for interfaces.
1900 LPCUTF8 m_szDebugClassName;
1901 BOOL m_fDebuggingClass;
1905 // Layout rest of fields below from largest to smallest to lessen the chance of wasting bytes with
1906 // compiler injected padding (especially with the difference between pointers and DWORDs on 64-bit).
1907 RelativePointer<PTR_EEClassOptionalFields> m_rpOptionalFields;
1909 // TODO: Remove this field. It is only used by SOS and object validation for stress.
1910 RelativePointer<PTR_MethodTable> m_pMethodTable;
1912 RelativePointer<PTR_FieldDesc> m_pFieldDescList;
1913 RelativePointer<PTR_MethodDescChunk> m_pChunks;
1917 // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
1918 UINT32 m_cbNativeSize; // size of fixed portion in bytes
1920 #ifdef FEATURE_COMINTEROP
1921 // For COM+ wrapper objects that extend an unmanaged class, this field
1922 // may contain a delegate to be called to allocate the aggregated
1923 // unmanaged class (instead of using CoCreateInstance).
1924 OBJECTHANDLE m_ohDelegate;
1926 // For interfaces this contains the COM interface type.
1927 CorIfaceAttr m_ComInterfaceType;
1928 #endif // FEATURE_COMINTEROP
1931 #ifdef FEATURE_COMINTEROP
1932 ComCallWrapperTemplate *m_pccwTemplate; // points to interop data structures used when this type is exposed to COM
1933 #endif // FEATURE_COMINTEROP
1935 DWORD m_dwAttrClass;
1939 * We maintain some auxillary flags in DEBUG builds,
1940 * this frees up some bits in m_wVMFlags
1946 // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
1947 // structure packing.
1949 BYTE m_fFieldsArePacked; // TRUE iff fields pointed to by GetPackedFields() are in packed state
1950 BYTE m_cbFixedEEClassFields; // Count of bytes of normal fields of this instance (EEClass,
1951 // LayoutEEClass etc.). Doesn't count bytes of "packed" fields
1952 BYTE m_cbBaseSizePadding; // How many bytes of padding are included in BaseSize
1955 // EEClass optional field support. Whether a particular EEClass instance has optional fields is determined
1956 // at class load time. The entire EEClassOptionalFields structure is allocated if the EEClass has need of
1957 // one or more optional fields.
1959 #ifndef DACCESS_COMPILE
1960 void AttachOptionalFields(EEClassOptionalFields *pFields)
1962 LIMITED_METHOD_CONTRACT;
1963 _ASSERTE(m_rpOptionalFields.IsNull());
1965 m_rpOptionalFields.SetValue(pFields);
1967 #endif // !DACCESS_COMPILE
1969 bool HasOptionalFields()
1971 LIMITED_METHOD_DAC_CONTRACT;
1972 return !m_rpOptionalFields.IsNull();
1975 PTR_EEClassOptionalFields GetOptionalFields()
1977 LIMITED_METHOD_DAC_CONTRACT;
1978 return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
1983 // Support for packed fields.
1986 // Get pointer to the packed fields structure attached to this instance.
1987 PTR_EEClassPackedFields GetPackedFields();
1989 // Get the value of the given field. Works regardless of whether the field is currently in its packed or
1991 DWORD GetPackableField(EEClassFieldId eField);
1993 // Set the value of the given field. The field *must* be in the unpacked state for this to be legal (in
1994 // practice all packable fields must be initialized during class construction and from then on remain
1996 void SetPackableField(EEClassFieldId eField, DWORD dwValue);
1998 //-------------------------------------------------------------
1999 // END CONCRETE DATA LAYOUT
2000 //-------------------------------------------------------------
2004 /************************************
2006 ************************************/
2008 #ifndef DACCESS_COMPILE
2010 * Constructor: prevent any other class from doing a new()
2012 EEClass(DWORD cbFixedEEClassFields);
2015 * Destructor: prevent any other class from deleting
2019 LIMITED_METHOD_CONTRACT;
2021 #endif // !DACCESS_COMPILE
2025 // --------------------------------------------------------------------------------------------
2026 template <typename Data>
2027 class FixedCapacityStackingAllocatedUTF8StringHash
2033 HashEntry * m_pNext; // Next item with same bucketed hash value
2034 DWORD m_dwHashValue; // Hash value
2035 LPCUTF8 m_pKey; // String key
2036 Data m_data; // Data
2039 HashEntry ** m_pBuckets; // Pointer to first entry for each bucket
2040 DWORD m_dwNumBuckets;
2041 BYTE * m_pMemory; // Current pointer into preallocated memory for entries
2042 BYTE * m_pMemoryStart; // Start pointer of pre-allocated memory fo entries
2044 INDEBUG(BYTE * m_pDebugEndMemory;)
2046 FixedCapacityStackingAllocatedUTF8StringHash()
2047 : m_pMemoryStart(NULL)
2048 { LIMITED_METHOD_CONTRACT; }
2053 { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2059 StackingAllocator * pAllocator);
2061 // Insert new entry at head of list
2067 // Return the first matching entry in the list, or NULL if there is no such entry
2072 // Return the next matching entry in the list, or NULL if there is no such entry.
2075 HashEntry * pEntry);
2079 //---------------------------------------------------------------------------------------
2081 class LayoutEEClass : public EEClass
2084 EEClassLayoutInfo m_LayoutInfo;
2086 #ifndef DACCESS_COMPILE
2087 LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2089 LIMITED_METHOD_CONTRACT;
2091 FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2094 #endif // !DACCESS_COMPILE
2097 class UMThunkMarshInfo;
2099 #ifdef FEATURE_COMINTEROP
2100 struct ComPlusCallInfo;
2101 #endif // FEATURE_COMINTEROP
2103 class DelegateEEClass : public EEClass
2106 PTR_Stub m_pStaticCallStub;
2107 PTR_Stub m_pInstRetBuffCallStub;
2108 RelativePointer<PTR_MethodDesc> m_pInvokeMethod;
2109 PTR_Stub m_pMultiCastInvokeStub;
2110 PTR_Stub m_pSecureDelegateInvokeStub;
2111 UMThunkMarshInfo* m_pUMThunkMarshInfo;
2112 RelativePointer<PTR_MethodDesc> m_pBeginInvokeMethod;
2113 RelativePointer<PTR_MethodDesc> m_pEndInvokeMethod;
2114 Volatile<PCODE> m_pMarshalStub;
2116 #ifdef FEATURE_COMINTEROP
2117 ComPlusCallInfo *m_pComPlusCallInfo;
2118 #endif // FEATURE_COMINTEROP
2121 // Ngened IL stub MethodDescs. Fixed up, wrapped with code:Stub, and installed to
2122 // m_pMarshalStub (forward) or m_pUMThunkMarshInfo (reverse) when first needed.
2124 MethodDesc* m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2125 MethodDesc* m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2127 PTR_MethodDesc GetInvokeMethod()
2129 return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2132 PTR_MethodDesc GetBeginInvokeMethod()
2134 return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2137 PTR_MethodDesc GetEndInvokeMethod()
2139 return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2142 #ifndef DACCESS_COMPILE
2143 DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2145 LIMITED_METHOD_CONTRACT;
2146 // Note: Memory allocated on loader heap is zero filled
2149 // We need a LoaderHeap that lives at least as long as the DelegateEEClass, but ideally no longer
2150 LoaderHeap *GetStubHeap();
2151 #endif // !DACCESS_COMPILE
2156 typedef DPTR(ArrayClass) PTR_ArrayClass;
2159 // Dynamically generated array class structure
2160 class ArrayClass : public EEClass
2162 #ifdef FEATURE_PREJIT
2163 friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2166 friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2168 #ifndef DACCESS_COMPILE
2169 ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2171 friend class NativeImageDumper;
2176 unsigned char m_rank;
2177 CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd
2181 LIMITED_METHOD_CONTRACT;
2185 void SetRank (unsigned Rank) {
2186 LIMITED_METHOD_CONTRACT;
2187 // The only code path calling this function is code:ClassLoader::CreateTypeHandleForTypeKey, which has
2188 // checked the rank already. Assert that the rank is less than MAX_RANK and that it fits in one byte.
2189 _ASSERTE((Rank <= MAX_RANK) && (Rank <= (unsigned char)(-1)));
2190 m_rank = (unsigned char)Rank;
2193 CorElementType GetArrayElementType() {
2194 LIMITED_METHOD_CONTRACT;
2195 return m_ElementType;
2197 void SetArrayElementType(CorElementType ElementType) {
2198 LIMITED_METHOD_CONTRACT;
2199 m_ElementType = ElementType;
2203 // Allocate a new MethodDesc for the methods we add to this class
2204 void InitArrayMethodDesc(
2205 ArrayMethodDesc* pNewMD,
2206 PCCOR_SIGNATURE pShortSig,
2209 LoaderAllocator *pLoaderAllocator,
2210 AllocMemTracker *pamTracker);
2212 // Generate a short sig for an array accessor
2213 VOID GenerateArrayAccessorCallSig(DWORD dwRank,
2214 DWORD dwFuncType, // Load, store, or <init>
2215 PCCOR_SIGNATURE *ppSig, // Generated signature
2216 DWORD * pcSig, // Generated signature size
2217 LoaderAllocator *pLoaderAllocator,
2218 AllocMemTracker *pamTracker
2219 #ifdef FEATURE_ARRAYSTUB_AS_IL
2227 inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2229 LIMITED_METHOD_CONTRACT;
2230 _ASSERTE(HasLayout());
2231 return &((LayoutEEClass *) this)->m_LayoutInfo;
2234 inline BOOL EEClass::IsBlittable()
2236 LIMITED_METHOD_CONTRACT;
2238 // Either we have an opaque bunch of bytes, or we have some fields that are
2239 // all isomorphic and explicitly layed out.
2240 return (HasLayout() && GetLayoutInfo()->IsBlittable());
2243 inline BOOL EEClass::IsManagedSequential()
2245 LIMITED_METHOD_CONTRACT;
2246 return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2249 inline BOOL EEClass::HasExplicitSize()
2251 LIMITED_METHOD_CONTRACT;
2252 return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2255 //==========================================================================
2256 // These routines manage the prestub (a bootstrapping stub that all
2257 // FunctionDesc's are initialized with.)
2258 //==========================================================================
2259 VOID InitPreStubManager();
2261 EXTERN_C void STDCALL ThePreStub();
2263 inline PCODE GetPreStubEntryPoint()
2265 return GetEEFuncEntryPoint(ThePreStub);
2268 #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2270 EXTERN_C void STDCALL ThePreStubCompactARM();
2272 inline PCODE GetPreStubCompactARMEntryPoint()
2274 return GetEEFuncEntryPoint(ThePreStubCompactARM);
2277 #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2279 PCODE TheUMThunkPreStub();
2281 PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
2285 // workaround: These classification bits need cleanup bad: for now, this gets around
2286 // IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
2287 #define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
2290 // The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
2291 // methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
2294 #define METH_NAME_CACHE_SIZE 5
2295 #define MAX_MISSES 3
2297 #ifdef EnC_SUPPORTED
2299 struct EnCAddedFieldElement;
2301 #endif // EnC_SUPPORTED
2304 // --------------------------------------------------------------------------------------------
2305 // For generic instantiations the FieldDescs stored for instance
2306 // fields are approximate, not exact, i.e. they are representatives owned by
2307 // canonical instantiation and they do not carry exact type information.
2308 // This will not include EnC related fields. (See EncApproxFieldDescIterator for that)
2309 class ApproxFieldDescIterator
2313 PTR_FieldDesc m_pFieldDescList;
2319 INSTANCE_FIELDS = 0x1,
2320 STATIC_FIELDS = 0x2,
2321 ALL_FIELDS = (INSTANCE_FIELDS | STATIC_FIELDS)
2323 ApproxFieldDescIterator();
2324 ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2327 Init(pMT, iteratorType);
2329 void Init(MethodTable *pMT, int iteratorType);
2330 PTR_FieldDesc Next();
2332 int GetIteratorType() {
2333 LIMITED_METHOD_CONTRACT;
2335 return m_iteratorType;
2339 LIMITED_METHOD_CONTRACT;
2340 return m_totalFields;
2342 int CountRemaining() {
2343 LIMITED_METHOD_CONTRACT;
2345 return m_totalFields - m_currField - 1;
2350 // DeepFieldDescIterator iterates over the entire
2351 // set of fields available to a class, inherited or
2355 class DeepFieldDescIterator
2358 ApproxFieldDescIterator m_fieldIter;
2361 MethodTable* m_classes[16];
2362 int m_deepTotalFields;
2363 bool m_lastNextFromParentClass;
2368 DeepFieldDescIterator()
2370 LIMITED_METHOD_CONTRACT;
2374 m_deepTotalFields = 0;
2375 m_lastNextFromParentClass = false;
2377 DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2378 bool includeParents = true)
2380 WRAPPER_NO_CONTRACT;
2382 Init(pMT, iteratorType, includeParents);
2384 void Init(MethodTable* pMT, int iteratorType,
2385 bool includeParents = true);
2389 bool Skip(int numSkip);
2393 LIMITED_METHOD_CONTRACT;
2394 return m_deepTotalFields;
2396 bool IsFieldFromParentClass()
2398 LIMITED_METHOD_CONTRACT;
2399 return m_lastNextFromParentClass;