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 | |
59 | VOID 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 | */ |
71 | class AppDomain; |
72 | class ArrayClass; |
73 | class ArrayMethodDesc; |
74 | class Assembly; |
75 | class ClassLoader; |
76 | class DictionaryLayout; |
77 | class DomainLocalBlock; |
78 | class FCallMethodDesc; |
79 | class EEClass; |
80 | class EnCFieldDesc; |
81 | class FieldDesc; |
82 | class FieldMarshaler; |
83 | struct LayoutRawFieldInfo; |
84 | class MetaSig; |
85 | class MethodDesc; |
86 | class MethodDescChunk; |
87 | class MethodTable; |
88 | class Module; |
89 | struct ModuleCtorInfo; |
90 | class Object; |
91 | class Stub; |
92 | class Substitution; |
93 | class SystemDomain; |
94 | class TypeHandle; |
95 | class StackingAllocator; |
96 | class AllocMemTracker; |
97 | class InteropMethodTableSlotDataMap; |
98 | class LoadingEntry_LockHolder; |
99 | class DispatchMapBuilder; |
100 | class LoaderAllocator; |
101 | class ComCallWrapperTemplate; |
102 | |
103 | typedef DPTR(DictionaryLayout) PTR_DictionaryLayout; |
104 | typedef 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 | //--------------------------------------------------------------------------------- |
114 | class 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 | //---------------------------------------------------------------------------------------------- |
140 | class 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 | //---------------------------------------------------------------------------------------------- |
193 | class 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. |
240 | class InterfaceImplEnum |
241 | { |
242 | Module* m_pModule; |
243 | HENUMInternalHolder hEnumInterfaceImpl; |
244 | const Substitution *m_pSubstChain; |
245 | Substitution m_CurrSubst; |
246 | mdTypeDef m_CurrTok; |
247 | public: |
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 | |
288 | class SparseVTableMap |
289 | { |
290 | public: |
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 | |
323 | private: |
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 | //======================================================================= |
350 | class 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 | // |
608 | typedef 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). |
673 | class 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 | }; |
740 | typedef 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 | |
765 | enum 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 | |
781 | typedef PackedDWORDFields<EEClass_Field_COUNT> EEClassPackedFields; |
782 | typedef 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 | // |
831 | class 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 | ************************************/ |
852 | public: |
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 |
939 | public: |
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 | |
978 | public: |
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 | |
1312 | private: |
1313 | inline void SetUnsafeValueClass() |
1314 | { |
1315 | LIMITED_METHOD_CONTRACT; |
1316 | m_VMFlags |= VMFLAG_UNSAFEVALUETYPE; |
1317 | } |
1318 | |
1319 | public: |
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 | |
1331 | public: |
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 | */ |
1542 | public: |
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 | */ |
1559 | public: |
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 | |
1734 | public: |
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) |
1794 | public: |
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 | // |
1824 | public: |
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 | |
1894 | public: |
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 |
1901 | public: |
1902 | LPCUTF8 m_szDebugClassName; |
1903 | BOOL m_fDebuggingClass; |
1904 | #endif |
1905 | |
1906 | private: |
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 | |
1956 | public: |
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 | |
1983 | private: |
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 | ************************************/ |
2009 | protected: |
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 | // -------------------------------------------------------------------------------------------- |
2028 | template <typename Data> |
2029 | class FixedCapacityStackingAllocatedUTF8StringHash |
2030 | { |
2031 | public: |
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 | // |
2083 | class LayoutEEClass : public EEClass |
2084 | { |
2085 | public: |
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 | |
2099 | class UMThunkMarshInfo; |
2100 | |
2101 | #ifdef FEATURE_COMINTEROP |
2102 | struct ComPlusCallInfo; |
2103 | #endif // FEATURE_COMINTEROP |
2104 | |
2105 | class DelegateEEClass : public EEClass |
2106 | { |
2107 | public: |
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 | |
2158 | typedef DPTR(ArrayClass) PTR_ArrayClass; |
2159 | |
2160 | |
2161 | // Dynamically generated array class structure |
2162 | class 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 | |
2176 | private: |
2177 | |
2178 | unsigned char m_rank; |
2179 | CorElementType m_ElementType;// Cache of element type in m_ElementTypeHnd |
2180 | |
2181 | public: |
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 | |
2229 | inline EEClassLayoutInfo *EEClass::GetLayoutInfo() |
2230 | { |
2231 | LIMITED_METHOD_CONTRACT; |
2232 | _ASSERTE(HasLayout()); |
2233 | return &((LayoutEEClass *) this)->m_LayoutInfo; |
2234 | } |
2235 | |
2236 | inline 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 | |
2245 | inline BOOL EEClass::IsManagedSequential() |
2246 | { |
2247 | LIMITED_METHOD_CONTRACT; |
2248 | return HasLayout() && GetLayoutInfo()->IsManagedSequential(); |
2249 | } |
2250 | |
2251 | inline 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 | //========================================================================== |
2261 | VOID InitPreStubManager(); |
2262 | |
2263 | EXTERN_C void STDCALL ThePreStub(); |
2264 | |
2265 | inline PCODE GetPreStubEntryPoint() |
2266 | { |
2267 | return GetEEFuncEntryPoint(ThePreStub); |
2268 | } |
2269 | |
2270 | #if defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_) |
2271 | |
2272 | EXTERN_C void STDCALL ThePreStubCompactARM(); |
2273 | |
2274 | inline PCODE GetPreStubCompactARMEntryPoint() |
2275 | { |
2276 | return GetEEFuncEntryPoint(ThePreStubCompactARM); |
2277 | } |
2278 | |
2279 | #endif // defined(HAS_COMPACT_ENTRYPOINTS) && defined(_TARGET_ARM_) |
2280 | |
2281 | PCODE TheUMThunkPreStub(); |
2282 | |
2283 | PCODE 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 | |
2301 | struct 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) |
2311 | class ApproxFieldDescIterator |
2312 | { |
2313 | private: |
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 | |
2357 | class DeepFieldDescIterator |
2358 | { |
2359 | private: |
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 | |
2369 | public: |
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 | |