1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
11 // NOTE: Even though EEClass is considered to contain cold data (relative to MethodTable), these data
12 // structures *are* touched (especially during startup as part of soft-binding). As a result, and given the
13 // number of EEClasses allocated for large assemblies, the size of this structure can have a direct impact on
14 // performance, especially startup performance.
16 // Given that the data itself is touched infrequently, we can trade off space reduction against cpu-usage to
17 // good effect here. A fair amount of work has gone into reducing the size of each EEClass instance (see
18 // EEClassOptionalFields and EEClassPackedFields) at the expense of somewhat more convoluted runtime access.
20 // Please consider this (and measure the impact of your changes against startup scenarios) before adding
21 // fields to EEClass or otherwise increasing its size.
23 // ============================================================================
31 #include "eecontract.h"
39 #ifdef FEATURE_COMINTEROP
40 #include "stdinterfaces.h"
44 #include "typehandle.h"
45 #include "methodtable.h"
48 #include "iterator_util.h"
50 #ifdef FEATURE_COMINTEROP
51 #include "..\md\winmd\inc\adapter.h"
53 #include "packedfields.inl"
55 #define IBCLOG(x) g_IBCLogger.##x
57 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
62 #define MAX_LOG2_PRIMITIVE_FIELD_SIZE 3
64 #define MAX_PRIMITIVE_FIELD_SIZE (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
67 * Forward declarations
71 class ArrayMethodDesc;
74 class DictionaryLayout;
75 class FCallMethodDesc;
80 struct LayoutRawFieldInfo;
83 class MethodDescChunk;
86 struct ModuleCtorInfo;
92 class StackingAllocator;
93 class AllocMemTracker;
94 class InteropMethodTableSlotDataMap;
95 class LoadingEntry_LockHolder;
96 class DispatchMapBuilder;
97 class LoaderAllocator;
98 class ComCallWrapperTemplate;
100 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
101 typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
104 //---------------------------------------------------------------------------------
105 // Fields in an explicit-layout class present varying degrees of risk depending
106 // on how they overlap.
108 // Each level is a superset of the lower (in numerical value) level - i.e.
109 // all kVerifiable fields are also kLegal, but not vice-versa.
110 //---------------------------------------------------------------------------------
111 class ExplicitFieldTrust
116 // Note: order is important here - each guarantee also implicitly guarantees all promises
117 // made by values lower in number.
119 // What's guaranteed. What the loader does.
120 //----- ----------------------- -------------------------------
121 kNone = 0, // no guarantees at all - Type refuses to load at all.
122 kLegal = 1, // guarantees no objref <-> scalar overlap and no unaligned objref - Type loads but field access won't verify
123 kVerifiable = 2, // guarantees no objref <-> objref overlap and all guarantees above - Type loads and field access will verify
124 kNonOverLayed = 3, // guarantees no overlap at all and all guarantees above - Type loads, field access verifies and Equals() may be optimized if structure is tightly packed
126 kMaxTrust = kNonOverLayed,
131 //----------------------------------------------------------------------------------------------
132 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
133 // into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
134 // class. This abstraction enforces the rule that the overall class is only as trustworthy as
135 // the least trustworthy field.
136 //----------------------------------------------------------------------------------------------
137 class ExplicitClassTrust : private ExplicitFieldTrust
142 LIMITED_METHOD_CONTRACT;
143 m_trust = kMaxTrust; // Yes, we start out with maximal trust. This reflects that explicit layout structures with no fields do represent no risk.
146 VOID AddField(TrustLevel fieldTrust)
148 LIMITED_METHOD_CONTRACT;
149 m_trust = min(m_trust, fieldTrust);
154 LIMITED_METHOD_CONTRACT;
155 return m_trust >= kLegal;
160 LIMITED_METHOD_CONTRACT;
161 return m_trust >= kVerifiable;
164 BOOL IsNonOverLayed()
166 LIMITED_METHOD_CONTRACT;
167 return m_trust >= kNonOverLayed;
170 TrustLevel GetTrustLevel()
172 LIMITED_METHOD_CONTRACT;
180 //----------------------------------------------------------------------------------------------
181 // This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
182 // into this function, this class will collect trust information about individual fields to be later
183 // aggregated into the overall class level.
185 // This abstraction enforces the rule that all fields are presumed guilty until explicitly declared
186 // safe by calling SetTrust(). If you fail to call SetTrust before leaving the block, the destructor
187 // will automatically cause the entire class to be declared illegal (and you will get an assert
188 // telling you to fix this bug.)
189 //----------------------------------------------------------------------------------------------
190 class ExplicitFieldTrustHolder : private ExplicitFieldTrust
193 ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
195 LIMITED_METHOD_CONTRACT;
196 m_pExplicitClassTrust = pExplicitClassTrust;
198 m_trustDeclared = FALSE;
200 m_fieldTrust = kNone;
203 VOID SetTrust(TrustLevel fieldTrust)
205 LIMITED_METHOD_CONTRACT;
207 _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
208 _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
211 m_trustDeclared = TRUE;
213 m_fieldTrust = fieldTrust;
216 ~ExplicitFieldTrustHolder()
218 LIMITED_METHOD_CONTRACT;
219 // If no SetTrust() was ever called, we will default to kNone (i.e. declare the entire type
220 // illegal.) It'd be nice to assert here but since this case can be legitimately reached
221 // on exception unwind, we cannot.
222 m_pExplicitClassTrust->AddField(m_fieldTrust);
227 ExplicitClassTrust* m_pExplicitClassTrust;
228 TrustLevel m_fieldTrust;
230 BOOL m_trustDeclared; // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
234 //*******************************************************************************
235 // Enumerator to traverse the interface declarations of a type, automatically building
236 // a substitution chain on the stack.
237 class InterfaceImplEnum
240 HENUMInternalHolder hEnumInterfaceImpl;
241 const Substitution *m_pSubstChain;
242 Substitution m_CurrSubst;
245 InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
246 : hEnumInterfaceImpl(pModule->GetMDImport())
250 hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
251 m_pSubstChain = pSubstChain;
255 // S_OK ... if has next (TRUE)
256 // S_FALSE ... if does not have next (FALSE)
263 if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
268 IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
269 m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
272 const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
273 mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
276 #ifdef FEATURE_COMINTEROP
278 // Class used to map MethodTable slot numbers to COM vtable slots numbers
279 // (either for calling a classic COM component or for constructing a classic COM
280 // vtable via which COM components can call managed classes). This structure is
281 // embedded in the EEClass but the mapping list itself is only allocated if the
282 // COM vtable is sparse.
285 class SparseVTableMap
288 #ifdef DACCESS_COMPILE
289 friend class NativeImageDumper;
295 // First run through MT slots calling RecordGap wherever a gap in VT slots
297 void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
299 // Then call FinalizeMapping to create the actual mapping list.
300 void FinalizeMapping(WORD TotalMTSlots);
302 // Map MT to VT slot.
303 WORD LookupVTSlot(WORD MTSlot);
305 // Retrieve the number of slots in the vtable (both empty and full).
306 WORD GetNumVTableSlots();
308 const void* GetMapList()
310 LIMITED_METHOD_CONTRACT;
311 return (void*)m_MapList;
314 #ifdef FEATURE_PREJIT
315 // Methods to persist structure
316 void Save(DataImage *image);
317 void Fixup(DataImage *image);
318 #endif // FEATURE_PREJIT
322 enum { MapGrow = 4 };
326 WORD m_Start; // Starting MT slot number
327 WORD m_Span; // # of consecutive slots that map linearly
328 WORD m_MapTo; // Starting VT slot number
331 Entry *m_MapList; // Pointer to array of Entry structures
332 WORD m_MapEntries; // Number of entries in above
333 WORD m_Allocated; // Number of entries allocated
335 WORD m_LastUsed; // Index of last entry used in successful lookup
337 WORD m_VTSlot; // Current VT slot number, used during list build
338 WORD m_MTSlot; // Current MT slot number, used during list build
340 void AllocOrExpand(); // Allocate or expand the mapping list for a new entry
342 #endif // FEATURE_COMINTEROP
344 //=======================================================================
345 // Adjunct to the EEClass structure for classes w/ layout
346 //=======================================================================
347 class EEClassLayoutInfo
349 static VOID CollectLayoutFieldMetadataThrowing(
350 mdTypeDef cl, // cl of the NStruct being loaded
351 BYTE packingSize, // packing size (from @dll.struct)
352 BYTE nlType, // nltype (from @dll.struct)
353 #ifdef FEATURE_COMINTEROP
354 BOOL isWinRT, // Is the type a WinRT type
355 #endif // FEATURE_COMINTEROP
356 BOOL fExplicitOffsets, // explicit offsets?
357 MethodTable *pParentMT, // the loaded superclass
358 ULONG cTotalFields, // total number of fields (instance and static)
359 HENUMInternal *phEnumField, // enumerator for field
360 Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
361 const SigTypeContext *pTypeContext, // Type parameters for NStruct being loaded
362 EEClassLayoutInfo *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
363 LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in. Needs room for cMember+1 elements
364 LoaderAllocator * pAllocator,
365 AllocMemTracker *pamTracker
369 friend class ClassLoader;
370 friend class EEClass;
371 friend class MethodTableBuilder;
372 #ifdef DACCESS_COMPILE
373 friend class NativeImageDumper;
377 // size (in bytes) of fixed portion of NStruct.
378 UINT32 m_cbNativeSize;
379 UINT32 m_cbManagedSize;
382 // 1,2,4 or 8: this is equal to the largest of the alignment requirements
383 // of each of the EEClass's members. If the NStruct extends another NStruct,
384 // the base NStruct is treated as the first member for the purpose of
386 BYTE m_LargestAlignmentRequirementOfAllMembers;
388 // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
389 // for the managed layout.
390 BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
394 // TRUE if the GC layout of the class is bit-for-bit identical
395 // to its unmanaged counterpart (i.e. no internal reference fields,
396 // no ansi-unicode char conversions required, etc.) Used to
397 // optimize marshaling.
399 // Post V1.0 addition: Is this type also sequential in managed memory?
400 e_MANAGED_SEQUENTIAL = 0x02,
401 // When a sequential/explicit type has no fields, it is conceptually
402 // zero-sized, but actually is 1 byte in length. This holds onto this
403 // fact and allows us to revert the 1 byte of padding when another
404 // explicit type inherits from this type.
406 // The size of the struct is explicitly specified in the meta-data.
407 e_HAS_EXPLICIT_SIZE = 0x08,
408 #ifdef UNIX_AMD64_ABI
410 #error "Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time."
411 #endif // FEATURE_HFA
412 e_NATIVE_PASS_IN_REGISTERS = 0x10, // Flag wheter a native struct is passed in registers.
413 #endif // UNIX_AMD64_ABI
415 // HFA type of the unmanaged layout
416 // Note that these are not flags, they are discrete values.
420 e_HFATypeFlags = 0x30,
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 UNIX_AMD64_ABI
514 bool IsNativeStructPassedInRegisters()
516 LIMITED_METHOD_CONTRACT;
517 return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
520 bool IsNativeStructPassedInRegisters()
524 #endif // UNIX_AMD64_ABI
526 CorElementType GetNativeHFATypeRaw();
530 LIMITED_METHOD_CONTRACT;
531 return (m_bFlags & e_HFATypeFlags) != 0;
534 CorElementType GetNativeHFAType()
536 LIMITED_METHOD_CONTRACT;
537 switch (m_bFlags & e_HFATypeFlags)
539 case e_R4_HFA: return ELEMENT_TYPE_R4;
540 case e_R8_HFA: return ELEMENT_TYPE_R8;
541 case e_16_HFA: return ELEMENT_TYPE_VALUETYPE;
542 default: return ELEMENT_TYPE_END;
545 #else // !FEATURE_HFA
548 return GetNativeHFATypeRaw() != ELEMENT_TYPE_END;
550 CorElementType GetNativeHFAType()
552 return GetNativeHFATypeRaw();
554 #endif // !FEATURE_HFA
557 void SetIsBlittable(BOOL isBlittable)
559 LIMITED_METHOD_CONTRACT;
560 m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
561 : (m_bFlags & ~e_BLITTABLE);
564 void SetIsManagedSequential(BOOL isManagedSequential)
566 LIMITED_METHOD_CONTRACT;
567 m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
568 : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
571 void SetIsZeroSized(BOOL isZeroSized)
573 LIMITED_METHOD_CONTRACT;
574 m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
575 : (m_bFlags & ~e_ZERO_SIZED);
578 void SetHasExplicitSize(BOOL hasExplicitSize)
580 LIMITED_METHOD_CONTRACT;
581 m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
582 : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
586 void SetNativeHFAType(CorElementType hfaType)
588 LIMITED_METHOD_CONTRACT;
589 // We should call this at most once.
590 _ASSERTE((m_bFlags & e_HFATypeFlags) == 0);
593 case ELEMENT_TYPE_R4: m_bFlags |= e_R4_HFA; break;
594 case ELEMENT_TYPE_R8: m_bFlags |= e_R8_HFA; break;
595 case ELEMENT_TYPE_VALUETYPE: m_bFlags |= e_16_HFA; break;
596 default: _ASSERTE(!"Invalid HFA Type");
600 #ifdef UNIX_AMD64_ABI
601 void SetNativeStructPassedInRegisters()
603 LIMITED_METHOD_CONTRACT;
604 m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
606 #endif // UNIX_AMD64_ABI
613 // This structure is used only when the classloader is building the interface map. Before the class
614 // is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
615 // for this class/interface by the metadata - inherited interfaces will not be present if they are
616 // not specifically declared.
618 // This structure is destroyed after resolving has completed.
622 // The interface method table; for instantiated interfaces, this is the generic interface
623 MethodTable *m_pMethodTable;
624 } BuildingInterfaceInfo_t;
628 // We should not need to touch anything in here once the classes are all loaded, unless we
629 // are doing reflection. Try to avoid paging this data structure in.
632 // Size of hash bitmap for method names
633 #define METHOD_HASH_BYTES 8
635 // Hash table size - prime number
636 #define METHOD_HASH_BITS 61
639 // These are some macros for forming fully qualified class names for a class.
640 // These are abstracted so that we can decide later if a max length for a
641 // class name is acceptable.
643 // It doesn't make any sense not to have a small but usually quite capable
644 // stack buffer to build class names into. Most class names that I can think
645 // of would fit in 128 characters, and that's a pretty small amount of stack
646 // to use in exchange for not having to new and delete the memory.
647 #define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4)
649 #define DefineFullyQualifiedNameForClass() \
650 ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
651 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
653 #define DefineFullyQualifiedNameForClassOnStack() \
654 ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
655 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
657 #define DefineFullyQualifiedNameForClassW() \
658 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
660 #define DefineFullyQualifiedNameForClassWOnStack() \
661 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
663 #define GetFullyQualifiedNameForClassNestedAware(pClass) \
664 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
666 #define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
667 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
669 #define GetFullyQualifiedNameForClass(pClass) \
670 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
672 #define GetFullyQualifiedNameForClassW(pClass) \
673 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
675 #define GetFullyQualifiedNameForClassW_WinRT(pClass) \
676 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
678 #define GetFullyQualifiedNameForClass_WinRT(pClass) \
679 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
681 // Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to
682 // save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached
683 // via the m_rpOptionalFields field EEClass (use the GetOptionalFields() accessor rather than the field
685 class EEClassOptionalFields
687 // All fields here are intentionally private. Use the corresponding accessor on EEClass instead (this
688 // makes it easier to add and remove fields from the optional section in the future). We make exceptions
689 // for MethodTableBuilder and NativeImageDumper, which need raw field-level access.
690 friend class EEClass;
691 friend class MethodTableBuilder;
692 #ifdef DACCESS_COMPILE
693 friend class NativeImageDumper;
697 // GENERICS RELATED FIELDS.
700 // If IsSharedByGenericInstantiations(), layout of handle dictionary for generic type
701 // (the last dictionary pointed to from PerInstInfo). Otherwise NULL.
702 PTR_DictionaryLayout m_pDictLayout;
704 // Variance info for each type parameter (gpNonVariant, gpCovariant, or gpContravariant)
705 // If NULL, this type has no type parameters that are co/contravariant
706 RelativePointer<PTR_BYTE> m_pVarianceInfo;
709 // COM RELATED FIELDS.
712 #ifdef FEATURE_COMINTEROP
713 SparseVTableMap *m_pSparseVTableMap;
715 TypeHandle m_pCoClassForIntf; // @TODO: Coclass for an interface
717 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
718 // Points to activation information if the type is an activatable COM/WinRT class.
719 ClassFactoryBase *m_pClassFactory;
720 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
722 WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
724 #endif // FEATURE_COMINTEROP
730 #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
731 DWORD m_cbModuleDynamicID;
733 #if defined(UNIX_AMD64_ABI)
734 // Number of eightBytes in the following arrays
735 int m_numberEightBytes;
736 // Classification of the eightBytes
737 SystemVClassificationType m_eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
738 // Size of data the eightBytes
739 unsigned int m_eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
740 #endif // UNIX_AMD64_ABI
742 // Set default values for optional fields.
745 PTR_BYTE GetVarianceInfo()
747 LIMITED_METHOD_DAC_CONTRACT;
749 return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
752 typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
755 // Another mechanism used to reduce the size of the average EEClass instance is the notion of packed fields.
756 // This is based on the observation that EEClass has a large number of integer fields that typically contain
757 // small values and that are fixed once class layout has completed. We can compact these fields by discarding
758 // the leading zero bits (and for small values there'll be a lot of these) and packing the significant data
759 // into compact bitfields. This is a dynamic operation (the exact packing used depends on the exact data
760 // stored in the fields).
762 // The PackedDWORDFields<> class (defined in PackedFields.inl) encapsulates this. It takes one template
763 // parameter, the number of fields to pack, and provides operations to get and set those fields until we're
764 // happy with the values, at which point it will compact them for us.
766 // The packed fields themselves are stored at the end of the EEClass instance (or the LayoutEEClass or the
767 // DelegateEEClass etc.) so we can take advantage of the variable sized nature of the fields. We gain nothing for
768 // runtime allocated EEClasses (we have to allocate a maximally sized structure for the packed fields because
769 // we can't tell at the beginning of EEClass layout what the field values will be). But in the ngen scenario
770 // we can compact the fields just prior to saving and only store the portion of the EEClass that is relvant,
771 // helping us with our goal of packing all the EEClass instances together as tightly as possible.
773 // Since each packed field is now accessed via an array-like index, we give each of those indices a name with
774 // the enum below to make the code more readable.
779 EEClass_Field_NumInstanceFields = 0,
780 EEClass_Field_NumMethods,
781 EEClass_Field_NumStaticFields,
782 EEClass_Field_NumHandleStatics,
783 EEClass_Field_NumBoxedStatics,
784 EEClass_Field_NonGCStaticFieldBytes,
785 EEClass_Field_NumThreadStaticFields,
786 EEClass_Field_NumHandleThreadStatics,
787 EEClass_Field_NumBoxedThreadStatics,
788 EEClass_Field_NonGCThreadStaticFieldBytes,
789 EEClass_Field_NumNonVirtualSlots,
793 typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
794 typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
797 // For most types there is a one-to-one mapping between MethodTable* and EEClass*
798 // However this is not the case for instantiated types where code and representation
799 // are shared between compatible instantiations (e.g. List<string> and List<object>)
800 // Then a single EEClass structure is shared between multiple MethodTable structures
801 // Uninstantiated generic types (e.g. List) have their own EEClass and MethodTable,
802 // used (a) as a representative for the generic type itself, (b) for static fields and
803 // methods, which aren't present in the instantiations, and (c) to hold some information
804 // (e.g. formal instantiations of superclass and implemented interfaces) that is common
805 // to all instantiations and isn't stored in the EEClass structures for instantiated types
808 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
810 // A word about EEClass vs. MethodTable
811 // ------------------------------------
813 // At compile-time, we are happy to touch both MethodTable and EEClass. However,
814 // at runtime we want to restrict ourselves to the MethodTable. This is critical
815 // for common code paths, where we want to keep the EEClass out of our working
816 // set. For uncommon code paths, like throwing exceptions or strange Contexts
817 // issues, it's okay to access the EEClass.
819 // To this end, the TypeHandle (CLASS_HANDLE) abstraction is now based on the
820 // MethodTable pointer instead of the EEClass pointer. If you are writing a
821 // runtime helper that calls GetClass() to access the associated EEClass, please
822 // stop to wonder if you are making a mistake.
824 // ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
827 // An code:EEClass is a representation of the part of a managed type that is not used very frequently (it is
828 // cold), and thus is segregated from the hot portion (which lives in code:MethodTable). As noted above an
829 // it is also the case that EEClass is SHARED among all instantiations of a generic type, so anything that
830 // is specific to a paritcular type can not live off the EEClass.
832 // From here you can get to
833 // code:MethodTable - The representation of the hot portion of a type.
834 // code:MethodDesc - The representation of a method
835 // code:FieldDesc - The representation of a field.
837 // EEClasses hold the following important fields
838 // * code:EEClass.m_pMethodTable - Points a MethodTable associated with
839 // * code:EEClass.m_pChunks - a list of code:MethodDescChunk which is simply a list of code:MethodDesc
840 // which represent the methods.
841 // * code:EEClass.m_pFieldDescList - a list of fields in the type.
843 class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
845 /************************************
847 ************************************/
848 // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
849 // USE ACCESSORS TO READ/WRITE private field members
851 // To access bmt stuff
852 friend class MethodTable;
853 friend class MethodTableBuilder;
854 friend class FieldDesc;
855 friend class CheckAsmOffsets;
856 friend class ClrDataAccess;
857 #ifdef DACCESS_COMPILE
858 friend class NativeImageDumper;
861 /************************************
862 * PUBLIC INSTANCE METHODS
863 ************************************/
868 LIMITED_METHOD_CONTRACT;
869 return IsTdSealed(m_dwAttrClass);
872 inline DWORD IsInterface()
875 return IsTdInterface(m_dwAttrClass);
878 inline DWORD IsAbstract()
881 return IsTdAbstract(m_dwAttrClass);
884 BOOL HasExplicitFieldOffsetLayout()
887 return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
890 BOOL HasSequentialLayout()
893 return IsTdSequentialLayout(GetAttrClass());
895 BOOL IsBeforeFieldInit()
898 return IsTdBeforeFieldInit(GetAttrClass());
901 DWORD GetProtection()
904 return (m_dwAttrClass & tdVisibilityMask);
907 // class is blittable
910 #ifndef DACCESS_COMPILE
911 void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
912 void Destruct(MethodTable * pMT);
914 static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
915 #endif // !DACCESS_COMPILE
918 // Add a new method to an already loaded type for EnC
919 static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
921 // Add a new field to an already loaded type for EnC
922 static HRESULT AddField(MethodTable * pMT, mdFieldDef fieldDesc, EnCFieldDesc **pAddedField);
923 static VOID FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdFieldDef fieldDef);
924 #endif // EnC_SUPPORTED
926 inline DWORD IsComImport()
929 return IsTdImport(m_dwAttrClass);
932 #ifdef FEATURE_PREJIT
935 void Save(DataImage *image, MethodTable *pMT);
936 void Fixup(DataImage *image, MethodTable *pMT);
937 #endif // FEATURE_PREJIT
939 EEClassLayoutInfo *GetLayoutInfo();
941 #ifdef DACCESS_COMPILE
942 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
945 static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
947 /************************************
948 * INSTANCE MEMBER VARIABLES
949 ************************************/
952 inline LPCUTF8 GetDebugClassName ()
954 LIMITED_METHOD_CONTRACT;
955 return m_szDebugClassName;
957 inline void SetDebugClassName (LPCUTF8 szDebugClassName)
959 LIMITED_METHOD_CONTRACT;
960 m_szDebugClassName = szDebugClassName;
964 * Controls debugging breaks and output if a method class
965 * is mentioned in the registry ("BreakOnClassBuild")
966 * Method layout within this class can cause a debug
967 * break by setting "BreakOnMethodName". Not accessible
973 #ifdef FEATURE_COMINTEROP
975 * Used to map MethodTable slots to VTable slots
977 inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
979 LIMITED_METHOD_CONTRACT;
980 return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
982 inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
984 LIMITED_METHOD_CONTRACT;
985 _ASSERTE(HasOptionalFields());
986 GetOptionalFields()->m_pSparseVTableMap = map;
988 #endif // FEATURE_COMINTEROP
992 * Maintain back pointer to statcally hot portion of EEClass.
993 * For an EEClass representing multiple instantiations of a generic type, this is the method table
994 * for the first instantiation requested and is the only one containing entries for non-virtual instance methods
995 * (i.e. non-vtable entries).
998 // Note that EEClass structures may be shared between generic instantiations
999 // (see IsSharedByGenericInstantiations). In these cases EEClass::GetMethodTable
1000 // will return the method table pointer corresponding to the "canonical"
1001 // instantiation, as defined in typehandle.h.
1003 inline PTR_MethodTable GetMethodTable()
1005 LIMITED_METHOD_CONTRACT;
1008 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1011 // DO NOT ADD ANY ASSERTS TO THIS METHOD.
1012 // DO NOT USE THIS METHOD.
1013 // Yes folks, for better or worse the debugger pokes supposed object addresses
1014 // to try to see if objects are valid, possibly firing an AccessViolation or worse,
1015 // and then catches the AV and reports a failure to the debug client. This makes
1016 // the debugger slightly more robust should any corrupted object references appear
1017 // in a session. Thus it is "correct" behaviour for this to AV when used with
1018 // an invalid object pointer, and incorrect behaviour for it to
1020 inline PTR_MethodTable GetMethodTableWithPossibleAV()
1022 CANNOT_HAVE_CONTRACT;
1025 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1028 #ifndef DACCESS_COMPILE
1029 inline void SetMethodTable(MethodTable* pMT)
1031 LIMITED_METHOD_CONTRACT;
1032 m_pMethodTable.SetValueMaybeNull(pMT);
1034 #endif // !DACCESS_COMPILE
1037 * Number of fields in the class, including inherited fields.
1038 * Does not include fields added from EnC.
1040 inline WORD GetNumInstanceFields()
1042 LIMITED_METHOD_CONTRACT;
1044 return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1047 inline void SetNumInstanceFields (WORD wNumInstanceFields)
1049 LIMITED_METHOD_CONTRACT;
1050 SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1054 * Number of static fields declared in this class.
1055 * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1057 inline WORD GetNumStaticFields()
1059 LIMITED_METHOD_CONTRACT;
1061 return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1063 inline void SetNumStaticFields (WORD wNumStaticFields)
1065 LIMITED_METHOD_CONTRACT;
1066 SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1069 inline WORD GetNumThreadStaticFields()
1071 LIMITED_METHOD_CONTRACT;
1073 return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1076 inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1078 LIMITED_METHOD_CONTRACT;
1079 SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1082 // Statics are stored in a big chunk inside the module
1084 inline DWORD GetModuleDynamicID()
1086 LIMITED_METHOD_CONTRACT;
1088 return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1091 inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1093 LIMITED_METHOD_CONTRACT;
1094 _ASSERTE(HasOptionalFields());
1095 GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
1099 * Difference between the InterfaceMap ptr and Vtable in the
1100 * MethodTable used to indicate the number of static bytes
1101 * Now interfaceMap ptr can be optional hence we store it here
1103 inline DWORD GetNonGCRegularStaticFieldBytes()
1105 LIMITED_METHOD_CONTRACT;
1106 return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1108 inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1110 LIMITED_METHOD_CONTRACT;
1111 SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1114 inline DWORD GetNonGCThreadStaticFieldBytes()
1116 LIMITED_METHOD_CONTRACT;
1117 return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1119 inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1121 LIMITED_METHOD_CONTRACT;
1122 SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1125 inline WORD GetNumNonVirtualSlots()
1127 LIMITED_METHOD_CONTRACT;
1128 return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1130 inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1132 LIMITED_METHOD_CONTRACT;
1133 SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1136 inline BOOL IsEquivalentType()
1138 LIMITED_METHOD_CONTRACT;
1139 return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1142 #ifdef FEATURE_TYPEEQUIVALENCE
1143 inline void SetIsEquivalentType()
1145 LIMITED_METHOD_CONTRACT;
1146 m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1148 #endif // FEATURE_TYPEEQUIVALENCE
1151 * Number of static handles allocated
1153 inline WORD GetNumHandleRegularStatics ()
1155 LIMITED_METHOD_CONTRACT;
1156 return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1158 inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1160 LIMITED_METHOD_CONTRACT;
1161 SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1165 * Number of static handles allocated for ThreadStatics
1167 inline WORD GetNumHandleThreadStatics ()
1169 LIMITED_METHOD_CONTRACT;
1170 return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1172 inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1174 LIMITED_METHOD_CONTRACT;
1175 SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1179 * Number of boxed statics allocated
1181 inline WORD GetNumBoxedRegularStatics ()
1183 LIMITED_METHOD_CONTRACT;
1184 return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1186 inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1188 LIMITED_METHOD_CONTRACT;
1189 SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1193 * Number of boxed statics allocated for ThreadStatics
1195 inline WORD GetNumBoxedThreadStatics ()
1197 LIMITED_METHOD_CONTRACT;
1198 return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1200 inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1202 LIMITED_METHOD_CONTRACT;
1203 SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
1207 * Number of bytes to subract from code:MethodTable::GetBaseSize() to get the actual number of bytes
1208 * of instance fields stored in the object on the GC heap.
1210 inline DWORD GetBaseSizePadding()
1212 LIMITED_METHOD_DAC_CONTRACT;
1213 return m_cbBaseSizePadding;
1215 inline void SetBaseSizePadding(DWORD dwPadding)
1217 LIMITED_METHOD_CONTRACT;
1218 _ASSERTE(FitsIn<BYTE>(dwPadding));
1219 m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1222 inline DWORD GetUnboxedNumInstanceFieldBytes()
1224 DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1226 _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1232 * Pointer to a list of FieldDescs declared in this class
1233 * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1236 #ifdef FEATURE_PREJIT
1237 static DWORD FieldDescListSize(MethodTable * pMT);
1240 inline PTR_FieldDesc GetFieldDescList()
1242 LIMITED_METHOD_DAC_CONTRACT;
1243 // Careful about using this method. If it's possible that fields may have been added via EnC, then
1244 // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1245 return m_pFieldDescList.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList));
1248 PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1250 #ifndef DACCESS_COMPILE
1251 inline void SetFieldDescList (FieldDesc* pFieldDescList)
1253 LIMITED_METHOD_CONTRACT;
1254 m_pFieldDescList.SetValue(pFieldDescList);
1256 #endif // !DACCESS_COMPILE
1258 inline WORD GetNumMethods()
1260 LIMITED_METHOD_DAC_CONTRACT;
1261 return (WORD)GetPackableField(EEClass_Field_NumMethods);
1263 inline void SetNumMethods (WORD wNumMethods)
1265 LIMITED_METHOD_CONTRACT;
1266 SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1270 * Cached metadata for this class (GetTypeDefProps)
1272 inline DWORD GetAttrClass()
1274 LIMITED_METHOD_CONTRACT;
1275 return m_dwAttrClass;
1277 inline void SetAttrClass (DWORD dwAttrClass)
1279 LIMITED_METHOD_CONTRACT;
1280 m_dwAttrClass = dwAttrClass;
1284 #ifdef FEATURE_COMINTEROP
1285 inline DWORD IsComClassInterface()
1287 LIMITED_METHOD_CONTRACT;
1288 return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1290 inline VOID SetIsComClassInterface()
1292 LIMITED_METHOD_CONTRACT;
1293 m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1295 inline void SetComEventItfType()
1297 LIMITED_METHOD_CONTRACT;
1298 _ASSERTE(IsInterface());
1299 m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1301 // class is a special COM event interface
1302 inline BOOL IsComEventItfType()
1304 LIMITED_METHOD_CONTRACT;
1305 return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1307 #endif // FEATURE_COMINTEROP
1310 inline DWORD IsDestroyed()
1312 LIMITED_METHOD_CONTRACT;
1313 return (m_wAuxFlags & AUXFLAG_DESTROYED);
1317 inline DWORD IsUnsafeValueClass()
1319 LIMITED_METHOD_CONTRACT;
1320 return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1325 inline void SetUnsafeValueClass()
1327 LIMITED_METHOD_CONTRACT;
1328 m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1332 inline BOOL HasNoGuid()
1334 LIMITED_METHOD_CONTRACT;
1335 return (m_VMFlags & VMFLAG_NO_GUID);
1337 inline void SetHasNoGuid()
1339 WRAPPER_NO_CONTRACT;
1340 FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1344 inline BOOL IsAlign8Candidate()
1346 LIMITED_METHOD_CONTRACT;
1347 return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1349 inline void SetAlign8Candidate()
1351 LIMITED_METHOD_CONTRACT;
1352 m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1355 inline void SetDestroyed()
1357 LIMITED_METHOD_CONTRACT;
1358 m_wAuxFlags |= AUXFLAG_DESTROYED;
1361 inline void SetHasFixedAddressVTStatics()
1363 LIMITED_METHOD_CONTRACT;
1364 m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1366 void SetHasOnlyAbstractMethods()
1368 LIMITED_METHOD_CONTRACT;
1369 m_VMFlags |= (DWORD) VMFLAG_ONLY_ABSTRACT_METHODS;
1371 #ifdef FEATURE_COMINTEROP
1372 void SetSparseForCOMInterop()
1374 LIMITED_METHOD_CONTRACT;
1375 m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1377 inline void SetProjectedFromWinRT()
1379 LIMITED_METHOD_CONTRACT;
1380 m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1382 inline void SetExportedToWinRT()
1384 LIMITED_METHOD_CONTRACT;
1385 m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1387 inline void SetMarshalingType(UINT32 mType)
1389 LIMITED_METHOD_CONTRACT;
1390 _ASSERTE(mType !=0);
1391 _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1394 case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1396 case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1398 case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1401 _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1404 #endif // FEATURE_COMINTEROP
1405 inline void SetHasLayout()
1407 LIMITED_METHOD_CONTRACT;
1408 m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT; //modified before the class is published
1410 inline void SetHasOverLayedFields()
1412 LIMITED_METHOD_CONTRACT;
1413 m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1415 inline void SetIsNested()
1417 LIMITED_METHOD_CONTRACT;
1418 m_VMFlags |= VMFLAG_ISNESTED;
1421 #ifdef FEATURE_READYTORUN
1422 inline BOOL HasLayoutDependsOnOtherModules()
1424 LIMITED_METHOD_CONTRACT;
1425 return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1428 inline void SetHasLayoutDependsOnOtherModules()
1430 LIMITED_METHOD_CONTRACT;
1431 m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1435 // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1436 inline BOOL IsDelegate()
1438 LIMITED_METHOD_CONTRACT;
1439 return m_VMFlags & VMFLAG_DELEGATE;
1441 inline void SetIsDelegate()
1443 LIMITED_METHOD_CONTRACT;
1444 m_VMFlags |= VMFLAG_DELEGATE;
1447 BOOL HasFixedAddressVTStatics()
1449 LIMITED_METHOD_CONTRACT;
1450 return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1453 BOOL HasOnlyAbstractMethods()
1455 LIMITED_METHOD_CONTRACT;
1456 return m_VMFlags & VMFLAG_ONLY_ABSTRACT_METHODS;
1459 #ifdef FEATURE_COMINTEROP
1460 BOOL IsSparseForCOMInterop()
1462 LIMITED_METHOD_CONTRACT;
1463 return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1465 BOOL IsProjectedFromWinRT()
1467 LIMITED_METHOD_DAC_CONTRACT;
1468 return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1470 BOOL IsExportedToWinRT()
1472 LIMITED_METHOD_CONTRACT;
1473 return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1475 BOOL IsMarshalingTypeSet()
1477 LIMITED_METHOD_CONTRACT;
1478 return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1480 BOOL IsMarshalingTypeFreeThreaded()
1482 LIMITED_METHOD_CONTRACT;
1483 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1485 BOOL IsMarshalingTypeInhibit()
1487 LIMITED_METHOD_CONTRACT;
1488 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1490 BOOL IsMarshalingTypeStandard()
1492 LIMITED_METHOD_CONTRACT;
1493 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1495 #endif // FEATURE_COMINTEROP
1498 LIMITED_METHOD_CONTRACT;
1499 return m_VMFlags & VMFLAG_HASLAYOUT;
1501 BOOL HasOverLayedField()
1503 LIMITED_METHOD_CONTRACT;
1504 return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1508 LIMITED_METHOD_CONTRACT;
1509 return m_VMFlags & VMFLAG_ISNESTED;
1511 BOOL HasFieldsWhichMustBeInited()
1513 LIMITED_METHOD_CONTRACT;
1514 return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1516 void SetHasFieldsWhichMustBeInited()
1518 LIMITED_METHOD_CONTRACT;
1519 m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1521 void SetCannotBeBlittedByObjectCloner()
1525 DWORD HasNonPublicFields()
1527 LIMITED_METHOD_CONTRACT;
1528 return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1530 void SetHasNonPublicFields()
1532 LIMITED_METHOD_CONTRACT;
1533 m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1535 DWORD IsNotTightlyPacked()
1537 LIMITED_METHOD_CONTRACT;
1538 return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1540 void SetIsNotTightlyPacked()
1542 LIMITED_METHOD_CONTRACT;
1543 m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1545 DWORD ContainsMethodImpls()
1547 LIMITED_METHOD_CONTRACT;
1548 return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1550 void SetContainsMethodImpls()
1552 LIMITED_METHOD_CONTRACT;
1553 m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1557 BOOL IsManagedSequential();
1559 BOOL HasExplicitSize();
1561 static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1564 * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1567 // This is what would be used in the calling convention for this type.
1568 CorElementType GetInternalCorElementType()
1570 LIMITED_METHOD_DAC_CONTRACT;
1572 return CorElementType(m_NormType);
1574 void SetInternalCorElementType (CorElementType _NormType)
1576 LIMITED_METHOD_CONTRACT;
1577 m_NormType = static_cast<BYTE>(_NormType);
1581 * Chain of MethodDesc chunks for the MethodTable
1584 inline PTR_MethodDescChunk GetChunks();
1586 #ifndef DACCESS_COMPILE
1587 inline void SetChunks (MethodDescChunk* pChunks)
1589 LIMITED_METHOD_CONTRACT;
1590 m_pChunks.SetValueMaybeNull(pChunks);
1592 #endif // !DACCESS_COMPILE
1593 void AddChunk (MethodDescChunk* pNewChunk);
1595 void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1597 inline PTR_GuidInfo GetGuidInfo()
1599 LIMITED_METHOD_DAC_CONTRACT;
1601 return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1604 inline void SetGuidInfo(GuidInfo* pGuidInfo)
1606 WRAPPER_NO_CONTRACT;
1607 #ifndef DACCESS_COMPILE
1608 EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1609 #endif // DACCESS_COMPILE
1613 #if defined(UNIX_AMD64_ABI)
1614 // Get number of eightbytes used by a struct passed in registers.
1615 inline int GetNumberEightBytes()
1617 LIMITED_METHOD_CONTRACT;
1618 _ASSERTE(HasOptionalFields());
1619 return GetOptionalFields()->m_numberEightBytes;
1622 // Get eightbyte classification for the eightbyte with the specified index.
1623 inline SystemVClassificationType GetEightByteClassification(int index)
1625 LIMITED_METHOD_CONTRACT;
1626 _ASSERTE(HasOptionalFields());
1627 return GetOptionalFields()->m_eightByteClassifications[index];
1630 // Get size of the data in the eightbyte with the specified index.
1631 inline unsigned int GetEightByteSize(int index)
1633 LIMITED_METHOD_CONTRACT;
1634 _ASSERTE(HasOptionalFields());
1635 return GetOptionalFields()->m_eightByteSizes[index];
1638 // Set the eightByte classification
1639 inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1641 LIMITED_METHOD_CONTRACT;
1642 _ASSERTE(HasOptionalFields());
1643 GetOptionalFields()->m_numberEightBytes = eightByteCount;
1644 for (int i = 0; i < eightByteCount; i++)
1646 GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1647 GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1650 #endif // UNIX_AMD64_ABI
1652 #if defined(FEATURE_HFA)
1653 bool CheckForHFA(MethodTable ** pByValueClassCache);
1654 VOID CheckForNativeHFA();
1655 #else // !FEATURE_HFA
1657 #endif // FEATURE_HFA
1659 #ifdef FEATURE_COMINTEROP
1660 inline TypeHandle GetCoClassForInterface()
1662 LIMITED_METHOD_CONTRACT;
1663 _ASSERTE(HasOptionalFields());
1664 return GetOptionalFields()->m_pCoClassForIntf;
1667 inline void SetCoClassForInterface(TypeHandle th)
1669 WRAPPER_NO_CONTRACT;
1670 _ASSERTE(HasOptionalFields());
1671 *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1674 inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1676 LIMITED_METHOD_CONTRACT;
1677 return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1678 : WinMDAdapter::RedirectedTypeIndex_Invalid;
1681 inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1683 LIMITED_METHOD_CONTRACT;
1684 _ASSERTE(HasOptionalFields());
1685 _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1686 GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1688 #endif // FEATURE_COMINTEROP
1690 inline UINT32 GetNativeSize()
1692 LIMITED_METHOD_DAC_CONTRACT;
1693 return m_cbNativeSize;
1695 static UINT32 GetOffsetOfNativeSize()
1697 LIMITED_METHOD_CONTRACT;
1698 return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1700 void SetNativeSize(UINT32 nativeSize)
1702 LIMITED_METHOD_CONTRACT;
1703 m_cbNativeSize = nativeSize;
1705 #ifdef FEATURE_COMINTEROP
1706 OBJECTHANDLE GetOHDelegate()
1708 LIMITED_METHOD_CONTRACT;
1709 return m_ohDelegate;
1711 void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1713 LIMITED_METHOD_CONTRACT;
1714 m_ohDelegate = _ohDelegate;
1716 // Set the COM interface type.
1717 CorIfaceAttr GetComInterfaceType()
1719 LIMITED_METHOD_CONTRACT;
1720 return m_ComInterfaceType;
1723 void SetComInterfaceType(CorIfaceAttr ItfType)
1725 WRAPPER_NO_CONTRACT;
1726 _ASSERTE(IsInterface());
1727 EnsureWritablePages(this);
1728 m_ComInterfaceType = ItfType;
1731 inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1733 LIMITED_METHOD_CONTRACT;
1734 return m_pccwTemplate;
1736 inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1738 WRAPPER_NO_CONTRACT;
1739 return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1742 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1743 inline ClassFactoryBase *GetComClassFactory()
1745 LIMITED_METHOD_CONTRACT;
1746 return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1748 inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1750 WRAPPER_NO_CONTRACT;
1751 _ASSERTE(HasOptionalFields());
1752 return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1754 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1755 #endif // FEATURE_COMINTEROP
1759 PTR_DictionaryLayout GetDictionaryLayout()
1762 WRAPPER_NO_CONTRACT;
1763 return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1766 void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1769 WRAPPER_NO_CONTRACT;
1770 _ASSERTE(HasOptionalFields());
1771 GetOptionalFields()->m_pDictLayout = pLayout;
1774 #ifndef DACCESS_COMPILE
1775 static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1777 LIMITED_METHOD_CONTRACT;
1778 if (pbVarianceInfo == NULL)
1779 return gpNonVariant;
1781 return (CorGenericParamAttr) (pbVarianceInfo[i]);
1784 CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1786 WRAPPER_NO_CONTRACT;
1787 return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1790 BYTE* GetVarianceInfo()
1792 LIMITED_METHOD_CONTRACT;
1793 return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1796 void SetVarianceInfo(BYTE *pVarianceInfo)
1798 LIMITED_METHOD_CONTRACT;
1799 _ASSERTE(HasOptionalFields());
1800 GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1802 #endif // !DACCESS_COMPILE
1804 // Check that a signature blob uses type parameters correctly
1805 // in accordance with the variance annotations specified by this class
1806 // The position parameter indicates the variance of the context we're in
1807 // (result type is gpCovariant, argument types are gpContravariant, deeper in a signature
1808 // we might be gpNonvariant e.g. in a pointer type or non-variant generic type)
1811 DWORD numGenericArgs,
1812 BYTE *pVarianceInfo,
1815 CorGenericParamAttr position);
1820 AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1822 #endif // defined(_DEBUG)
1824 //-------------------------------------------------------------
1825 // CONCRETE DATA LAYOUT
1827 // Although accessed far less frequently than MethodTables, EEClasses are still
1828 // pulled into working set, especially at startup. This has motivated several space
1829 // optimizations in field layout where each is balanced against the need to access
1830 // a particular field efficiently.
1832 // Currently, the following strategy is used:
1834 // - Any field that has a default value for the vast majority of EEClass instances
1835 // should be stored in the EEClassOptionalFields (see header comment)
1837 // - Any field that is nearly always a small positive integer and is infrequently
1838 // accessed should be in the EEClassPackedFields (see header comment)
1840 // If none of these categories apply - such as for always-meaningful pointer members or
1841 // sets of flags - a full field is used. Please avoid adding such members if possible.
1842 //-------------------------------------------------------------
1844 // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1846 // Flags for m_VMFlags
1851 #ifdef FEATURE_READYTORUN
1852 VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
1854 VMFLAG_DELEGATE = 0x00000002,
1856 // VMFLAG_UNUSED = 0x0000001c,
1858 VMFLAG_FIXED_ADDRESS_VT_STATICS = 0x00000020, // Value type Statics in this class will be pinned
1859 VMFLAG_HASLAYOUT = 0x00000040,
1860 VMFLAG_ISNESTED = 0x00000080,
1862 VMFLAG_IS_EQUIVALENT_TYPE = 0x00000200,
1864 // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
1865 VMFLAG_HASOVERLAYEDFIELDS = 0x00000400,
1867 // Set this if this class or its parent have instance fields which
1868 // must be explicitly inited in a constructor (e.g. pointers of any
1869 // kind, gc or native).
1871 // Currently this is used by the verifier when verifying value classes
1872 // - it's ok to use uninitialised value classes if there are no
1873 // pointer fields in them.
1874 VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED = 0x00000800,
1876 VMFLAG_UNSAFEVALUETYPE = 0x00001000,
1878 VMFLAG_BESTFITMAPPING_INITED = 0x00002000, // VMFLAG_BESTFITMAPPING and VMFLAG_THROWONUNMAPPABLECHAR are valid only if this is set
1879 VMFLAG_BESTFITMAPPING = 0x00004000, // BestFitMappingAttribute.Value
1880 VMFLAG_THROWONUNMAPPABLECHAR = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar
1882 // unused = 0x00010000,
1883 VMFLAG_NO_GUID = 0x00020000,
1884 VMFLAG_HASNONPUBLICFIELDS = 0x00040000,
1885 // unused = 0x00080000,
1886 VMFLAG_CONTAINS_STACK_PTR = 0x00100000,
1887 VMFLAG_PREFER_ALIGN8 = 0x00200000, // Would like to have 8-byte alignment
1888 VMFLAG_ONLY_ABSTRACT_METHODS = 0x00400000, // Type only contains abstract methods
1890 #ifdef FEATURE_COMINTEROP
1891 VMFLAG_SPARSE_FOR_COMINTEROP = 0x00800000,
1892 // interfaces may have a coclass attribute
1893 VMFLAG_HASCOCLASSATTRIB = 0x01000000,
1894 VMFLAG_COMEVENTITFMASK = 0x02000000, // class is a special COM event interface
1895 VMFLAG_PROJECTED_FROM_WINRT = 0x04000000,
1896 VMFLAG_EXPORTED_TO_WINRT = 0x08000000,
1897 #endif // FEATURE_COMINTEROP
1899 // This one indicates that the fields of the valuetype are
1900 // not tightly packed and is used to check whether we can
1901 // do bit-equality on value types to implement ValueType::Equals.
1902 // It is not valid for classes, and only matters if ContainsPointer
1904 VMFLAG_NOT_TIGHTLY_PACKED = 0x10000000,
1906 // True if methoddesc on this class have any real (non-interface) methodimpls
1907 VMFLAG_CONTAINS_METHODIMPLS = 0x20000000,
1909 #ifdef FEATURE_COMINTEROP
1910 VMFLAG_MARSHALINGTYPE_MASK = 0xc0000000,
1912 VMFLAG_MARSHALINGTYPE_INHIBIT = 0x40000000,
1913 VMFLAG_MARSHALINGTYPE_FREETHREADED = 0x80000000,
1914 VMFLAG_MARSHALINGTYPE_STANDARD = 0xc0000000,
1919 // C_ASSERTs in Jitinterface.cpp need this to be public to check the offset.
1920 // Put it first so the offset rarely changes, which just reduces the number of times we have to fiddle
1922 RelativePointer<PTR_GuidInfo> m_pGuidInfo; // The cached guid information for interfaces.
1926 LPCUTF8 m_szDebugClassName;
1927 BOOL m_fDebuggingClass;
1931 // Layout rest of fields below from largest to smallest to lessen the chance of wasting bytes with
1932 // compiler injected padding (especially with the difference between pointers and DWORDs on 64-bit).
1933 RelativePointer<PTR_EEClassOptionalFields> m_rpOptionalFields;
1935 // TODO: Remove this field. It is only used by SOS and object validation for stress.
1936 RelativePointer<PTR_MethodTable> m_pMethodTable;
1938 RelativePointer<PTR_FieldDesc> m_pFieldDescList;
1939 RelativePointer<PTR_MethodDescChunk> m_pChunks;
1943 // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
1944 UINT32 m_cbNativeSize; // size of fixed portion in bytes
1946 #ifdef FEATURE_COMINTEROP
1947 // For COM+ wrapper objects that extend an unmanaged class, this field
1948 // may contain a delegate to be called to allocate the aggregated
1949 // unmanaged class (instead of using CoCreateInstance).
1950 OBJECTHANDLE m_ohDelegate;
1952 // For interfaces this contains the COM interface type.
1953 CorIfaceAttr m_ComInterfaceType;
1954 #endif // FEATURE_COMINTEROP
1957 #ifdef FEATURE_COMINTEROP
1958 ComCallWrapperTemplate *m_pccwTemplate; // points to interop data structures used when this type is exposed to COM
1959 #endif // FEATURE_COMINTEROP
1961 DWORD m_dwAttrClass;
1965 * We maintain some auxillary flags in DEBUG builds,
1966 * this frees up some bits in m_wVMFlags
1972 // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
1973 // structure packing.
1975 BYTE m_fFieldsArePacked; // TRUE iff fields pointed to by GetPackedFields() are in packed state
1976 BYTE m_cbFixedEEClassFields; // Count of bytes of normal fields of this instance (EEClass,
1977 // LayoutEEClass etc.). Doesn't count bytes of "packed" fields
1978 BYTE m_cbBaseSizePadding; // How many bytes of padding are included in BaseSize
1981 // EEClass optional field support. Whether a particular EEClass instance has optional fields is determined
1982 // at class load time. The entire EEClassOptionalFields structure is allocated if the EEClass has need of
1983 // one or more optional fields.
1985 #ifndef DACCESS_COMPILE
1986 void AttachOptionalFields(EEClassOptionalFields *pFields)
1988 LIMITED_METHOD_CONTRACT;
1989 _ASSERTE(m_rpOptionalFields.IsNull());
1991 m_rpOptionalFields.SetValue(pFields);
1993 #endif // !DACCESS_COMPILE
1995 bool HasOptionalFields()
1997 LIMITED_METHOD_DAC_CONTRACT;
1998 return !m_rpOptionalFields.IsNull();
2001 PTR_EEClassOptionalFields GetOptionalFields()
2003 LIMITED_METHOD_DAC_CONTRACT;
2004 return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
2009 // Support for packed fields.
2012 // Get pointer to the packed fields structure attached to this instance.
2013 PTR_EEClassPackedFields GetPackedFields();
2015 // Get the value of the given field. Works regardless of whether the field is currently in its packed or
2017 DWORD GetPackableField(EEClassFieldId eField);
2019 // Set the value of the given field. The field *must* be in the unpacked state for this to be legal (in
2020 // practice all packable fields must be initialized during class construction and from then on remain
2022 void SetPackableField(EEClassFieldId eField, DWORD dwValue);
2024 //-------------------------------------------------------------
2025 // END CONCRETE DATA LAYOUT
2026 //-------------------------------------------------------------
2030 /************************************
2032 ************************************/
2034 #ifndef DACCESS_COMPILE
2036 * Constructor: prevent any other class from doing a new()
2038 EEClass(DWORD cbFixedEEClassFields);
2041 * Destructor: prevent any other class from deleting
2045 LIMITED_METHOD_CONTRACT;
2047 #endif // !DACCESS_COMPILE
2051 // --------------------------------------------------------------------------------------------
2052 template <typename Data>
2053 class FixedCapacityStackingAllocatedUTF8StringHash
2059 HashEntry * m_pNext; // Next item with same bucketed hash value
2060 DWORD m_dwHashValue; // Hash value
2061 LPCUTF8 m_pKey; // String key
2062 Data m_data; // Data
2065 HashEntry ** m_pBuckets; // Pointer to first entry for each bucket
2066 DWORD m_dwNumBuckets;
2067 BYTE * m_pMemory; // Current pointer into preallocated memory for entries
2068 BYTE * m_pMemoryStart; // Start pointer of pre-allocated memory fo entries
2070 INDEBUG(BYTE * m_pDebugEndMemory;)
2072 FixedCapacityStackingAllocatedUTF8StringHash()
2073 : m_pMemoryStart(NULL)
2074 { LIMITED_METHOD_CONTRACT; }
2079 { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2085 StackingAllocator * pAllocator);
2087 // Insert new entry at head of list
2093 // Return the first matching entry in the list, or NULL if there is no such entry
2098 // Return the next matching entry in the list, or NULL if there is no such entry.
2101 HashEntry * pEntry);
2105 //---------------------------------------------------------------------------------------
2107 class LayoutEEClass : public EEClass
2110 EEClassLayoutInfo m_LayoutInfo;
2112 #ifndef DACCESS_COMPILE
2113 LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2115 LIMITED_METHOD_CONTRACT;
2117 FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2120 #endif // !DACCESS_COMPILE
2123 class UMThunkMarshInfo;
2125 #ifdef FEATURE_COMINTEROP
2126 struct ComPlusCallInfo;
2127 #endif // FEATURE_COMINTEROP
2129 class DelegateEEClass : public EEClass
2132 PTR_Stub m_pStaticCallStub;
2133 PTR_Stub m_pInstRetBuffCallStub;
2134 RelativePointer<PTR_MethodDesc> m_pInvokeMethod;
2135 PTR_Stub m_pMultiCastInvokeStub;
2136 PTR_Stub m_pSecureDelegateInvokeStub;
2137 UMThunkMarshInfo* m_pUMThunkMarshInfo;
2138 RelativePointer<PTR_MethodDesc> m_pBeginInvokeMethod;
2139 RelativePointer<PTR_MethodDesc> m_pEndInvokeMethod;
2140 Volatile<PCODE> m_pMarshalStub;
2142 #ifdef FEATURE_COMINTEROP
2143 ComPlusCallInfo *m_pComPlusCallInfo;
2144 #endif // FEATURE_COMINTEROP
2147 // Ngened IL stub MethodDescs. Fixed up, wrapped with code:Stub, and installed to
2148 // m_pMarshalStub (forward) or m_pUMThunkMarshInfo (reverse) when first needed.
2150 MethodDesc* m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2151 MethodDesc* m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2153 PTR_MethodDesc GetInvokeMethod()
2155 return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2158 PTR_MethodDesc GetBeginInvokeMethod()
2160 return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2163 PTR_MethodDesc GetEndInvokeMethod()
2165 return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2168 #ifndef DACCESS_COMPILE
2169 DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2171 LIMITED_METHOD_CONTRACT;
2172 // Note: Memory allocated on loader heap is zero filled
2175 // We need a LoaderHeap that lives at least as long as the DelegateEEClass, but ideally no longer
2176 LoaderHeap *GetStubHeap();
2177 #endif // !DACCESS_COMPILE
2182 typedef DPTR(ArrayClass) PTR_ArrayClass;
2185 // Dynamically generated array class structure
2186 class ArrayClass : public EEClass
2188 #ifdef FEATURE_PREJIT
2189 friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2192 friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2194 #ifndef DACCESS_COMPILE
2195 ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2197 friend class NativeImageDumper;
2202 unsigned char m_rank;
2203 CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd
2207 LIMITED_METHOD_CONTRACT;
2211 void SetRank (unsigned Rank) {
2212 LIMITED_METHOD_CONTRACT;
2213 // The only code path calling this function is code:ClassLoader::CreateTypeHandleForTypeKey, which has
2214 // checked the rank already. Assert that the rank is less than MAX_RANK and that it fits in one byte.
2215 _ASSERTE((Rank <= MAX_RANK) && (Rank <= (unsigned char)(-1)));
2216 m_rank = (unsigned char)Rank;
2219 CorElementType GetArrayElementType() {
2220 LIMITED_METHOD_CONTRACT;
2221 return m_ElementType;
2223 void SetArrayElementType(CorElementType ElementType) {
2224 LIMITED_METHOD_CONTRACT;
2225 m_ElementType = ElementType;
2229 // Allocate a new MethodDesc for the methods we add to this class
2230 void InitArrayMethodDesc(
2231 ArrayMethodDesc* pNewMD,
2232 PCCOR_SIGNATURE pShortSig,
2235 LoaderAllocator *pLoaderAllocator,
2236 AllocMemTracker *pamTracker);
2238 // Generate a short sig for an array accessor
2239 VOID GenerateArrayAccessorCallSig(DWORD dwRank,
2240 DWORD dwFuncType, // Load, store, or <init>
2241 PCCOR_SIGNATURE *ppSig, // Generated signature
2242 DWORD * pcSig, // Generated signature size
2243 LoaderAllocator *pLoaderAllocator,
2244 AllocMemTracker *pamTracker
2245 #ifdef FEATURE_ARRAYSTUB_AS_IL
2253 inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2255 LIMITED_METHOD_CONTRACT;
2256 _ASSERTE(HasLayout());
2257 return &((LayoutEEClass *) this)->m_LayoutInfo;
2260 inline BOOL EEClass::IsBlittable()
2262 LIMITED_METHOD_CONTRACT;
2264 // Either we have an opaque bunch of bytes, or we have some fields that are
2265 // all isomorphic and explicitly layed out.
2266 return (HasLayout() && GetLayoutInfo()->IsBlittable());
2269 inline BOOL EEClass::IsManagedSequential()
2271 LIMITED_METHOD_CONTRACT;
2272 return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2275 inline BOOL EEClass::HasExplicitSize()
2277 LIMITED_METHOD_CONTRACT;
2278 return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2281 //==========================================================================
2282 // These routines manage the prestub (a bootstrapping stub that all
2283 // FunctionDesc's are initialized with.)
2284 //==========================================================================
2285 VOID InitPreStubManager();
2287 EXTERN_C void STDCALL ThePreStub();
2289 inline PCODE GetPreStubEntryPoint()
2291 return GetEEFuncEntryPoint(ThePreStub);
2294 #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2296 EXTERN_C void STDCALL ThePreStubCompactARM();
2298 inline PCODE GetPreStubCompactARMEntryPoint()
2300 return GetEEFuncEntryPoint(ThePreStubCompactARM);
2303 #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2305 PCODE TheUMThunkPreStub();
2307 PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
2311 // workaround: These classification bits need cleanup bad: for now, this gets around
2312 // IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
2313 #define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
2316 // The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
2317 // methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
2320 #define METH_NAME_CACHE_SIZE 5
2321 #define MAX_MISSES 3
2323 #ifdef EnC_SUPPORTED
2325 struct EnCAddedFieldElement;
2327 #endif // EnC_SUPPORTED
2330 // --------------------------------------------------------------------------------------------
2331 // For generic instantiations the FieldDescs stored for instance
2332 // fields are approximate, not exact, i.e. they are representatives owned by
2333 // canonical instantiation and they do not carry exact type information.
2334 // This will not include EnC related fields. (See EncApproxFieldDescIterator for that)
2335 class ApproxFieldDescIterator
2339 PTR_FieldDesc m_pFieldDescList;
2345 INSTANCE_FIELDS = 0x1,
2346 STATIC_FIELDS = 0x2,
2347 ALL_FIELDS = (INSTANCE_FIELDS | STATIC_FIELDS)
2349 ApproxFieldDescIterator();
2350 ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2353 Init(pMT, iteratorType);
2355 void Init(MethodTable *pMT, int iteratorType);
2356 PTR_FieldDesc Next();
2358 int GetIteratorType() {
2359 LIMITED_METHOD_CONTRACT;
2361 return m_iteratorType;
2365 LIMITED_METHOD_CONTRACT;
2366 return m_totalFields;
2368 int CountRemaining() {
2369 LIMITED_METHOD_CONTRACT;
2371 return m_totalFields - m_currField - 1;
2376 // DeepFieldDescIterator iterates over the entire
2377 // set of fields available to a class, inherited or
2381 class DeepFieldDescIterator
2384 ApproxFieldDescIterator m_fieldIter;
2387 MethodTable* m_classes[16];
2388 int m_deepTotalFields;
2389 bool m_lastNextFromParentClass;
2394 DeepFieldDescIterator()
2396 LIMITED_METHOD_CONTRACT;
2400 m_deepTotalFields = 0;
2401 m_lastNextFromParentClass = false;
2403 DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2404 bool includeParents = true)
2406 WRAPPER_NO_CONTRACT;
2408 Init(pMT, iteratorType, includeParents);
2410 void Init(MethodTable* pMT, int iteratorType,
2411 bool includeParents = true);
2415 bool Skip(int numSkip);
2419 LIMITED_METHOD_CONTRACT;
2420 return m_deepTotalFields;
2422 bool IsFieldFromParentClass()
2424 LIMITED_METHOD_CONTRACT;
2425 return m_lastNextFromParentClass;