7da1c84604dcfd166254f7f4a5da06a99ebdc9b5
[platform/upstream/coreclr.git] / src / vm / typedesc.cpp
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 // File: typedesc.cpp
6 // 
7
8
9 // 
10 // This file contains definitions for methods in the code:TypeDesc class and its 
11 // subclasses 
12 //     code:ParamTypeDesc, 
13 //     code:ArrayTypeDesc, 
14 //     code:TyVarTypeDesc, 
15 //     code:FnPtrTypeDesc
16 // 
17
18 // 
19 // ============================================================================
20
21 #include "common.h"
22 #include "typedesc.h"
23 #include "typestring.h"
24 #if defined(FEATURE_PREJIT)
25 #include "compile.h"
26 #endif
27 #include "array.h"
28 #include "stackprobe.h"
29
30
31 #ifndef DACCESS_COMPILE
32 #ifdef _DEBUG
33
34 BOOL ParamTypeDesc::Verify() {
35
36     STATIC_CONTRACT_NOTHROW;
37     STATIC_CONTRACT_GC_NOTRIGGER;
38     STATIC_CONTRACT_FORBID_FAULT;
39     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
40     STATIC_CONTRACT_DEBUG_ONLY;
41     STATIC_CONTRACT_SUPPORTS_DAC;
42
43     _ASSERTE(m_TemplateMT.IsNull() || GetTemplateMethodTableInternal()->SanityCheck());
44     _ASSERTE(!GetTypeParam().IsNull());
45     BAD_FORMAT_NOTHROW_ASSERT(GetTypeParam().IsTypeDesc() || !GetTypeParam().AsMethodTable()->IsArray());
46     BAD_FORMAT_NOTHROW_ASSERT(CorTypeInfo::IsModifier_NoThrow(GetInternalCorElementType()) ||
47                               GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE);
48     GetTypeParam().Verify();
49     return(true);
50 }
51
52 BOOL ArrayTypeDesc::Verify() {
53
54     STATIC_CONTRACT_NOTHROW;
55     STATIC_CONTRACT_GC_NOTRIGGER;
56     STATIC_CONTRACT_FORBID_FAULT;
57     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
58     STATIC_CONTRACT_DEBUG_ONLY;
59     STATIC_CONTRACT_SUPPORTS_DAC;
60
61     // m_TemplateMT == 0 may be null when building types involving TypeVarTypeDesc's
62     BAD_FORMAT_NOTHROW_ASSERT(m_TemplateMT.IsNull() || GetTemplateMethodTable()->IsArray());
63     BAD_FORMAT_NOTHROW_ASSERT(CorTypeInfo::IsArray_NoThrow(GetInternalCorElementType()));
64     ParamTypeDesc::Verify();
65     return(true);
66 }
67
68 #endif
69
70 #endif // #ifndef DACCESS_COMPILE
71
72 TypeHandle TypeDesc::GetBaseTypeParam()
73 {
74     LIMITED_METHOD_DAC_CONTRACT;
75
76     _ASSERTE(HasTypeParam());
77
78     TypeHandle th = dac_cast<PTR_ParamTypeDesc>(this)->GetTypeParam();
79     while (th.HasTypeParam())
80     {
81         th = dac_cast<PTR_ParamTypeDesc>(th.AsTypeDesc())->GetTypeParam();
82     }
83     _ASSERTE(!th.IsNull());
84
85     return th;
86 }
87
88 PTR_Module TypeDesc::GetLoaderModule()
89 {
90     STATIC_CONTRACT_NOTHROW;
91     STATIC_CONTRACT_GC_NOTRIGGER;
92     STATIC_CONTRACT_FORBID_FAULT;
93     SUPPORTS_DAC;
94
95     if (HasTypeParam())
96     {
97         return GetBaseTypeParam().GetLoaderModule();
98     }
99     else if (IsGenericVariable())
100     {
101         return dac_cast<PTR_TypeVarTypeDesc>(this)->GetModule();
102     }
103     else
104     {
105         PTR_Module retVal = NULL;
106         BOOL fFail = FALSE;
107
108         _ASSERTE(GetInternalCorElementType() == ELEMENT_TYPE_FNPTR);
109         PTR_FnPtrTypeDesc asFnPtr = dac_cast<PTR_FnPtrTypeDesc>(this);
110         BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), fFail = TRUE );
111         if (!fFail)
112         {
113             retVal =  ClassLoader::ComputeLoaderModuleForFunctionPointer(asFnPtr->GetRetAndArgTypesPointer(), asFnPtr->GetNumArgs()+1);
114         }                                              
115         END_SO_INTOLERANT_CODE;
116         return retVal;
117     }
118 }
119
120
121 PTR_Module TypeDesc::GetZapModule()
122 {
123     WRAPPER_NO_CONTRACT;
124     SUPPORTS_DAC;
125     return ExecutionManager::FindZapModule(dac_cast<TADDR>(this));
126 }
127
128 PTR_BaseDomain TypeDesc::GetDomain()
129 {
130     CONTRACTL
131     {
132         NOTHROW;
133         GC_NOTRIGGER;
134         FORBID_FAULT;
135         SUPPORTS_DAC;
136     }
137     CONTRACTL_END
138
139     Module *pZapModule = GetZapModule();
140     if (pZapModule != NULL)
141     {
142         return pZapModule->GetDomain();
143     }
144
145     if (HasTypeParam())
146     {
147         return GetBaseTypeParam().GetDomain();
148     }
149     if (IsGenericVariable())
150     {
151         PTR_TypeVarTypeDesc asVar = dac_cast<PTR_TypeVarTypeDesc>(this);
152         return asVar->GetModule()->GetDomain();
153     }
154     _ASSERTE(GetInternalCorElementType() == ELEMENT_TYPE_FNPTR);
155     PTR_FnPtrTypeDesc asFnPtr = dac_cast<PTR_FnPtrTypeDesc>(this);
156     return BaseDomain::ComputeBaseDomain(asFnPtr->GetRetAndArgTypesPointer()[0].GetDomain(),
157                                          Instantiation(asFnPtr->GetRetAndArgTypesPointer(), asFnPtr->GetNumArgs()+1));
158 }
159
160 PTR_Module TypeDesc::GetModule() {
161     CONTRACTL
162     {
163         NOTHROW;
164         GC_NOTRIGGER;
165         FORBID_FAULT;
166         SO_TOLERANT;
167         SUPPORTS_DAC;
168         // Function pointer types belong to no module
169         //PRECONDITION(GetInternalCorElementType() != ELEMENT_TYPE_FNPTR);
170     }
171     CONTRACTL_END
172
173     // Note here we are making the assumption that a typeDesc lives in
174     // the classloader of its element type.
175
176     if (HasTypeParam())
177     {
178         return GetBaseTypeParam().GetModule();
179     }
180
181     if (IsGenericVariable())
182     {
183         PTR_TypeVarTypeDesc asVar = dac_cast<PTR_TypeVarTypeDesc>(this);
184         return asVar->GetModule();
185     }
186
187     _ASSERTE(GetInternalCorElementType() == ELEMENT_TYPE_FNPTR);
188
189     return GetLoaderModule();
190 }
191
192 BOOL TypeDesc::IsDomainNeutral()
193 {
194     CONTRACTL
195     {
196         NOTHROW;
197         GC_NOTRIGGER;
198         FORBID_FAULT;
199     }
200     CONTRACTL_END
201
202     return GetDomain()->IsSharedDomain();
203 }
204
205 BOOL ParamTypeDesc::OwnsTemplateMethodTable()
206 {
207     CONTRACTL
208     {
209         NOTHROW;
210         GC_NOTRIGGER;
211     }
212     CONTRACTL_END;
213
214     CorElementType kind = GetInternalCorElementType();
215
216     // The m_TemplateMT for pointer types is UIntPtr
217     if (!CorTypeInfo::IsArray_NoThrow(kind))
218     {
219         return FALSE;
220     }
221
222     CorElementType elemType = m_Arg.GetSignatureCorElementType();
223
224     // This check matches precisely one in Module::CreateArrayMethodTable
225     //
226     // They indicate if an array TypeDesc is non-canonical (in much the same a a generic
227     // method table being non-canonical), i.e. it is not the primary
228     // owner of the m_TemplateMT (the primary owner is the TypeDesc for object[])
229
230     if (CorTypeInfo::IsGenericVariable_NoThrow(elemType))
231     {
232         return FALSE;
233     }
234
235     return TRUE;
236 }
237
238 Assembly* TypeDesc::GetAssembly() {
239     STATIC_CONTRACT_NOTHROW;
240     STATIC_CONTRACT_GC_NOTRIGGER;
241     STATIC_CONTRACT_FORBID_FAULT;
242
243     Module *pModule = GetModule();
244     PREFIX_ASSUME(pModule!=NULL);
245     return pModule->GetAssembly();
246 }
247
248 void TypeDesc::GetName(SString &ssBuf)
249 {
250     CONTRACTL
251     {
252         THROWS;
253         GC_NOTRIGGER;
254         INJECT_FAULT(COMPlusThrowOM(););
255     }
256     CONTRACTL_END
257
258     CorElementType kind = GetInternalCorElementType();
259     TypeHandle th;
260     int rank;
261
262     if (CorTypeInfo::IsModifier(kind))
263         th = GetTypeParam();
264     else
265         th = TypeHandle(this);
266
267     if (kind == ELEMENT_TYPE_ARRAY)
268         rank = ((ArrayTypeDesc*) this)->GetRank();
269     else if (CorTypeInfo::IsGenericVariable(kind))
270         rank = ((TypeVarTypeDesc*) this)->GetIndex();
271     else
272         rank = 0;
273
274     ConstructName(kind, th, rank, ssBuf);
275 }
276
277 void TypeDesc::ConstructName(CorElementType kind,
278                              TypeHandle param,
279                              int rank,
280                              SString &ssBuff)
281 {
282     CONTRACTL
283     {
284         THROWS;
285         GC_NOTRIGGER;
286         INJECT_FAULT(COMPlusThrowOM()); // SString operations can allocate.
287     }
288     CONTRACTL_END
289
290     if (CorTypeInfo::IsModifier(kind))
291     {
292         param.GetName(ssBuff);
293     }
294
295     switch(kind)
296     {
297     case ELEMENT_TYPE_BYREF:
298         ssBuff.Append(W('&'));
299         break;
300
301     case ELEMENT_TYPE_PTR:
302         ssBuff.Append(W('*'));
303         break;
304
305     case ELEMENT_TYPE_SZARRAY:
306         ssBuff.Append(W("[]"));
307         break;
308
309     case ELEMENT_TYPE_ARRAY:
310         ssBuff.Append(W('['));
311
312         if (rank == 1)
313         {
314             ssBuff.Append(W('*'));
315         }
316         else
317         {
318             while(--rank > 0)
319             {
320                 ssBuff.Append(W(','));
321             }
322         }
323
324         ssBuff.Append(W(']'));
325         break;
326
327     case ELEMENT_TYPE_VAR:
328     case ELEMENT_TYPE_MVAR:
329         if (kind == ELEMENT_TYPE_VAR)
330         {
331             ssBuff.Printf(W("!%d"), rank);
332         }
333         else
334         {
335             ssBuff.Printf(W("!!%d"), rank);
336         }
337         break;
338
339     case ELEMENT_TYPE_FNPTR:
340         ssBuff.Printf(W("FNPTR"));
341         break;
342
343     default:
344         LPCUTF8 namesp = CorTypeInfo::GetNamespace(kind);
345         if(namesp && *namesp) {
346             ssBuff.AppendUTF8(namesp);
347             ssBuff.Append(W('.'));
348         }
349
350         LPCUTF8 name = CorTypeInfo::GetName(kind);
351         BAD_FORMAT_NOTHROW_ASSERT(name);
352         if (name && *name) {
353             ssBuff.AppendUTF8(name);
354         }
355     }
356 }
357
358 BOOL TypeDesc::IsArray()
359 {
360     LIMITED_METHOD_DAC_CONTRACT;
361     return CorTypeInfo::IsArray_NoThrow(GetInternalCorElementType());
362 }
363
364 BOOL TypeDesc::IsGenericVariable()
365 {
366     LIMITED_METHOD_DAC_CONTRACT;
367     return CorTypeInfo::IsGenericVariable_NoThrow(GetInternalCorElementType());
368 }
369
370 BOOL TypeDesc::IsFnPtr()
371 {
372     LIMITED_METHOD_DAC_CONTRACT;
373     return (GetInternalCorElementType() == ELEMENT_TYPE_FNPTR);
374 }
375
376 BOOL TypeDesc::IsNativeValueType()
377 {
378     WRAPPER_NO_CONTRACT;
379     return (GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE);
380 }
381
382 BOOL TypeDesc::HasTypeParam()
383 {
384     WRAPPER_NO_CONTRACT;
385     SUPPORTS_DAC;
386     return CorTypeInfo::IsModifier_NoThrow(GetInternalCorElementType()) ||
387            GetInternalCorElementType() == ELEMENT_TYPE_VALUETYPE;
388 }
389
390 #ifndef DACCESS_COMPILE
391
392 BOOL TypeDesc::CanCastTo(TypeHandle toType, TypeHandlePairList *pVisited)
393 {
394     CONTRACTL
395     {
396         THROWS;
397         GC_TRIGGERS;
398         INJECT_FAULT(COMPlusThrowOM());
399     }
400     CONTRACTL_END
401
402     if (TypeHandle(this) == toType)
403         return TRUE;
404
405     //A boxed variable type can be cast to any of its constraints, or object, if none are specified
406     if (IsGenericVariable())
407     {
408         TypeVarTypeDesc *tyvar = (TypeVarTypeDesc*) this;
409
410         DWORD numConstraints;
411         TypeHandle *constraints = tyvar->GetConstraints(&numConstraints, CLASS_DEPENDENCIES_LOADED);
412
413         if (toType == g_pObjectClass)
414             return TRUE;
415
416         if (toType == g_pValueTypeClass) 
417         {
418             mdGenericParam genericParamToken = tyvar->GetToken();
419             DWORD flags;
420             if (FAILED(tyvar->GetModule()->GetMDImport()->GetGenericParamProps(genericParamToken, NULL, &flags, NULL, NULL, NULL)))
421             {
422                 return FALSE;
423             }
424             DWORD specialConstraints = flags & gpSpecialConstraintMask;
425             if ((specialConstraints & gpNotNullableValueTypeConstraint) != 0) 
426                 return TRUE;
427         }
428
429         if (constraints == NULL)
430             return FALSE;
431
432         for (DWORD i = 0; i < numConstraints; i++)
433         {
434             if (constraints[i].CanCastTo(toType, pVisited))
435                 return TRUE;
436         }
437         return FALSE;
438     }
439
440     // If we're not casting to a TypeDesc (i.e. not to a reference array type, variable type etc.)
441     // then we must be trying to cast to a class or interface type.
442     if (!toType.IsTypeDesc())
443     {
444         if (!IsArray())
445         {
446             // I am a variable type, pointer type, function pointer type
447             // etc.  I am not an object or value type.  Therefore
448             // I can't be cast to an object or value type.
449             return FALSE;
450         }
451
452         MethodTable *pMT = GetMethodTable();
453         _ASSERTE(pMT != 0);
454
455         // This does the right thing if 'type' == System.Array or System.Object, System.Clonable ...
456         if (pMT->CanCastToClassOrInterface(toType.AsMethodTable(), pVisited) != 0)
457         {
458             return TRUE;
459         }
460
461         if (IsArray() && toType.AsMethodTable()->IsInterface())
462         {
463             if (ArraySupportsBizarreInterface((ArrayTypeDesc*)this, toType.AsMethodTable()))
464             {
465                 return TRUE;
466             }
467
468         }
469
470         return FALSE;
471     }
472
473     TypeDesc* toTypeDesc = toType.AsTypeDesc();
474
475     CorElementType toKind = toTypeDesc->GetInternalCorElementType();
476     CorElementType fromKind = GetInternalCorElementType();
477
478     // The element kinds must match, only exception is that SZARRAY matches a one dimension ARRAY
479     if (!(toKind == fromKind || (toKind == ELEMENT_TYPE_ARRAY && fromKind == ELEMENT_TYPE_SZARRAY)))
480         return FALSE;
481
482     switch (toKind)
483     {
484     case ELEMENT_TYPE_ARRAY:
485         if (dac_cast<PTR_ArrayTypeDesc>(this)->GetRank() != dac_cast<PTR_ArrayTypeDesc>(toTypeDesc)->GetRank())
486             return FALSE;
487         // fall through
488     case ELEMENT_TYPE_SZARRAY:
489     case ELEMENT_TYPE_BYREF:
490     case ELEMENT_TYPE_PTR:
491         return TypeDesc::CanCastParam(dac_cast<PTR_ParamTypeDesc>(this)->GetTypeParam(), dac_cast<PTR_ParamTypeDesc>(toTypeDesc)->GetTypeParam(), pVisited);
492
493     case ELEMENT_TYPE_VAR:
494     case ELEMENT_TYPE_MVAR:
495     case ELEMENT_TYPE_FNPTR:
496         return FALSE;
497
498     default:
499         BAD_FORMAT_NOTHROW_ASSERT(toKind == ELEMENT_TYPE_TYPEDBYREF || CorTypeInfo::IsPrimitiveType(toKind));
500         return TRUE;
501     }
502 }
503
504 BOOL TypeDesc::CanCastParam(TypeHandle fromParam, TypeHandle toParam, TypeHandlePairList *pVisited)
505 {
506     CONTRACTL
507     {
508         THROWS;
509         GC_TRIGGERS;
510         INJECT_FAULT(COMPlusThrowOM());
511     }
512     CONTRACTL_END
513
514         // While boxed value classes inherit from object their
515         // unboxed versions do not.  Parameterized types have the
516         // unboxed version, thus, if the from type parameter is value
517         // class then only an exact match/equivalence works.
518     if (fromParam.IsEquivalentTo(toParam))
519         return TRUE;
520
521         // Object parameters dont need an exact match but only inheritance, check for that
522     CorElementType fromParamCorType = fromParam.GetVerifierCorElementType();
523     if (CorTypeInfo::IsObjRef(fromParamCorType))
524     {
525         return fromParam.CanCastTo(toParam, pVisited);
526     }
527     else if (CorTypeInfo::IsGenericVariable(fromParamCorType))
528     {
529         TypeVarTypeDesc* varFromParam = fromParam.AsGenericVariable();
530             
531         if (!varFromParam->ConstraintsLoaded())
532             varFromParam->LoadConstraints(CLASS_DEPENDENCIES_LOADED);
533
534         if (!varFromParam->ConstrainedAsObjRef())
535             return FALSE;
536             
537         return fromParam.CanCastTo(toParam, pVisited);
538     }
539     else if(CorTypeInfo::IsPrimitiveType(fromParamCorType))
540     {
541         CorElementType toParamCorType = toParam.GetVerifierCorElementType();
542         if(CorTypeInfo::IsPrimitiveType(toParamCorType))
543         {
544             if (toParamCorType == fromParamCorType)
545                 return TRUE;
546
547             // Primitive types such as E_T_I4 and E_T_U4 are interchangeable
548             // Enums with interchangeable underlying types are interchangable
549             // BOOL is NOT interchangeable with I1/U1, neither CHAR -- with I2/U2
550             if((toParamCorType != ELEMENT_TYPE_BOOLEAN)
551                 &&(fromParamCorType != ELEMENT_TYPE_BOOLEAN)
552                 &&(toParamCorType != ELEMENT_TYPE_CHAR)
553                 &&(fromParamCorType != ELEMENT_TYPE_CHAR))
554             {
555                 if ((CorTypeInfo::Size(toParamCorType) == CorTypeInfo::Size(fromParamCorType))
556                     && (CorTypeInfo::IsFloat(toParamCorType) == CorTypeInfo::IsFloat(fromParamCorType)))
557                 {
558                     return TRUE;
559                 }
560             }
561         } // end if(CorTypeInfo::IsPrimitiveType(toParamCorType))
562     } // end if(CorTypeInfo::IsPrimitiveType(fromParamCorType)) 
563
564         // Anything else is not a match.
565     return FALSE;
566 }
567
568 TypeHandle::CastResult TypeDesc::CanCastToNoGC(TypeHandle toType)
569 {
570     CONTRACTL
571     {
572         NOTHROW;
573         GC_NOTRIGGER;
574         FORBID_FAULT;
575         SO_TOLERANT;
576     }
577     CONTRACTL_END
578
579     if (TypeHandle(this) == toType)
580         return TypeHandle::CanCast;
581
582     //A boxed variable type can be cast to any of its constraints, or object, if none are specified
583     if (IsGenericVariable())
584     {
585         TypeVarTypeDesc *tyvar = (TypeVarTypeDesc*) this;
586
587         if (!tyvar->ConstraintsLoaded())
588             return TypeHandle::MaybeCast;
589
590         DWORD numConstraints;
591         TypeHandle *constraints = tyvar->GetCachedConstraints(&numConstraints);
592
593         if (toType == g_pObjectClass)
594             return TypeHandle::CanCast;
595
596         if (toType == g_pValueTypeClass)
597             return TypeHandle::MaybeCast;
598
599         if (constraints == NULL)
600             return TypeHandle::CannotCast;
601
602         for (DWORD i = 0; i < numConstraints; i++)
603         {
604             if (constraints[i].CanCastToNoGC(toType) == TypeHandle::CanCast)
605                 return TypeHandle::CanCast;
606         }
607         return TypeHandle::MaybeCast;
608     }
609
610     // If we're not casting to a TypeDesc (i.e. not to a reference array type, variable type etc.)
611     // then we must be trying to cast to a class or interface type.
612     if (!toType.IsTypeDesc())
613     {
614         if (!IsArray())
615         {
616             // I am a variable type, pointer type, function pointer type
617             // etc.  I am not an object or value type.  Therefore
618             // I can't be cast to an object or value type.
619             return TypeHandle::CannotCast;
620         }
621
622         MethodTable *pMT = GetMethodTable();
623         _ASSERTE(pMT != 0);
624
625         // This does the right thing if 'type' == System.Array or System.Object, System.Clonable ...
626         return pMT->CanCastToClassOrInterfaceNoGC(toType.AsMethodTable());
627     }
628
629     TypeDesc* toTypeDesc = toType.AsTypeDesc();
630
631     CorElementType toKind = toTypeDesc->GetInternalCorElementType();
632     CorElementType fromKind = GetInternalCorElementType();
633
634     // The element kinds must match, only exception is that SZARRAY matches a one dimension ARRAY
635     if (!(toKind == fromKind || (toKind == ELEMENT_TYPE_ARRAY && fromKind == ELEMENT_TYPE_SZARRAY)))
636         return TypeHandle::CannotCast;
637
638     switch (toKind)
639     {
640     case ELEMENT_TYPE_ARRAY:
641         if (dac_cast<PTR_ArrayTypeDesc>(this)->GetRank() != dac_cast<PTR_ArrayTypeDesc>(toTypeDesc)->GetRank())
642             return TypeHandle::CannotCast;
643         // fall through
644     case ELEMENT_TYPE_SZARRAY:
645     case ELEMENT_TYPE_BYREF:
646     case ELEMENT_TYPE_PTR:
647         return TypeDesc::CanCastParamNoGC(dac_cast<PTR_ParamTypeDesc>(this)->GetTypeParam(), dac_cast<PTR_ParamTypeDesc>(toTypeDesc)->GetTypeParam());
648
649     case ELEMENT_TYPE_VAR:
650     case ELEMENT_TYPE_MVAR:
651     case ELEMENT_TYPE_FNPTR:
652         return TypeHandle::CannotCast;
653
654     default:
655         BAD_FORMAT_NOTHROW_ASSERT(toKind == ELEMENT_TYPE_TYPEDBYREF || CorTypeInfo::IsPrimitiveType_NoThrow(toKind));
656         return TypeHandle::CanCast;
657     }
658 }
659
660 TypeHandle::CastResult TypeDesc::CanCastParamNoGC(TypeHandle fromParam, TypeHandle toParam)
661 {
662     CONTRACTL
663     {
664         NOTHROW;
665         GC_NOTRIGGER;
666         FORBID_FAULT;
667         SO_TOLERANT;
668     }
669     CONTRACTL_END
670
671         // While boxed value classes inherit from object their
672         // unboxed versions do not.  Parameterized types have the
673         // unboxed version, thus, if the from type parameter is value
674         // class then only an exact match works.
675     if (fromParam == toParam)
676         return TypeHandle::CanCast;
677
678         // Object parameters dont need an exact match but only inheritance, check for that
679     CorElementType fromParamCorType = fromParam.GetVerifierCorElementType();
680     if (CorTypeInfo::IsObjRef_NoThrow(fromParamCorType))
681     {
682         return fromParam.CanCastToNoGC(toParam);
683     }
684     else if (CorTypeInfo::IsGenericVariable_NoThrow(fromParamCorType))
685     {
686         TypeVarTypeDesc* varFromParam = fromParam.AsGenericVariable();
687             
688         if (!varFromParam->ConstraintsLoaded())
689             return TypeHandle::MaybeCast;
690
691         if (!varFromParam->ConstrainedAsObjRef())
692             return TypeHandle::CannotCast;
693             
694         return fromParam.CanCastToNoGC(toParam);
695     }
696     else if (CorTypeInfo::IsPrimitiveType_NoThrow(fromParamCorType))
697     {
698         CorElementType toParamCorType = toParam.GetVerifierCorElementType();
699         if(CorTypeInfo::IsPrimitiveType_NoThrow(toParamCorType))
700         {
701             if (toParamCorType == fromParamCorType)
702                 return TypeHandle::CanCast;
703
704             // Primitive types such as E_T_I4 and E_T_U4 are interchangeable
705             // Enums with interchangeable underlying types are interchangable
706             // BOOL is NOT interchangeable with I1/U1, neither CHAR -- with I2/U2
707             if((toParamCorType != ELEMENT_TYPE_BOOLEAN)
708                 &&(fromParamCorType != ELEMENT_TYPE_BOOLEAN)
709                 &&(toParamCorType != ELEMENT_TYPE_CHAR)
710                 &&(fromParamCorType != ELEMENT_TYPE_CHAR))
711             {
712                 if ((CorTypeInfo::Size_NoThrow(toParamCorType) == CorTypeInfo::Size_NoThrow(fromParamCorType))
713                     && (CorTypeInfo::IsFloat_NoThrow(toParamCorType) == CorTypeInfo::IsFloat_NoThrow(fromParamCorType)))
714                 {
715                     return TypeHandle::CanCast;
716                 }
717             }
718         } // end if(CorTypeInfo::IsPrimitiveType(toParamCorType))
719     } // end if(CorTypeInfo::IsPrimitiveType(fromParamCorType)) 
720     else
721     {
722         // Types with equivalence need the slow path
723         MethodTable * pFromMT = fromParam.GetMethodTable();
724         if (pFromMT != NULL && pFromMT->HasTypeEquivalence())
725             return TypeHandle::MaybeCast;
726         MethodTable * pToMT = toParam.GetMethodTable();
727         if (pToMT != NULL && pToMT->HasTypeEquivalence())
728             return TypeHandle::MaybeCast;
729     }
730
731     // Anything else is not a match.
732     return TypeHandle::CannotCast;
733 }
734
735 BOOL TypeDesc::IsEquivalentTo(TypeHandle type COMMA_INDEBUG(TypeHandlePairList *pVisited))
736 {
737     CONTRACTL
738     {
739         THROWS;
740         GC_TRIGGERS;
741         MODE_ANY;
742         SO_TOLERANT;
743     }
744     CONTRACTL_END;
745
746     if (TypeHandle(this) == type)
747         return TRUE;
748
749     if (!type.IsTypeDesc())
750         return FALSE;
751
752     TypeDesc *pOther = type.AsTypeDesc();
753
754     // bail early for normal types
755     if (!HasTypeEquivalence() || !pOther->HasTypeEquivalence())
756         return FALSE;
757
758     // if the TypeDesc types are different, then they are not equivalent
759     if (GetInternalCorElementType() != pOther->GetInternalCorElementType())
760         return FALSE;
761         
762     if (HasTypeParam())
763     {
764         // pointer, byref, array
765
766         // Arrays must have the same rank.
767         if (IsArray())
768         {
769             ArrayTypeDesc *pThisArray = (ArrayTypeDesc *)this;
770             ArrayTypeDesc *pOtherArray = (ArrayTypeDesc *)pOther;
771             if (pThisArray->GetRank() != pOtherArray->GetRank())
772                 return FALSE;
773         }
774
775         return GetTypeParam().IsEquivalentTo(pOther->GetTypeParam() COMMA_INDEBUG(pVisited));
776     }
777
778     // var, mvar, fnptr
779     return FALSE;
780 }
781 #endif // #ifndef DACCESS_COMPILE
782
783
784
785 TypeHandle TypeDesc::GetParent() {
786
787     STATIC_CONTRACT_NOTHROW;
788     STATIC_CONTRACT_GC_NOTRIGGER;
789     STATIC_CONTRACT_FORBID_FAULT;
790
791     CorElementType kind = GetInternalCorElementType();
792     if (CorTypeInfo::IsArray_NoThrow(kind)) {
793         _ASSERTE(IsArray());
794         BAD_FORMAT_NOTHROW_ASSERT(kind == ELEMENT_TYPE_SZARRAY || kind == ELEMENT_TYPE_ARRAY);
795         return ((ArrayTypeDesc*)this)->GetParent();
796     }
797     if (CorTypeInfo::IsPrimitiveType_NoThrow(kind))
798         return (MethodTable*)g_pObjectClass;
799     return TypeHandle();
800 }
801
802 #ifndef DACCESS_COMPILE
803
804 #ifndef CROSSGEN_COMPILE
805 OBJECTREF ParamTypeDesc::GetManagedClassObject()
806 {
807     CONTRACTL {
808         THROWS;
809         GC_TRIGGERS;
810         MODE_COOPERATIVE;
811
812         INJECT_FAULT(COMPlusThrowOM());
813
814         PRECONDITION(GetInternalCorElementType() == ELEMENT_TYPE_ARRAY ||
815                      GetInternalCorElementType() == ELEMENT_TYPE_SZARRAY ||
816                      GetInternalCorElementType() == ELEMENT_TYPE_BYREF ||
817                      GetInternalCorElementType() == ELEMENT_TYPE_PTR);
818     }
819     CONTRACTL_END;
820
821     if (m_hExposedClassObject == NULL) {
822         REFLECTCLASSBASEREF  refClass = NULL;
823         GCPROTECT_BEGIN(refClass);
824         if (GetAssembly()->IsIntrospectionOnly())
825             refClass = (REFLECTCLASSBASEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__CLASS_INTROSPECTION_ONLY));
826         else
827             refClass = (REFLECTCLASSBASEREF) AllocateObject(g_pRuntimeTypeClass);
828
829         LoaderAllocator *pLoaderAllocator = GetLoaderAllocator();
830         TypeHandle th = TypeHandle(this);
831         ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetType(th);
832         ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetKeepAlive(pLoaderAllocator->GetExposedObject());
833
834         // Let all threads fight over who wins using InterlockedCompareExchange.
835         // Only the winner can set m_hExposedClassObject from NULL.
836         LOADERHANDLE hExposedClassObject = pLoaderAllocator->AllocateHandle(refClass);
837
838         EnsureWritablePages(this);
839         if (FastInterlockCompareExchangePointer(&m_hExposedClassObject, hExposedClassObject, static_cast<LOADERHANDLE>(NULL)))
840         {
841             pLoaderAllocator->ClearHandle(hExposedClassObject);
842         }
843
844         if (OwnsTemplateMethodTable())
845         {
846             // Set the handle on template methodtable as well to make Object.GetType for arrays take the fast path
847             EnsureWritablePages(GetTemplateMethodTableInternal()->GetWriteableDataForWrite())->m_hExposedClassObject = m_hExposedClassObject;
848         }
849
850         // Log the TypeVarTypeDesc access
851         g_IBCLogger.LogTypeMethodTableWriteableAccess(&th);
852
853         GCPROTECT_END();
854     }
855     return GetManagedClassObjectIfExists();
856 }
857 #endif // CROSSGEN_COMPILE
858
859 #endif // #ifndef DACCESS_COMPILE
860
861 BOOL TypeDesc::IsRestored()
862 {
863     STATIC_CONTRACT_NOTHROW;
864     STATIC_CONTRACT_GC_NOTRIGGER;
865     STATIC_CONTRACT_FORBID_FAULT;
866     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
867     SUPPORTS_DAC;
868
869     TypeHandle th = TypeHandle(this);
870     g_IBCLogger.LogTypeMethodTableAccess(&th);
871     return IsRestored_NoLogging();
872 }
873
874 BOOL TypeDesc::IsRestored_NoLogging()
875 {
876     STATIC_CONTRACT_NOTHROW;
877     STATIC_CONTRACT_GC_NOTRIGGER;
878     STATIC_CONTRACT_FORBID_FAULT;
879     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
880     SUPPORTS_DAC;
881
882     return (m_typeAndFlags & TypeDesc::enum_flag_Unrestored) == 0;
883 }
884
885 ClassLoadLevel TypeDesc::GetLoadLevel()
886 {
887     STATIC_CONTRACT_NOTHROW;
888     STATIC_CONTRACT_GC_NOTRIGGER;
889     STATIC_CONTRACT_FORBID_FAULT;
890     SUPPORTS_DAC;
891
892     if (m_typeAndFlags & TypeDesc::enum_flag_UnrestoredTypeKey)
893     {
894         return CLASS_LOAD_UNRESTOREDTYPEKEY;
895     }
896     else if (m_typeAndFlags & TypeDesc::enum_flag_Unrestored)
897     {
898         return CLASS_LOAD_UNRESTORED;
899     }
900     else if (m_typeAndFlags & TypeDesc::enum_flag_IsNotFullyLoaded)
901     {
902         if (m_typeAndFlags & TypeDesc::enum_flag_DependenciesLoaded)
903         {
904             return CLASS_DEPENDENCIES_LOADED;
905         }
906         else
907         {
908             return CLASS_LOAD_EXACTPARENTS;
909         }
910     }
911
912     return CLASS_LOADED;
913 }
914
915
916 // Recursive worker that pumps the transitive closure of a type's dependencies to the specified target level.
917 // Dependencies include:
918 //
919 //   - parent
920 //   - interfaces
921 //   - canonical type, for non-canonical instantiations
922 //   - typical type, for non-typical instantiations
923 //
924 // Parameters:
925 //
926 //   pVisited - used to prevent endless recursion in the case of cyclic dependencies
927 //
928 //   level    - target level to pump to - must be CLASS_DEPENDENCIES_LOADED or CLASS_LOADED
929 //
930 //              if CLASS_DEPENDENCIES_LOADED, all transitive dependencies are resolved to their
931 //                 exact types.
932 //
933 //              if CLASS_LOADED, all type-safety checks are done on the type and all its transitive
934 //                 dependencies. Note that for the CLASS_LOADED case, some types may be left
935 //                 on the pending list rather that pushed to CLASS_LOADED in the case of cyclic
936 //                 dependencies - the root caller must handle this.
937 //
938 //
939 //   pfBailed - if we or one of our depedencies bails early due to cyclic dependencies, we
940 //              must set *pfBailed to TRUE. Otherwise, we must *leave it unchanged* (thus, the
941 //              boolean acts as a cumulative OR.)
942 //
943 //   pPending - if one of our dependencies bailed, the type cannot yet be promoted to CLASS_LOADED
944 //              as the dependencies will be checked later and may fail a security check then.
945 //              Instead, DoFullyLoad() will add the type to the pending list - the root caller
946 //              is responsible for promoting the type after the full transitive closure has been
947 //              walked. Note that it would be just as correct to always defer to the pending list -
948 //              however, that is a little less performant.
949 //              
950 //  pInstContext - instantiation context created in code:SigPointer.GetTypeHandleThrowing and ultimately
951 //                 passed down to code:TypeVarTypeDesc.SatisfiesConstraints.
952 //
953 void TypeDesc::DoFullyLoad(Generics::RecursionGraph *pVisited, ClassLoadLevel level,
954                            DFLPendingList *pPending, BOOL *pfBailed, const InstantiationContext *pInstContext)
955 {
956     CONTRACTL
957     {
958         THROWS;
959         GC_TRIGGERS;
960     }
961     CONTRACTL_END
962
963     _ASSERTE(level == CLASS_LOADED || level == CLASS_DEPENDENCIES_LOADED);
964     _ASSERTE(pfBailed != NULL);
965     _ASSERTE(!(level == CLASS_LOADED && pPending == NULL));
966
967
968 #ifndef DACCESS_COMPILE
969
970     if (Generics::RecursionGraph::HasSeenType(pVisited, TypeHandle(this)))
971     {
972         *pfBailed = TRUE;
973         return;
974     }
975
976     if (GetLoadLevel() >= level)
977     {
978         return;
979     }
980
981     if (level == CLASS_LOADED)
982     {
983         UINT numTH = pPending->Count();
984         TypeHandle *pTypeHndPending = pPending->Table();
985         for (UINT idxPending = 0; idxPending < numTH; idxPending++)
986         {
987             if (pTypeHndPending[idxPending].IsTypeDesc() && pTypeHndPending[idxPending].AsTypeDesc() == this)
988             {
989                 *pfBailed = TRUE;
990                 return;
991             }
992         }
993
994     }
995
996
997     BOOL fBailed = FALSE;
998
999     // First ensure that we're loaded to just below CLASS_LOADED
1000     ClassLoader::EnsureLoaded(TypeHandle(this), (ClassLoadLevel) (level-1));
1001     
1002     Generics::RecursionGraph newVisited(pVisited, TypeHandle(this));
1003
1004     if (HasTypeParam())
1005     {
1006         // Fully load the type parameter
1007         GetTypeParam().DoFullyLoad(&newVisited, level, pPending, &fBailed, pInstContext);
1008
1009         ParamTypeDesc* pPTD = (ParamTypeDesc*) this;
1010
1011         // Fully load the template method table
1012         if (!pPTD->m_TemplateMT.IsNull())
1013         {
1014             pPTD->GetTemplateMethodTableInternal()->DoFullyLoad(&newVisited, level, pPending, &fBailed, pInstContext);
1015         }
1016     }
1017
1018     switch (level)
1019     {
1020         case CLASS_DEPENDENCIES_LOADED:
1021             FastInterlockOr(&m_typeAndFlags, TypeDesc::enum_flag_DependenciesLoaded);
1022             break;
1023
1024         case CLASS_LOADED:
1025             if (fBailed)
1026             {
1027                 // We couldn't complete security checks on some dependency because he is already being processed by one of our callers.
1028                 // Do not mark this class fully loaded yet. Put him on the pending list and he will be marked fully loaded when
1029                 // everything unwinds.
1030
1031                 *pfBailed = TRUE;
1032
1033                 TypeHandle* pthPending = pPending->AppendThrowing();
1034                 *pthPending = TypeHandle(this);
1035             }
1036             else
1037             {
1038                 // Finally, mark this method table as fully loaded
1039                 SetIsFullyLoaded();
1040             }
1041             break;
1042
1043         default:
1044             _ASSERTE(!"Can't get here.");
1045             break;
1046     }
1047 #endif
1048 }
1049
1050
1051 #ifdef FEATURE_PREJIT
1052 void TypeDesc::DoRestoreTypeKey()
1053 {
1054     CONTRACTL
1055     {
1056         THROWS;
1057         GC_TRIGGERS;
1058     }
1059     CONTRACTL_END
1060
1061 #ifndef DACCESS_COMPILE
1062     if (HasTypeParam())
1063     {
1064         ParamTypeDesc* pPTD = (ParamTypeDesc*) this;
1065         EnsureWritablePages(pPTD);
1066
1067         // Must have the same loader module, so not encoded
1068         CONSISTENCY_CHECK(!pPTD->m_Arg.IsEncodedFixup());
1069         ClassLoader::EnsureLoaded(pPTD->m_Arg, CLASS_LOAD_UNRESTORED);
1070
1071         // Might live somewhere else e.g. Object[] is shared across all ref array types
1072         Module::RestoreMethodTablePointer(&(pPTD->m_TemplateMT), NULL, CLASS_LOAD_UNRESTORED);
1073     }
1074     else
1075     {
1076         EnsureWritablePages(this);
1077     }
1078
1079     FastInterlockAnd(&m_typeAndFlags, ~TypeDesc::enum_flag_UnrestoredTypeKey);
1080 #endif
1081 }
1082
1083 #ifndef DACCESS_COMPILE
1084
1085 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
1086 // This just performs a shallow save
1087 void TypeDesc::Save(DataImage *image)
1088 {
1089     STANDARD_VM_CONTRACT;
1090
1091     ClassLoader::EnsureLoaded(TypeHandle(this));
1092
1093     if (LoggingOn(LF_ZAP, LL_INFO10000))
1094     {
1095         StackSString name;
1096         TypeString::AppendType(name, TypeHandle(this));
1097         LOG((LF_ZAP, LL_INFO10000, "TypeDesc::Save %S\n", name.GetUnicode()));
1098     }
1099
1100     if (IsGenericVariable())
1101     {
1102         ((TypeVarTypeDesc*)this)->Save(image);
1103     }
1104     else if (GetInternalCorElementType() == ELEMENT_TYPE_FNPTR)
1105     {
1106         ((FnPtrTypeDesc *)this)->Save(image);
1107     }
1108     else
1109     {
1110         _ASSERTE(HasTypeParam());
1111         ((ParamTypeDesc*)this)->Save(image);
1112     }
1113
1114 }
1115
1116 void TypeDesc::Fixup(DataImage *image)
1117 {
1118     STANDARD_VM_CONTRACT;
1119
1120     if (IsGenericVariable())
1121     {
1122         TypeVarTypeDesc* tyvar = (TypeVarTypeDesc*) this;
1123         tyvar->Fixup(image);
1124     }
1125     else if (GetInternalCorElementType() == ELEMENT_TYPE_FNPTR)
1126     {
1127         ((FnPtrTypeDesc*)this)->Fixup(image);
1128     }
1129     else
1130     {
1131         // Works for array and PTR/BYREF types, but not function pointers
1132         _ASSERTE(HasTypeParam());
1133         
1134         if (IsArray())
1135         {
1136             ((ArrayTypeDesc*) this)->Fixup(image);
1137         }
1138         else
1139         {
1140             ((ParamTypeDesc*) this)->Fixup(image);
1141         }
1142     }
1143
1144     if (NeedsRestore(image))
1145     {
1146         TypeDesc *pTD = (TypeDesc*) image->GetImagePointer(this);
1147         _ASSERTE(pTD != NULL);        
1148         pTD->m_typeAndFlags |= TypeDesc::enum_flag_Unrestored | TypeDesc::enum_flag_UnrestoredTypeKey | TypeDesc::enum_flag_IsNotFullyLoaded;
1149     }
1150
1151 }
1152
1153 BOOL TypeDesc::ComputeNeedsRestore(DataImage *image, TypeHandleList *pVisited)
1154 {
1155     STATIC_STANDARD_VM_CONTRACT;
1156
1157     _ASSERTE(GetAppDomain()->IsCompilationDomain());
1158
1159     if (HasTypeParam())
1160     {
1161         return dac_cast<PTR_ParamTypeDesc>(this)->ComputeNeedsRestore(image, pVisited);
1162     }
1163     else
1164         return FALSE;
1165 }
1166
1167
1168
1169 void ParamTypeDesc::Save(DataImage *image)
1170 {
1171     STANDARD_VM_CONTRACT;
1172
1173     if (IsArray())
1174     {
1175         image->StoreStructure(this, sizeof(ArrayTypeDesc), DataImage::ITEM_ARRAY_TYPEDESC);
1176     }
1177     else
1178     {
1179         image->StoreStructure(this, sizeof(ParamTypeDesc), DataImage::ITEM_PARAM_TYPEDESC);
1180     }
1181
1182     // This set of checks matches precisely those in Module::CreateArrayMethodTable
1183     // and ParamTypeDesc::ComputeNeedsRestore
1184     //
1185     // They indicate if an array TypeDesc is non-canonical (in much the same a a generic
1186     // method table being non-canonical), i.e. it is not the primary
1187     // owner of the m_TemplateMT (the primary owner is the TypeDesc for object[])
1188     //
1189     if (OwnsTemplateMethodTable())
1190     {
1191         // This TypeDesc should be the only one saving this MT
1192         _ASSERTE(!image->IsStored(GetTemplateMethodTableInternal()));
1193         Module::SaveMethodTable(image, GetTemplateMethodTableInternal(), 0);
1194     }
1195
1196 }
1197
1198
1199 void ParamTypeDesc::Fixup(DataImage *image)
1200 {
1201     STANDARD_VM_CONTRACT;
1202
1203     _ASSERTE(image->GetModule()->GetAssembly() ==
1204              GetAppDomain()->ToCompilationDomain()->GetTargetAssembly());
1205
1206     if (LoggingOn(LF_ZAP, LL_INFO10000))
1207     {
1208         StackSString name;
1209         TypeString::AppendType(name, TypeHandle(this));
1210         LOG((LF_ZAP, LL_INFO10000, "ParamTypeDesc::Fixup %S\n", name.GetUnicode()));
1211     }
1212
1213     if (!m_TemplateMT.IsNull())
1214     {
1215         if (OwnsTemplateMethodTable())
1216         {
1217             // In all other cases the type desc "owns" the m_TemplateMT
1218             // and it is always stored in the same module as the TypeDesc (i.e. the
1219             // TypeDesc and the MT are "tightly-knit") In other words if one is present in
1220             // an NGEN image then then other will be, and if one is "used" at runtime then
1221             // the other will be too.
1222             image->FixupMethodTablePointer(this, &m_TemplateMT);
1223             GetTemplateMethodTableInternal()->Fixup(image);
1224         }
1225         else
1226         {
1227             // Fixup the pointer to the possibly-shared m_TemplateMT. This might be in a different module.
1228             image->FixupMethodTablePointer(this, &m_TemplateMT);
1229         }
1230     }
1231
1232     // Fixup the pointer to the element type.
1233     image->HardBindTypeHandlePointer(this, offsetof(ParamTypeDesc, m_Arg));
1234
1235     // The managed object will get regenerated on demand
1236     image->ZeroField(this, offsetof(ParamTypeDesc, m_hExposedClassObject), sizeof(m_hExposedClassObject));
1237 }
1238
1239 void ArrayTypeDesc::Fixup(DataImage *image)
1240 {
1241     STANDARD_VM_CONTRACT;
1242
1243     ParamTypeDesc::Fixup(image);
1244
1245 #ifdef FEATURE_COMINTEROP
1246     // We don't save CCW templates into ngen images
1247     image->ZeroField(this, offsetof(ArrayTypeDesc, m_pCCWTemplate), sizeof(m_pCCWTemplate));
1248 #endif // FEATURE_COMINTEROP
1249 }
1250
1251 BOOL ParamTypeDesc::ComputeNeedsRestore(DataImage *image, TypeHandleList *pVisited)
1252 {
1253     STATIC_STANDARD_VM_CONTRACT;
1254
1255     _ASSERTE(GetAppDomain()->IsCompilationDomain());
1256
1257     if (m_typeAndFlags & TypeDesc::enum_flag_NeedsRestore)
1258     {
1259         return TRUE;
1260     }
1261     if (m_typeAndFlags & TypeDesc::enum_flag_PreRestored)
1262     {
1263         return FALSE;
1264     }
1265
1266     BOOL res = FALSE;
1267     if (!image->CanPrerestoreEagerBindToTypeHandle(m_Arg, pVisited))
1268     {
1269         res = TRUE;
1270     }
1271
1272     // This set of checks matches precisely those in Module::CreateArrayMethodTable and ParamTypeDesc::Fixup
1273     //
1274     if (!m_TemplateMT.IsNull())
1275     { 
1276         if (OwnsTemplateMethodTable())
1277         {
1278             if (GetTemplateMethodTableInternal()->ComputeNeedsRestore(image, pVisited))
1279             {
1280                 res = TRUE;
1281             }
1282         }
1283         else
1284         {
1285             if (!image->CanPrerestoreEagerBindToMethodTable(GetTemplateMethodTableInternal(), pVisited))
1286             {
1287                 res = TRUE;
1288             }
1289         }
1290     }
1291
1292     // Cache the results of running the algorithm.
1293     // We can only cache the result if we have not speculatively assumed
1294     // that any types are not NeedsRestore, i.e. the visited list is empty
1295     if (pVisited == NULL)
1296     {
1297         if (LoggingOn(LF_ZAP, LL_INFO10000))
1298         {
1299             StackSString name;
1300             TypeString::AppendType(name, TypeHandle(this));
1301             LOG((LF_ZAP, LL_INFO10000, "ParamTypeDesc::ComputeNeedsRestore=%d for %S\n", res, name.GetUnicode()));
1302         }
1303         m_typeAndFlags |= (res ? TypeDesc::enum_flag_NeedsRestore : TypeDesc::enum_flag_PreRestored);
1304     }
1305     return res;
1306 }
1307 #endif // FEATURE_NATIVE_IMAGE_GENERATION
1308
1309 void TypeDesc::SetIsRestored()
1310 {
1311     STATIC_CONTRACT_THROWS;
1312     STATIC_CONTRACT_GC_NOTRIGGER;
1313     STATIC_CONTRACT_FORBID_FAULT;
1314     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
1315
1316     TypeHandle th = TypeHandle(this);
1317     FastInterlockAnd(EnsureWritablePages(&m_typeAndFlags), ~TypeDesc::enum_flag_Unrestored);
1318 }
1319
1320 #endif // #ifndef DACCESS_COMPILE
1321
1322 void TypeDesc::Restore()
1323 {
1324     CONTRACTL
1325     {
1326         THROWS;
1327         GC_TRIGGERS;
1328         INJECT_FAULT(COMPlusThrowOM(););
1329         CONSISTENCY_CHECK(!HasUnrestoredTypeKey());
1330     }
1331     CONTRACTL_END;
1332
1333 #ifndef DACCESS_COMPILE
1334     if (HasTypeParam())
1335     {
1336         ParamTypeDesc *pPTD = dac_cast<PTR_ParamTypeDesc>(this);
1337
1338         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_EXACTPARENTS);
1339
1340         // Must have the same loader module
1341         ClassLoader::EnsureLoaded(pPTD->m_Arg, CLASS_LOAD_EXACTPARENTS);
1342
1343         // Method-table pointer must have been restored by DoRestoreTypeKey
1344         Module::RestoreMethodTablePointer(&pPTD->m_TemplateMT, NULL, CLASS_LOAD_EXACTPARENTS);
1345     }
1346
1347     SetIsRestored();
1348 #else
1349     DacNotImpl();
1350 #endif // #ifndef DACCESS_COMPILE
1351 }
1352
1353 #endif // FEATURE_PREJIT
1354
1355
1356 #ifndef DACCESS_COMPILE
1357
1358 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
1359 void TypeVarTypeDesc::Save(DataImage *image)
1360 {
1361     STANDARD_VM_CONTRACT;
1362
1363     // We don't persist the constraints: instead, load them back on demand
1364     m_numConstraints = (DWORD) -1;
1365
1366     LOG((LF_ZAP, LL_INFO10000, "  TypeVarTypeDesc::Save %x (%p)\n", GetToken(), this));
1367     image->StoreStructure(this, sizeof(TypeVarTypeDesc),
1368                                     DataImage::ITEM_TYVAR_TYPEDESC);
1369 }
1370
1371 void TypeVarTypeDesc::Fixup(DataImage *image)
1372 {
1373     STANDARD_VM_CONTRACT;
1374
1375     LOG((LF_ZAP, LL_INFO10000, "  TypeVarTypeDesc::Fixup %x (%p)\n", GetToken(), this));
1376     image->FixupRelativePointerField(this, offsetof(TypeVarTypeDesc, m_pModule));
1377     image->ZeroField(this, offsetof(TypeVarTypeDesc, m_hExposedClassObject), sizeof(m_hExposedClassObject));
1378
1379     // We don't persist the constraints: instead, load them back on demand
1380     image->ZeroPointerField(this, offsetof(TypeVarTypeDesc, m_constraints));
1381
1382 }
1383 #endif // FEATURE_NATIVE_IMAGE_GENERATION
1384
1385 MethodDesc * TypeVarTypeDesc::LoadOwnerMethod()
1386 {
1387     CONTRACTL
1388     {
1389         THROWS;
1390         GC_TRIGGERS;
1391         MODE_ANY;
1392
1393         PRECONDITION(TypeFromToken(m_typeOrMethodDef) == mdtMethodDef);
1394     }
1395     CONTRACTL_END;
1396
1397     MethodDesc *pMD = GetModule()->LookupMethodDef(m_typeOrMethodDef);
1398     if (pMD == NULL)
1399     {
1400         pMD = MemberLoader::GetMethodDescFromMethodDef(GetModule(), m_typeOrMethodDef, FALSE);
1401     }
1402     return pMD;
1403 }
1404
1405 TypeHandle TypeVarTypeDesc::LoadOwnerType()
1406 {
1407     CONTRACTL
1408     {
1409         THROWS;
1410         GC_TRIGGERS;
1411         MODE_ANY;
1412
1413         PRECONDITION(TypeFromToken(m_typeOrMethodDef) == mdtTypeDef);
1414     }
1415     CONTRACTL_END;
1416
1417     TypeHandle genericType = GetModule()->LookupTypeDef(m_typeOrMethodDef);
1418     if (genericType.IsNull())
1419     {
1420         genericType = ClassLoader::LoadTypeDefThrowing(GetModule(), m_typeOrMethodDef,
1421             ClassLoader::ThrowIfNotFound,
1422             ClassLoader::PermitUninstDefOrRef);
1423     }
1424     return genericType;
1425 }
1426
1427 TypeHandle* TypeVarTypeDesc::GetCachedConstraints(DWORD *pNumConstraints)
1428 {
1429     LIMITED_METHOD_CONTRACT;
1430     PRECONDITION(CheckPointer(pNumConstraints));
1431     PRECONDITION(m_numConstraints != (DWORD) -1);
1432
1433     *pNumConstraints = m_numConstraints;
1434     return m_constraints;
1435 }
1436
1437
1438
1439
1440 TypeHandle* TypeVarTypeDesc::GetConstraints(DWORD *pNumConstraints, ClassLoadLevel level /* = CLASS_LOADED */)
1441 {
1442     WRAPPER_NO_CONTRACT;
1443     PRECONDITION(CheckPointer(pNumConstraints));
1444     PRECONDITION(level == CLASS_DEPENDENCIES_LOADED || level == CLASS_LOADED);
1445
1446     if (m_numConstraints == (DWORD) -1)
1447         LoadConstraints(level);
1448
1449     *pNumConstraints = m_numConstraints;
1450     return m_constraints;
1451 }
1452
1453
1454 void TypeVarTypeDesc::LoadConstraints(ClassLoadLevel level /* = CLASS_LOADED */)
1455 {
1456     CONTRACTL
1457     {
1458         THROWS;
1459         GC_TRIGGERS;
1460         MODE_ANY;
1461
1462         INJECT_FAULT(COMPlusThrowOM());
1463
1464         PRECONDITION(level == CLASS_DEPENDENCIES_LOADED || level == CLASS_LOADED);
1465     }
1466     CONTRACTL_END;
1467
1468     _ASSERTE(((INT_PTR)&m_constraints) % sizeof(m_constraints) == 0);
1469     _ASSERTE(((INT_PTR)&m_numConstraints) % sizeof(m_numConstraints) == 0);
1470
1471     DWORD numConstraints = m_numConstraints;
1472
1473     if (numConstraints == (DWORD) -1)
1474     {
1475         EnsureWritablePages(this);
1476
1477         IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
1478
1479         HENUMInternalHolder hEnum(pInternalImport);
1480         mdGenericParamConstraint tkConstraint;
1481
1482         SigTypeContext typeContext;
1483         mdToken defToken = GetTypeOrMethodDef();
1484
1485         MethodTable *pMT = NULL;
1486         if (TypeFromToken(defToken) == mdtMethodDef)
1487         {
1488             MethodDesc *pMD = LoadOwnerMethod();
1489             _ASSERTE(pMD->IsGenericMethodDefinition());
1490             
1491             SigTypeContext::InitTypeContext(pMD,&typeContext);
1492             
1493             _ASSERTE(!typeContext.m_methodInst.IsEmpty());
1494             pMT = pMD->GetMethodTable();
1495         }
1496         else
1497         {
1498             _ASSERTE(TypeFromToken(defToken) == mdtTypeDef);
1499             TypeHandle genericType = LoadOwnerType();
1500             _ASSERTE(genericType.IsGenericTypeDefinition());
1501
1502             SigTypeContext::InitTypeContext(genericType,&typeContext);
1503         }
1504         
1505         hEnum.EnumInit(mdtGenericParamConstraint, GetToken());
1506         numConstraints = pInternalImport->EnumGetCount(&hEnum);
1507         if (numConstraints != 0)
1508         {
1509             LoaderAllocator* pAllocator = GetModule()->GetLoaderAllocator();
1510             // If there is a single class constraint we put in in element 0 of the array
1511             AllocMemHolder<TypeHandle> constraints 
1512                 (pAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(numConstraints) * S_SIZE_T(sizeof(TypeHandle))));
1513
1514             DWORD i = 0;
1515             while (pInternalImport->EnumNext(&hEnum, &tkConstraint))
1516             {
1517                 _ASSERTE(i <= numConstraints);
1518                 mdToken tkConstraintType, tkParam;
1519                 if (FAILED(pInternalImport->GetGenericParamConstraintProps(tkConstraint, &tkParam, &tkConstraintType)))
1520                 {
1521                     GetModule()->GetAssembly()->ThrowTypeLoadException(pInternalImport, pMT->GetCl(), IDS_CLASSLOAD_BADFORMAT);
1522                 }
1523                 _ASSERTE(tkParam == GetToken());
1524                 TypeHandle thConstraint = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(GetModule(), tkConstraintType, 
1525                                                                                       &typeContext, 
1526                                                                                       ClassLoader::ThrowIfNotFound, 
1527                                                                                       ClassLoader::FailIfUninstDefOrRef,
1528                                                                                       ClassLoader::LoadTypes,
1529                                                                                       level);
1530
1531                 constraints[i++] = thConstraint;
1532
1533                 // Method type constraints behave contravariantly
1534                 // (cf Bounded polymorphism e.g. see
1535                 //     Cardelli & Wegner, On understanding types, data abstraction and polymorphism, Computing Surveys 17(4), Dec 1985)                
1536                 if (pMT != NULL && pMT->HasVariance() && TypeFromToken(tkConstraintType) == mdtTypeSpec)
1537                 {
1538                     ULONG cSig;
1539                     PCCOR_SIGNATURE pSig;
1540                     if (FAILED(pInternalImport->GetTypeSpecFromToken(tkConstraintType, &pSig, &cSig)))
1541                     {
1542                         GetModule()->GetAssembly()->ThrowTypeLoadException(pInternalImport, pMT->GetCl(), IDS_CLASSLOAD_BADFORMAT);
1543                     }
1544                     if (!EEClass::CheckVarianceInSig(pMT->GetNumGenericArgs(),
1545                                                      pMT->GetClass()->GetVarianceInfo(), 
1546                                                      pMT->GetModule(),
1547                                                      SigPointer(pSig, cSig),
1548                                                      gpContravariant))
1549                     {
1550                         GetModule()->GetAssembly()->ThrowTypeLoadException(pInternalImport, pMT->GetCl(), IDS_CLASSLOAD_VARIANCE_IN_CONSTRAINT);
1551                     }
1552                 }
1553             }
1554
1555             if (InterlockedCompareExchangeT(&m_constraints, constraints.operator->(), NULL) == NULL)
1556             {
1557                 constraints.SuppressRelease();
1558             }
1559         }
1560         
1561         m_numConstraints = numConstraints;
1562     }
1563
1564     for (DWORD i = 0; i < numConstraints; i++)
1565     {
1566         ClassLoader::EnsureLoaded(m_constraints[i], level);
1567     }
1568 }
1569
1570 BOOL TypeVarTypeDesc::ConstrainedAsObjRef()
1571 {
1572     CONTRACTL
1573     {
1574         NOTHROW;
1575         GC_NOTRIGGER;
1576         MODE_ANY;
1577         PRECONDITION(ConstraintsLoaded());
1578     }
1579     CONTRACTL_END;
1580     
1581     IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
1582     mdGenericParam genericParamToken = GetToken();
1583     DWORD flags;
1584     if (FAILED(pInternalImport->GetGenericParamProps(genericParamToken, NULL, &flags, NULL, NULL, NULL)))
1585     {
1586         return FALSE;
1587     }
1588     DWORD specialConstraints = flags & gpSpecialConstraintMask;
1589     
1590     if ((specialConstraints & gpReferenceTypeConstraint) != 0)
1591         return TRUE;
1592     
1593     return ConstrainedAsObjRefHelper();
1594 }
1595
1596 // A recursive helper that helps determine whether this variable is constrained as ObjRef.
1597 // Please note that we do not check the gpReferenceTypeConstraint special constraint here
1598 // because this property does not propagate up the constraining hierarchy.
1599 // (e.g. "class A<S, T> where S : T, where T : class" does not guarantee that S is ObjRef)
1600 BOOL TypeVarTypeDesc::ConstrainedAsObjRefHelper()
1601 {
1602     CONTRACTL
1603     {
1604         NOTHROW;
1605         GC_NOTRIGGER;
1606         MODE_ANY;
1607     }
1608     CONTRACTL_END;
1609
1610     DWORD dwNumConstraints = 0;
1611     TypeHandle* constraints = GetCachedConstraints(&dwNumConstraints);
1612
1613     for (DWORD i = 0; i < dwNumConstraints; i++)
1614     {
1615         TypeHandle constraint = constraints[i];
1616
1617         if (constraint.IsGenericVariable() && constraint.AsGenericVariable()->ConstrainedAsObjRefHelper())
1618             return TRUE;
1619         
1620         if (!constraint.IsInterface() && CorTypeInfo::IsObjRef_NoThrow(constraint.GetInternalCorElementType()))
1621         {
1622             // Object, ValueType, and Enum are ObjRefs but they do not constrain the var to ObjRef!
1623             MethodTable *mt = constraint.GetMethodTable();
1624
1625             if (mt != g_pObjectClass &&
1626                 mt != g_pValueTypeClass &&
1627                 mt != g_pEnumClass)
1628             {
1629                 return TRUE;
1630             }
1631         }
1632     }
1633
1634     return FALSE;
1635 }
1636
1637 BOOL TypeVarTypeDesc::ConstrainedAsValueType()
1638 {
1639     CONTRACTL
1640     {
1641         NOTHROW;
1642         GC_NOTRIGGER;
1643         MODE_ANY;
1644         PRECONDITION(ConstraintsLoaded());
1645     }
1646     CONTRACTL_END;
1647     
1648     IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
1649     mdGenericParam genericParamToken = GetToken();
1650     DWORD flags;
1651     if (FAILED(pInternalImport->GetGenericParamProps(genericParamToken, NULL, &flags, NULL, NULL, NULL)))
1652     {
1653         return FALSE;
1654     }
1655     DWORD specialConstraints = flags & gpSpecialConstraintMask;
1656
1657     if ((specialConstraints & gpNotNullableValueTypeConstraint) != 0)
1658         return TRUE;
1659
1660     DWORD dwNumConstraints = 0;
1661     TypeHandle* constraints = GetCachedConstraints(&dwNumConstraints);
1662
1663     for (DWORD i = 0; i < dwNumConstraints; i++)
1664     {
1665         TypeHandle constraint = constraints[i];
1666
1667         if (constraint.IsGenericVariable())
1668         {
1669             if (constraint.AsGenericVariable()->ConstrainedAsValueType())
1670                 return TRUE;
1671         }
1672         else
1673         {
1674             // the following condition will also disqualify interfaces
1675             if (!CorTypeInfo::IsObjRef_NoThrow(constraint.GetInternalCorElementType()))
1676                 return TRUE;
1677         }
1678     }
1679
1680     return FALSE;
1681 }
1682
1683 //---------------------------------------------------------------------------------------------------------------------
1684 // Loads the type of a constraint given the constraint token and instantiation context. If pInstContext is
1685 // not NULL and the constraint's type is a typespec, pInstContext will be used to instantiate the typespec.
1686 // Otherwise typical instantiation is returned if the constraint type is generic.
1687 //---------------------------------------------------------------------------------------------------------------------
1688 static
1689 TypeHandle LoadTypeVarConstraint(TypeVarTypeDesc *pTypeVar, mdGenericParamConstraint tkConstraint,
1690                                  const InstantiationContext *pInstContext)
1691 {
1692     CONTRACTL
1693     {
1694         THROWS;
1695         GC_TRIGGERS;
1696         INJECT_FAULT(COMPlusThrowOM());
1697         MODE_ANY;
1698         PRECONDITION(CheckPointer(pTypeVar));
1699     }
1700     CONTRACTL_END;
1701
1702     Module *pTyModule = pTypeVar->GetModule();
1703     IMDInternalImport* pInternalImport = pTyModule->GetMDImport();
1704
1705     mdToken tkConstraintType, tkParam;
1706     IfFailThrow(pInternalImport->GetGenericParamConstraintProps(tkConstraint, &tkParam, &tkConstraintType));
1707     _ASSERTE(tkParam == pTypeVar->GetToken());
1708     mdToken tkOwnerToken = pTypeVar->GetTypeOrMethodDef();
1709     
1710     if (TypeFromToken(tkConstraintType) == mdtTypeSpec && pInstContext != NULL)
1711     {
1712         if(pInstContext->m_pSubstChain == NULL)
1713         {
1714             // The substitution chain will be null in situations
1715             // where we are instantiating types that are open, and therefore
1716             // we should be using the fully open TypeVar constraint instantiation code
1717             // below. However, in the case of a open method on a closed generic class
1718             // we will also have a null substitution chain. In this case, if we can ensure
1719             // that the instantiation type parameters are non type-var types, it is valid
1720             // to use the passed in instantiation when instantiating the type var constraint.
1721             BOOL fContextContainsValidGenericTypeParams = FALSE;
1722
1723             if (TypeFromToken(tkOwnerToken) == mdtMethodDef)
1724             {
1725                 SigTypeContext sigTypeContext;
1726
1727                 MethodDesc *pMD = pTypeVar->LoadOwnerMethod();
1728
1729                 SigTypeContext::InitTypeContext(pMD, &sigTypeContext);
1730                 fContextContainsValidGenericTypeParams = SigTypeContext::IsValidTypeOnlyInstantiationOf(&sigTypeContext, pInstContext->m_pArgContext);
1731             }
1732
1733             if (!fContextContainsValidGenericTypeParams)
1734                 goto LoadConstraintOnOpenType;
1735         }
1736
1737         // obtain the constraint type's signature if it's a typespec
1738         ULONG cbSig;
1739         PCCOR_SIGNATURE ptr;
1740         
1741         IfFailThrow(pInternalImport->GetSigFromToken(tkConstraintType, &cbSig, &ptr));
1742         
1743         SigPointer pSig(ptr, cbSig);
1744         
1745         // instantiate the signature using the current InstantiationContext
1746         return pSig.GetTypeHandleThrowing(pTyModule,
1747                                           pInstContext->m_pArgContext,
1748                                           ClassLoader::LoadTypes, CLASS_DEPENDENCIES_LOADED, FALSE,
1749                                           pInstContext->m_pSubstChain);
1750     }
1751     else
1752     {
1753 LoadConstraintOnOpenType:
1754
1755         SigTypeContext sigTypeContext;
1756         
1757         switch (TypeFromToken(tkOwnerToken))
1758         {
1759             case mdtTypeDef:
1760             {
1761                 // the type variable is declared by a type - load the handle of the type
1762                 TypeHandle thOwner = pTyModule->GetClassLoader()->LoadTypeDefThrowing(pTyModule,
1763                                                                                       tkOwnerToken,
1764                                                                                       ClassLoader::ThrowIfNotFound,
1765                                                                                       ClassLoader::PermitUninstDefOrRef,
1766                                                                                       tdNoTypes,
1767                                                                                       CLASS_LOAD_APPROXPARENTS
1768                                                                                      );
1769
1770                 SigTypeContext::InitTypeContext(thOwner, &sigTypeContext);
1771                 break;
1772             }
1773
1774             case mdtMethodDef:
1775             {
1776                 // the type variable is declared by a method - load its method desc
1777                 MethodDesc *pMD = pTyModule->LookupMethodDef(tkOwnerToken);
1778
1779                 SigTypeContext::InitTypeContext(pMD, &sigTypeContext);
1780                 break;
1781             }
1782
1783             default:
1784             {
1785                 COMPlusThrow(kBadImageFormatException);
1786             }
1787         }
1788
1789         // load the (typical instantiation of) constraint type
1790         return ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pTyModule,
1791                                                            tkConstraintType,
1792                                                            &sigTypeContext,
1793                                                            ClassLoader::ThrowIfNotFound, 
1794                                                            ClassLoader::FailIfUninstDefOrRef,
1795                                                            ClassLoader::LoadTypes,
1796                                                            CLASS_DEPENDENCIES_LOADED);
1797     }
1798 }
1799
1800 //---------------------------------------------------------------------------------------------------------------------
1801 // We come here only if a type parameter with a special constraint is instantiated by an argument that is itself
1802 // a type parameter. In this case, we'll need to examine *its* constraints to see if the range of types that would satisfy its
1803 // constraints is a subset of the range of types that would satisfy the special constraint.
1804 //
1805 // This routine will return TRUE if it can prove that argument "pTyArg" has a constraint that will satisfy the special constraint.
1806 //
1807 // (NOTE: It does not check against anything other than one specific specialConstraint (it doesn't even know what they are.) This is
1808 // just one step in the checking of constraints.)
1809 //---------------------------------------------------------------------------------------------------------------------
1810 static
1811 BOOL SatisfiesSpecialConstraintRecursive(TypeVarTypeDesc *pTyArg, DWORD specialConstraint, TypeHandleList *pVisitedVars = NULL)
1812 {
1813     CONTRACTL
1814     {
1815         THROWS;
1816         GC_TRIGGERS;
1817         INJECT_FAULT(COMPlusThrowOM());
1818         MODE_ANY;
1819         PRECONDITION(CheckPointer(pTyArg));
1820     }
1821     CONTRACTL_END;
1822
1823     // The caller must invoke for all special constraints that apply - this fcn can only reliably test against one
1824     // constraint at a time.
1825     _ASSERTE(specialConstraint == gpNotNullableValueTypeConstraint
1826           || specialConstraint == gpReferenceTypeConstraint
1827           || specialConstraint == gpDefaultConstructorConstraint);
1828
1829     IMDInternalImport* pInternalImport = pTyArg->GetModule()->GetMDImport();
1830
1831     // Get the argument type's own special constraints
1832     DWORD argFlags;
1833     IfFailThrow(pTyArg->GetModule()->GetMDImport()->GetGenericParamProps(pTyArg->GetToken(), NULL, &argFlags, NULL, NULL, NULL));
1834     
1835     DWORD argSpecialConstraints = argFlags & gpSpecialConstraintMask;
1836
1837     // First, if the argument's own special constraints match the parameter's special constraints,
1838     // we can safely conclude the constraint is satisfied.
1839     switch (specialConstraint)
1840     {
1841         case gpNotNullableValueTypeConstraint:
1842         {
1843             if ((argSpecialConstraints & gpNotNullableValueTypeConstraint) != 0)
1844             {
1845                 return TRUE;
1846             }
1847             break;
1848         }
1849     
1850         case gpReferenceTypeConstraint:
1851         {
1852             // gpReferenceTypeConstraint is not "inherited" so ignore it if pTyArg is a variable
1853             // constraining the argument rather than the argument itself.
1854
1855             if (pVisitedVars == NULL && (argSpecialConstraints & gpReferenceTypeConstraint) != 0)
1856             {
1857                 return TRUE;
1858             }
1859             break;
1860         }
1861  
1862         case gpDefaultConstructorConstraint:
1863         {
1864             // gpDefaultConstructorConstraint is not "inherited" so ignore it if pTyArg is a variable
1865             // constraining the argument rather than the argument itself.
1866
1867             if ((pVisitedVars == NULL && (argSpecialConstraints & gpDefaultConstructorConstraint) != 0) ||
1868                 (argSpecialConstraints & gpNotNullableValueTypeConstraint) != 0)
1869             {
1870                 return TRUE;
1871             }
1872             break;
1873         }
1874     }
1875
1876     // The special constraints did not match. However, we may find a primary type constraint
1877     // that would always satisfy the special constraint.
1878     HENUMInternalHolder hEnum(pInternalImport);
1879     hEnum.EnumInit(mdtGenericParamConstraint, pTyArg->GetToken());
1880
1881     mdGenericParamConstraint tkConstraint;
1882     while (pInternalImport->EnumNext(&hEnum, &tkConstraint))
1883     {
1884         // We pass NULL instantiation context here because when checking for special constraints, it makes
1885         // no difference whether we load a typical (e.g. A<T>) or concrete (e.g. A<string>) instantiation.
1886         TypeHandle thConstraint = LoadTypeVarConstraint(pTyArg, tkConstraint, NULL);
1887
1888         if (thConstraint.IsGenericVariable())
1889         {
1890             // The variable is constrained by another variable, which we need to check recursively. An
1891             // example of why this is necessary follows:
1892             // 
1893             // class A<T> where T : class
1894             // { }
1895             // class B<S, R> : A<S> where S : R where R : EventArgs
1896             // { }
1897             // 
1898             if (!TypeHandleList::Exists(pVisitedVars, thConstraint))
1899             {
1900                 TypeHandleList newVisitedVars(thConstraint, pVisitedVars);
1901                 if (SatisfiesSpecialConstraintRecursive(thConstraint.AsGenericVariable(),
1902                                                         specialConstraint,
1903                                                         &newVisitedVars))
1904                 {
1905                     return TRUE;
1906                 }
1907             }
1908         }
1909         else if (thConstraint.IsInterface())
1910         {
1911             // This is a secondary constraint - this tells us nothing about the eventual instantiation that
1912             // we can use here.
1913         }
1914         else 
1915         {
1916             // This is a type constraint. Remember that the eventual instantiation is only guaranteed to be
1917             // something *derived* from this type, not the actual type itself. To emphasize, we rename the local.
1918
1919             TypeHandle thAncestorOfType = thConstraint;
1920
1921             if (specialConstraint == gpNotNullableValueTypeConstraint)
1922             {
1923                 if (thAncestorOfType.IsValueType() && !(thAncestorOfType.AsMethodTable()->IsNullable()))
1924                 {
1925                     return TRUE;
1926                 }
1927             }
1928             
1929             if (specialConstraint == gpReferenceTypeConstraint)
1930             {
1931
1932                 if (!thAncestorOfType.IsTypeDesc())
1933                 {
1934                     MethodTable *pAncestorMT = thAncestorOfType.AsMethodTable();
1935
1936                     if ((!(pAncestorMT->IsValueType())) && pAncestorMT != g_pObjectClass && pAncestorMT != g_pValueTypeClass)
1937                     {
1938                         // ValueTypes are sealed except when they aren't (cough, cough, System.Enum...). Sigh.
1939                         // Don't put all our trust in IsValueType() here - check the ancestry chain as well.
1940                         BOOL fIsValueTypeAnAncestor = FALSE;
1941                         MethodTable *pParentMT = pAncestorMT->GetParentMethodTable();
1942                         while (pParentMT)
1943                         {
1944                             if (pParentMT == g_pValueTypeClass)
1945                             {
1946                                 fIsValueTypeAnAncestor = TRUE;
1947                                 break;
1948                             }
1949                             pParentMT = pParentMT->GetParentMethodTable();
1950                         }
1951
1952                         if (!fIsValueTypeAnAncestor)
1953                         {
1954                             return TRUE;
1955                         }
1956                     }
1957                 }
1958             }
1959          
1960             if (specialConstraint == gpDefaultConstructorConstraint)
1961             {
1962                 // If a valuetype, just check to ensure that doesn't have a private default ctor.
1963                 // If not a valuetype, not much we can conclude knowing just an ancestor class.
1964                 if (thAncestorOfType.IsValueType() && thAncestorOfType.GetMethodTable()->HasExplicitOrImplicitPublicDefaultConstructor())
1965                 {
1966                     return TRUE;
1967                 }
1968             }
1969             
1970         }
1971     }
1972
1973     // If we got here, we found no evidence that the argument's constraints are strict enough to satisfy the parameter's constraints.
1974     return FALSE;
1975 }
1976
1977 //---------------------------------------------------------------------------------------------------------------------
1978 // Walks the "constraining chain" of a type variable and appends all concrete constraints as well as type vars
1979 // to the provided ArrayList. Upon leaving the function, the list contains all types that the type variable is
1980 // known to be assignable to.
1981 //
1982 // E.g.
1983 // class A<S, T> where S : T, IComparable where T : EventArgs
1984 // {
1985 //     void f<U>(U u) where U : S, IDisposable { }
1986 // }
1987 // This would put 5 types to the U's list: S, T, IDisposable, IComparable, and EventArgs.
1988 //---------------------------------------------------------------------------------------------------------------------
1989 static
1990 void GatherConstraintsRecursive(TypeVarTypeDesc *pTyArg, ArrayList *pArgList, const InstantiationContext *pInstContext,
1991                                 TypeHandleList *pVisitedVars = NULL)
1992 {
1993     CONTRACTL
1994     {
1995         THROWS;
1996         GC_TRIGGERS;
1997         INJECT_FAULT(COMPlusThrowOM());
1998         MODE_ANY;
1999         PRECONDITION(CheckPointer(pTyArg));
2000         PRECONDITION(CheckPointer(pArgList));
2001     }
2002     CONTRACTL_END;
2003
2004     IMDInternalImport* pInternalImport = pTyArg->GetModule()->GetMDImport();
2005
2006     // enumerate constraints of the pTyArg
2007     HENUMInternalHolder hEnum(pInternalImport);
2008     hEnum.EnumInit(mdtGenericParamConstraint, pTyArg->GetToken());
2009
2010     mdGenericParamConstraint tkConstraint;
2011     while (pInternalImport->EnumNext(&hEnum, &tkConstraint))
2012     {
2013         TypeHandle thConstraint = LoadTypeVarConstraint(pTyArg, tkConstraint, pInstContext);
2014
2015         if (thConstraint.IsGenericVariable())
2016         {
2017             // see if it's safe to recursively call ourselves
2018             if (!TypeHandleList::Exists(pVisitedVars, thConstraint))
2019             {
2020                 pArgList->Append(thConstraint.AsPtr());
2021
2022                 TypeHandleList newVisitedVars(thConstraint, pVisitedVars);
2023                 GatherConstraintsRecursive(thConstraint.AsGenericVariable(), pArgList, pInstContext, &newVisitedVars);
2024             }
2025
2026             // Note: circular type parameter constraints will be detected and reported later in
2027             // MethodTable::DoFullyLoad, we just have to avoid SO here.
2028         }
2029         else
2030         {
2031             pArgList->Append(thConstraint.AsPtr());
2032         }
2033     }
2034 }
2035
2036 // pTypeContextOfConstraintDeclarer = type context of the generic type that declares the constraint
2037 //                                    This is needed to load the "X" type when the constraint is the frm
2038 //                                    "where T:X".
2039 //                                    Caution: Do NOT use it to load types or constraints attached to "thArg".
2040 //                                     
2041 // thArg                            = typehandle of the type being substituted for the type parameter.
2042 // 
2043 // pInstContext                     = the instantiation context (type context + substitution chain) to be
2044 //                                    used when loading constraints attached to "thArg".
2045 //
2046 BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstraintDeclarer, TypeHandle thArg,
2047                                            const InstantiationContext *pInstContext/*=NULL*/)
2048 {
2049     CONTRACTL
2050     {
2051         THROWS;
2052         GC_TRIGGERS;
2053         MODE_ANY;
2054
2055         PRECONDITION(!thArg.IsNull());
2056         INJECT_FAULT(COMPlusThrowOM());
2057     }
2058     CONTRACTL_END;
2059
2060     IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
2061     mdGenericParamConstraint tkConstraint;
2062         
2063     INDEBUG(mdToken defToken = GetTypeOrMethodDef());
2064     _ASSERTE(TypeFromToken(defToken) == mdtMethodDef || TypeFromToken(defToken) == mdtTypeDef);
2065
2066     // prepare for the enumeration of this variable's general constraints
2067     mdGenericParam genericParamToken = GetToken();
2068     
2069     HENUMInternalHolder hEnum(pInternalImport);
2070     hEnum.EnumInit(mdtGenericParamConstraint, genericParamToken);
2071
2072     ArrayList argList;
2073
2074     // First check special constraints (must-be-reference-type, must-be-value-type, and must-have-default-constructor)
2075     DWORD flags;
2076     IfFailThrow(pInternalImport->GetGenericParamProps(genericParamToken, NULL, &flags, NULL, NULL, NULL));
2077     
2078     DWORD specialConstraints = flags & gpSpecialConstraintMask;
2079
2080     if (thArg.IsGenericVariable())
2081     {
2082         TypeVarTypeDesc *pTyVar = thArg.AsGenericVariable();
2083
2084         if ((specialConstraints & gpNotNullableValueTypeConstraint) != 0)
2085         {
2086             if (!SatisfiesSpecialConstraintRecursive(pTyVar, gpNotNullableValueTypeConstraint))
2087             {
2088                 return FALSE;
2089             }
2090         }
2091
2092         if ((specialConstraints & gpReferenceTypeConstraint) != 0)
2093         {
2094             if (!SatisfiesSpecialConstraintRecursive(pTyVar, gpReferenceTypeConstraint))
2095             {
2096                 return FALSE;
2097             }
2098         }
2099
2100         if ((specialConstraints & gpDefaultConstructorConstraint) != 0)
2101         {
2102             if (!SatisfiesSpecialConstraintRecursive(pTyVar, gpDefaultConstructorConstraint))
2103             {
2104                 return FALSE;
2105             }
2106         }
2107
2108         if (hEnum.EnumGetCount() == 0)
2109         {
2110             // return immediately if there are no general constraints to satisfy (fast path)
2111             return TRUE;
2112         }
2113
2114         // Now walk the "constraining chain" of type variables and gather all constraint types.
2115         // 
2116         // This work should not be left to code:TypeHandle.CanCastTo because we need typespec constraints
2117         // to be instantiated in pInstContext. If we just do thArg.CanCastTo(thConstraint), it would load
2118         // typical instantiations of the constraints and the can-cast-to check may fail. In addition,
2119         // code:TypeHandle.CanCastTo will SO if the constraints are circular.
2120         // 
2121         // Consider:
2122         // 
2123         // class A<T>
2124         // {
2125         //     void f<U>(B<U, T> b) where U : A<T> { }
2126         // }
2127         // class B<S, R> where S : A<R> { }
2128         // 
2129         // If we load the signature of, say, A<int>.f<U> (concrete class but typical method), and end up
2130         // here verifying that S : A<R> is satisfied by U : A<T>, we must instantiate the constraint type
2131         // A<T> using pInstContext so that it becomes A<int>. Otherwise the constraint check fails.
2132         //  
2133         GatherConstraintsRecursive(pTyVar, &argList, pInstContext);
2134     }
2135     else
2136     {
2137         if ((specialConstraints & gpNotNullableValueTypeConstraint) != 0)
2138         { 
2139             if (!thArg.IsValueType()) 
2140                 return FALSE;
2141             else
2142             {
2143                 // the type argument is a value type, however if it is any kind of Nullable we want to fail
2144                 // as the constraint accepts any value type except Nullable types (Nullable itself is a value type)
2145                 if (thArg.AsMethodTable()->IsNullable())
2146                     return FALSE;
2147             }
2148         }
2149        
2150         if ((specialConstraints & gpReferenceTypeConstraint) != 0)
2151         {
2152             if (thArg.IsValueType())
2153                 return FALSE;
2154         }
2155     
2156         if ((specialConstraints & gpDefaultConstructorConstraint) != 0)
2157         {
2158             if (thArg.IsTypeDesc() || (!thArg.AsMethodTable()->HasExplicitOrImplicitPublicDefaultConstructor()))
2159                 return FALSE;
2160         }
2161     }
2162
2163     // Complete the list by adding thArg itself. If thArg is not a generic variable this will be the only
2164     // item in the list. If it is a generic variable, we need it in the list as well in addition to all the
2165     // constraints gathered by GatherConstraintsRecursive, because e.g. class A<S, T> : where S : T
2166     // can be instantiated using A<U, U>.
2167     argList.Append(thArg.AsPtr());
2168
2169     // At this point argList contains all types that thArg is known to be assignable to. The list may
2170     // contain duplicates and it consists of zero or more type variables, zero or more possibly generic
2171     // interfaces, and at most one possibly generic class.
2172
2173     // Now check general subtype constraints
2174     while (pInternalImport->EnumNext(&hEnum, &tkConstraint))
2175     {
2176         mdToken tkConstraintType, tkParam;
2177         IfFailThrow(pInternalImport->GetGenericParamConstraintProps(tkConstraint, &tkParam, &tkConstraintType));
2178         
2179         _ASSERTE(tkParam == GetToken());
2180         TypeHandle thConstraint = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(GetModule(), 
2181                                                                               tkConstraintType, 
2182                                                                               pTypeContextOfConstraintDeclarer, 
2183                                                                               ClassLoader::ThrowIfNotFound, 
2184                                                                               ClassLoader::FailIfUninstDefOrRef,
2185                                                                               ClassLoader::LoadTypes,
2186                                                                               CLASS_DEPENDENCIES_LOADED);
2187
2188         // System.Object constraint will be always satisfied - even if argList is empty
2189         if (!thConstraint.IsObjectType())
2190         {
2191             BOOL fCanCast = FALSE;
2192             
2193             // loop over all types that we know the arg will be assignable to
2194             ArrayList::Iterator iter = argList.Iterate();
2195             while (iter.Next())  
2196             {
2197                 TypeHandle thElem = TypeHandle::FromPtr(iter.GetElement());
2198
2199                 if (thElem.IsGenericVariable())
2200                 {
2201                     // if a generic variable equals to the constraint, then this constraint will be satisfied
2202                     if (thElem == thConstraint)
2203                     {
2204                         fCanCast = TRUE;
2205                         break;
2206                     }
2207
2208                     // and any variable with the gpNotNullableValueTypeConstraint special constraint
2209                     // satisfies the "derived from System.ValueType" general subtype constraint
2210                     if (thConstraint == g_pValueTypeClass)
2211                     {
2212                         TypeVarTypeDesc *pTyElem = thElem.AsGenericVariable();
2213                         IfFailThrow(pTyElem->GetModule()->GetMDImport()->GetGenericParamProps(
2214                             pTyElem->GetToken(), 
2215                             NULL, 
2216                             &flags, 
2217                             NULL, 
2218                             NULL, 
2219                             NULL));
2220                         
2221                         if ((flags & gpNotNullableValueTypeConstraint) != 0)
2222                         {
2223                             fCanCast = TRUE;
2224                             break;
2225                         }
2226                     }
2227                 }
2228                 else
2229                 {
2230                     // if a concrete type can be cast to the constraint, then this constraint will be satisifed
2231                     if (thElem.CanCastTo(thConstraint))
2232                     {
2233                         fCanCast = TRUE;
2234                         break;
2235                     }
2236                 }
2237             }
2238
2239             if (!fCanCast)
2240                 return FALSE;
2241         }
2242     }      
2243     return TRUE;
2244 }
2245
2246
2247 #ifndef CROSSGEN_COMPILE
2248 OBJECTREF TypeVarTypeDesc::GetManagedClassObject()
2249 {
2250     CONTRACTL {
2251         THROWS;
2252         GC_TRIGGERS;
2253         MODE_COOPERATIVE;
2254
2255         INJECT_FAULT(COMPlusThrowOM());
2256         
2257         PRECONDITION(IsGenericVariable());
2258     }
2259     CONTRACTL_END;
2260             
2261     if (m_hExposedClassObject == NULL) {
2262         REFLECTCLASSBASEREF  refClass = NULL;
2263         GCPROTECT_BEGIN(refClass);
2264         if (GetAssembly()->IsIntrospectionOnly())
2265             refClass = (REFLECTCLASSBASEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__CLASS_INTROSPECTION_ONLY));
2266         else
2267             refClass = (REFLECTCLASSBASEREF) AllocateObject(g_pRuntimeTypeClass);
2268
2269         LoaderAllocator *pLoaderAllocator = GetLoaderAllocator();
2270         TypeHandle th = TypeHandle(this);
2271         ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetType(th);
2272         ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetKeepAlive(pLoaderAllocator->GetExposedObject());
2273
2274         // Let all threads fight over who wins using InterlockedCompareExchange.
2275         // Only the winner can set m_hExposedClassObject from NULL.      
2276         LOADERHANDLE hExposedClassObject = pLoaderAllocator->AllocateHandle(refClass);
2277
2278         if (FastInterlockCompareExchangePointer(EnsureWritablePages(&m_hExposedClassObject), hExposedClassObject, static_cast<LOADERHANDLE>(NULL)))
2279         {
2280             pLoaderAllocator->ClearHandle(hExposedClassObject);
2281         }
2282
2283         GCPROTECT_END();
2284     }
2285     return GetManagedClassObjectIfExists();
2286 }
2287 #endif // CROSSGEN_COMPILE
2288
2289 #endif //!DACCESS_COMPILE
2290
2291 TypeHandle * 
2292 FnPtrTypeDesc::GetRetAndArgTypes()
2293
2294     CONTRACTL
2295     {
2296         THROWS;
2297         GC_TRIGGERS;
2298         MODE_ANY;
2299     }
2300     CONTRACTL_END;
2301
2302     // Decode encoded type handles on demand
2303 #if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
2304     for (DWORD i = 0; i <= m_NumArgs; i++)
2305     {
2306         Module::RestoreTypeHandlePointerRaw(&m_RetAndArgTypes[i]);
2307     }
2308 #endif //defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
2309
2310     return m_RetAndArgTypes;
2311 } // FnPtrTypeDesc::GetRetAndArgTypes
2312
2313 #ifndef DACCESS_COMPILE
2314
2315 // Returns TRUE if all return and argument types are externally visible.
2316 BOOL 
2317 FnPtrTypeDesc::IsExternallyVisible() const
2318 {
2319     CONTRACTL
2320     {
2321         THROWS;
2322         GC_TRIGGERS;
2323         MODE_ANY;
2324     }
2325     CONTRACTL_END;
2326     
2327     const TypeHandle * rgRetAndArgTypes = GetRetAndArgTypes();
2328     for (DWORD i = 0; i <= m_NumArgs; i++)
2329     {
2330         if (!rgRetAndArgTypes[i].IsExternallyVisible())
2331         {
2332             return FALSE;
2333         }
2334     }
2335     // All return/arguments types are externally visible
2336     return TRUE;
2337 } // FnPtrTypeDesc::IsExternallyVisible
2338
2339 // Returns TRUE if any of return or argument types is part of an assembly loaded for introspection.
2340 BOOL 
2341 FnPtrTypeDesc::IsIntrospectionOnly() const
2342 {
2343     CONTRACTL
2344     {
2345         THROWS;
2346         GC_TRIGGERS;
2347     }
2348     CONTRACTL_END;
2349     
2350     const TypeHandle * rgRetAndArgTypes = GetRetAndArgTypes();
2351     for (DWORD i = 0; i <= m_NumArgs; i++)
2352     {
2353         if (rgRetAndArgTypes[i].IsIntrospectionOnly())
2354         {
2355             return TRUE;
2356         }
2357     }
2358     // None of the return/arguments type was loaded for introspection
2359     return FALSE;
2360 } // FnPtrTypeDesc::IsIntrospectionOnly
2361
2362 // Returns TRUE if any of return or argument types is part of an assembly loaded for introspection.
2363 // Instantiations of generic types are also recursively checked.
2364 BOOL 
2365 FnPtrTypeDesc::ContainsIntrospectionOnlyTypes() const
2366 {
2367     CONTRACTL
2368     {
2369         THROWS;
2370         GC_TRIGGERS;
2371     }
2372     CONTRACTL_END;
2373     
2374     const TypeHandle * rgRetAndArgTypes = GetRetAndArgTypes();
2375     for (DWORD i = 0; i <= m_NumArgs; i++)
2376     {
2377         if (rgRetAndArgTypes[i].ContainsIntrospectionOnlyTypes())
2378         {
2379             return TRUE;
2380         }
2381     }
2382     // None of the return/arguments type contains types loaded for introspection
2383     return FALSE;
2384 } // FnPtrTypeDesc::ContainsIntrospectionOnlyTypes
2385
2386 #endif //DACCESS_COMPILE
2387
2388 #if defined(FEATURE_NATIVE_IMAGE_GENERATION) && !defined(DACCESS_COMPILE)
2389
2390 void FnPtrTypeDesc::Save(DataImage * image)
2391 {
2392     STANDARD_VM_CONTRACT;
2393
2394     image->StoreStructure(
2395         this, 
2396         sizeof(FnPtrTypeDesc) + (m_NumArgs * sizeof(TypeHandle)), 
2397         DataImage::ITEM_FPTR_TYPEDESC);
2398 }
2399
2400 void FnPtrTypeDesc::Fixup(DataImage * image)
2401 {
2402     STANDARD_VM_CONTRACT;
2403
2404     for (DWORD i = 0; i <= m_NumArgs; i++)
2405     {
2406         image->FixupTypeHandlePointerInPlace(
2407             this, 
2408             (BYTE *)&m_RetAndArgTypes[i] - (BYTE *)this);
2409     }
2410 }
2411
2412 #endif //defined(FEATURE_NATIVE_IMAGE_GENERATION) && !defined(DACCESS_COMPILE)
2413
2414 #ifdef DACCESS_COMPILE
2415
2416 void
2417 ParamTypeDesc::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2418 {
2419     SUPPORTS_DAC;
2420     DAC_ENUM_DTHIS();
2421
2422     PTR_MethodTable pTemplateMT = GetTemplateMethodTableInternal();
2423     if (pTemplateMT.IsValid())
2424     {
2425         pTemplateMT->EnumMemoryRegions(flags);
2426     }
2427
2428     m_Arg.EnumMemoryRegions(flags);
2429 }
2430
2431 void
2432 TypeVarTypeDesc::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2433 {
2434     SUPPORTS_DAC;
2435     DAC_ENUM_DTHIS();
2436
2437     PTR_TypeVarTypeDesc ptrThis(this);
2438
2439     if (GetModule().IsValid())
2440     {
2441         GetModule()->EnumMemoryRegions(flags, true);
2442     }
2443
2444     if (m_numConstraints != (DWORD)-1)
2445     {
2446         PTR_TypeHandle constraint = m_constraints;
2447         for (DWORD i = 0; i < m_numConstraints; i++)
2448         {
2449             if (constraint.IsValid())
2450             {
2451                 constraint->EnumMemoryRegions(flags);
2452             }
2453             constraint++;
2454         }
2455     }
2456 } // TypeVarTypeDesc::EnumMemoryRegions
2457
2458 void
2459 FnPtrTypeDesc::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2460 {
2461     SUPPORTS_DAC;
2462     DAC_ENUM_DTHIS();
2463
2464     for (DWORD i = 0; i < m_NumArgs; i++)
2465     {
2466         m_RetAndArgTypes[i].EnumMemoryRegions(flags);
2467     }
2468 }
2469
2470 #endif //DACCESS_COMPILE