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.
12 // ============================================================================
19 #include "classloadlevel.h"
20 #include "fixuppointer.h"
28 class TypeVarTypeDesc;
37 class InstantiationContext;
39 namespace Generics { class RecursionGraph; }
40 struct CORINFO_CLASS_STRUCT_;
42 typedef DPTR(class TypeVarTypeDesc) PTR_TypeVarTypeDesc;
43 typedef SPTR(class FnPtrTypeDesc) PTR_FnPtrTypeDesc;
44 typedef DPTR(class ParamTypeDesc) PTR_ParamTypeDesc;
45 typedef DPTR(class ArrayTypeDesc) PTR_ArrayTypeDesc;
46 typedef DPTR(class TypeDesc) PTR_TypeDesc;
47 typedef DPTR(class TypeHandle) PTR_TypeHandle;
50 typedef CUnorderedArray<TypeHandle, 40> DFLPendingList;
52 class TypeHandlePairList;
54 #ifdef FEATURE_COMINTEROP
55 class ComCallWrapperTemplate;
56 #endif // FEATURE_COMINTEROP
58 /*************************************************************************/
59 // A TypeHandle is the FUNDAMENTAL concept of type identity in the CLR.
60 // That is two types are equal if and only if their type handles
61 // are equal. A TypeHandle, is a pointer sized struture that encodes
62 // everything you need to know to figure out what kind of type you are
63 // actually dealing with.
65 // At the present time a TypeHandle can point at two possible things
67 // 1) A MethodTable (Intrinsics, Classes, Value Types and their instantiations)
68 // 2) A TypeDesc (all other cases: arrays, byrefs, pointer types, function pointers, generic type variables)
70 // or with IL stubs, a third thing:
72 // 3) A MethodTable for a native value type.
74 // Array MTs are not valid TypeHandles: for example no allocated object will
75 // ever return such a type handle from Object::GetTypeHandle(), and
76 // these type handles should not be passed across the JIT Interface
77 // as CORINFO_CLASS_HANDLEs. However some code in the EE does create
78 // temporary TypeHandles out of these MTs, so we can't yet assert
79 // !pMT->IsArray() in the TypeHandle constructor.
81 // Wherever possible, you should be using TypeHandles or MethodTables.
82 // Code that is known to work over Class/ValueClass types (including their
83 // instantaitions) is currently written to use MethodTables.
85 // TypeDescs in turn break down into several variants and are
86 // for special cases around the edges
87 // - array types whose method tables get share
88 // - types for function pointers for verification and reflection
89 // - types for generic parameters for verification and reflection
91 // Generic type instantiations (in C# syntax: C<ty_1,...,ty_n>) are represented by
92 // MethodTables, i.e. a new MethodTable gets allocated for each such instantiation.
93 // The entries in these tables (i.e. the code) are, however, often shared.
94 // Clients of TypeHandle don't need to know any of this detail; just use the
95 // GetInstantiation and HasInstantiation methods.
101 LIMITED_METHOD_DAC_CONTRACT;
106 static TypeHandle FromPtr(PTR_VOID aPtr)
108 LIMITED_METHOD_DAC_CONTRACT;
110 return TypeHandle(dac_cast<TADDR>(aPtr));
112 // Create a TypeHandle from the target address of a MethodTable
113 static TypeHandle FromTAddr(TADDR data)
115 LIMITED_METHOD_DAC_CONTRACT;
117 return TypeHandle(data);
120 // When you ask for a class in JitInterface when all you have
121 // is a methodDesc of an array method...
122 // Convert from a JitInterface handle to an internal EE TypeHandle
123 explicit TypeHandle(struct CORINFO_CLASS_STRUCT_*aPtr)
125 LIMITED_METHOD_DAC_CONTRACT;
127 m_asTAddr = dac_cast<TADDR>(aPtr);
128 // NormalizeUnsharedArrayMT();
129 INDEBUGIMPL(Verify());
132 TypeHandle(MethodTable const * aMT) {
133 LIMITED_METHOD_DAC_CONTRACT;
135 m_asTAddr = dac_cast<TADDR>(aMT);
136 // NormalizeUnsharedArrayMT();
137 INDEBUGIMPL(Verify());
140 explicit TypeHandle(TypeDesc *aType) {
141 LIMITED_METHOD_DAC_CONTRACT;
144 m_asTAddr = (dac_cast<TADDR>(aType) | 2);
145 INDEBUGIMPL(Verify());
148 inline BOOL IsNativeValueType() const;
149 inline MethodTable *AsNativeValueType() const;
152 // This constructor has been made private. You must use the explicit static functions
153 // TypeHandle::FromPtr and TypeHandle::TAddr instead of these constructors.
154 // Allowing a public constructor that takes a "void *" or a "TADDR" is error-prone.
155 explicit TypeHandle(TADDR aTAddr)
157 LIMITED_METHOD_DAC_CONTRACT;
159 // NormalizeUnsharedArrayMT();
160 INDEBUGIMPL(Verify());
165 FORCEINLINE int operator==(const TypeHandle& typeHnd) const {
166 LIMITED_METHOD_DAC_CONTRACT;
168 return(m_asTAddr == typeHnd.m_asTAddr);
171 FORCEINLINE int operator!=(const TypeHandle& typeHnd) const {
172 LIMITED_METHOD_DAC_CONTRACT;
174 return(m_asTAddr != typeHnd.m_asTAddr);
177 // Methods for probing exactly what kind of a type handle we have
178 FORCEINLINE BOOL IsNull() const {
179 LIMITED_METHOD_DAC_CONTRACT;
181 if (m_asTAddr == 0) {
182 #ifndef DACCESS_COMPILE
183 PREFIX_ASSUME(m_asPtr == NULL);
188 #ifndef DACCESS_COMPILE
189 PREFIX_ASSUME(m_asPtr != NULL);
194 return(m_asTAddr == 0);
198 // Note that this returns denormalized BOOL to help the compiler with optimizations
199 FORCEINLINE BOOL IsTypeDesc() const {
200 LIMITED_METHOD_DAC_CONTRACT;
203 PREFIX_ASSUME(m_asTAddr != NULL);
204 #ifndef DACCESS_COMPILE
205 PREFIX_ASSUME(m_asPtr != NULL);
213 return(m_asTAddr & 2);
219 BOOL IsFnPtrType() const;
221 inline PTR_MethodTable AsMethodTable() const;
223 inline PTR_TypeDesc AsTypeDesc() const;
225 // To the extent possible, you should try to use methods like the ones
226 // below that treat all types uniformly.
228 // Gets the size that this type would take up embedded in another object
229 // thus objects all return sizeof(void*).
230 unsigned GetSize() const;
232 // Returns the type name, including the generic instantiation if possible.
233 // See the TypeString class for better control over name formatting.
234 void GetName(SString &result) const;
236 // Returns the ELEMENT_TYPE_* that you would use in a signature
237 // The only normalization that happens is that for type handles
238 // for instantiated types (e.g. class List<String> or
239 // value type Pair<int,int>)) this returns either ELEMENT_TYPE_CLASS
240 // or ELEMENT_TYPE_VALUE, _not_ ELEMENT_TYPE_WITH.
241 CorElementType GetSignatureCorElementType() const;
244 // - Will return enums underlying type
245 // - Will return underlying primitive for System.Int32 etc...
246 // - Will return underlying primitive as will be used in the calling convention
252 // will return ELEMENT_TYPE_I4 in x86 instead of ELEMENT_TYPE_VALUETYPE. We
253 // call this type of value type a primitive value type
255 // Internal representation is used among another things for the calling convention
256 // (jit benefits of primitive value types) or optimizing marshalling.
258 // This will NOT convert E_T_ARRAY, E_T_SZARRAY etc. to E_T_CLASS (though it probably
259 // should). Use CorTypeInfo::IsObjRef for that.
260 CorElementType GetInternalCorElementType() const;
262 // This helper will return the same as GetSignatureCorElementType except:
263 // - Will return enums underlying type
264 CorElementType GetVerifierCorElementType() const;
266 //-------------------------------------------------------------------
269 // There are two variants of the "CanCastTo" method:
272 // - restore encoded pointers on demand
273 // - might throw, might trigger GC
274 // - return type is boolean (FALSE = cannot cast, TRUE = can cast)
277 // - do not restore encoded pointers on demand
278 // - does not throw, does not trigger GC
279 // - return type is three-valued (CanCast, CannotCast, MaybeCast)
280 // - MaybeCast indicates that the test tripped on an encoded pointer
281 // so the caller should now call CanCastTo if it cares
283 // Note that if the TypeHandle is a valuetype, the caller is responsible
284 // for checking that the valuetype is in its boxed form before calling
285 // CanCastTo. Otherwise, the caller should be using IsBoxedAndCanCastTo()
286 typedef enum { CannotCast, CanCast, MaybeCast } CastResult;
288 BOOL CanCastTo(TypeHandle type, TypeHandlePairList *pVisited = NULL) const;
289 BOOL IsBoxedAndCanCastTo(TypeHandle type, TypeHandlePairList *pVisited) const;
290 CastResult CanCastToNoGC(TypeHandle type) const;
292 #ifndef DACCESS_COMPILE
293 // Type equivalence based on Guid and TypeIdentifier attributes
294 inline BOOL IsEquivalentTo(TypeHandle type COMMA_INDEBUG(TypeHandlePairList *pVisited = NULL)) const;
297 // Get the parent, known to be decoded
298 TypeHandle GetParent() const;
300 // Obtain element type for an array or pointer, returning NULL otherwise
301 TypeHandle GetTypeParam() const;
303 // Obtain instantiation from an instantiated type
304 // NULL if not instantiated
305 Instantiation GetInstantiation() const;
307 // Does this type satisfy its class constraints, recursively up the hierarchy
308 BOOL SatisfiesClassConstraints() const;
310 TypeHandle Instantiate(Instantiation inst) const;
311 TypeHandle MakePointer() const;
312 TypeHandle MakeByRef() const;
313 TypeHandle MakeSZArray() const;
314 TypeHandle MakeArray(int rank) const;
315 TypeHandle MakeNativeValueType() const;
317 // Obtain instantiation from an instantiated type *or* a pointer to the element type for an array
318 Instantiation GetClassOrArrayInstantiation() const;
320 // Is this type instantiated?
321 BOOL HasInstantiation() const;
323 // Is this a generic type whose type arguments are its formal type parameters?
324 BOOL IsGenericTypeDefinition() const;
326 // Is this either a non-generic type (e.g. a non-genric class type or an array type or a pointer type etc.)
327 // or a generic type whose type arguments are its formal type parameters?
328 //Equivalent to (!HasInstantiation() || IsGenericTypeDefinition());
329 inline BOOL IsTypicalTypeDefinition() const;
333 Interop_ManagedToNative, // use for RCW-related queries
334 Interop_NativeToManaged, // use for CCW-related queries
337 inline BOOL SupportsGenericInterop(InteropKind interopKind) const;
339 BOOL IsSharedByGenericInstantiations() const;
341 // Recursively search the type arguments and if
342 // one of the type arguments is Canon then return TRUE
344 // A<__Canon> is the canonical TypeHandle (aka "representative" generic MT)
345 // A<B<__Canon>> is a subtype that contains a Canonical type
347 BOOL IsCanonicalSubtype() const;
349 // Similar to IsCanonicalSubtype, but applied to a vector.
350 static BOOL IsCanonicalSubtypeInstantiation(Instantiation inst);
352 // For an uninstantiated generic type, return the number of type parameters required for instantiation
353 // For an instantiated type, return the number of type parameters in the instantiation
354 // Otherwise return 0
355 DWORD GetNumGenericArgs() const;
357 BOOL IsValueType() const;
358 BOOL IsInterface() const;
359 BOOL IsAbstract() const;
361 inline DWORD IsObjectType() const
363 LIMITED_METHOD_CONTRACT;
364 return *this == TypeHandle(g_pObjectClass);
367 // Retrieve the key corresponding to this handle
368 TypeKey GetTypeKey() const;
370 // To what level has this type been loaded?
371 ClassLoadLevel GetLoadLevel() const;
373 // Equivalent to GetLoadLevel() == CLASS_LOADED
374 BOOL IsFullyLoaded() const;
376 void DoFullyLoad(Generics::RecursionGraph *pVisited, ClassLoadLevel level, DFLPendingList *pPending, BOOL *pfBailed,
377 const InstantiationContext *pInstContext);
379 inline void SetIsFullyLoaded();
383 // Check that this type matches the key given
384 // i.e. that all aspects (element type, module/token, rank for arrays, instantiation for generic types) match up
385 CHECK CheckMatchesKey(TypeKey *pKey) const;
387 // Check that this type is loaded up to the level indicated
388 // Also check that it is non-null
389 CHECK CheckLoadLevel(ClassLoadLevel level);
391 // Equivalent to CheckLoadLevel(CLASS_LOADED)
392 CHECK CheckFullyLoaded();
396 CorElementType GetHFAType() const;
398 #ifdef FEATURE_64BIT_ALIGNMENT
399 bool RequiresAlign8() const;
400 #endif // FEATURE_64BIT_ALIGNMENT
402 #ifndef DACCESS_COMPILE
404 BOOL IsBlittable() const;
405 BOOL HasLayout() const;
407 #ifdef FEATURE_COMINTEROP
408 TypeHandle GetCoClassForInterface() const;
409 DWORD IsComClassInterface() const;
410 BOOL IsComObjectType() const;
411 BOOL IsComEventItfType() const;
412 CorIfaceAttr GetComInterfaceType() const;
413 TypeHandle GetDefItfForComClassItf() const;
415 BOOL IsProjectedFromWinRT() const;
416 BOOL IsExportedToWinRT() const;
418 ComCallWrapperTemplate *GetComCallWrapperTemplate() const;
419 BOOL SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate);
420 #endif // FEATURE_COMINTEROP
424 // Unlike AsMethodTable, GetMethodTable will get the method table
425 // of the type, regardless of whether it is an array etc. Note, however
426 // this method table may be shared, and some types (like TypeByRef), have
427 // no method table (and this function returns NULL for them)
428 inline PTR_MethodTable GetMethodTable() const;
430 // Returns the method table which should be used for visibility checking.
431 // Like GetMethodTable except for TypeDescs returns the root ElementType.
432 // So for Foo[] instead of returning Array returns Foo.
433 inline MethodTable* GetMethodTableOfElementType() const;
435 // Returns the MethodTable for the SZARRAY or ARRAY type
436 inline MethodTable * GetPossiblySharedArrayMethodTable() const;
438 // As above but returns a TypeHandle (so it will return a non-null result
439 // for generic type variables, for instance).
440 inline TypeHandle GetElementType() const;
442 // Return the canonical representative MT amongst the set of MT's that share
443 // code with the MT for the given TypeHandle because of generics.
444 PTR_MethodTable GetCanonicalMethodTable() const;
446 // The module that defined the underlying type
447 // (First strip off array/ptr qualifiers and generic type arguments)
448 PTR_Module GetModule() const;
450 // The ngen'ed module where this type lives
451 PTR_Module GetZapModule() const;
453 // Does this immediate item live in an NGEN module?
454 BOOL IsZapped() const;
456 // The module where this type lives for the purposes of loading and prejitting
457 // Note: NGen time result might differ from runtime result for parametrized types (generics, arrays, etc.)
458 // See code:ClassLoader::ComputeLoaderModule or file:clsload.hpp#LoaderModule for more information
459 PTR_Module GetLoaderModule() const;
461 // The assembly that defined this type (== GetModule()->GetAssembly())
462 Assembly * GetAssembly() const;
464 // GetDomain on an instantiated type, e.g. C<ty1,ty2> returns the SharedDomain if all the
465 // constituent parts of the type are SharedDomain (i.e. domain-neutral),
466 // and returns an AppDomain if any of the parts are from an AppDomain,
467 // i.e. are domain-bound. If any of the parts are domain-bound
468 // then they will all belong to the same domain.
469 PTR_BaseDomain GetDomain() const;
471 PTR_LoaderAllocator GetLoaderAllocator() const;
473 // Get the class token, assuming the type handle represents a named type,
474 // i.e. a class, a value type, a generic instantiation etc.
475 inline mdTypeDef GetCl() const;
479 // ARRAY or SZARRAY TypeDesc (arrays with a shared MethodTable)
480 // If this is TRUE, it is OK to call AsArray()
481 // Also see IsArrayType()
482 BOOL IsArray() const;
484 // See comment of IsArrayType() for the explanation of this method
486 void NormalizeUnsharedArrayMT();
490 // Note that this does not imply that it is OK to call AsArray(). See IsArray()
492 // All arrays, even those with a unique unshared MethodTable, have an ArrayTypeDesc
493 // which is used for type identity. However, over time, people have started
494 // wrapping the MethodTables directly in a TypeHandle. Note that such
495 // TypeHandles cannot be used for type identity. However, IsArrayType() lets
496 // you check even for such cases where IsArray() returns FALSE, but the type
497 // still is an array type.
499 // @TODO: Change all the constructors of TypeHandle which take a MethodTable
500 // to call NormalizeUnsharedArrayMT(). TypeHandle::Verify() can then enforce
501 // that IsArray() is fully correct.
502 BOOL IsArrayType() const;
505 BOOL IsGenericVariable() const;
508 BOOL IsByRef() const;
510 // BYREFLIKE (does not return TRUE for IsByRef types)
511 BOOL IsByRefLike() const;
514 BOOL IsPointer() const;
516 // True if this type *is* a formal generic type parameter or any component of it is a formal generic type parameter
517 BOOL ContainsGenericVariables(BOOL methodOnly=FALSE) const;
519 Module* GetDefiningModuleForOpenType() const;
521 // Is actually ParamTypeDesc (ARRAY, SZARRAY, BYREF, PTR)
522 BOOL HasTypeParam() const;
524 BOOL IsRestored_NoLogging() const;
525 BOOL IsRestored() const;
527 // Does this type have zap-encoded components (generic arguments, etc)?
528 BOOL HasUnrestoredTypeKey() const;
530 // True if this type handle is a zap-encoded fixup
531 BOOL IsEncodedFixup() const;
533 // Only used at NGEN-time
534 BOOL ComputeNeedsRestore(DataImage *image, TypeHandleList *pVisited) const;
536 void DoRestoreTypeKey();
538 void CheckRestore() const;
539 BOOL IsExternallyVisible() const;
541 // Does this type participate in type equivalence?
542 inline BOOL HasTypeEquivalence() const;
544 // Not clear we should have this.
545 inline PTR_ArrayTypeDesc AsArray() const;
547 FnPtrTypeDesc* AsFnPtrType() const;
549 TypeVarTypeDesc* AsGenericVariable() const;
551 Instantiation GetInstantiationOfParentClass(MethodTable *pWhichParent) const;
553 PTR_VOID AsPtr() const { // Please don't use this if you can avoid it
554 LIMITED_METHOD_DAC_CONTRACT;
556 return(PTR_VOID(m_asTAddr));
559 TADDR AsTAddr() const {
560 LIMITED_METHOD_DAC_CONTRACT;
565 INDEBUGIMPL(BOOL Verify();) // DEBUGGING Make certain this is a valid type handle
567 #ifdef DACCESS_COMPILE
568 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
571 OBJECTREF GetManagedClassObject() const;
572 OBJECTREF GetManagedClassObjectFast() const;
574 static TypeHandle MergeArrayTypeHandlesToCommonParent(
575 TypeHandle ta, TypeHandle tb);
577 static TypeHandle MergeTypeHandlesToCommonParent(
578 TypeHandle ta, TypeHandle tb);
581 BOOL NotifyDebuggerLoad(AppDomain *domain, BOOL attaching) const;
582 void NotifyDebuggerUnload(AppDomain *domain) const;
584 // Execute the callback functor for each MethodTable that makes up the given type handle. This method
585 // does not invoke the functor for generic variables
587 inline void ForEachComponentMethodTable(T &callback) const;
590 static TypeHandle MergeClassWithInterface(
591 TypeHandle tClass, TypeHandle tInterface);
595 TADDR m_asTAddr; // we look at the low order bits
596 #ifndef DACCESS_COMPILE
598 PTR_MethodTable m_asMT;
599 PTR_TypeDesc m_asTypeDesc;
600 PTR_ArrayTypeDesc m_asArrayTypeDesc;
601 PTR_ParamTypeDesc m_asParamTypeDesc;
602 PTR_TypeVarTypeDesc m_asTypeVarTypeDesc;
603 PTR_FnPtrTypeDesc m_asFnPtrTypeDesc;
610 TypeHandle m_typeHandle;
611 TypeHandleList* m_pNext;
614 TypeHandleList(TypeHandle t, TypeHandleList* pNext) : m_typeHandle(t),m_pNext(pNext),m_fBrokenCycle(false) { };
615 static BOOL Exists(TypeHandleList* pList, TypeHandle t)
617 LIMITED_METHOD_CONTRACT;
618 while (pList != NULL) { if (pList->m_typeHandle == t) return TRUE; pList = pList->m_pNext; }
622 // Supports enumeration of the list.
623 static BOOL GetNext(TypeHandleList** ppList, TypeHandle* pHandle)
625 LIMITED_METHOD_CONTRACT;
628 *pHandle = (*ppList)->m_typeHandle;
629 (*ppList) = (*ppList)->m_pNext;
635 void MarkBrokenCycle(TypeHandle th)
637 LIMITED_METHOD_CONTRACT;
638 TypeHandleList* pList = this;
639 while (pList->m_typeHandle != th) { pList->m_fBrokenCycle = true; pList = pList->m_pNext; }
641 bool HasBrokenCycleMark()
643 LIMITED_METHOD_CONTRACT;
644 return m_fBrokenCycle;
648 class TypeHandlePairList // TODO: Template for TypeHandleList, TypeHandlePairList, TokenPairList?
650 TypeHandle m_typeHandle1;
651 TypeHandle m_typeHandle2;
652 TypeHandlePairList *m_pNext;
654 TypeHandlePairList(TypeHandle t1, TypeHandle t2, TypeHandlePairList *pNext) : m_typeHandle1(t1), m_typeHandle2(t2), m_pNext(pNext) { };
655 static BOOL Exists(TypeHandlePairList *pList, TypeHandle t1, TypeHandle t2)
657 LIMITED_METHOD_CONTRACT;
658 while (pList != NULL)
660 if (pList->m_typeHandle1 == t1 && pList->m_typeHandle2 == t2)
662 if (pList->m_typeHandle1 == t2 && pList->m_typeHandle2 == t1)
665 pList = pList->m_pNext;
672 inline CHECK CheckPointer(TypeHandle th, IsNullOK ok = NULL_NOT_OK)
674 STATIC_CONTRACT_NOTHROW;
675 STATIC_CONTRACT_GC_NOTRIGGER;
676 STATIC_CONTRACT_FORBID_FAULT;
678 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
682 CHECK_MSG(ok, "Illegal null TypeHandle");
686 __if_exists(TypeHandle::Check)
691 CHECK(CheckInvariant(o));
698 #endif // CHECK_INVARIANTS
700 /*************************************************************************/
701 // dac_casts for TypeHandle makes FixupPointer<TypeHandle> work.
703 // TypeHandle is wrapper around pointer to MethodTable or TypeDesc. Even though
704 // it may feel counterintuitive, it is possible to treat it like a pointer and
705 // use the regular FixupPointer to implement TypeHandle indirection cells.
706 // The lowest bit of TypeHandle (when wrapped inside FixupPointer) is
707 // used to mark optional indirection.
710 inline TADDR dac_cast(TypeHandle src)
713 return src.AsTAddr();
717 inline TypeHandle dac_cast(TADDR src)
720 return TypeHandle::FromTAddr(src);
723 /*************************************************************************/
724 // Instantiation is representation of generic instantiation.
725 // It is simple read-only array of TypeHandles. In NGen, the type handles
726 // may be encoded using indirections. That's one reason why it is convenient
727 // to have wrapper class that performs the decoding.
731 // Construct empty instantiation
733 : m_pArgs(NULL), m_nArgs(0)
735 LIMITED_METHOD_DAC_CONTRACT;
739 Instantiation(const Instantiation & inst)
740 : m_pArgs(inst.m_pArgs), m_nArgs(inst.m_nArgs)
742 LIMITED_METHOD_DAC_CONTRACT;
743 _ASSERTE(m_nArgs == 0 || m_pArgs != NULL);
746 // Construct instantiation from array of FixupPointers
747 Instantiation(FixupPointer<TypeHandle> * pArgs, DWORD nArgs)
748 : m_pArgs(pArgs), m_nArgs(nArgs)
750 LIMITED_METHOD_DAC_CONTRACT;
751 _ASSERTE(m_nArgs == 0 || m_pArgs != NULL);
754 // Construct instantiation from array of TypeHandles
755 Instantiation(TypeHandle * pArgs, DWORD nArgs)
758 LIMITED_METHOD_DAC_CONTRACT;
760 DACCOP_IGNORE(CastOfMarshalledType, "Dual mode DAC problem, but since the size is the same, the cast is safe");
761 m_pArgs = (FixupPointer<TypeHandle> *)pArgs;
762 _ASSERTE(m_nArgs == 0 || m_pArgs != NULL);
765 #ifdef DACCESS_COMPILE
766 // Construct instantiation from target array of FixupPointers in DAC.
767 // This method will create local copy of the instantiation arguments.
768 Instantiation(DPTR(FixupPointer<TypeHandle>) pArgs, DWORD nArgs)
770 LIMITED_METHOD_DAC_CONTRACT;
772 // Create a local copy of the instanitation under DAC
773 PVOID pLocalArgs = PTR_READ(dac_cast<TADDR>(pArgs), nArgs * sizeof(TypeHandle));
774 m_pArgs = (FixupPointer<TypeHandle> *)pLocalArgs;
778 _ASSERTE(m_nArgs == 0 || m_pArgs != NULL);
782 // Return i-th instantiation argument
783 TypeHandle operator[](DWORD iArg) const
785 LIMITED_METHOD_DAC_CONTRACT;
786 _ASSERTE(iArg < m_nArgs);
787 return m_pArgs[iArg].GetValue();
790 DWORD GetNumArgs() const
792 LIMITED_METHOD_DAC_CONTRACT;
798 LIMITED_METHOD_DAC_CONTRACT;
802 // Unsafe access to the instantiation. Do not use unless absolutely necessary!!!
803 FixupPointer<TypeHandle> * GetRawArgs() const
805 LIMITED_METHOD_DAC_CONTRACT;
810 // Note that for DAC builds, m_pArgs may be host allocated buffer, not a copy of an object marshalled by DAC.
811 FixupPointer<TypeHandle> * m_pArgs;
815 #endif // TYPEHANDLE_H