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.
4
5// ==--==
6//
7// File: CLASS.H
8//
9
10//
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.
15//
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.
19//
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.
22//
23// ============================================================================
24
25#ifndef CLASS_H
26#define CLASS_H
27
28/*
29 * Include Files
30 */
31#include "eecontract.h"
32#include "argslot.h"
33#include "vars.hpp"
34#include "cor.h"
35#include "clrex.h"
36#include "hash.h"
37#include "crst.h"
38#include "cgensys.h"
39#include "declsec.h"
40#ifdef FEATURE_COMINTEROP
41#include "stdinterfaces.h"
42#endif
43#include "slist.h"
44#include "spinlock.h"
45#include "typehandle.h"
46#include "perfcounters.h"
47#include "methodtable.h"
48#include "eeconfig.h"
49#include "typectxt.h"
50#include "iterator_util.h"
51
52#ifdef FEATURE_COMINTEROP
53#include "..\md\winmd\inc\adapter.h"
54#endif
55#include "packedfields.inl"
56#include "array.h"
57#define IBCLOG(x) g_IBCLogger.##x
58
59VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
60
61/*
62 * Macro definitions
63 */
64#define MAX_LOG2_PRIMITIVE_FIELD_SIZE 3
65
66#define MAX_PRIMITIVE_FIELD_SIZE (1 << MAX_LOG2_PRIMITIVE_FIELD_SIZE)
67
68/*
69 * Forward declarations
70 */
71class AppDomain;
72class ArrayClass;
73class ArrayMethodDesc;
74class Assembly;
75class ClassLoader;
76class DictionaryLayout;
77class DomainLocalBlock;
78class FCallMethodDesc;
79class EEClass;
80class EnCFieldDesc;
81class FieldDesc;
82class FieldMarshaler;
83struct LayoutRawFieldInfo;
84class MetaSig;
85class MethodDesc;
86class MethodDescChunk;
87class MethodTable;
88class Module;
89struct ModuleCtorInfo;
90class Object;
91class Stub;
92class Substitution;
93class SystemDomain;
94class TypeHandle;
95class StackingAllocator;
96class AllocMemTracker;
97class InteropMethodTableSlotDataMap;
98class LoadingEntry_LockHolder;
99class DispatchMapBuilder;
100class LoaderAllocator;
101class ComCallWrapperTemplate;
102
103typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
104typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
105
106
107//---------------------------------------------------------------------------------
108// Fields in an explicit-layout class present varying degrees of risk depending
109// on how they overlap.
110//
111// Each level is a superset of the lower (in numerical value) level - i.e.
112// all kVerifiable fields are also kLegal, but not vice-versa.
113//---------------------------------------------------------------------------------
114class ExplicitFieldTrust
115{
116 public:
117 enum TrustLevel
118 {
119 // Note: order is important here - each guarantee also implicitly guarantees all promises
120 // made by values lower in number.
121
122 // What's guaranteed. What the loader does.
123 //----- ----------------------- -------------------------------
124 kNone = 0, // no guarantees at all - Type refuses to load at all.
125 kLegal = 1, // guarantees no objref <-> scalar overlap and no unaligned objref - Type loads but field access won't verify
126 kVerifiable = 2, // guarantees no objref <-> objref overlap and all guarantees above - Type loads and field access will verify
127 kNonOverLayed = 3, // guarantees no overlap at all and all guarantees above - Type loads, field access verifies and Equals() may be optimized if structure is tightly packed
128
129 kMaxTrust = kNonOverLayed,
130 };
131
132};
133
134//----------------------------------------------------------------------------------------------
135// This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
136// into this function, we will manage all updates to the class's trust level through the ExplicitClassTrust
137// class. This abstraction enforces the rule that the overall class is only as trustworthy as
138// the least trustworthy field.
139//----------------------------------------------------------------------------------------------
140class ExplicitClassTrust : private ExplicitFieldTrust
141{
142 public:
143 ExplicitClassTrust()
144 {
145 LIMITED_METHOD_CONTRACT;
146 m_trust = kMaxTrust; // Yes, we start out with maximal trust. This reflects that explicit layout structures with no fields do represent no risk.
147 }
148
149 VOID AddField(TrustLevel fieldTrust)
150 {
151 LIMITED_METHOD_CONTRACT;
152 m_trust = min(m_trust, fieldTrust);
153 }
154
155 BOOL IsLegal()
156 {
157 LIMITED_METHOD_CONTRACT;
158 return m_trust >= kLegal;
159 }
160
161 BOOL IsVerifiable()
162 {
163 LIMITED_METHOD_CONTRACT;
164 return m_trust >= kVerifiable;
165 }
166
167 BOOL IsNonOverLayed()
168 {
169 LIMITED_METHOD_CONTRACT;
170 return m_trust >= kNonOverLayed;
171 }
172
173 TrustLevel GetTrustLevel()
174 {
175 LIMITED_METHOD_CONTRACT;
176 return m_trust;
177 }
178
179 private:
180 TrustLevel m_trust;
181};
182
183//----------------------------------------------------------------------------------------------
184// This class is a helper for HandleExplicitLayout. To make it harder to introduce security holes
185// into this function, this class will collect trust information about individual fields to be later
186// aggregated into the overall class level.
187//
188// This abstraction enforces the rule that all fields are presumed guilty until explicitly declared
189// safe by calling SetTrust(). If you fail to call SetTrust before leaving the block, the destructor
190// will automatically cause the entire class to be declared illegal (and you will get an assert
191// telling you to fix this bug.)
192//----------------------------------------------------------------------------------------------
193class ExplicitFieldTrustHolder : private ExplicitFieldTrust
194{
195 public:
196 ExplicitFieldTrustHolder(ExplicitClassTrust *pExplicitClassTrust)
197 {
198 LIMITED_METHOD_CONTRACT;
199 m_pExplicitClassTrust = pExplicitClassTrust;
200#ifdef _DEBUG
201 m_trustDeclared = FALSE;
202#endif
203 m_fieldTrust = kNone;
204 }
205
206 VOID SetTrust(TrustLevel fieldTrust)
207 {
208 LIMITED_METHOD_CONTRACT;
209
210 _ASSERTE(fieldTrust >= kNone && fieldTrust <= kMaxTrust);
211 _ASSERTE(!m_trustDeclared && "You should not set the trust value more than once.");
212
213#ifdef _DEBUG
214 m_trustDeclared = TRUE;
215#endif
216 m_fieldTrust = fieldTrust;
217 }
218
219 ~ExplicitFieldTrustHolder()
220 {
221 LIMITED_METHOD_CONTRACT;
222 // If no SetTrust() was ever called, we will default to kNone (i.e. declare the entire type
223 // illegal.) It'd be nice to assert here but since this case can be legitimately reached
224 // on exception unwind, we cannot.
225 m_pExplicitClassTrust->AddField(m_fieldTrust);
226 }
227
228
229 private:
230 ExplicitClassTrust* m_pExplicitClassTrust;
231 TrustLevel m_fieldTrust;
232#ifdef _DEBUG
233 BOOL m_trustDeclared; // Debug flag to detect multiple Sets. (Which we treat as a bug as this shouldn't be necessary.)
234#endif
235};
236
237//*******************************************************************************
238// Enumerator to traverse the interface declarations of a type, automatically building
239// a substitution chain on the stack.
240class InterfaceImplEnum
241{
242 Module* m_pModule;
243 HENUMInternalHolder hEnumInterfaceImpl;
244 const Substitution *m_pSubstChain;
245 Substitution m_CurrSubst;
246 mdTypeDef m_CurrTok;
247public:
248 InterfaceImplEnum(Module *pModule, mdTypeDef cl, const Substitution *pSubstChain)
249 : hEnumInterfaceImpl(pModule->GetMDImport())
250 {
251 WRAPPER_NO_CONTRACT;
252 m_pModule = pModule;
253 hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
254 m_pSubstChain = pSubstChain;
255 }
256
257 // Returns:
258 // S_OK ... if has next (TRUE)
259 // S_FALSE ... if does not have next (FALSE)
260 // error code.
261 HRESULT Next()
262 {
263 WRAPPER_NO_CONTRACT;
264 HRESULT hr;
265 mdInterfaceImpl ii;
266 if (!m_pModule->GetMDImport()->EnumNext(&hEnumInterfaceImpl, &ii))
267 {
268 return S_FALSE;
269 }
270
271 IfFailRet(m_pModule->GetMDImport()->GetTypeOfInterfaceImpl(ii, &m_CurrTok));
272 m_CurrSubst = Substitution(m_CurrTok, m_pModule, m_pSubstChain);
273 return S_OK;
274 }
275 const Substitution *CurrentSubst() const { LIMITED_METHOD_CONTRACT; return &m_CurrSubst; }
276 mdTypeDef CurrentToken() const { LIMITED_METHOD_CONTRACT; return m_CurrTok; }
277};
278
279#ifdef FEATURE_COMINTEROP
280//
281// Class used to map MethodTable slot numbers to COM vtable slots numbers
282// (either for calling a classic COM component or for constructing a classic COM
283// vtable via which COM components can call managed classes). This structure is
284// embedded in the EEClass but the mapping list itself is only allocated if the
285// COM vtable is sparse.
286//
287
288class SparseVTableMap
289{
290public:
291#ifdef DACCESS_COMPILE
292 friend class NativeImageDumper;
293#endif
294
295 SparseVTableMap();
296 ~SparseVTableMap();
297
298 // First run through MT slots calling RecordGap wherever a gap in VT slots
299 // occurs.
300 void RecordGap(WORD StartMTSlot, WORD NumSkipSlots);
301
302 // Then call FinalizeMapping to create the actual mapping list.
303 void FinalizeMapping(WORD TotalMTSlots);
304
305 // Map MT to VT slot.
306 WORD LookupVTSlot(WORD MTSlot);
307
308 // Retrieve the number of slots in the vtable (both empty and full).
309 WORD GetNumVTableSlots();
310
311 const void* GetMapList()
312 {
313 LIMITED_METHOD_CONTRACT;
314 return (void*)m_MapList;
315 }
316
317#ifdef FEATURE_PREJIT
318 // Methods to persist structure
319 void Save(DataImage *image);
320 void Fixup(DataImage *image);
321#endif // FEATURE_PREJIT
322
323private:
324
325 enum { MapGrow = 4 };
326
327 struct Entry
328 {
329 WORD m_Start; // Starting MT slot number
330 WORD m_Span; // # of consecutive slots that map linearly
331 WORD m_MapTo; // Starting VT slot number
332 };
333
334 Entry *m_MapList; // Pointer to array of Entry structures
335 WORD m_MapEntries; // Number of entries in above
336 WORD m_Allocated; // Number of entries allocated
337
338 WORD m_LastUsed; // Index of last entry used in successful lookup
339
340 WORD m_VTSlot; // Current VT slot number, used during list build
341 WORD m_MTSlot; // Current MT slot number, used during list build
342
343 void AllocOrExpand(); // Allocate or expand the mapping list for a new entry
344};
345#endif // FEATURE_COMINTEROP
346
347//=======================================================================
348// Adjunct to the EEClass structure for classes w/ layout
349//=======================================================================
350class EEClassLayoutInfo
351{
352 static VOID CollectLayoutFieldMetadataThrowing(
353 mdTypeDef cl, // cl of the NStruct being loaded
354 BYTE packingSize, // packing size (from @dll.struct)
355 BYTE nlType, // nltype (from @dll.struct)
356#ifdef FEATURE_COMINTEROP
357 BOOL isWinRT, // Is the type a WinRT type
358#endif // FEATURE_COMINTEROP
359 BOOL fExplicitOffsets, // explicit offsets?
360 MethodTable *pParentMT, // the loaded superclass
361 ULONG cMembers, // total number of members (methods + fields)
362 HENUMInternal *phEnumField, // enumerator for field
363 Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
364 const SigTypeContext *pTypeContext, // Type parameters for NStruct being loaded
365 EEClassLayoutInfo *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
366 LayoutRawFieldInfo *pInfoArrayOut, // caller-allocated array to fill in. Needs room for cMember+1 elements
367 LoaderAllocator * pAllocator,
368 AllocMemTracker *pamTracker
369 );
370
371
372 friend class ClassLoader;
373 friend class EEClass;
374 friend class MethodTableBuilder;
375#ifdef DACCESS_COMPILE
376 friend class NativeImageDumper;
377#endif
378
379 private:
380 // size (in bytes) of fixed portion of NStruct.
381 UINT32 m_cbNativeSize;
382 UINT32 m_cbManagedSize;
383
384 public:
385 // 1,2,4 or 8: this is equal to the largest of the alignment requirements
386 // of each of the EEClass's members. If the NStruct extends another NStruct,
387 // the base NStruct is treated as the first member for the purpose of
388 // this calculation.
389 BYTE m_LargestAlignmentRequirementOfAllMembers;
390
391 // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember
392 // for the managed layout.
393 BYTE m_ManagedLargestAlignmentRequirementOfAllMembers;
394
395 private:
396 enum {
397 // TRUE if the GC layout of the class is bit-for-bit identical
398 // to its unmanaged counterpart (i.e. no internal reference fields,
399 // no ansi-unicode char conversions required, etc.) Used to
400 // optimize marshaling.
401 e_BLITTABLE = 0x01,
402 // Post V1.0 addition: Is this type also sequential in managed memory?
403 e_MANAGED_SEQUENTIAL = 0x02,
404 // When a sequential/explicit type has no fields, it is conceptually
405 // zero-sized, but actually is 1 byte in length. This holds onto this
406 // fact and allows us to revert the 1 byte of padding when another
407 // explicit type inherits from this type.
408 e_ZERO_SIZED = 0x04,
409 // The size of the struct is explicitly specified in the meta-data.
410 e_HAS_EXPLICIT_SIZE = 0x08,
411#ifdef UNIX_AMD64_ABI
412#ifdef FEATURE_HFA
413#error Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time.
414#endif // FEATURE_HFA
415 e_NATIVE_PASS_IN_REGISTERS = 0x10, // Flag wheter a native struct is passed in registers.
416#endif // UNIX_AMD64_ABI
417#ifdef FEATURE_HFA
418 // HFA type of the unmanaged layout
419 e_R4_HFA = 0x10,
420 e_R8_HFA = 0x20,
421#endif
422 };
423
424 BYTE m_bFlags;
425
426 // Packing size in bytes (1, 2, 4, 8 etc.)
427 BYTE m_cbPackingSize;
428
429 // # of fields that are of the calltime-marshal variety.
430 UINT m_numCTMFields;
431
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;
436
437
438 public:
439 BOOL GetNativeSize() const
440 {
441 LIMITED_METHOD_CONTRACT;
442 return m_cbNativeSize;
443 }
444
445 UINT32 GetManagedSize() const
446 {
447 LIMITED_METHOD_CONTRACT;
448 return m_cbManagedSize;
449 }
450
451
452 BYTE GetLargestAlignmentRequirementOfAllMembers() const
453 {
454 LIMITED_METHOD_CONTRACT;
455 return m_LargestAlignmentRequirementOfAllMembers;
456 }
457
458 UINT GetNumCTMFields() const
459 {
460 LIMITED_METHOD_CONTRACT;
461 return m_numCTMFields;
462 }
463
464 PTR_FieldMarshaler GetFieldMarshalers() const
465 {
466 LIMITED_METHOD_CONTRACT;
467 return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
468 }
469
470#ifndef DACCESS_COMPILE
471 void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
472 {
473 LIMITED_METHOD_CONTRACT;
474 m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
475 }
476#endif // DACCESS_COMPILE
477
478 BOOL IsBlittable() const
479 {
480 LIMITED_METHOD_CONTRACT;
481 return (m_bFlags & e_BLITTABLE) == e_BLITTABLE;
482 }
483
484 BOOL IsManagedSequential() const
485 {
486 LIMITED_METHOD_CONTRACT;
487 return (m_bFlags & e_MANAGED_SEQUENTIAL) == e_MANAGED_SEQUENTIAL;
488 }
489
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
496 {
497 LIMITED_METHOD_CONTRACT;
498 return (m_bFlags & e_ZERO_SIZED) == e_ZERO_SIZED;
499 }
500
501 BOOL HasExplicitSize() const
502 {
503 LIMITED_METHOD_CONTRACT;
504 return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE;
505 }
506
507 DWORD GetPackingSize() const
508 {
509 LIMITED_METHOD_CONTRACT;
510 return m_cbPackingSize;
511 }
512
513#ifdef UNIX_AMD64_ABI
514 bool IsNativeStructPassedInRegisters()
515 {
516 LIMITED_METHOD_CONTRACT;
517 return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
518 }
519#else
520 bool IsNativeStructPassedInRegisters()
521 {
522 return false;
523 }
524#endif // UNIX_AMD64_ABI
525
526 CorElementType GetNativeHFATypeRaw();
527#ifdef FEATURE_HFA
528 bool IsNativeHFA()
529 {
530 LIMITED_METHOD_CONTRACT;
531 return (m_bFlags & (e_R4_HFA | e_R8_HFA)) != 0;
532 }
533
534 CorElementType GetNativeHFAType()
535 {
536 LIMITED_METHOD_CONTRACT;
537 if (IsNativeHFA())
538 return (m_bFlags & e_R4_HFA) ? ELEMENT_TYPE_R4 : ELEMENT_TYPE_R8;
539 return ELEMENT_TYPE_END;
540 }
541#else // !FEATURE_HFA
542 bool IsNativeHFA()
543 {
544 return GetNativeHFATypeRaw() != ELEMENT_TYPE_END;
545 }
546 CorElementType GetNativeHFAType()
547 {
548 return GetNativeHFATypeRaw();
549 }
550#endif // !FEATURE_HFA
551
552 private:
553 void SetIsBlittable(BOOL isBlittable)
554 {
555 LIMITED_METHOD_CONTRACT;
556 m_bFlags = isBlittable ? (m_bFlags | e_BLITTABLE)
557 : (m_bFlags & ~e_BLITTABLE);
558 }
559
560 void SetIsManagedSequential(BOOL isManagedSequential)
561 {
562 LIMITED_METHOD_CONTRACT;
563 m_bFlags = isManagedSequential ? (m_bFlags | e_MANAGED_SEQUENTIAL)
564 : (m_bFlags & ~e_MANAGED_SEQUENTIAL);
565 }
566
567 void SetIsZeroSized(BOOL isZeroSized)
568 {
569 LIMITED_METHOD_CONTRACT;
570 m_bFlags = isZeroSized ? (m_bFlags | e_ZERO_SIZED)
571 : (m_bFlags & ~e_ZERO_SIZED);
572 }
573
574 void SetHasExplicitSize(BOOL hasExplicitSize)
575 {
576 LIMITED_METHOD_CONTRACT;
577 m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
578 : (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
579 }
580
581#ifdef FEATURE_HFA
582 void SetNativeHFAType(CorElementType hfaType)
583 {
584 LIMITED_METHOD_CONTRACT;
585 m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA;
586 }
587#endif
588#ifdef UNIX_AMD64_ABI
589 void SetNativeStructPassedInRegisters()
590 {
591 LIMITED_METHOD_CONTRACT;
592 m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
593 }
594#endif // UNIX_AMD64_ABI
595
596};
597
598
599
600//
601// This structure is used only when the classloader is building the interface map. Before the class
602// is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
603// for this class/interface by the metadata - inherited interfaces will not be present if they are
604// not specifically declared.
605//
606// This structure is destroyed after resolving has completed.
607//
608typedef struct
609{
610 // The interface method table; for instantiated interfaces, this is the generic interface
611 MethodTable *m_pMethodTable;
612} BuildingInterfaceInfo_t;
613
614
615//
616// We should not need to touch anything in here once the classes are all loaded, unless we
617// are doing reflection. Try to avoid paging this data structure in.
618//
619
620// Size of hash bitmap for method names
621#define METHOD_HASH_BYTES 8
622
623// Hash table size - prime number
624#define METHOD_HASH_BITS 61
625
626
627// These are some macros for forming fully qualified class names for a class.
628// These are abstracted so that we can decide later if a max length for a
629// class name is acceptable.
630
631// It doesn't make any sense not to have a small but usually quite capable
632// stack buffer to build class names into. Most class names that I can think
633// of would fit in 128 characters, and that's a pretty small amount of stack
634// to use in exchange for not having to new and delete the memory.
635#define DEFAULT_NONSTACK_CLASSNAME_SIZE (MAX_CLASSNAME_LENGTH/4)
636
637#define DefineFullyQualifiedNameForClass() \
638 ScratchBuffer<DEFAULT_NONSTACK_CLASSNAME_SIZE> _scratchbuffer_; \
639 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_;
640
641#define DefineFullyQualifiedNameForClassOnStack() \
642 ScratchBuffer<MAX_CLASSNAME_LENGTH> _scratchbuffer_; \
643 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_;
644
645#define DefineFullyQualifiedNameForClassW() \
646 InlineSString<DEFAULT_NONSTACK_CLASSNAME_SIZE> _ssclsname_w_;
647
648#define DefineFullyQualifiedNameForClassWOnStack() \
649 InlineSString<MAX_CLASSNAME_LENGTH> _ssclsname_w_;
650
651#define GetFullyQualifiedNameForClassNestedAware(pClass) \
652 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_).GetUTF8(_scratchbuffer_)
653
654#define GetFullyQualifiedNameForClassNestedAwareW(pClass) \
655 pClass->_GetFullyQualifiedNameForClassNestedAware(_ssclsname_w_).GetUnicode()
656
657#define GetFullyQualifiedNameForClass(pClass) \
658 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
659
660#define GetFullyQualifiedNameForClassW(pClass) \
661 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
662
663#define GetFullyQualifiedNameForClassW_WinRT(pClass) \
664 pClass->_GetFullyQualifiedNameForClass(_ssclsname_w_).GetUnicode()
665
666#define GetFullyQualifiedNameForClass_WinRT(pClass) \
667 pClass->_GetFullyQualifiedNameForClass(_ssclsname_).GetUTF8(_scratchbuffer_)
668
669// Structure containing EEClass fields used by a minority of EEClass instances. This separation allows us to
670// save memory and improve the density of accessed fields in the EEClasses themselves. This class is reached
671// via the m_rpOptionalFields field EEClass (use the GetOptionalFields() accessor rather than the field
672// itself).
673class EEClassOptionalFields
674{
675 // All fields here are intentionally private. Use the corresponding accessor on EEClass instead (this
676 // makes it easier to add and remove fields from the optional section in the future). We make exceptions
677 // for MethodTableBuilder and NativeImageDumper, which need raw field-level access.
678 friend class EEClass;
679 friend class MethodTableBuilder;
680#ifdef DACCESS_COMPILE
681 friend class NativeImageDumper;
682#endif
683
684 //
685 // GENERICS RELATED FIELDS.
686 //
687
688 // If IsSharedByGenericInstantiations(), layout of handle dictionary for generic type
689 // (the last dictionary pointed to from PerInstInfo). Otherwise NULL.
690 PTR_DictionaryLayout m_pDictLayout;
691
692 // Variance info for each type parameter (gpNonVariant, gpCovariant, or gpContravariant)
693 // If NULL, this type has no type parameters that are co/contravariant
694 RelativePointer<PTR_BYTE> m_pVarianceInfo;
695
696 //
697 // COM RELATED FIELDS.
698 //
699
700#ifdef FEATURE_COMINTEROP
701 SparseVTableMap *m_pSparseVTableMap;
702
703 TypeHandle m_pCoClassForIntf; // @TODO: Coclass for an interface
704
705#ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
706 // Points to activation information if the type is an activatable COM/WinRT class.
707 ClassFactoryBase *m_pClassFactory;
708#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
709
710 WinMDAdapter::RedirectedTypeIndex m_WinRTRedirectedTypeIndex;
711
712#endif // FEATURE_COMINTEROP
713
714 //
715 // MISC FIELDS
716 //
717
718 #define MODULE_NON_DYNAMIC_STATICS ((DWORD)-1)
719 DWORD m_cbModuleDynamicID;
720
721#if defined(UNIX_AMD64_ABI)
722 // Number of eightBytes in the following arrays
723 int m_numberEightBytes;
724 // Classification of the eightBytes
725 SystemVClassificationType m_eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
726 // Size of data the eightBytes
727 unsigned int m_eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS];
728#endif // UNIX_AMD64_ABI
729
730 // Set default values for optional fields.
731 inline void Init();
732
733 PTR_BYTE GetVarianceInfo()
734 {
735 LIMITED_METHOD_DAC_CONTRACT;
736
737 return ReadPointerMaybeNull(this, &EEClassOptionalFields::m_pVarianceInfo);
738 }
739};
740typedef DPTR(EEClassOptionalFields) PTR_EEClassOptionalFields;
741
742//
743// Another mechanism used to reduce the size of the average EEClass instance is the notion of packed fields.
744// This is based on the observation that EEClass has a large number of integer fields that typically contain
745// small values and that are fixed once class layout has completed. We can compact these fields by discarding
746// the leading zero bits (and for small values there'll be a lot of these) and packing the significant data
747// into compact bitfields. This is a dynamic operation (the exact packing used depends on the exact data
748// stored in the fields).
749//
750// The PackedDWORDFields<> class (defined in PackedFields.inl) encapsulates this. It takes one template
751// parameter, the number of fields to pack, and provides operations to get and set those fields until we're
752// happy with the values, at which point it will compact them for us.
753//
754// The packed fields themselves are stored at the end of the EEClass instance (or the LayoutEEClass or the
755// DelegateEEClass etc.) so we can take advantage of the variable sized nature of the fields. We gain nothing for
756// runtime allocated EEClasses (we have to allocate a maximally sized structure for the packed fields because
757// we can't tell at the beginning of EEClass layout what the field values will be). But in the ngen scenario
758// we can compact the fields just prior to saving and only store the portion of the EEClass that is relvant,
759// helping us with our goal of packing all the EEClass instances together as tightly as possible.
760//
761// Since each packed field is now accessed via an array-like index, we give each of those indices a name with
762// the enum below to make the code more readable.
763//
764
765enum EEClassFieldId
766{
767 EEClass_Field_NumInstanceFields = 0,
768 EEClass_Field_NumMethods,
769 EEClass_Field_NumStaticFields,
770 EEClass_Field_NumHandleStatics,
771 EEClass_Field_NumBoxedStatics,
772 EEClass_Field_NonGCStaticFieldBytes,
773 EEClass_Field_NumThreadStaticFields,
774 EEClass_Field_NumHandleThreadStatics,
775 EEClass_Field_NumBoxedThreadStatics,
776 EEClass_Field_NonGCThreadStaticFieldBytes,
777 EEClass_Field_NumNonVirtualSlots,
778 EEClass_Field_COUNT
779};
780
781typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields;
782typedef DPTR(EEClassPackedFields) PTR_EEClassPackedFields;
783
784//@GENERICS:
785// For most types there is a one-to-one mapping between MethodTable* and EEClass*
786// However this is not the case for instantiated types where code and representation
787// are shared between compatible instantiations (e.g. List<string> and List<object>)
788// Then a single EEClass structure is shared between multiple MethodTable structures
789// Uninstantiated generic types (e.g. List) have their own EEClass and MethodTable,
790// used (a) as a representative for the generic type itself, (b) for static fields and
791// methods, which aren't present in the instantiations, and (c) to hold some information
792// (e.g. formal instantiations of superclass and implemented interfaces) that is common
793// to all instantiations and isn't stored in the EEClass structures for instantiated types
794//
795//
796// ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
797//
798// A word about EEClass vs. MethodTable
799// ------------------------------------
800//
801// At compile-time, we are happy to touch both MethodTable and EEClass. However,
802// at runtime we want to restrict ourselves to the MethodTable. This is critical
803// for common code paths, where we want to keep the EEClass out of our working
804// set. For uncommon code paths, like throwing exceptions or strange Contexts
805// issues, it's okay to access the EEClass.
806//
807// To this end, the TypeHandle (CLASS_HANDLE) abstraction is now based on the
808// MethodTable pointer instead of the EEClass pointer. If you are writing a
809// runtime helper that calls GetClass() to access the associated EEClass, please
810// stop to wonder if you are making a mistake.
811//
812// ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE ** NOTE
813
814
815// An code:EEClass is a representation of the part of a managed type that is not used very frequently (it is
816// cold), and thus is segregated from the hot portion (which lives in code:MethodTable). As noted above an
817// it is also the case that EEClass is SHARED among all instantiations of a generic type, so anything that
818// is specific to a paritcular type can not live off the EEClass.
819//
820// From here you can get to
821// code:MethodTable - The representation of the hot portion of a type.
822// code:MethodDesc - The representation of a method
823// code:FieldDesc - The representation of a field.
824//
825// EEClasses hold the following important fields
826// * code:EEClass.m_pMethodTable - Points a MethodTable associated with
827// * code:EEClass.m_pChunks - a list of code:MethodDescChunk which is simply a list of code:MethodDesc
828// which represent the methods.
829// * code:EEClass.m_pFieldDescList - a list of fields in the type.
830//
831class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
832{
833 /************************************
834 * FRIEND FUNCTIONS
835 ************************************/
836 // DO NOT ADD FRIENDS UNLESS ABSOLUTELY NECESSARY
837 // USE ACCESSORS TO READ/WRITE private field members
838
839 // To access bmt stuff
840 friend class MethodTable;
841 friend class MethodTableBuilder;
842 friend class FieldDesc;
843 friend class CheckAsmOffsets;
844 friend class ClrDataAccess;
845#ifdef DACCESS_COMPILE
846 friend class NativeImageDumper;
847#endif
848
849 /************************************
850 * PUBLIC INSTANCE METHODS
851 ************************************/
852public:
853
854 DWORD IsSealed()
855 {
856 LIMITED_METHOD_CONTRACT;
857 return IsTdSealed(m_dwAttrClass);
858 }
859
860 inline DWORD IsInterface()
861 {
862 WRAPPER_NO_CONTRACT;
863 return IsTdInterface(m_dwAttrClass);
864 }
865
866 inline DWORD IsAbstract()
867 {
868 WRAPPER_NO_CONTRACT;
869 return IsTdAbstract(m_dwAttrClass);
870 }
871
872 BOOL HasExplicitFieldOffsetLayout()
873 {
874 WRAPPER_NO_CONTRACT;
875 return IsTdExplicitLayout(GetAttrClass()) && HasLayout();
876 }
877
878 BOOL HasSequentialLayout()
879 {
880 WRAPPER_NO_CONTRACT;
881 return IsTdSequentialLayout(GetAttrClass());
882 }
883 BOOL IsBeforeFieldInit()
884 {
885 WRAPPER_NO_CONTRACT;
886 return IsTdBeforeFieldInit(GetAttrClass());
887 }
888
889 DWORD GetProtection()
890 {
891 WRAPPER_NO_CONTRACT;
892 return (m_dwAttrClass & tdVisibilityMask);
893 }
894
895 // class is blittable
896 BOOL IsBlittable();
897
898#ifndef DACCESS_COMPILE
899 void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker);
900 void Destruct(MethodTable * pMT);
901
902 static EEClass * CreateMinimalClass(LoaderHeap *pHeap, AllocMemTracker *pamTracker);
903#endif // !DACCESS_COMPILE
904
905#ifdef EnC_SUPPORTED
906 // Add a new method to an already loaded type for EnC
907 static HRESULT AddMethod(MethodTable * pMT, mdMethodDef methodDef, RVA newRVA, MethodDesc **ppMethod);
908
909 // Add a new field to an already loaded type for EnC
910 static HRESULT AddField(MethodTable * pMT, mdFieldDef fieldDesc, EnCFieldDesc **pAddedField);
911 static VOID FixupFieldDescForEnC(MethodTable * pMT, EnCFieldDesc *pFD, mdFieldDef fieldDef);
912#endif // EnC_SUPPORTED
913
914 inline DWORD IsComImport()
915 {
916 WRAPPER_NO_CONTRACT;
917 return IsTdImport(m_dwAttrClass);
918 }
919
920#ifdef FEATURE_PREJIT
921 DWORD GetSize();
922
923 void Save(DataImage *image, MethodTable *pMT);
924 void Fixup(DataImage *image, MethodTable *pMT);
925#endif // FEATURE_PREJIT
926
927 EEClassLayoutInfo *GetLayoutInfo();
928
929#ifdef DACCESS_COMPILE
930 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, MethodTable *pMT);
931#endif
932
933 static CorElementType ComputeInternalCorElementTypeForValueType(MethodTable * pMT);
934
935 /************************************
936 * INSTANCE MEMBER VARIABLES
937 ************************************/
938#ifdef _DEBUG
939public:
940 inline LPCUTF8 GetDebugClassName ()
941 {
942 LIMITED_METHOD_CONTRACT;
943 return m_szDebugClassName;
944 }
945 inline void SetDebugClassName (LPCUTF8 szDebugClassName)
946 {
947 LIMITED_METHOD_CONTRACT;
948 m_szDebugClassName = szDebugClassName;
949 }
950
951 /*
952 * Controls debugging breaks and output if a method class
953 * is mentioned in the registry ("BreakOnClassBuild")
954 * Method layout within this class can cause a debug
955 * break by setting "BreakOnMethodName". Not accessible
956 * outside the class.
957 */
958
959#endif // _DEBUG
960
961#ifdef FEATURE_COMINTEROP
962 /*
963 * Used to map MethodTable slots to VTable slots
964 */
965 inline SparseVTableMap* GetSparseCOMInteropVTableMap ()
966 {
967 LIMITED_METHOD_CONTRACT;
968 return HasOptionalFields() ? GetOptionalFields()->m_pSparseVTableMap : NULL;
969 }
970 inline void SetSparseCOMInteropVTableMap (SparseVTableMap *map)
971 {
972 LIMITED_METHOD_CONTRACT;
973 _ASSERTE(HasOptionalFields());
974 GetOptionalFields()->m_pSparseVTableMap = map;
975 }
976#endif // FEATURE_COMINTEROP
977
978public:
979 /*
980 * Maintain back pointer to statcally hot portion of EEClass.
981 * For an EEClass representing multiple instantiations of a generic type, this is the method table
982 * for the first instantiation requested and is the only one containing entries for non-virtual instance methods
983 * (i.e. non-vtable entries).
984 */
985
986 // Note that EEClass structures may be shared between generic instantiations
987 // (see IsSharedByGenericInstantiations). In these cases EEClass::GetMethodTable
988 // will return the method table pointer corresponding to the "canonical"
989 // instantiation, as defined in typehandle.h.
990 //
991 inline PTR_MethodTable GetMethodTable()
992 {
993 LIMITED_METHOD_CONTRACT;
994 SUPPORTS_DAC;
995
996 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
997 }
998
999 // DO NOT ADD ANY ASSERTS TO THIS METHOD.
1000 // DO NOT USE THIS METHOD.
1001 // Yes folks, for better or worse the debugger pokes supposed object addresses
1002 // to try to see if objects are valid, possibly firing an AccessViolation or worse,
1003 // and then catches the AV and reports a failure to the debug client. This makes
1004 // the debugger slightly more robust should any corrupted object references appear
1005 // in a session. Thus it is "correct" behaviour for this to AV when used with
1006 // an invalid object pointer, and incorrect behaviour for it to
1007 // assert.
1008 inline PTR_MethodTable GetMethodTableWithPossibleAV()
1009 {
1010 CANNOT_HAVE_CONTRACT;
1011 SUPPORTS_DAC;
1012
1013 return ReadPointerMaybeNull(this, &EEClass::m_pMethodTable);
1014 }
1015
1016#ifndef DACCESS_COMPILE
1017 inline void SetMethodTable(MethodTable* pMT)
1018 {
1019 LIMITED_METHOD_CONTRACT;
1020 m_pMethodTable.SetValueMaybeNull(pMT);
1021 }
1022#endif // !DACCESS_COMPILE
1023
1024 /*
1025 * Number of fields in the class, including inherited fields.
1026 * Does not include fields added from EnC.
1027 */
1028 inline WORD GetNumInstanceFields()
1029 {
1030 LIMITED_METHOD_CONTRACT;
1031 SUPPORTS_DAC;
1032 return (WORD)GetPackableField(EEClass_Field_NumInstanceFields);
1033 }
1034
1035 inline void SetNumInstanceFields (WORD wNumInstanceFields)
1036 {
1037 LIMITED_METHOD_CONTRACT;
1038 SetPackableField(EEClass_Field_NumInstanceFields, wNumInstanceFields);
1039 }
1040
1041 /*
1042 * Number of static fields declared in this class.
1043 * Implementation Note: Static values are laid out at the end of the MethodTable vtable.
1044 */
1045 inline WORD GetNumStaticFields()
1046 {
1047 LIMITED_METHOD_CONTRACT;
1048 SUPPORTS_DAC;
1049 return (WORD)GetPackableField(EEClass_Field_NumStaticFields);
1050 }
1051 inline void SetNumStaticFields (WORD wNumStaticFields)
1052 {
1053 LIMITED_METHOD_CONTRACT;
1054 SetPackableField(EEClass_Field_NumStaticFields, wNumStaticFields);
1055 }
1056
1057 inline WORD GetNumThreadStaticFields()
1058 {
1059 LIMITED_METHOD_CONTRACT;
1060 SUPPORTS_DAC;
1061 return (WORD)GetPackableField(EEClass_Field_NumThreadStaticFields);
1062 }
1063
1064 inline void SetNumThreadStaticFields (WORD wNumThreadStaticFields)
1065 {
1066 LIMITED_METHOD_CONTRACT;
1067 SetPackableField(EEClass_Field_NumThreadStaticFields, wNumThreadStaticFields);
1068 }
1069
1070 // Statics are stored in a big chunk inside the module
1071
1072 inline DWORD GetModuleDynamicID()
1073 {
1074 LIMITED_METHOD_CONTRACT;
1075 SUPPORTS_DAC;
1076 return HasOptionalFields() ? GetOptionalFields()->m_cbModuleDynamicID : MODULE_NON_DYNAMIC_STATICS;
1077 }
1078
1079 inline void SetModuleDynamicID(DWORD cbModuleDynamicID)
1080 {
1081 LIMITED_METHOD_CONTRACT;
1082 _ASSERTE(HasOptionalFields());
1083 GetOptionalFields()->m_cbModuleDynamicID = cbModuleDynamicID;
1084 }
1085
1086 /*
1087 * Difference between the InterfaceMap ptr and Vtable in the
1088 * MethodTable used to indicate the number of static bytes
1089 * Now interfaceMap ptr can be optional hence we store it here
1090 */
1091 inline DWORD GetNonGCRegularStaticFieldBytes()
1092 {
1093 LIMITED_METHOD_CONTRACT;
1094 return GetPackableField(EEClass_Field_NonGCStaticFieldBytes);
1095 }
1096 inline void SetNonGCRegularStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1097 {
1098 LIMITED_METHOD_CONTRACT;
1099 SetPackableField(EEClass_Field_NonGCStaticFieldBytes, cbNonGCStaticFieldBytes);
1100 }
1101
1102 inline DWORD GetNonGCThreadStaticFieldBytes()
1103 {
1104 LIMITED_METHOD_CONTRACT;
1105 return GetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes);
1106 }
1107 inline void SetNonGCThreadStaticFieldBytes (DWORD cbNonGCStaticFieldBytes)
1108 {
1109 LIMITED_METHOD_CONTRACT;
1110 SetPackableField(EEClass_Field_NonGCThreadStaticFieldBytes, cbNonGCStaticFieldBytes);
1111 }
1112
1113 inline WORD GetNumNonVirtualSlots()
1114 {
1115 LIMITED_METHOD_CONTRACT;
1116 return (WORD)GetPackableField(EEClass_Field_NumNonVirtualSlots);
1117 }
1118 inline void SetNumNonVirtualSlots(WORD wNumNonVirtualSlots)
1119 {
1120 LIMITED_METHOD_CONTRACT;
1121 SetPackableField(EEClass_Field_NumNonVirtualSlots, wNumNonVirtualSlots);
1122 }
1123
1124 inline BOOL IsEquivalentType()
1125 {
1126 LIMITED_METHOD_CONTRACT;
1127 return m_VMFlags & VMFLAG_IS_EQUIVALENT_TYPE;
1128 }
1129
1130#ifdef FEATURE_TYPEEQUIVALENCE
1131 inline void SetIsEquivalentType()
1132 {
1133 LIMITED_METHOD_CONTRACT;
1134 m_VMFlags |= VMFLAG_IS_EQUIVALENT_TYPE;
1135 }
1136#endif // FEATURE_TYPEEQUIVALENCE
1137
1138 /*
1139 * Number of static handles allocated
1140 */
1141 inline WORD GetNumHandleRegularStatics ()
1142 {
1143 LIMITED_METHOD_CONTRACT;
1144 return (WORD)GetPackableField(EEClass_Field_NumHandleStatics);
1145 }
1146 inline void SetNumHandleRegularStatics (WORD wNumHandleRegularStatics)
1147 {
1148 LIMITED_METHOD_CONTRACT;
1149 SetPackableField(EEClass_Field_NumHandleStatics, wNumHandleRegularStatics);
1150 }
1151
1152 /*
1153 * Number of static handles allocated for ThreadStatics
1154 */
1155 inline WORD GetNumHandleThreadStatics ()
1156 {
1157 LIMITED_METHOD_CONTRACT;
1158 return (WORD)GetPackableField(EEClass_Field_NumHandleThreadStatics);
1159 }
1160 inline void SetNumHandleThreadStatics (WORD wNumHandleThreadStatics)
1161 {
1162 LIMITED_METHOD_CONTRACT;
1163 SetPackableField(EEClass_Field_NumHandleThreadStatics, wNumHandleThreadStatics);
1164 }
1165
1166 /*
1167 * Number of boxed statics allocated
1168 */
1169 inline WORD GetNumBoxedRegularStatics ()
1170 {
1171 LIMITED_METHOD_CONTRACT;
1172 return (WORD)GetPackableField(EEClass_Field_NumBoxedStatics);
1173 }
1174 inline void SetNumBoxedRegularStatics (WORD wNumBoxedRegularStatics)
1175 {
1176 LIMITED_METHOD_CONTRACT;
1177 SetPackableField(EEClass_Field_NumBoxedStatics, wNumBoxedRegularStatics);
1178 }
1179
1180 /*
1181 * Number of boxed statics allocated for ThreadStatics
1182 */
1183 inline WORD GetNumBoxedThreadStatics ()
1184 {
1185 LIMITED_METHOD_CONTRACT;
1186 return (WORD)GetPackableField(EEClass_Field_NumBoxedThreadStatics);
1187 }
1188 inline void SetNumBoxedThreadStatics (WORD wNumBoxedThreadStatics)
1189 {
1190 LIMITED_METHOD_CONTRACT;
1191 SetPackableField(EEClass_Field_NumBoxedThreadStatics, wNumBoxedThreadStatics);
1192 }
1193
1194 /*
1195 * Number of bytes to subract from code:MethodTable::GetBaseSize() to get the actual number of bytes
1196 * of instance fields stored in the object on the GC heap.
1197 */
1198 inline DWORD GetBaseSizePadding()
1199 {
1200 LIMITED_METHOD_DAC_CONTRACT;
1201 return m_cbBaseSizePadding;
1202 }
1203 inline void SetBaseSizePadding(DWORD dwPadding)
1204 {
1205 LIMITED_METHOD_CONTRACT;
1206 _ASSERTE(FitsIn<BYTE>(dwPadding));
1207 m_cbBaseSizePadding = static_cast<BYTE>(dwPadding);
1208 }
1209
1210 inline DWORD GetUnboxedNumInstanceFieldBytes()
1211 {
1212 DWORD cbBoxedSize = GetMethodTable()->GetNumInstanceFieldBytes();
1213
1214 _ASSERTE(GetMethodTable()->IsValueType() || GetMethodTable()->IsEnum());
1215 return cbBoxedSize;
1216 }
1217
1218
1219 /*
1220 * Pointer to a list of FieldDescs declared in this class
1221 * There are (m_wNumInstanceFields - GetParentClass()->m_wNumInstanceFields + m_wNumStaticFields) entries
1222 * in this array
1223 */
1224#ifdef FEATURE_PREJIT
1225 static DWORD FieldDescListSize(MethodTable * pMT);
1226#endif
1227
1228 inline PTR_FieldDesc GetFieldDescList()
1229 {
1230 LIMITED_METHOD_DAC_CONTRACT;
1231 // Careful about using this method. If it's possible that fields may have been added via EnC, then
1232 // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
1233 return m_pFieldDescList.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList));
1234 }
1235
1236 PTR_FieldDesc GetFieldDescByIndex(DWORD fieldIndex);
1237
1238#ifndef DACCESS_COMPILE
1239 inline void SetFieldDescList (FieldDesc* pFieldDescList)
1240 {
1241 LIMITED_METHOD_CONTRACT;
1242 m_pFieldDescList.SetValue(pFieldDescList);
1243 }
1244#endif // !DACCESS_COMPILE
1245
1246 inline WORD GetNumMethods()
1247 {
1248 LIMITED_METHOD_DAC_CONTRACT;
1249 return (WORD)GetPackableField(EEClass_Field_NumMethods);
1250 }
1251 inline void SetNumMethods (WORD wNumMethods)
1252 {
1253 LIMITED_METHOD_CONTRACT;
1254 SetPackableField(EEClass_Field_NumMethods, wNumMethods);
1255 }
1256
1257 /*
1258 * Cached metadata for this class (GetTypeDefProps)
1259 */
1260 inline DWORD GetAttrClass()
1261 {
1262 LIMITED_METHOD_CONTRACT;
1263 return m_dwAttrClass;
1264 }
1265 inline void SetAttrClass (DWORD dwAttrClass)
1266 {
1267 LIMITED_METHOD_CONTRACT;
1268 m_dwAttrClass = dwAttrClass;
1269 }
1270
1271
1272#ifdef FEATURE_COMINTEROP
1273 inline DWORD IsComClassInterface()
1274 {
1275 LIMITED_METHOD_CONTRACT;
1276 return (m_VMFlags & VMFLAG_HASCOCLASSATTRIB);
1277 }
1278 inline VOID SetIsComClassInterface()
1279 {
1280 LIMITED_METHOD_CONTRACT;
1281 m_VMFlags |= VMFLAG_HASCOCLASSATTRIB;
1282 }
1283 inline void SetComEventItfType()
1284 {
1285 LIMITED_METHOD_CONTRACT;
1286 _ASSERTE(IsInterface());
1287 m_VMFlags |= VMFLAG_COMEVENTITFMASK;
1288 }
1289 // class is a special COM event interface
1290 inline BOOL IsComEventItfType()
1291 {
1292 LIMITED_METHOD_CONTRACT;
1293 return (m_VMFlags & VMFLAG_COMEVENTITFMASK);
1294 }
1295#endif // FEATURE_COMINTEROP
1296
1297#ifdef _DEBUG
1298 inline DWORD IsDestroyed()
1299 {
1300 LIMITED_METHOD_CONTRACT;
1301 return (m_wAuxFlags & AUXFLAG_DESTROYED);
1302 }
1303#endif
1304
1305 inline DWORD IsUnsafeValueClass()
1306 {
1307 LIMITED_METHOD_CONTRACT;
1308 return (m_VMFlags & VMFLAG_UNSAFEVALUETYPE);
1309 }
1310
1311
1312private:
1313 inline void SetUnsafeValueClass()
1314 {
1315 LIMITED_METHOD_CONTRACT;
1316 m_VMFlags |= VMFLAG_UNSAFEVALUETYPE;
1317 }
1318
1319public:
1320 inline BOOL HasNoGuid()
1321 {
1322 LIMITED_METHOD_CONTRACT;
1323 return (m_VMFlags & VMFLAG_NO_GUID);
1324 }
1325 inline void SetHasNoGuid()
1326 {
1327 WRAPPER_NO_CONTRACT;
1328 FastInterlockOr(EnsureWritablePages(&m_VMFlags), VMFLAG_NO_GUID);
1329 }
1330
1331public:
1332 inline BOOL IsAlign8Candidate()
1333 {
1334 LIMITED_METHOD_CONTRACT;
1335 return (m_VMFlags & VMFLAG_PREFER_ALIGN8);
1336 }
1337 inline void SetAlign8Candidate()
1338 {
1339 LIMITED_METHOD_CONTRACT;
1340 m_VMFlags |= VMFLAG_PREFER_ALIGN8;
1341 }
1342#ifdef _DEBUG
1343 inline void SetDestroyed()
1344 {
1345 LIMITED_METHOD_CONTRACT;
1346 m_wAuxFlags |= AUXFLAG_DESTROYED;
1347 }
1348#endif
1349 inline void SetHasFixedAddressVTStatics()
1350 {
1351 LIMITED_METHOD_CONTRACT;
1352 m_VMFlags |= (DWORD) VMFLAG_FIXED_ADDRESS_VT_STATICS;
1353 }
1354#ifdef FEATURE_COMINTEROP
1355 void SetSparseForCOMInterop()
1356 {
1357 LIMITED_METHOD_CONTRACT;
1358 m_VMFlags |= (DWORD) VMFLAG_SPARSE_FOR_COMINTEROP;
1359 }
1360 inline void SetProjectedFromWinRT()
1361 {
1362 LIMITED_METHOD_CONTRACT;
1363 m_VMFlags |= (DWORD) VMFLAG_PROJECTED_FROM_WINRT;
1364 }
1365 inline void SetExportedToWinRT()
1366 {
1367 LIMITED_METHOD_CONTRACT;
1368 m_VMFlags |= (DWORD) VMFLAG_EXPORTED_TO_WINRT;
1369 }
1370 inline void SetMarshalingType(UINT32 mType)
1371 {
1372 LIMITED_METHOD_CONTRACT;
1373 _ASSERTE(mType !=0);
1374 _ASSERTE((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == 0);
1375 switch(mType)
1376 {
1377 case 1: m_VMFlags |= VMFLAG_MARSHALINGTYPE_INHIBIT;
1378 break;
1379 case 2: m_VMFlags |= VMFLAG_MARSHALINGTYPE_FREETHREADED;
1380 break;
1381 case 3: m_VMFlags |= VMFLAG_MARSHALINGTYPE_STANDARD;
1382 break;
1383 default:
1384 _ASSERTE(!"Invalid MarshalingBehaviorAttribute value");
1385 }
1386 }
1387#endif // FEATURE_COMINTEROP
1388 inline void SetHasLayout()
1389 {
1390 LIMITED_METHOD_CONTRACT;
1391 m_VMFlags |= (DWORD) VMFLAG_HASLAYOUT; //modified before the class is published
1392 }
1393 inline void SetHasOverLayedFields()
1394 {
1395 LIMITED_METHOD_CONTRACT;
1396 m_VMFlags |= VMFLAG_HASOVERLAYEDFIELDS;
1397 }
1398 inline void SetIsNested()
1399 {
1400 LIMITED_METHOD_CONTRACT;
1401 m_VMFlags |= VMFLAG_ISNESTED;
1402 }
1403
1404#ifdef FEATURE_READYTORUN
1405 inline BOOL HasLayoutDependsOnOtherModules()
1406 {
1407 LIMITED_METHOD_CONTRACT;
1408 return m_VMFlags & VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1409 }
1410
1411 inline void SetHasLayoutDependsOnOtherModules()
1412 {
1413 LIMITED_METHOD_CONTRACT;
1414 m_VMFlags |= VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES;
1415 }
1416#endif
1417
1418 // Is this delegate? Returns false for System.Delegate and System.MulticastDelegate.
1419 inline BOOL IsDelegate()
1420 {
1421 LIMITED_METHOD_CONTRACT;
1422 return m_VMFlags & VMFLAG_DELEGATE;
1423 }
1424 inline void SetIsDelegate()
1425 {
1426 LIMITED_METHOD_CONTRACT;
1427 m_VMFlags |= VMFLAG_DELEGATE;
1428 }
1429
1430 BOOL HasFixedAddressVTStatics()
1431 {
1432 LIMITED_METHOD_CONTRACT;
1433 return m_VMFlags & VMFLAG_FIXED_ADDRESS_VT_STATICS;
1434 }
1435#ifdef FEATURE_COMINTEROP
1436 BOOL IsSparseForCOMInterop()
1437 {
1438 LIMITED_METHOD_CONTRACT;
1439 return m_VMFlags & VMFLAG_SPARSE_FOR_COMINTEROP;
1440 }
1441 BOOL IsProjectedFromWinRT()
1442 {
1443 LIMITED_METHOD_DAC_CONTRACT;
1444 return m_VMFlags & VMFLAG_PROJECTED_FROM_WINRT;
1445 }
1446 BOOL IsExportedToWinRT()
1447 {
1448 LIMITED_METHOD_CONTRACT;
1449 return m_VMFlags & VMFLAG_EXPORTED_TO_WINRT;
1450 }
1451 BOOL IsMarshalingTypeSet()
1452 {
1453 LIMITED_METHOD_CONTRACT;
1454 return (m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK);
1455 }
1456 BOOL IsMarshalingTypeFreeThreaded()
1457 {
1458 LIMITED_METHOD_CONTRACT;
1459 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_FREETHREADED);
1460 }
1461 BOOL IsMarshalingTypeInhibit()
1462 {
1463 LIMITED_METHOD_CONTRACT;
1464 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_INHIBIT);
1465 }
1466 BOOL IsMarshalingTypeStandard()
1467 {
1468 LIMITED_METHOD_CONTRACT;
1469 return ((m_VMFlags & VMFLAG_MARSHALINGTYPE_MASK) == VMFLAG_MARSHALINGTYPE_STANDARD);
1470 }
1471#endif // FEATURE_COMINTEROP
1472 BOOL HasLayout()
1473 {
1474 LIMITED_METHOD_CONTRACT;
1475 return m_VMFlags & VMFLAG_HASLAYOUT;
1476 }
1477 BOOL HasOverLayedField()
1478 {
1479 LIMITED_METHOD_CONTRACT;
1480 return m_VMFlags & VMFLAG_HASOVERLAYEDFIELDS;
1481 }
1482 BOOL IsNested()
1483 {
1484 LIMITED_METHOD_CONTRACT;
1485 return m_VMFlags & VMFLAG_ISNESTED;
1486 }
1487 BOOL HasFieldsWhichMustBeInited()
1488 {
1489 LIMITED_METHOD_CONTRACT;
1490 return (m_VMFlags & VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED);
1491 }
1492 void SetHasFieldsWhichMustBeInited()
1493 {
1494 LIMITED_METHOD_CONTRACT;
1495 m_VMFlags |= (DWORD)VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED;
1496 }
1497 void SetCannotBeBlittedByObjectCloner()
1498 {
1499 /* no op */
1500 }
1501 DWORD HasNonPublicFields()
1502 {
1503 LIMITED_METHOD_CONTRACT;
1504 return (m_VMFlags & VMFLAG_HASNONPUBLICFIELDS);
1505 }
1506 void SetHasNonPublicFields()
1507 {
1508 LIMITED_METHOD_CONTRACT;
1509 m_VMFlags |= (DWORD)VMFLAG_HASNONPUBLICFIELDS;
1510 }
1511 DWORD IsNotTightlyPacked()
1512 {
1513 LIMITED_METHOD_CONTRACT;
1514 return (m_VMFlags & VMFLAG_NOT_TIGHTLY_PACKED);
1515 }
1516 void SetIsNotTightlyPacked()
1517 {
1518 LIMITED_METHOD_CONTRACT;
1519 m_VMFlags |= (DWORD)VMFLAG_NOT_TIGHTLY_PACKED;
1520 }
1521 DWORD ContainsMethodImpls()
1522 {
1523 LIMITED_METHOD_CONTRACT;
1524 return (m_VMFlags & VMFLAG_CONTAINS_METHODIMPLS);
1525 }
1526 void SetContainsMethodImpls()
1527 {
1528 LIMITED_METHOD_CONTRACT;
1529 m_VMFlags |= (DWORD)VMFLAG_CONTAINS_METHODIMPLS;
1530 }
1531
1532
1533 BOOL IsManagedSequential();
1534
1535 BOOL HasExplicitSize();
1536
1537 static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
1538
1539 /*
1540 * The CorElementType for this class (most classes = ELEMENT_TYPE_CLASS)
1541 */
1542public:
1543 // This is what would be used in the calling convention for this type.
1544 CorElementType GetInternalCorElementType()
1545 {
1546 LIMITED_METHOD_DAC_CONTRACT;
1547
1548 return CorElementType(m_NormType);
1549 }
1550 void SetInternalCorElementType (CorElementType _NormType)
1551 {
1552 LIMITED_METHOD_CONTRACT;
1553 m_NormType = static_cast<BYTE>(_NormType);
1554 }
1555
1556 /*
1557 * Chain of MethodDesc chunks for the MethodTable
1558 */
1559public:
1560 inline PTR_MethodDescChunk GetChunks();
1561
1562#ifndef DACCESS_COMPILE
1563 inline void SetChunks (MethodDescChunk* pChunks)
1564 {
1565 LIMITED_METHOD_CONTRACT;
1566 m_pChunks.SetValueMaybeNull(pChunks);
1567 }
1568#endif // !DACCESS_COMPILE
1569 void AddChunk (MethodDescChunk* pNewChunk);
1570
1571 void AddChunkIfItHasNotBeenAdded (MethodDescChunk* pNewChunk);
1572
1573 inline PTR_GuidInfo GetGuidInfo()
1574 {
1575 LIMITED_METHOD_DAC_CONTRACT;
1576
1577 return ReadPointerMaybeNull(this, &EEClass::m_pGuidInfo);
1578 }
1579
1580 inline void SetGuidInfo(GuidInfo* pGuidInfo)
1581 {
1582 WRAPPER_NO_CONTRACT;
1583 #ifndef DACCESS_COMPILE
1584 EnsureWritablePages(&m_pGuidInfo)->SetValueMaybeNull(pGuidInfo);
1585 #endif // DACCESS_COMPILE
1586 }
1587
1588
1589#if defined(UNIX_AMD64_ABI)
1590 // Get number of eightbytes used by a struct passed in registers.
1591 inline int GetNumberEightBytes()
1592 {
1593 LIMITED_METHOD_CONTRACT;
1594 _ASSERTE(HasOptionalFields());
1595 return GetOptionalFields()->m_numberEightBytes;
1596 }
1597
1598 // Get eightbyte classification for the eightbyte with the specified index.
1599 inline SystemVClassificationType GetEightByteClassification(int index)
1600 {
1601 LIMITED_METHOD_CONTRACT;
1602 _ASSERTE(HasOptionalFields());
1603 return GetOptionalFields()->m_eightByteClassifications[index];
1604 }
1605
1606 // Get size of the data in the eightbyte with the specified index.
1607 inline unsigned int GetEightByteSize(int index)
1608 {
1609 LIMITED_METHOD_CONTRACT;
1610 _ASSERTE(HasOptionalFields());
1611 return GetOptionalFields()->m_eightByteSizes[index];
1612 }
1613
1614 // Set the eightByte classification
1615 inline void SetEightByteClassification(int eightByteCount, SystemVClassificationType *eightByteClassifications, unsigned int *eightByteSizes)
1616 {
1617 LIMITED_METHOD_CONTRACT;
1618 _ASSERTE(HasOptionalFields());
1619 GetOptionalFields()->m_numberEightBytes = eightByteCount;
1620 for (int i = 0; i < eightByteCount; i++)
1621 {
1622 GetOptionalFields()->m_eightByteClassifications[i] = eightByteClassifications[i];
1623 GetOptionalFields()->m_eightByteSizes[i] = eightByteSizes[i];
1624 }
1625 }
1626#endif // UNIX_AMD64_ABI
1627
1628#if defined(FEATURE_HFA)
1629 bool CheckForHFA(MethodTable ** pByValueClassCache);
1630 VOID CheckForNativeHFA();
1631#else // !FEATURE_HFA
1632 bool CheckForHFA();
1633#endif // FEATURE_HFA
1634
1635#ifdef FEATURE_COMINTEROP
1636 inline TypeHandle GetCoClassForInterface()
1637 {
1638 LIMITED_METHOD_CONTRACT;
1639 _ASSERTE(HasOptionalFields());
1640 return GetOptionalFields()->m_pCoClassForIntf;
1641 }
1642
1643 inline void SetCoClassForInterface(TypeHandle th)
1644 {
1645 WRAPPER_NO_CONTRACT;
1646 _ASSERTE(HasOptionalFields());
1647 *EnsureWritablePages(&GetOptionalFields()->m_pCoClassForIntf) = th;
1648 }
1649
1650 inline WinMDAdapter::RedirectedTypeIndex GetWinRTRedirectedTypeIndex()
1651 {
1652 LIMITED_METHOD_CONTRACT;
1653 return HasOptionalFields() ? GetOptionalFields()->m_WinRTRedirectedTypeIndex
1654 : WinMDAdapter::RedirectedTypeIndex_Invalid;
1655 }
1656
1657 inline void SetWinRTRedirectedTypeIndex(WinMDAdapter::RedirectedTypeIndex index)
1658 {
1659 LIMITED_METHOD_CONTRACT;
1660 _ASSERTE(HasOptionalFields());
1661 _ASSERTE(index != WinMDAdapter::RedirectedTypeIndex_Invalid);
1662 GetOptionalFields()->m_WinRTRedirectedTypeIndex = index;
1663 }
1664#endif // FEATURE_COMINTEROP
1665
1666 inline UINT32 GetNativeSize()
1667 {
1668 LIMITED_METHOD_DAC_CONTRACT;
1669 return m_cbNativeSize;
1670 }
1671 static UINT32 GetOffsetOfNativeSize()
1672 {
1673 LIMITED_METHOD_CONTRACT;
1674 return (UINT32)(offsetof(EEClass, m_cbNativeSize));
1675 }
1676 void SetNativeSize(UINT32 nativeSize)
1677 {
1678 LIMITED_METHOD_CONTRACT;
1679 m_cbNativeSize = nativeSize;
1680 }
1681#ifdef FEATURE_COMINTEROP
1682 OBJECTHANDLE GetOHDelegate()
1683 {
1684 LIMITED_METHOD_CONTRACT;
1685 return m_ohDelegate;
1686 }
1687 void SetOHDelegate (OBJECTHANDLE _ohDelegate)
1688 {
1689 LIMITED_METHOD_CONTRACT;
1690 m_ohDelegate = _ohDelegate;
1691 }
1692 // Set the COM interface type.
1693 CorIfaceAttr GetComInterfaceType()
1694 {
1695 LIMITED_METHOD_CONTRACT;
1696 return m_ComInterfaceType;
1697 }
1698
1699 void SetComInterfaceType(CorIfaceAttr ItfType)
1700 {
1701 WRAPPER_NO_CONTRACT;
1702 _ASSERTE(IsInterface());
1703 EnsureWritablePages(this);
1704 m_ComInterfaceType = ItfType;
1705 }
1706
1707 inline ComCallWrapperTemplate *GetComCallWrapperTemplate()
1708 {
1709 LIMITED_METHOD_CONTRACT;
1710 return m_pccwTemplate;
1711 }
1712 inline BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1713 {
1714 WRAPPER_NO_CONTRACT;
1715 return (InterlockedCompareExchangeT(EnsureWritablePages(&m_pccwTemplate), pTemplate, NULL) == NULL);
1716 }
1717
1718#ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1719 inline ClassFactoryBase *GetComClassFactory()
1720 {
1721 LIMITED_METHOD_CONTRACT;
1722 return HasOptionalFields() ? GetOptionalFields()->m_pClassFactory : NULL;
1723 }
1724 inline BOOL SetComClassFactory(ClassFactoryBase *pFactory)
1725 {
1726 WRAPPER_NO_CONTRACT;
1727 _ASSERTE(HasOptionalFields());
1728 return (InterlockedCompareExchangeT(EnsureWritablePages(&GetOptionalFields()->m_pClassFactory), pFactory, NULL) == NULL);
1729 }
1730#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1731#endif // FEATURE_COMINTEROP
1732
1733
1734public:
1735 PTR_DictionaryLayout GetDictionaryLayout()
1736 {
1737 SUPPORTS_DAC;
1738 WRAPPER_NO_CONTRACT;
1739 return HasOptionalFields() ? GetOptionalFields()->m_pDictLayout : NULL;
1740 }
1741
1742 void SetDictionaryLayout(PTR_DictionaryLayout pLayout)
1743 {
1744 SUPPORTS_DAC;
1745 WRAPPER_NO_CONTRACT;
1746 _ASSERTE(HasOptionalFields());
1747 GetOptionalFields()->m_pDictLayout = pLayout;
1748 }
1749
1750#ifndef DACCESS_COMPILE
1751 static CorGenericParamAttr GetVarianceOfTypeParameter(BYTE * pbVarianceInfo, DWORD i)
1752 {
1753 LIMITED_METHOD_CONTRACT;
1754 if (pbVarianceInfo == NULL)
1755 return gpNonVariant;
1756 else
1757 return (CorGenericParamAttr) (pbVarianceInfo[i]);
1758 }
1759
1760 CorGenericParamAttr GetVarianceOfTypeParameter(DWORD i)
1761 {
1762 WRAPPER_NO_CONTRACT;
1763 return GetVarianceOfTypeParameter(GetVarianceInfo(), i);
1764 }
1765
1766 BYTE* GetVarianceInfo()
1767 {
1768 LIMITED_METHOD_CONTRACT;
1769 return HasOptionalFields() ? GetOptionalFields()->GetVarianceInfo() : NULL;
1770 }
1771
1772 void SetVarianceInfo(BYTE *pVarianceInfo)
1773 {
1774 LIMITED_METHOD_CONTRACT;
1775 _ASSERTE(HasOptionalFields());
1776 GetOptionalFields()->m_pVarianceInfo.SetValueMaybeNull(pVarianceInfo);
1777 }
1778#endif // !DACCESS_COMPILE
1779
1780 // Check that a signature blob uses type parameters correctly
1781 // in accordance with the variance annotations specified by this class
1782 // The position parameter indicates the variance of the context we're in
1783 // (result type is gpCovariant, argument types are gpContravariant, deeper in a signature
1784 // we might be gpNonvariant e.g. in a pointer type or non-variant generic type)
1785 static BOOL
1786 CheckVarianceInSig(
1787 DWORD numGenericArgs,
1788 BYTE *pVarianceInfo,
1789 Module * pModule,
1790 SigPointer sp,
1791 CorGenericParamAttr position);
1792
1793#if defined(_DEBUG)
1794public:
1795 enum{
1796 AUXFLAG_DESTROYED = 0x00000008, // The Destruct() method has already been called on this class
1797 };
1798#endif // defined(_DEBUG)
1799
1800 //-------------------------------------------------------------
1801 // CONCRETE DATA LAYOUT
1802 //
1803 // Although accessed far less frequently than MethodTables, EEClasses are still
1804 // pulled into working set, especially at startup. This has motivated several space
1805 // optimizations in field layout where each is balanced against the need to access
1806 // a particular field efficiently.
1807 //
1808 // Currently, the following strategy is used:
1809 //
1810 // - Any field that has a default value for the vast majority of EEClass instances
1811 // should be stored in the EEClassOptionalFields (see header comment)
1812 //
1813 // - Any field that is nearly always a small positive integer and is infrequently
1814 // accessed should be in the EEClassPackedFields (see header comment)
1815 //
1816 // If none of these categories apply - such as for always-meaningful pointer members or
1817 // sets of flags - a full field is used. Please avoid adding such members if possible.
1818 //-------------------------------------------------------------
1819
1820 // @TODO: needed for asm code in cgenx86.cpp. Can this enum be private?
1821 //
1822 // Flags for m_VMFlags
1823 //
1824public:
1825 enum
1826 {
1827#ifdef FEATURE_READYTORUN
1828 VMFLAG_LAYOUT_DEPENDS_ON_OTHER_MODULES = 0x00000001,
1829#endif
1830 VMFLAG_DELEGATE = 0x00000002,
1831
1832 // VMFLAG_UNUSED = 0x0000001c,
1833
1834 VMFLAG_FIXED_ADDRESS_VT_STATICS = 0x00000020, // Value type Statics in this class will be pinned
1835 VMFLAG_HASLAYOUT = 0x00000040,
1836 VMFLAG_ISNESTED = 0x00000080,
1837
1838 VMFLAG_IS_EQUIVALENT_TYPE = 0x00000200,
1839
1840 // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure.
1841 VMFLAG_HASOVERLAYEDFIELDS = 0x00000400,
1842
1843 // Set this if this class or its parent have instance fields which
1844 // must be explicitly inited in a constructor (e.g. pointers of any
1845 // kind, gc or native).
1846 //
1847 // Currently this is used by the verifier when verifying value classes
1848 // - it's ok to use uninitialised value classes if there are no
1849 // pointer fields in them.
1850 VMFLAG_HAS_FIELDS_WHICH_MUST_BE_INITED = 0x00000800,
1851
1852 VMFLAG_UNSAFEVALUETYPE = 0x00001000,
1853
1854 VMFLAG_BESTFITMAPPING_INITED = 0x00002000, // VMFLAG_BESTFITMAPPING and VMFLAG_THROWONUNMAPPABLECHAR are valid only if this is set
1855 VMFLAG_BESTFITMAPPING = 0x00004000, // BestFitMappingAttribute.Value
1856 VMFLAG_THROWONUNMAPPABLECHAR = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar
1857
1858 // unused = 0x00010000,
1859 VMFLAG_NO_GUID = 0x00020000,
1860 VMFLAG_HASNONPUBLICFIELDS = 0x00040000,
1861 // unused = 0x00080000,
1862 VMFLAG_CONTAINS_STACK_PTR = 0x00100000,
1863 VMFLAG_PREFER_ALIGN8 = 0x00200000, // Would like to have 8-byte alignment
1864 // unused = 0x00400000,
1865
1866#ifdef FEATURE_COMINTEROP
1867 VMFLAG_SPARSE_FOR_COMINTEROP = 0x00800000,
1868 // interfaces may have a coclass attribute
1869 VMFLAG_HASCOCLASSATTRIB = 0x01000000,
1870 VMFLAG_COMEVENTITFMASK = 0x02000000, // class is a special COM event interface
1871 VMFLAG_PROJECTED_FROM_WINRT = 0x04000000,
1872 VMFLAG_EXPORTED_TO_WINRT = 0x08000000,
1873#endif // FEATURE_COMINTEROP
1874
1875 // This one indicates that the fields of the valuetype are
1876 // not tightly packed and is used to check whether we can
1877 // do bit-equality on value types to implement ValueType::Equals.
1878 // It is not valid for classes, and only matters if ContainsPointer
1879 // is false.
1880 VMFLAG_NOT_TIGHTLY_PACKED = 0x10000000,
1881
1882 // True if methoddesc on this class have any real (non-interface) methodimpls
1883 VMFLAG_CONTAINS_METHODIMPLS = 0x20000000,
1884
1885#ifdef FEATURE_COMINTEROP
1886 VMFLAG_MARSHALINGTYPE_MASK = 0xc0000000,
1887
1888 VMFLAG_MARSHALINGTYPE_INHIBIT = 0x40000000,
1889 VMFLAG_MARSHALINGTYPE_FREETHREADED = 0x80000000,
1890 VMFLAG_MARSHALINGTYPE_STANDARD = 0xc0000000,
1891#endif
1892 };
1893
1894public:
1895 // C_ASSERTs in Jitinterface.cpp need this to be public to check the offset.
1896 // Put it first so the offset rarely changes, which just reduces the number of times we have to fiddle
1897 // with the offset.
1898 RelativePointer<PTR_GuidInfo> m_pGuidInfo; // The cached guid information for interfaces.
1899
1900#ifdef _DEBUG
1901public:
1902 LPCUTF8 m_szDebugClassName;
1903 BOOL m_fDebuggingClass;
1904#endif
1905
1906private:
1907 // Layout rest of fields below from largest to smallest to lessen the chance of wasting bytes with
1908 // compiler injected padding (especially with the difference between pointers and DWORDs on 64-bit).
1909 RelativePointer<PTR_EEClassOptionalFields> m_rpOptionalFields;
1910
1911 // TODO: Remove this field. It is only used by SOS and object validation for stress.
1912 RelativePointer<PTR_MethodTable> m_pMethodTable;
1913
1914 RelativePointer<PTR_FieldDesc> m_pFieldDescList;
1915 RelativePointer<PTR_MethodDescChunk> m_pChunks;
1916
1917 union
1918 {
1919 // valid only if EEClass::IsBlittable() or EEClass::HasLayout() is true
1920 UINT32 m_cbNativeSize; // size of fixed portion in bytes
1921
1922#ifdef FEATURE_COMINTEROP
1923 // For COM+ wrapper objects that extend an unmanaged class, this field
1924 // may contain a delegate to be called to allocate the aggregated
1925 // unmanaged class (instead of using CoCreateInstance).
1926 OBJECTHANDLE m_ohDelegate;
1927
1928 // For interfaces this contains the COM interface type.
1929 CorIfaceAttr m_ComInterfaceType;
1930#endif // FEATURE_COMINTEROP
1931 };
1932
1933#ifdef FEATURE_COMINTEROP
1934 ComCallWrapperTemplate *m_pccwTemplate; // points to interop data structures used when this type is exposed to COM
1935#endif // FEATURE_COMINTEROP
1936
1937 DWORD m_dwAttrClass;
1938 DWORD m_VMFlags;
1939
1940 /*
1941 * We maintain some auxillary flags in DEBUG builds,
1942 * this frees up some bits in m_wVMFlags
1943 */
1944#if defined(_DEBUG)
1945 WORD m_wAuxFlags;
1946#endif
1947
1948 // NOTE: Following BYTE fields are layed out together so they'll fit within the same DWORD for efficient
1949 // structure packing.
1950 BYTE m_NormType;
1951 BYTE m_fFieldsArePacked; // TRUE iff fields pointed to by GetPackedFields() are in packed state
1952 BYTE m_cbFixedEEClassFields; // Count of bytes of normal fields of this instance (EEClass,
1953 // LayoutEEClass etc.). Doesn't count bytes of "packed" fields
1954 BYTE m_cbBaseSizePadding; // How many bytes of padding are included in BaseSize
1955
1956public:
1957 // EEClass optional field support. Whether a particular EEClass instance has optional fields is determined
1958 // at class load time. The entire EEClassOptionalFields structure is allocated if the EEClass has need of
1959 // one or more optional fields.
1960
1961#ifndef DACCESS_COMPILE
1962 void AttachOptionalFields(EEClassOptionalFields *pFields)
1963 {
1964 LIMITED_METHOD_CONTRACT;
1965 _ASSERTE(m_rpOptionalFields.IsNull());
1966
1967 m_rpOptionalFields.SetValue(pFields);
1968 }
1969#endif // !DACCESS_COMPILE
1970
1971 bool HasOptionalFields()
1972 {
1973 LIMITED_METHOD_DAC_CONTRACT;
1974 return !m_rpOptionalFields.IsNull();
1975 }
1976
1977 PTR_EEClassOptionalFields GetOptionalFields()
1978 {
1979 LIMITED_METHOD_DAC_CONTRACT;
1980 return m_rpOptionalFields.GetValueMaybeNull(PTR_HOST_MEMBER_TADDR(EEClass, this, m_rpOptionalFields));
1981 }
1982
1983private:
1984 //
1985 // Support for packed fields.
1986 //
1987
1988 // Get pointer to the packed fields structure attached to this instance.
1989 PTR_EEClassPackedFields GetPackedFields();
1990
1991 // Get the value of the given field. Works regardless of whether the field is currently in its packed or
1992 // unpacked state.
1993 DWORD GetPackableField(EEClassFieldId eField);
1994
1995 // Set the value of the given field. The field *must* be in the unpacked state for this to be legal (in
1996 // practice all packable fields must be initialized during class construction and from then on remain
1997 // immutable).
1998 void SetPackableField(EEClassFieldId eField, DWORD dwValue);
1999
2000 //-------------------------------------------------------------
2001 // END CONCRETE DATA LAYOUT
2002 //-------------------------------------------------------------
2003
2004
2005
2006 /************************************
2007 * PROTECTED METHODS
2008 ************************************/
2009protected:
2010#ifndef DACCESS_COMPILE
2011 /*
2012 * Constructor: prevent any other class from doing a new()
2013 */
2014 EEClass(DWORD cbFixedEEClassFields);
2015
2016 /*
2017 * Destructor: prevent any other class from deleting
2018 */
2019 ~EEClass()
2020 {
2021 LIMITED_METHOD_CONTRACT;
2022 }
2023#endif // !DACCESS_COMPILE
2024
2025};
2026
2027// --------------------------------------------------------------------------------------------
2028template <typename Data>
2029class FixedCapacityStackingAllocatedUTF8StringHash
2030{
2031public:
2032 // Entry
2033 struct HashEntry
2034 {
2035 HashEntry * m_pNext; // Next item with same bucketed hash value
2036 DWORD m_dwHashValue; // Hash value
2037 LPCUTF8 m_pKey; // String key
2038 Data m_data; // Data
2039 };
2040
2041 HashEntry ** m_pBuckets; // Pointer to first entry for each bucket
2042 DWORD m_dwNumBuckets;
2043 BYTE * m_pMemory; // Current pointer into preallocated memory for entries
2044 BYTE * m_pMemoryStart; // Start pointer of pre-allocated memory fo entries
2045
2046 INDEBUG(BYTE * m_pDebugEndMemory;)
2047
2048 FixedCapacityStackingAllocatedUTF8StringHash()
2049 : m_pMemoryStart(NULL)
2050 { LIMITED_METHOD_CONTRACT; }
2051
2052 static DWORD
2053 GetHashCode(
2054 LPCUTF8 szString)
2055 { WRAPPER_NO_CONTRACT; return HashStringA(szString); }
2056
2057 // Throws on error
2058 void
2059 Init(
2060 DWORD dwMaxEntries,
2061 StackingAllocator * pAllocator);
2062
2063 // Insert new entry at head of list
2064 void
2065 Insert(
2066 LPCUTF8 pszName,
2067 const Data & data);
2068
2069 // Return the first matching entry in the list, or NULL if there is no such entry
2070 HashEntry *
2071 Lookup(
2072 LPCUTF8 pszName);
2073
2074 // Return the next matching entry in the list, or NULL if there is no such entry.
2075 HashEntry *
2076 FindNext(
2077 HashEntry * pEntry);
2078};
2079
2080
2081//---------------------------------------------------------------------------------------
2082//
2083class LayoutEEClass : public EEClass
2084{
2085public:
2086 EEClassLayoutInfo m_LayoutInfo;
2087
2088#ifndef DACCESS_COMPILE
2089 LayoutEEClass() : EEClass(sizeof(LayoutEEClass))
2090 {
2091 LIMITED_METHOD_CONTRACT;
2092#ifdef _DEBUG
2093 FillMemory(&m_LayoutInfo, sizeof(m_LayoutInfo), 0xcc);
2094#endif
2095 }
2096#endif // !DACCESS_COMPILE
2097};
2098
2099class UMThunkMarshInfo;
2100
2101#ifdef FEATURE_COMINTEROP
2102struct ComPlusCallInfo;
2103#endif // FEATURE_COMINTEROP
2104
2105class DelegateEEClass : public EEClass
2106{
2107public:
2108 PTR_Stub m_pStaticCallStub;
2109 PTR_Stub m_pInstRetBuffCallStub;
2110 RelativePointer<PTR_MethodDesc> m_pInvokeMethod;
2111 PTR_Stub m_pMultiCastInvokeStub;
2112 PTR_Stub m_pSecureDelegateInvokeStub;
2113 UMThunkMarshInfo* m_pUMThunkMarshInfo;
2114 RelativePointer<PTR_MethodDesc> m_pBeginInvokeMethod;
2115 RelativePointer<PTR_MethodDesc> m_pEndInvokeMethod;
2116 Volatile<PCODE> m_pMarshalStub;
2117
2118#ifdef FEATURE_COMINTEROP
2119 ComPlusCallInfo *m_pComPlusCallInfo;
2120#endif // FEATURE_COMINTEROP
2121
2122 //
2123 // Ngened IL stub MethodDescs. Fixed up, wrapped with code:Stub, and installed to
2124 // m_pMarshalStub (forward) or m_pUMThunkMarshInfo (reverse) when first needed.
2125 //
2126 MethodDesc* m_pForwardStubMD; // marshaling stub for calls to unmanaged code
2127 MethodDesc* m_pReverseStubMD; // marshaling stub for calls from unmanaged code
2128
2129 PTR_MethodDesc GetInvokeMethod()
2130 {
2131 return ReadPointer(this, &DelegateEEClass::m_pInvokeMethod);
2132 }
2133
2134 PTR_MethodDesc GetBeginInvokeMethod()
2135 {
2136 return ReadPointer(this, &DelegateEEClass::m_pBeginInvokeMethod);
2137 }
2138
2139 PTR_MethodDesc GetEndInvokeMethod()
2140 {
2141 return ReadPointer(this, &DelegateEEClass::m_pEndInvokeMethod);
2142 }
2143
2144#ifndef DACCESS_COMPILE
2145 DelegateEEClass() : EEClass(sizeof(DelegateEEClass))
2146 {
2147 LIMITED_METHOD_CONTRACT;
2148 // Note: Memory allocated on loader heap is zero filled
2149 }
2150
2151 // We need a LoaderHeap that lives at least as long as the DelegateEEClass, but ideally no longer
2152 LoaderHeap *GetStubHeap();
2153#endif // !DACCESS_COMPILE
2154
2155};
2156
2157
2158typedef DPTR(ArrayClass) PTR_ArrayClass;
2159
2160
2161// Dynamically generated array class structure
2162class ArrayClass : public EEClass
2163{
2164#ifdef FEATURE_PREJIT
2165 friend void EEClass::Fixup(DataImage *image, MethodTable *pMethodTable);
2166#endif
2167
2168 friend MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementType arrayKind, unsigned Rank, AllocMemTracker *pamTracker);
2169
2170#ifndef DACCESS_COMPILE
2171 ArrayClass() : EEClass(sizeof(ArrayClass)) { LIMITED_METHOD_CONTRACT; }
2172#else
2173 friend class NativeImageDumper;
2174#endif
2175
2176private:
2177
2178 unsigned char m_rank;
2179 CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd
2180
2181public:
2182 DWORD GetRank() {
2183 LIMITED_METHOD_CONTRACT;
2184 SUPPORTS_DAC;
2185 return m_rank;
2186 }
2187 void SetRank (unsigned Rank) {
2188 LIMITED_METHOD_CONTRACT;
2189 // The only code path calling this function is code:ClassLoader::CreateTypeHandleForTypeKey, which has
2190 // checked the rank already. Assert that the rank is less than MAX_RANK and that it fits in one byte.
2191 _ASSERTE((Rank <= MAX_RANK) && (Rank <= (unsigned char)(-1)));
2192 m_rank = (unsigned char)Rank;
2193 }
2194
2195 CorElementType GetArrayElementType() {
2196 LIMITED_METHOD_CONTRACT;
2197 return m_ElementType;
2198 }
2199 void SetArrayElementType(CorElementType ElementType) {
2200 LIMITED_METHOD_CONTRACT;
2201 m_ElementType = ElementType;
2202 }
2203
2204
2205 // Allocate a new MethodDesc for the methods we add to this class
2206 void InitArrayMethodDesc(
2207 ArrayMethodDesc* pNewMD,
2208 PCCOR_SIGNATURE pShortSig,
2209 DWORD cShortSig,
2210 DWORD dwVtableSlot,
2211 LoaderAllocator *pLoaderAllocator,
2212 AllocMemTracker *pamTracker);
2213
2214 // Generate a short sig for an array accessor
2215 VOID GenerateArrayAccessorCallSig(DWORD dwRank,
2216 DWORD dwFuncType, // Load, store, or <init>
2217 PCCOR_SIGNATURE *ppSig, // Generated signature
2218 DWORD * pcSig, // Generated signature size
2219 LoaderAllocator *pLoaderAllocator,
2220 AllocMemTracker *pamTracker
2221#ifdef FEATURE_ARRAYSTUB_AS_IL
2222 ,BOOL fForStubAsIL
2223#endif
2224 );
2225
2226
2227};
2228
2229inline EEClassLayoutInfo *EEClass::GetLayoutInfo()
2230{
2231 LIMITED_METHOD_CONTRACT;
2232 _ASSERTE(HasLayout());
2233 return &((LayoutEEClass *) this)->m_LayoutInfo;
2234}
2235
2236inline BOOL EEClass::IsBlittable()
2237{
2238 LIMITED_METHOD_CONTRACT;
2239
2240 // Either we have an opaque bunch of bytes, or we have some fields that are
2241 // all isomorphic and explicitly layed out.
2242 return (HasLayout() && GetLayoutInfo()->IsBlittable());
2243}
2244
2245inline BOOL EEClass::IsManagedSequential()
2246{
2247 LIMITED_METHOD_CONTRACT;
2248 return HasLayout() && GetLayoutInfo()->IsManagedSequential();
2249}
2250
2251inline BOOL EEClass::HasExplicitSize()
2252{
2253 LIMITED_METHOD_CONTRACT;
2254 return HasLayout() && GetLayoutInfo()->HasExplicitSize();
2255}
2256
2257//==========================================================================
2258// These routines manage the prestub (a bootstrapping stub that all
2259// FunctionDesc's are initialized with.)
2260//==========================================================================
2261VOID InitPreStubManager();
2262
2263EXTERN_C void STDCALL ThePreStub();
2264
2265inline PCODE GetPreStubEntryPoint()
2266{
2267 return GetEEFuncEntryPoint(ThePreStub);
2268}
2269
2270#if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2271
2272EXTERN_C void STDCALL ThePreStubCompactARM();
2273
2274inline PCODE GetPreStubCompactARMEntryPoint()
2275{
2276 return GetEEFuncEntryPoint(ThePreStubCompactARM);
2277}
2278
2279#endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_)
2280
2281PCODE TheUMThunkPreStub();
2282
2283PCODE TheVarargNDirectStub(BOOL hasRetBuffArg);
2284
2285
2286
2287// workaround: These classification bits need cleanup bad: for now, this gets around
2288// IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
2289#define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
2290
2291//
2292// The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
2293// methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
2294//
2295
2296#define METH_NAME_CACHE_SIZE 5
2297#define MAX_MISSES 3
2298
2299#ifdef EnC_SUPPORTED
2300
2301struct EnCAddedFieldElement;
2302
2303#endif // EnC_SUPPORTED
2304
2305
2306// --------------------------------------------------------------------------------------------
2307// For generic instantiations the FieldDescs stored for instance
2308// fields are approximate, not exact, i.e. they are representatives owned by
2309// canonical instantiation and they do not carry exact type information.
2310// This will not include EnC related fields. (See EncApproxFieldDescIterator for that)
2311class ApproxFieldDescIterator
2312{
2313private:
2314 int m_iteratorType;
2315 PTR_FieldDesc m_pFieldDescList;
2316 int m_currField;
2317 int m_totalFields;
2318
2319 public:
2320 enum IteratorType {
2321 INSTANCE_FIELDS = 0x1,
2322 STATIC_FIELDS = 0x2,
2323 ALL_FIELDS = (INSTANCE_FIELDS | STATIC_FIELDS)
2324 };
2325 ApproxFieldDescIterator();
2326 ApproxFieldDescIterator(MethodTable *pMT, int iteratorType)
2327 {
2328 SUPPORTS_DAC;
2329 Init(pMT, iteratorType);
2330 }
2331 void Init(MethodTable *pMT, int iteratorType);
2332 PTR_FieldDesc Next();
2333
2334 int GetIteratorType() {
2335 LIMITED_METHOD_CONTRACT;
2336 SUPPORTS_DAC;
2337 return m_iteratorType;
2338 }
2339
2340 int Count() {
2341 LIMITED_METHOD_CONTRACT;
2342 return m_totalFields;
2343 }
2344 int CountRemaining() {
2345 LIMITED_METHOD_CONTRACT;
2346 SUPPORTS_DAC;
2347 return m_totalFields - m_currField - 1;
2348 }
2349};
2350
2351//
2352// DeepFieldDescIterator iterates over the entire
2353// set of fields available to a class, inherited or
2354// introduced.
2355//
2356
2357class DeepFieldDescIterator
2358{
2359private:
2360 ApproxFieldDescIterator m_fieldIter;
2361 int m_numClasses;
2362 int m_curClass;
2363 MethodTable* m_classes[16];
2364 int m_deepTotalFields;
2365 bool m_lastNextFromParentClass;
2366
2367 bool NextClass();
2368
2369public:
2370 DeepFieldDescIterator()
2371 {
2372 LIMITED_METHOD_CONTRACT;
2373
2374 m_numClasses = 0;
2375 m_curClass = 0;
2376 m_deepTotalFields = 0;
2377 m_lastNextFromParentClass = false;
2378 }
2379 DeepFieldDescIterator(MethodTable* pMT, int iteratorType,
2380 bool includeParents = true)
2381 {
2382 WRAPPER_NO_CONTRACT;
2383
2384 Init(pMT, iteratorType, includeParents);
2385 }
2386 void Init(MethodTable* pMT, int iteratorType,
2387 bool includeParents = true);
2388
2389 FieldDesc* Next();
2390
2391 bool Skip(int numSkip);
2392
2393 int Count()
2394 {
2395 LIMITED_METHOD_CONTRACT;
2396 return m_deepTotalFields;
2397 }
2398 bool IsFieldFromParentClass()
2399 {
2400 LIMITED_METHOD_CONTRACT;
2401 return m_lastNextFromParentClass;
2402 }
2403};
2404
2405#endif // !CLASS_H
2406