[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / clsload.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: clsload.cpp
6 //
7 // ============================================================================
8
9 #include "common.h"
10 #include "winwrap.h"
11 #include "ceeload.h"
12 #include "siginfo.hpp"
13 #include "vars.hpp"
14 #include "clsload.hpp"
15 #include "classhash.inl"
16 #include "class.h"
17 #include "method.hpp"
18 #include "ecall.h"
19 #include "stublink.h"
20 #include "object.h"
21 #include "excep.h"
22 #include "threads.h"
23 #include "comsynchronizable.h"
24 #include "threads.h"
25 #include "dllimport.h"
26 #include "dbginterface.h"
27 #include "log.h"
28 #include "eeconfig.h"
29 #include "fieldmarshaler.h"
30 #include "jitinterface.h"
31 #include "vars.hpp"
32 #include "assembly.hpp"
33 #include "eeprofinterfaces.h"
34 #include "eehash.h"
35 #include "typehash.h"
36 #include "comdelegate.h"
37 #include "array.h"
38 #include "posterror.h"
39 #include "wrappers.h"
40 #include "generics.h"
41 #include "typestring.h"
42 #include "typedesc.h"
43 #include "cgencpu.h"
44 #include "eventtrace.h"
45 #include "typekey.h"
46 #include "pendingload.h"
47 #include "proftoeeinterfaceimpl.h"
48 #include "virtualcallstub.h"
49 #include "stringarraylist.h"
50
51
52 // This method determines the "loader module" for an instantiated type
53 // or method. The rule must ensure that any types involved in the
54 // instantiated type or method do not outlive the loader module itself
55 // with respect to app-domain unloading (e.g. MyList<MyType> can't be
56 // put in the module of MyList if MyList's assembly is
57 // app-domain-neutral but MyType's assembly is app-domain-specific).
58 // The rule we use is:
59 //
60 // * Pick the first type in the class instantiation, followed by
61 //   method instantiation, whose loader module is non-shared (app-domain-bound)
62 // * If no type is app-domain-bound, return the module containing the generic type itself
63 //
64 // Some useful effects of this rule (for ngen purposes) are:
65 //
66 // * G<object,...,object> lives in the module defining G
67 // * non-mscorlib instantiations of mscorlib-defined generic types live in the module
68 //   of the instantiation (when only one module is invloved in the instantiation)
69 //
70
71 /* static */
72 PTR_Module ClassLoader::ComputeLoaderModuleWorker(
73     Module *     pDefinitionModule,  // the module that declares the generic type or method
74     mdToken      token,              // method or class token for this item
75     Instantiation classInst,         // the type arguments to the type (if any)
76     Instantiation methodInst)        // the type arguments to the method (if any)
77 {
78     CONTRACT(Module*)
79     {
80         NOTHROW;
81         GC_NOTRIGGER;
82         FORBID_FAULT;
83         MODE_ANY;
84         PRECONDITION(CheckPointer(pDefinitionModule, NULL_OK));
85         POSTCONDITION(CheckPointer(RETVAL));
86         SUPPORTS_DAC;
87     }
88     CONTRACT_END
89
90     if (classInst.IsEmpty() && methodInst.IsEmpty())
91         RETURN PTR_Module(pDefinitionModule);
92
93 #ifndef DACCESS_COMPILE
94 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
95     //
96     // Use special loader module placement during compilation of fragile native images.
97     //
98     // ComputeLoaderModuleForCompilation algorithm assumes that we are using fragile native image
99     // for CoreLib (or compiling CoreLib itself). It is not the case for ReadyToRun compilation because
100     // CoreLib as always treated as IL there (see code:PEFile::ShouldTreatNIAsMSIL for details).
101     //
102     if (IsCompilationProcess() && !IsReadyToRunCompilation())
103     {
104         RETURN(ComputeLoaderModuleForCompilation(pDefinitionModule, token, classInst, methodInst));
105     }
106 #endif // FEATURE_PREJIT
107 #endif // #ifndef DACCESS_COMPILE
108
109     Module *pLoaderModule = NULL;
110
111     if (pDefinitionModule)
112     {
113         if (pDefinitionModule->IsCollectible())
114             goto ComputeCollectibleLoaderModule;
115         pLoaderModule = pDefinitionModule;
116     }
117
118     for (DWORD i = 0; i < classInst.GetNumArgs(); i++)
119     {
120         TypeHandle classArg = classInst[i];
121         _ASSERTE(!classArg.IsEncodedFixup());
122         Module* pModule = classArg.GetLoaderModule();
123         if (pModule->IsCollectible())
124             goto ComputeCollectibleLoaderModule;
125         if (pLoaderModule == NULL)
126             pLoaderModule = pModule;
127     }
128
129     for (DWORD i = 0; i < methodInst.GetNumArgs(); i++)
130     {
131         TypeHandle methodArg = methodInst[i];
132         _ASSERTE(!methodArg.IsEncodedFixup());
133         Module *pModule = methodArg.GetLoaderModule();
134         if (pModule->IsCollectible())
135             goto ComputeCollectibleLoaderModule;
136         if (pLoaderModule == NULL)
137             pLoaderModule = pModule;
138     }
139
140     if (pLoaderModule == NULL)
141     {
142         CONSISTENCY_CHECK(MscorlibBinder::GetModule() && MscorlibBinder::GetModule()->IsSystem());
143
144         pLoaderModule = MscorlibBinder::GetModule();
145     }
146
147     if (FALSE)
148     {
149 ComputeCollectibleLoaderModule:
150         LoaderAllocator *pLoaderAllocatorOfDefiningType = NULL;
151         LoaderAllocator *pOldestLoaderAllocator = NULL;
152         Module *pOldestLoaderModule = NULL;
153         UINT64 oldestFoundAge = 0;
154         DWORD classArgsCount = classInst.GetNumArgs();
155         DWORD totalArgsCount = classArgsCount + methodInst.GetNumArgs();
156
157         if (pDefinitionModule != NULL) pLoaderAllocatorOfDefiningType = pDefinitionModule->GetLoaderAllocator();
158
159         for (DWORD i = 0; i < totalArgsCount; i++) {
160
161             TypeHandle arg;
162
163             if (i < classArgsCount)
164                 arg = classInst[i];
165             else
166                 arg = methodInst[i - classArgsCount];
167
168             Module *pModuleCheck = arg.GetLoaderModule();
169             LoaderAllocator *pLoaderAllocatorCheck = pModuleCheck->GetLoaderAllocator();
170
171             if (pLoaderAllocatorCheck != pLoaderAllocatorOfDefiningType &&
172                 pLoaderAllocatorCheck->IsCollectible() && 
173                 pLoaderAllocatorCheck->GetCreationNumber() > oldestFoundAge)
174             {
175                 pOldestLoaderModule = pModuleCheck;
176                 pOldestLoaderAllocator = pLoaderAllocatorCheck;
177                 oldestFoundAge = pLoaderAllocatorCheck->GetCreationNumber();
178             }
179         }
180
181         // Only if we didn't find a different loader allocator than the defining loader allocator do we
182         // use the defining loader allocator
183         if (pOldestLoaderModule != NULL)
184             pLoaderModule = pOldestLoaderModule;
185         else
186             pLoaderModule = pDefinitionModule;
187     }
188     RETURN PTR_Module(pLoaderModule);
189 }
190
191 #ifndef DACCESS_COMPILE
192 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
193 /* static */
194 PTR_Module ClassLoader::ComputeLoaderModuleForCompilation(
195     Module *     pDefinitionModule,  // the module that declares the generic type or method
196     mdToken      token,              // method or class token for this item
197     Instantiation classInst,         // the type arguments to the type (if any)
198     Instantiation methodInst)        // the type arguments to the method (if any)
199 {
200     CONTRACT(Module*)
201     {
202         NOTHROW;
203         GC_NOTRIGGER;
204         FORBID_FAULT;
205         MODE_ANY;
206         PRECONDITION(CheckPointer(pDefinitionModule, NULL_OK));
207         POSTCONDITION(CheckPointer(RETVAL));
208     }
209     CONTRACT_END
210
211     // The NGEN rule for compiling constructed types and instantiated methods
212     // into modules other than their "natural" LoaderModule. This is at the heart of
213     // "full generics NGEN".
214     //
215     // If this instantiation doesn't have a unique home then use the ngen module 
216
217     // OK, we're certainly NGEN'ing.  And if we're NGEN'ing then we're not on the debugger thread.
218     CONSISTENCY_CHECK(((GetThread() && GetAppDomain()) || IsGCThread()) &&
219         "unexpected: running a load on debug thread but IsCompilationProcess() returned TRUE");
220
221     // Save it into its PreferredZapModule if it's always going to be saved there.
222     // This is a stable choice - no need to record it in the table (as we do for others below)
223     if (Module::IsAlwaysSavedInPreferredZapModule(classInst, methodInst))
224     {
225         RETURN (Module::ComputePreferredZapModule(pDefinitionModule, classInst, methodInst));
226     }
227
228     // Check if this compilation process has already decided on an adjustment.  Once we decide
229     // on the LoaderModule for an item it must be stable for the duration of a
230     // compilation process, no matter how many modules get NGEN'd.
231     
232     ZapperLoaderModuleTableKey key(pDefinitionModule, 
233                                    token, 
234                                    classInst, 
235                                    methodInst);
236
237     Module * pZapperLoaderModule = g_pCEECompileInfo->LookupZapperLoaderModule(&key);
238     if (pZapperLoaderModule != NULL)
239     {
240         RETURN (pZapperLoaderModule);
241     }
242
243     // OK, we need to compute a non-standard zapping module.
244
245     Module * pPreferredZapModule = Module::ComputePreferredZapModule(pDefinitionModule, classInst, methodInst);
246
247     // Check if we're NGEN'ing but where perhaps the compilation domain 
248     // isn't set up yet.  This can happen in following situations:
249     // - Managed code running during startup before compilation domain is setup.
250     // - Exceptions (e.g. invalid program exceptions) thrown from compilation domain and caught in default domain
251
252     // We're a little stuck - we can't force the item into an NGEN image at this point.  So just bail out
253     // and use the loader module we've computed without recording the choice. The loader module should always 
254     // be mscorlib in this case.
255     AppDomain * pAppDomain = GetAppDomain();
256     if (!pAppDomain->IsCompilationDomain() ||
257         !pAppDomain->ToCompilationDomain()->GetTargetModule())
258     {
259         _ASSERTE(pPreferredZapModule->IsSystem() || IsNgenPDBCompilationProcess());
260         RETURN (pPreferredZapModule);
261     }
262
263     Module * pTargetModule = pAppDomain->ToCompilationDomain()->GetTargetModule();
264
265     // If it is multi-module assembly and we have not saved PZM yet, do not create
266     // speculative instantiation - just save it in PZM.
267     if (pTargetModule->GetAssembly() == pPreferredZapModule->GetAssembly() && 
268         !pPreferredZapModule->IsModuleSaved())
269     {
270         pZapperLoaderModule = pPreferredZapModule;
271     }
272     else
273     {
274         // Everything else can be saved into the current module.
275         pZapperLoaderModule = pTargetModule;
276     }
277
278     // If generating WinMD resilient code and we so far choose to use the target module,
279     // we need to check if the definition module or any of the instantiation type can
280     // cause version resilient problems.
281     if (g_fNGenWinMDResilient && pZapperLoaderModule == pTargetModule)
282     {
283         if (pDefinitionModule != NULL && !pDefinitionModule->IsInCurrentVersionBubble())
284         {
285             pZapperLoaderModule = pDefinitionModule;
286             goto ModuleAdjustedForVersionResiliency;
287         }
288
289         for (DWORD i = 0; i < classInst.GetNumArgs(); i++)
290         {
291             Module * pModule = classInst[i].GetLoaderModule();
292             if (!pModule->IsInCurrentVersionBubble())
293             {
294                 pZapperLoaderModule = pModule;
295                 goto ModuleAdjustedForVersionResiliency;
296             }
297         }
298
299         for (DWORD i = 0; i < methodInst.GetNumArgs(); i++)
300         {
301             Module * pModule = methodInst[i].GetLoaderModule();
302             if (!pModule->IsInCurrentVersionBubble())
303             {
304                 pZapperLoaderModule = pModule;
305                 goto ModuleAdjustedForVersionResiliency;
306             }
307         }
308 ModuleAdjustedForVersionResiliency: ;
309     }
310
311     // Record this choice just in case we're NGEN'ing multiple modules
312     // to make sure we always do the same thing if we're asked to compute 
313     // the loader module again.
314
315     // Note this whole code path only happens while NGEN'ing, so this violation
316     // is not so bad.  It is needed since we allocate stuff on the heap.
317     CONTRACT_VIOLATION(ThrowsViolation|FaultViolation);
318
319     // Copy the instantiation arrays so they can escape the scope of this method.
320     // Since this is a permanent entry in a table for this compilation process
321     // we do not need to collect these.  If we did have to we would do it when we deleteed the
322     // ZapperLoaderModuleTable.
323     NewArrayHolder<TypeHandle> pClassArgs = NULL;
324     if (!classInst.IsEmpty())
325     {
326         pClassArgs = new TypeHandle[classInst.GetNumArgs()];
327         for (unsigned int i = 0; i < classInst.GetNumArgs(); i++)
328             pClassArgs[i] = classInst[i];
329     }
330
331     NewArrayHolder<TypeHandle> pMethodArgs = NULL;
332     if (!methodInst.IsEmpty())
333     {
334         pMethodArgs = new TypeHandle[methodInst.GetNumArgs()];
335         for (unsigned int i = 0; i < methodInst.GetNumArgs(); i++)
336             pMethodArgs[i] = methodInst[i];
337     }
338
339     ZapperLoaderModuleTableKey key2(pDefinitionModule, 
340                                     token, 
341                                     Instantiation(pClassArgs, classInst.GetNumArgs()),
342                                     Instantiation(pMethodArgs, methodInst.GetNumArgs()));
343     g_pCEECompileInfo->RecordZapperLoaderModule(&key2, pZapperLoaderModule);
344
345     pClassArgs.SuppressRelease();
346     pMethodArgs.SuppressRelease();
347
348     RETURN (pZapperLoaderModule);
349 }
350 #endif // FEATURE_NATIVE_IMAGE_GENERATION
351 #endif // #ifndef DACCESS_COMPILE
352
353 /*static*/
354 Module * ClassLoader::ComputeLoaderModule(MethodTable * pMT, 
355                                           mdToken       token, 
356                                           Instantiation methodInst)
357 {
358     CONTRACTL
359     {
360         NOTHROW;
361         GC_NOTRIGGER;
362         MODE_ANY;
363         SUPPORTS_DAC;
364     }
365     CONTRACTL_END;
366
367     return ComputeLoaderModuleWorker(pMT->GetModule(), 
368                                token,
369                                pMT->GetInstantiation(),
370                                methodInst);
371 }
372 /*static*/
373 Module *ClassLoader::ComputeLoaderModule(TypeKey *typeKey)
374 {
375     CONTRACTL
376     {
377         NOTHROW;
378         GC_NOTRIGGER;
379         MODE_ANY;
380         SUPPORTS_DAC;
381     }
382     CONTRACTL_END;
383
384
385     if (typeKey->GetKind() == ELEMENT_TYPE_CLASS)
386         return ComputeLoaderModuleWorker(typeKey->GetModule(),
387                                    typeKey->GetTypeToken(),
388                                    typeKey->GetInstantiation(),
389                                    Instantiation());
390     else if (typeKey->GetKind() == ELEMENT_TYPE_FNPTR)
391         return ComputeLoaderModuleForFunctionPointer(typeKey->GetRetAndArgTypes(), typeKey->GetNumArgs() + 1);
392     else                                                    
393         return ComputeLoaderModuleForParamType(typeKey->GetElementType());
394 }
395
396 /*static*/ 
397 BOOL ClassLoader::IsTypicalInstantiation(Module *pModule, mdToken token, Instantiation inst)
398 {
399     CONTRACTL
400     {
401         NOTHROW;
402         GC_NOTRIGGER;
403         FORBID_FAULT;
404         PRECONDITION(CheckPointer(pModule));
405         PRECONDITION(TypeFromToken(token) == mdtTypeDef || TypeFromToken(token) == mdtMethodDef);
406         SUPPORTS_DAC;
407     }
408     CONTRACTL_END
409
410     for (DWORD i = 0; i < inst.GetNumArgs(); i++)
411     {
412         TypeHandle thArg = inst[i];
413
414         if (thArg.IsGenericVariable())
415         {
416             TypeVarTypeDesc* tyvar = thArg.AsGenericVariable();
417
418             PREFIX_ASSUME(tyvar!=NULL);
419             if ((tyvar->GetTypeOrMethodDef() != token) ||
420                 (tyvar->GetModule() != dac_cast<PTR_Module>(pModule)) ||
421                 (tyvar->GetIndex() != i))
422                 return FALSE;
423         }
424         else
425         {
426             return FALSE;
427         }
428     }
429     return TRUE;
430 }
431
432 // External class loader entry point: load a type by name
433 /*static*/
434 TypeHandle ClassLoader::LoadTypeByNameThrowing(Assembly *pAssembly,
435                                                LPCUTF8 nameSpace,
436                                                LPCUTF8 name,
437                                                NotFoundAction fNotFound,
438                                                ClassLoader::LoadTypesFlag fLoadTypes,
439                                                ClassLoadLevel level)
440 {
441     CONTRACT(TypeHandle)
442     {
443         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
444         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
445         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
446         MODE_ANY;
447
448         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
449
450         PRECONDITION(CheckPointer(pAssembly));
451         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
452         POSTCONDITION(CheckPointer(RETVAL, 
453                      (fNotFound == ThrowIfNotFound && fLoadTypes == LoadTypes )? NULL_NOT_OK : NULL_OK));
454         POSTCONDITION(RETVAL.IsNull() || RETVAL.CheckLoadLevel(level));
455         SUPPORTS_DAC;
456 #ifdef DACCESS_COMPILE
457         PRECONDITION((fNotFound == ClassLoader::ReturnNullIfNotFound) && (fLoadTypes == DontLoadTypes));
458 #endif
459     }
460     CONTRACT_END
461
462     NameHandle nameHandle(nameSpace, name);
463     if (fLoadTypes == DontLoadTypes)
464         nameHandle.SetTokenNotToLoad(tdAllTypes);
465     if (fNotFound == ThrowIfNotFound)
466         RETURN pAssembly->GetLoader()->LoadTypeHandleThrowIfFailed(&nameHandle, level);
467     else
468         RETURN pAssembly->GetLoader()->LoadTypeHandleThrowing(&nameHandle, level);
469 }
470
471 #ifndef DACCESS_COMPILE
472
473 #define DAC_LOADS_TYPE(level, expression) \
474     if (FORBIDGC_LOADER_USE_ENABLED() || (expression)) \
475         { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); } 
476 #else 
477
478 #define DAC_LOADS_TYPE(level, expression) { LOADS_TYPE(CLASS_LOAD_BEGIN); } 
479 #endif // #ifndef DACCESS_COMPILE
480
481 //
482 // Find a class given name, using the classloader's global list of known classes.
483 // If the type is found, it will be restored unless pName->GetTokenNotToLoad() prohibits that
484 // Returns NULL if class not found AND pName->OKToLoad returns false
485 TypeHandle ClassLoader::LoadTypeHandleThrowIfFailed(NameHandle* pName, ClassLoadLevel level,
486                                                     Module* pLookInThisModuleOnly/*=NULL*/)
487 {
488     CONTRACT(TypeHandle)
489     {
490         INSTANCE_CHECK;
491         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
492         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
493         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
494         DAC_LOADS_TYPE(level, !pName->OKToLoad());
495         MODE_ANY;
496         PRECONDITION(CheckPointer(pName));
497         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
498         POSTCONDITION(CheckPointer(RETVAL, pName->OKToLoad() ? NULL_NOT_OK : NULL_OK));
499         POSTCONDITION(RETVAL.IsNull() || RETVAL.CheckLoadLevel(level));
500         SUPPORTS_DAC;
501     }
502     CONTRACT_END;
503
504     // Lookup in the classes that this class loader knows about
505     TypeHandle typeHnd = LoadTypeHandleThrowing(pName, level, pLookInThisModuleOnly);
506
507     if(typeHnd.IsNull()) {
508
509         if ( pName->OKToLoad() ) {
510 #ifdef _DEBUG_IMPL
511             {
512                 LPCUTF8 szName = pName->GetName();
513                 if (szName == NULL)
514                     szName = "<UNKNOWN>";
515                 
516                 StackSString codeBase;
517                 GetAssembly()->GetCodeBase(codeBase);
518
519                 LOG((LF_CLASSLOADER, LL_INFO10, "Failed to find class \"%s\" in the manifest for assembly \"%ws\"\n", szName, (LPCWSTR)codeBase));
520             }
521 #endif
522
523 #ifndef DACCESS_COMPILE
524             m_pAssembly->ThrowTypeLoadException(pName, IDS_CLASSLOAD_GENERAL);
525 #else
526             DacNotImpl();
527 #endif
528         }
529     }
530
531     RETURN(typeHnd);
532 }
533
534 #ifndef DACCESS_COMPILE
535
536 //<TODO>@TODO: Need to allow exceptions to be thrown when classloader is cleaned up</TODO>
537 EEClassHashEntry_t* ClassLoader::InsertValue(EEClassHashTable *pClassHash, EEClassHashTable *pClassCaseInsHash, LPCUTF8 pszNamespace, LPCUTF8 pszClassName, HashDatum Data, EEClassHashEntry_t *pEncloser, AllocMemTracker *pamTracker)
538 {
539     CONTRACTL
540     {
541         INSTANCE_CHECK;
542         THROWS;
543         GC_NOTRIGGER;
544         MODE_ANY;
545         INJECT_FAULT(COMPlusThrowOM(););
546     }
547     CONTRACTL_END
548
549     LPUTF8 pszLowerCaseNS = NULL;
550     LPUTF8 pszLowerCaseName = NULL;
551     EEClassHashEntry_t *pCaseInsEntry = NULL;
552
553     EEClassHashEntry_t *pEntry = pClassHash->AllocNewEntry(pamTracker);
554    
555     if (pClassCaseInsHash) {
556         CreateCanonicallyCasedKey(pszNamespace, pszClassName, &pszLowerCaseNS, &pszLowerCaseName);
557         pCaseInsEntry = pClassCaseInsHash->AllocNewEntry(pamTracker);
558     }
559
560
561     {
562         // ! We cannot fail after this point.
563         CANNOTTHROWCOMPLUSEXCEPTION();
564         FAULT_FORBID();
565
566
567         pClassHash->InsertValueUsingPreallocatedEntry(pEntry, pszNamespace, pszClassName, Data, pEncloser);
568     
569         //If we're keeping a table for case-insensitive lookup, keep that up to date
570         if (pClassCaseInsHash)
571             pClassCaseInsHash->InsertValueUsingPreallocatedEntry(pCaseInsEntry, pszLowerCaseNS, pszLowerCaseName, pEntry, pEncloser);
572         
573         return pEntry;
574     }
575
576 }
577
578 #endif // #ifndef DACCESS_COMPILE
579
580 BOOL ClassLoader::CompareNestedEntryWithExportedType(IMDInternalImport *  pImport,
581                                                      mdExportedType       mdCurrent,
582                                                      EEClassHashTable *   pClassHash,
583                                                      PTR_EEClassHashEntry pEntry)
584 {
585     CONTRACTL
586     {
587         INSTANCE_CHECK;
588         NOTHROW;
589         GC_NOTRIGGER;
590         MODE_ANY;
591         FORBID_FAULT;
592         SUPPORTS_DAC;
593     }
594     CONTRACTL_END;
595
596     LPCUTF8 Key[2];
597
598     do
599     {
600         if (FAILED(pImport->GetExportedTypeProps(
601             mdCurrent, 
602             &Key[0], 
603             &Key[1], 
604             &mdCurrent, 
605             NULL,   //binding (type def)
606             NULL))) //flags
607         {
608             return FALSE;
609         }
610         
611         if (pClassHash->CompareKeys(pEntry, Key))
612         {
613             // Reached top level class for mdCurrent - return whether
614             // or not pEntry is a top level class
615             // (pEntry is a top level class if its pEncloser is NULL)
616             if ((TypeFromToken(mdCurrent) != mdtExportedType) ||
617                 (mdCurrent == mdExportedTypeNil))
618             {
619                 return pEntry->GetEncloser() == NULL;
620             }
621         }
622         else // Keys don't match - wrong entry
623         {
624             return FALSE;
625         }
626     }
627     while ((pEntry = pEntry->GetEncloser()) != NULL);
628
629     // Reached the top level class for pEntry, but mdCurrent is nested
630     return FALSE;
631 }
632
633
634 BOOL ClassLoader::CompareNestedEntryWithTypeDef(IMDInternalImport *  pImport,
635                                                 mdTypeDef            mdCurrent,
636                                                 EEClassHashTable *   pClassHash,
637                                                 PTR_EEClassHashEntry pEntry)
638 {
639     CONTRACTL
640     {
641         INSTANCE_CHECK;
642         NOTHROW;
643         GC_NOTRIGGER;
644         MODE_ANY;
645         FORBID_FAULT;
646         SUPPORTS_DAC;
647     }
648     CONTRACTL_END;
649
650     LPCUTF8 Key[2];
651
652     do {
653         if (FAILED(pImport->GetNameOfTypeDef(mdCurrent, &Key[1], &Key[0])))
654         {
655             return FALSE;
656         }
657         
658         if (pClassHash->CompareKeys(pEntry, Key)) {
659             // Reached top level class for mdCurrent - return whether
660             // or not pEntry is a top level class
661             // (pEntry is a top level class if its pEncloser is NULL)
662             if (FAILED(pImport->GetNestedClassProps(mdCurrent, &mdCurrent)))
663                 return pEntry->GetEncloser() == NULL;
664         }
665         else // Keys don't match - wrong entry
666             return FALSE;
667     }
668     while ((pEntry = pEntry->GetEncloser()) != NULL);
669
670     // Reached the top level class for pEntry, but mdCurrent is nested
671     return FALSE;
672 }
673
674
675 BOOL ClassLoader::CompareNestedEntryWithTypeRef(IMDInternalImport *  pImport,
676                                                 mdTypeRef            mdCurrent,
677                                                 EEClassHashTable *   pClassHash,
678                                                 PTR_EEClassHashEntry pEntry)
679 {
680     CONTRACTL
681     {
682         INSTANCE_CHECK;
683         NOTHROW;
684         GC_NOTRIGGER;
685         MODE_ANY;
686         FORBID_FAULT;
687         SUPPORTS_DAC;
688     }
689     CONTRACTL_END;
690
691     LPCUTF8 Key[2];
692
693     do {
694         if (FAILED(pImport->GetNameOfTypeRef(mdCurrent, &Key[0], &Key[1])))
695         {
696             return FALSE;
697         }
698         
699         if (pClassHash->CompareKeys(pEntry, Key))
700         {
701             if (FAILED(pImport->GetResolutionScopeOfTypeRef(mdCurrent, &mdCurrent)))
702             {
703                 return FALSE;
704             }
705             // Reached top level class for mdCurrent - return whether
706             // or not pEntry is a top level class
707             // (pEntry is a top level class if its pEncloser is NULL)
708             if ((TypeFromToken(mdCurrent) != mdtTypeRef) ||
709                 (mdCurrent == mdTypeRefNil))
710                 return pEntry->GetEncloser() == NULL;
711         }
712         else // Keys don't match - wrong entry
713             return FALSE;
714     }
715     while ((pEntry = pEntry->GetEncloser())!=NULL);
716
717     // Reached the top level class for pEntry, but mdCurrent is nested
718     return FALSE;
719 }
720
721
722 /*static*/
723 BOOL ClassLoader::IsNested(Module *pModule, mdToken token, mdToken *mdEncloser)
724 {
725     CONTRACTL
726     {
727         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
728         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
729         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
730         MODE_ANY;
731         SUPPORTS_DAC;
732     }
733     CONTRACTL_END;
734
735     switch(TypeFromToken(token)) {
736         case mdtTypeDef:
737             return (SUCCEEDED(pModule->GetMDImport()->GetNestedClassProps(token, mdEncloser)));
738
739         case mdtTypeRef:
740             IfFailThrow(pModule->GetMDImport()->GetResolutionScopeOfTypeRef(token, mdEncloser));
741             return ((TypeFromToken(*mdEncloser) == mdtTypeRef) &&
742                     (*mdEncloser != mdTypeRefNil));
743
744         case mdtExportedType:
745             IfFailThrow(pModule->GetAssembly()->GetManifestImport()->GetExportedTypeProps(
746                 token,
747                 NULL,   // namespace
748                 NULL,   // name
749                 mdEncloser, 
750                 NULL,   //binding (type def)
751                 NULL)); //flags
752             return ((TypeFromToken(*mdEncloser) == mdtExportedType) &&
753                     (*mdEncloser != mdExportedTypeNil));
754
755         default:
756             ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE);
757     }
758 }
759
760 BOOL ClassLoader::IsNested(const NameHandle* pName, mdToken *mdEncloser)
761 {
762     CONTRACTL
763     {
764         INSTANCE_CHECK;
765         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
766         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
767         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
768         MODE_ANY;
769         SUPPORTS_DAC;
770     }
771     CONTRACTL_END;
772
773     if (pName->GetTypeModule()) {
774         if (TypeFromToken(pName->GetTypeToken()) == mdtBaseType)
775         {
776             if (!pName->GetBucket().IsNull())
777                 return TRUE;
778             return FALSE;
779         }
780         else
781             return IsNested(pName->GetTypeModule(), pName->GetTypeToken(), mdEncloser);
782     }
783     else
784         return FALSE;
785 }
786
787 void ClassLoader::GetClassValue(NameHandleTable nhTable,
788                                     const NameHandle *pName,
789                                     HashDatum *pData,
790                                     EEClassHashTable **ppTable,
791                                     Module* pLookInThisModuleOnly,
792                                     HashedTypeEntry* pFoundEntry,
793                                     Loader::LoadFlag loadFlag,
794                                     BOOL& needsToBuildHashtable)
795 {
796     CONTRACTL
797     {
798         INSTANCE_CHECK;
799         MODE_ANY;
800         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
801         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
802         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
803         PRECONDITION(CheckPointer(pName));
804         SUPPORTS_DAC;
805     }
806     CONTRACTL_END
807
808
809     mdToken             mdEncloser;
810     EEClassHashEntry_t  *pBucket = NULL;
811
812     needsToBuildHashtable = FALSE;
813
814 #if _DEBUG
815     if (pName->GetName()) {
816         if (pName->GetNameSpace() == NULL)
817             LOG((LF_CLASSLOADER, LL_INFO1000, "Looking up %s by name.\n",
818                  pName->GetName()));
819         else
820             LOG((LF_CLASSLOADER, LL_INFO1000, "Looking up %s.%s by name.\n",
821                  pName->GetNameSpace(), pName->GetName()));
822     }
823 #endif
824
825     BOOL isNested = IsNested(pName, &mdEncloser);
826
827     PTR_Assembly assembly = GetAssembly();
828     PREFIX_ASSUME(assembly != NULL);
829     ModuleIterator i = assembly->IterateModules();
830
831     while (i.Next()) 
832     {
833         Module * pCurrentClsModule = i.GetModule();
834         PREFIX_ASSUME(pCurrentClsModule != NULL);
835
836         if (pCurrentClsModule->IsResource())
837             continue;
838         if (pLookInThisModuleOnly && (pCurrentClsModule != pLookInThisModuleOnly))
839             continue;
840
841 #ifdef FEATURE_READYTORUN
842         if (nhTable == nhCaseSensitive && pCurrentClsModule->IsReadyToRun() && pCurrentClsModule->GetReadyToRunInfo()->HasHashtableOfTypes() &&
843             pCurrentClsModule->GetAvailableClassHash() == NULL)
844         {
845             // For R2R modules, we only search the hashtable of token types stored in the module's image, and don't fallback
846             // to searching m_pAvailableClasses or m_pAvailableClassesCaseIns (in fact, we don't even allocate them for R2R modules).
847             // Also note that type lookups in R2R modules only support case sensitive lookups.
848
849             mdToken mdFoundTypeToken;
850             if (pCurrentClsModule->GetReadyToRunInfo()->TryLookupTypeTokenFromName(pName, &mdFoundTypeToken))
851             {
852                 if (TypeFromToken(mdFoundTypeToken) == mdtExportedType)
853                 {
854                     mdToken mdUnused;
855                     Module * pTargetModule = GetAssembly()->FindModuleByExportedType(mdFoundTypeToken, loadFlag, mdTypeDefNil, &mdUnused);
856
857                     pFoundEntry->SetTokenBasedEntryValue(mdFoundTypeToken, pTargetModule);
858                 }
859                 else
860                 {
861                     pFoundEntry->SetTokenBasedEntryValue(mdFoundTypeToken, pCurrentClsModule);
862                 }
863
864                 return; // Return on the first success
865             }
866         }
867         else
868 #endif
869         {
870             EEClassHashTable* pTable = NULL;
871             if (nhTable == nhCaseSensitive)
872             {
873                 *ppTable = pTable = pCurrentClsModule->GetAvailableClassHash();
874
875 #ifdef FEATURE_READYTORUN
876                 if (pTable == NULL && pCurrentClsModule->IsReadyToRun() && !pCurrentClsModule->GetReadyToRunInfo()->HasHashtableOfTypes())
877                 {
878                     // Old R2R image generated without the hashtable of types.
879                     // We fallback to the slow path of creating the hashtable dynamically 
880                     // at execution time in that scenario. The caller will handle
881                     pFoundEntry->SetClassHashBasedEntryValue(NULL);
882                     needsToBuildHashtable = TRUE;
883                     return;
884                 }
885 #endif
886             }
887             else
888             {
889                 // currently we expect only these two kinds--for DAC builds, nhTable will be nhCaseSensitive
890                 _ASSERTE(nhTable == nhCaseInsensitive);
891                 *ppTable = pTable = pCurrentClsModule->GetAvailableClassCaseInsHash();
892
893                 if (pTable == NULL)
894                 {
895                     // We have not built the table yet - the caller will handle
896                     pFoundEntry->SetClassHashBasedEntryValue(NULL);
897                     needsToBuildHashtable = TRUE;
898                     return;
899                 }
900             }
901             _ASSERTE(pTable);
902
903             if (isNested)
904             {
905                 Module *pNameModule = pName->GetTypeModule();
906                 PREFIX_ASSUME(pNameModule != NULL);
907
908                 EEClassHashTable::LookupContext sContext;
909                 if ((pBucket = pTable->GetValue(pName, pData, TRUE, &sContext)) != NULL)
910                 {
911                     switch (TypeFromToken(pName->GetTypeToken()))
912                     {
913                     case mdtTypeDef:
914                         while ((!CompareNestedEntryWithTypeDef(pNameModule->GetMDImport(),
915                                                                mdEncloser,
916                                                                pCurrentClsModule->GetAvailableClassHash(),
917                                                                pBucket->GetEncloser())) &&
918                                                                (pBucket = pTable->FindNextNestedClass(pName, pData, &sContext)) != NULL);
919                         break;
920                     case mdtTypeRef:
921                         while ((!CompareNestedEntryWithTypeRef(pNameModule->GetMDImport(),
922                                                                mdEncloser,
923                                                                pCurrentClsModule->GetAvailableClassHash(),
924                                                                pBucket->GetEncloser())) &&
925                                                                (pBucket = pTable->FindNextNestedClass(pName, pData, &sContext)) != NULL);
926                         break;
927                     case mdtExportedType:
928                         while ((!CompareNestedEntryWithExportedType(pNameModule->GetAssembly()->GetManifestImport(),
929                                                                     mdEncloser,
930                                                                     pCurrentClsModule->GetAvailableClassHash(),
931                                                                     pBucket->GetEncloser())) &&
932                                                                     (pBucket = pTable->FindNextNestedClass(pName, pData, &sContext)) != NULL);
933                         break;
934                     default:
935                         while ((pBucket->GetEncloser() != pName->GetBucket().GetClassHashBasedEntryValue()) &&
936                             (pBucket = pTable->FindNextNestedClass(pName, pData, &sContext)) != NULL);
937                     }
938                 }
939             }
940             else
941             {
942                 pBucket = pTable->GetValue(pName, pData, FALSE, NULL);
943             }
944
945             if (pBucket) // Return on the first success
946             {
947                 pFoundEntry->SetClassHashBasedEntryValue(pBucket);
948                 return;
949             }
950         }
951     }
952
953     // No results found: default to a NULL EEClassHashEntry_t result
954     pFoundEntry->SetClassHashBasedEntryValue(NULL);
955 }
956
957 #ifndef DACCESS_COMPILE
958
959 VOID ClassLoader::PopulateAvailableClassHashTable(Module* pModule,
960                                                   AllocMemTracker *pamTracker)
961 {
962     CONTRACTL
963     {
964         INSTANCE_CHECK;
965         THROWS;
966         GC_TRIGGERS;
967         MODE_ANY;
968         INJECT_FAULT(COMPlusThrowOM(););
969     }
970     CONTRACTL_END;
971
972     mdTypeDef           td;
973     HENUMInternal       hTypeDefEnum;
974     IMDInternalImport * pImport = pModule->GetMDImport();
975
976     LPCSTR szWinRtNamespacePrefix = NULL;
977     DWORD  cchWinRtNamespacePrefix = 0;
978
979 #ifdef FEATURE_COMINTEROP
980     SString            ssFileName;
981     StackScratchBuffer ssFileNameBuffer;
982     
983     if (pModule->GetAssembly()->IsWinMD())
984     {   // WinMD file in execution context (not ReflectionOnly context) - use its file name as WinRT namespace prefix 
985         //  (Windows requirement)
986         // Note: Reflection can work on 'unfinished' WinMD files where the types are in 'wrong' WinMD file (i.e. 
987         //  type namespace does not start with the file name)
988         
989         _ASSERTE(pModule->GetFile()->IsAssembly()); // No multi-module WinMD file support
990         _ASSERTE(!pModule->GetFile()->GetPath().IsEmpty());
991         
992         SplitPath(
993             pModule->GetFile()->GetPath(),
994             NULL,   // Drive
995             NULL,   // Directory
996             &ssFileName, 
997             NULL);  // Extension
998         
999         szWinRtNamespacePrefix = ssFileName.GetUTF8(ssFileNameBuffer);
1000         cchWinRtNamespacePrefix = (DWORD)strlen(szWinRtNamespacePrefix);
1001     }
1002 #endif //FEATURE_COMINTEROP
1003
1004     IfFailThrow(pImport->EnumTypeDefInit(&hTypeDefEnum));
1005
1006     // Now loop through all the classdefs adding the CVID and scope to the hash
1007     while(pImport->EnumTypeDefNext(&hTypeDefEnum, &td)) {
1008         
1009         AddAvailableClassHaveLock(pModule,
1010                                   td,
1011                                   pamTracker,
1012                                   szWinRtNamespacePrefix,
1013                                   cchWinRtNamespacePrefix);
1014     }
1015     pImport->EnumTypeDefClose(&hTypeDefEnum);
1016 }
1017
1018
1019 void ClassLoader::LazyPopulateCaseSensitiveHashTablesDontHaveLock()
1020 {
1021     CONTRACTL
1022     {
1023         INSTANCE_CHECK;
1024         THROWS;
1025         GC_TRIGGERS;
1026         MODE_ANY;
1027         INJECT_FAULT(COMPlusThrowOM());
1028     }
1029     CONTRACTL_END;
1030
1031
1032     CrstHolder ch(&m_AvailableClassLock);
1033     LazyPopulateCaseSensitiveHashTables();
1034 }
1035
1036 void ClassLoader::LazyPopulateCaseSensitiveHashTables()
1037 {
1038     CONTRACTL
1039     {
1040         INSTANCE_CHECK;
1041         THROWS;
1042         GC_TRIGGERS;
1043         MODE_ANY;
1044         INJECT_FAULT(COMPlusThrowOM());
1045     }
1046     CONTRACTL_END;
1047
1048     AllocMemTracker amTracker;
1049     ModuleIterator i = GetAssembly()->IterateModules();
1050
1051     // Create a case-sensitive hashtable for each module, and fill it with the module's typedef entries
1052     while (i.Next())
1053     {
1054         Module *pModule = i.GetModule();
1055         PREFIX_ASSUME(pModule != NULL);
1056         if (pModule->IsResource() || pModule->GetAvailableClassHash() != NULL)
1057             continue;
1058
1059         // Lazy construction of the case-sensitive hashtable of types is *only* a scenario for ReadyToRun images
1060         // (either images compiled with an old version of crossgen, or for case-insensitive type lookups in R2R modules)
1061         _ASSERT(pModule->IsReadyToRun());
1062
1063         EEClassHashTable * pNewClassHash = EEClassHashTable::Create(pModule, AVAILABLE_CLASSES_HASH_BUCKETS, FALSE /* bCaseInsensitive */, &amTracker);
1064         pModule->SetAvailableClassHash(pNewClassHash);
1065
1066         PopulateAvailableClassHashTable(pModule, &amTracker);
1067     }
1068
1069     // Add exported types of the manifest module to the hashtable
1070     if (!GetAssembly()->GetManifestModule()->IsResource())
1071     {
1072         IMDInternalImport * pManifestImport = GetAssembly()->GetManifestImport();
1073         HENUMInternalHolder phEnum(pManifestImport);
1074         phEnum.EnumInit(mdtExportedType, mdTokenNil);
1075
1076         mdToken mdExportedType;
1077         while (pManifestImport->EnumNext(&phEnum, &mdExportedType))
1078             AddExportedTypeHaveLock(GetAssembly()->GetManifestModule(), mdExportedType, &amTracker);
1079     }
1080
1081     amTracker.SuppressRelease();
1082 }
1083
1084 void ClassLoader::LazyPopulateCaseInsensitiveHashTables()
1085 {
1086     CONTRACTL
1087     {
1088         INSTANCE_CHECK;
1089         THROWS;
1090         GC_TRIGGERS;
1091         MODE_ANY;
1092         INJECT_FAULT(COMPlusThrowOM());
1093     }
1094     CONTRACTL_END;
1095
1096     if (!GetAssembly()->GetManifestModule()->IsResource() && GetAssembly()->GetManifestModule()->GetAvailableClassHash() == NULL)
1097     {
1098         // This is a R2R assembly, and a case insensitive type lookup was triggered. 
1099         // Construct the case-sensitive table first, since the case-insensitive table 
1100         // create piggy-backs on the first.
1101         LazyPopulateCaseSensitiveHashTables();
1102     }
1103
1104     // Add any unhashed modules into our hash tables, and try again.
1105     
1106     AllocMemTracker amTracker;
1107     ModuleIterator i = GetAssembly()->IterateModules();
1108
1109     while (i.Next()) 
1110     {
1111         Module *pModule = i.GetModule();
1112         if (pModule->IsResource())
1113             continue;
1114
1115         if (pModule->GetAvailableClassCaseInsHash() == NULL) 
1116         {
1117             EEClassHashTable *pNewClassCaseInsHash = pModule->GetAvailableClassHash()->MakeCaseInsensitiveTable(pModule, &amTracker);
1118
1119             LOG((LF_CLASSLOADER, LL_INFO10, "%s's classes being added to case insensitive hash table\n",
1120                  pModule->GetSimpleName()));
1121
1122             {
1123                 CANNOTTHROWCOMPLUSEXCEPTION();
1124                 FAULT_FORBID();
1125                 
1126                 amTracker.SuppressRelease();
1127                 pModule->SetAvailableClassCaseInsHash(pNewClassCaseInsHash);
1128                 FastInterlockDecrement((LONG*)&m_cUnhashedModules);
1129             }
1130         }
1131     }
1132 }
1133
1134 /*static*/
1135 void DECLSPEC_NORETURN ClassLoader::ThrowTypeLoadException(TypeKey *pKey,
1136                                                            UINT resIDWhy)
1137 {
1138     STATIC_CONTRACT_THROWS;
1139
1140     StackSString fullName;
1141     StackSString assemblyName;
1142     TypeString::AppendTypeKey(fullName, pKey);
1143     pKey->GetModule()->GetAssembly()->GetDisplayName(assemblyName);
1144     ::ThrowTypeLoadException(fullName, assemblyName, NULL, resIDWhy);        
1145 }
1146
1147 #endif
1148
1149
1150 TypeHandle ClassLoader::LoadConstructedTypeThrowing(TypeKey *pKey,
1151                                                     LoadTypesFlag fLoadTypes /*= LoadTypes*/,
1152                                                     ClassLoadLevel level /*=CLASS_LOADED*/,
1153                                                     const InstantiationContext *pInstContext /*=NULL*/)
1154 {
1155     CONTRACT(TypeHandle)
1156     {
1157         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1158         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1159         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1160         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
1161         PRECONDITION(CheckPointer(pKey));
1162         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1163         PRECONDITION(CheckPointer(pInstContext, NULL_OK));
1164         POSTCONDITION(CheckPointer(RETVAL, fLoadTypes==DontLoadTypes ? NULL_OK : NULL_NOT_OK));
1165         POSTCONDITION(RETVAL.IsNull() || RETVAL.GetLoadLevel() >= level);
1166         MODE_ANY;
1167         SUPPORTS_DAC;
1168     }
1169     CONTRACT_END
1170
1171     TypeHandle typeHnd;
1172     ClassLoadLevel existingLoadLevel = CLASS_LOAD_BEGIN;
1173
1174     // Lookup in the classes that this class loader knows about
1175
1176     if (pKey->HasInstantiation() && ClassLoader::IsTypicalSharedInstantiation(pKey->GetInstantiation()))
1177     {
1178         _ASSERTE(pKey->GetModule() == ComputeLoaderModule(pKey));
1179         typeHnd = pKey->GetModule()->LookupFullyCanonicalInstantiation(pKey->GetTypeToken(), &existingLoadLevel);
1180     }
1181
1182     if (typeHnd.IsNull())
1183     {
1184         typeHnd = LookupTypeHandleForTypeKey(pKey);
1185         if (!typeHnd.IsNull())
1186         {
1187             existingLoadLevel = typeHnd.GetLoadLevel();
1188             if (existingLoadLevel >= level)
1189                 g_IBCLogger.LogTypeHashTableAccess(&typeHnd);
1190         }
1191     }
1192
1193     // If something has been published in the tables, and it's at the right level, just return it
1194     if (!typeHnd.IsNull() && existingLoadLevel >= level)
1195     {
1196         RETURN typeHnd;
1197     }
1198
1199 #ifndef DACCESS_COMPILE
1200     if (typeHnd.IsNull() && pKey->HasInstantiation())
1201     {
1202         if (!Generics::CheckInstantiation(pKey->GetInstantiation()))
1203             pKey->GetModule()->GetAssembly()->ThrowTypeLoadException(pKey->GetModule()->GetMDImport(), pKey->GetTypeToken(), IDS_CLASSLOAD_INVALIDINSTANTIATION);
1204     }
1205 #endif
1206
1207     // If we're not loading any types at all, then we're not creating
1208     // instantiations either because we're in FORBIDGC_LOADER_USE mode, so
1209     // we should bail out here.
1210     if (fLoadTypes == DontLoadTypes)
1211         RETURN TypeHandle();
1212
1213 #ifndef DACCESS_COMPILE
1214     // If we got here, we now have to allocate a new parameterized type.
1215     // By definition, forbidgc-users aren't allowed to reach this point.
1216     CONSISTENCY_CHECK(!FORBIDGC_LOADER_USE_ENABLED());
1217
1218     Module *pLoaderModule = ComputeLoaderModule(pKey);
1219     RETURN(pLoaderModule->GetClassLoader()->LoadTypeHandleForTypeKey(pKey, typeHnd, level, pInstContext));
1220 #else
1221     DacNotImpl();
1222     RETURN(typeHnd);
1223 #endif
1224 }
1225
1226
1227 /*static*/
1228 void ClassLoader::EnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level)
1229 {
1230     CONTRACTL
1231     {
1232         PRECONDITION(CheckPointer(typeHnd));
1233         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1234         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1235         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1236         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1237         if (FORBIDGC_LOADER_USE_ENABLED()) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); } 
1238         SUPPORTS_DAC;
1239
1240         MODE_ANY;
1241     }
1242     CONTRACTL_END
1243
1244 #ifndef DACCESS_COMPILE // Nothing to do for the DAC case
1245
1246     if (typeHnd.GetLoadLevel() < level)
1247     {
1248 #ifdef FEATURE_PREJIT
1249         if (typeHnd.GetLoadLevel() == CLASS_LOAD_UNRESTOREDTYPEKEY)
1250         {
1251             typeHnd.DoRestoreTypeKey();
1252         }        
1253 #endif
1254         if (level > CLASS_LOAD_UNRESTORED)
1255         {
1256             TypeKey typeKey = typeHnd.GetTypeKey();
1257             
1258             Module *pLoaderModule = ComputeLoaderModule(&typeKey);
1259             pLoaderModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, typeHnd, level);
1260         }
1261     }
1262
1263 #endif // DACCESS_COMPILE
1264 }
1265
1266 /*static*/
1267 void ClassLoader::TryEnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level)
1268 {
1269     WRAPPER_NO_CONTRACT;
1270
1271 #ifndef DACCESS_COMPILE // Nothing to do for the DAC case
1272
1273     EX_TRY
1274     {
1275         ClassLoader::EnsureLoaded(typeHnd, level);
1276     }
1277     EX_CATCH
1278     {
1279         // Some type may not load successfully. For eg. generic instantiations
1280         // that do not satisfy the constraints of the type arguments.
1281     }
1282     EX_END_CATCH(RethrowTerminalExceptions);
1283
1284 #endif // DACCESS_COMPILE
1285 }
1286
1287 // This is separated out to avoid the overhead of C++ exception handling in the non-locking case.
1288 /* static */
1289 TypeHandle ClassLoader::LookupTypeKeyUnderLock(TypeKey *pKey,
1290                                                EETypeHashTable *pTable,
1291                                                CrstBase *pLock)
1292 {
1293     WRAPPER_NO_CONTRACT;
1294     SUPPORTS_DAC;
1295
1296     // m_AvailableTypesLock has to be taken in cooperative mode to avoid deadlocks during GC
1297     GCX_MAYBE_COOP_NO_THREAD_BROKEN(!IsGCThread());
1298
1299     CrstHolder ch(pLock);
1300     return pTable->GetValue(pKey);
1301 }
1302
1303 /* static */
1304 TypeHandle ClassLoader::LookupTypeKey(TypeKey *pKey,
1305                                       EETypeHashTable *pTable,
1306                                       CrstBase *pLock,
1307                                       BOOL fCheckUnderLock)
1308 {
1309     CONTRACTL {
1310         NOTHROW;
1311         GC_NOTRIGGER; 
1312         FORBID_FAULT;
1313         PRECONDITION(CheckPointer(pKey));
1314         PRECONDITION(pKey->IsConstructed());
1315         PRECONDITION(CheckPointer(pTable));
1316         PRECONDITION(!fCheckUnderLock || CheckPointer(pLock));
1317         MODE_ANY;
1318         SUPPORTS_DAC;
1319     } CONTRACTL_END;
1320
1321     TypeHandle th;
1322
1323     if (fCheckUnderLock)
1324     {
1325         th = LookupTypeKeyUnderLock(pKey, pTable, pLock);
1326     }
1327     else
1328     {
1329         th = pTable->GetValue(pKey);
1330     }
1331     return th;
1332 }
1333
1334
1335 #ifdef FEATURE_PREJIT
1336 /* static */
1337 TypeHandle ClassLoader::LookupInPreferredZapModule(TypeKey *pKey, BOOL fCheckUnderLock)
1338 {
1339     CONTRACTL {
1340         NOTHROW;
1341         GC_NOTRIGGER; 
1342         FORBID_FAULT;
1343         PRECONDITION(CheckPointer(pKey));
1344         PRECONDITION(pKey->IsConstructed());
1345         MODE_ANY;
1346         SUPPORTS_DAC;
1347     } CONTRACTL_END;
1348
1349     // First look for an NGEN'd type in the preferred ngen module
1350     TypeHandle th;
1351     PTR_Module pPreferredZapModule = Module::ComputePreferredZapModule(pKey);
1352     
1353     if (pPreferredZapModule != NULL && pPreferredZapModule->HasNativeImage())
1354     {
1355         th = LookupTypeKey(pKey,
1356                            pPreferredZapModule->GetAvailableParamTypes(),
1357                            &pPreferredZapModule->GetClassLoader()->m_AvailableTypesLock,
1358                            fCheckUnderLock);
1359     }
1360
1361     return th;
1362 }
1363 #endif // FEATURE_PREJIT
1364
1365
1366 /* static */
1367 TypeHandle ClassLoader::LookupInLoaderModule(TypeKey *pKey, BOOL fCheckUnderLock)
1368 {
1369     CONTRACTL {
1370         NOTHROW;
1371         GC_NOTRIGGER; 
1372         FORBID_FAULT;
1373         PRECONDITION(CheckPointer(pKey));
1374         PRECONDITION(pKey->IsConstructed());
1375         MODE_ANY;
1376         SUPPORTS_DAC;
1377     } CONTRACTL_END;
1378
1379     Module *pLoaderModule = ComputeLoaderModule(pKey);
1380     PREFIX_ASSUME(pLoaderModule!=NULL);
1381     
1382     return LookupTypeKey(pKey,
1383                          pLoaderModule->GetAvailableParamTypes(),
1384                          &pLoaderModule->GetClassLoader()->m_AvailableTypesLock,
1385                          fCheckUnderLock);
1386 }
1387
1388
1389 /* static */
1390 TypeHandle ClassLoader::LookupTypeHandleForTypeKey(TypeKey *pKey)
1391 {
1392     WRAPPER_NO_CONTRACT;
1393     SUPPORTS_DAC;
1394
1395     // Make an initial lookup without taking any locks.
1396     TypeHandle th = LookupTypeHandleForTypeKeyInner(pKey, FALSE);
1397
1398     // A non-null TypeHandle for the above lookup indicates success
1399     // A null TypeHandle only indicates "well, it might have been there,
1400     // try again with a lock".  This kind of negative result will
1401     // only happen while accessing the underlying EETypeHashTable 
1402     // during a resize, i.e. very rarely. In such a case, we just
1403     // perform the lookup again, but indicate that appropriate locks
1404     // should be taken.
1405
1406     if (th.IsNull())
1407     {
1408         th = LookupTypeHandleForTypeKeyInner(pKey, TRUE);
1409     }
1410
1411     return th;
1412 }
1413 /* static */
1414 TypeHandle ClassLoader::LookupTypeHandleForTypeKeyInner(TypeKey *pKey, BOOL fCheckUnderLock)
1415 {
1416     CONTRACTL
1417     {
1418         NOTHROW;
1419         GC_NOTRIGGER; 
1420         FORBID_FAULT;
1421         PRECONDITION(CheckPointer(pKey));
1422         MODE_ANY;
1423         SUPPORTS_DAC;
1424     }
1425     CONTRACTL_END
1426
1427     // Check if it's the typical instantiation.  In this case it's not stored in the same
1428     // way as other constructed types.
1429     if (!pKey->IsConstructed() || 
1430         (pKey->GetKind() == ELEMENT_TYPE_CLASS && ClassLoader::IsTypicalInstantiation(pKey->GetModule(), 
1431                                                                                       pKey->GetTypeToken(),
1432                                                                                       pKey->GetInstantiation())))
1433     {
1434         return TypeHandle(pKey->GetModule()->LookupTypeDef(pKey->GetTypeToken()));
1435     }
1436
1437 #ifdef FEATURE_PREJIT
1438     // The following ways of finding a constructed type should be mutually exclusive!
1439     //  1. Look for a zapped item in the PreferredZapModule
1440     //  2. Look for a unzapped (JIT-loaded) item in the LoaderModule
1441
1442     TypeHandle thPZM = LookupInPreferredZapModule(pKey, fCheckUnderLock);
1443     if (!thPZM.IsNull())
1444     {
1445         return thPZM;
1446     }
1447 #endif // FEATURE_PREJIT
1448
1449     // Next look in the loader module.  This is where the item is guaranteed to live if
1450     // it is not latched from an NGEN image, i.e. if it is JIT loaded. 
1451     // If the thing is not NGEN'd then this may
1452     // be different to pPreferredZapModule.  If they are the same then 
1453     // we can reuse the results of the lookup above.
1454     TypeHandle thLM = LookupInLoaderModule(pKey, fCheckUnderLock);
1455     if (!thLM.IsNull())
1456     {
1457         return thLM;
1458     }
1459
1460     return TypeHandle();
1461 }
1462
1463 // FindClassModuleThrowing discovers which module the type you're looking for is in and loads the Module if necessary.
1464 // Basically, it iterates through all of the assembly's modules until a name match is found in a module's
1465 // AvailableClassHashTable.
1466 //
1467 // The possible outcomes are:
1468 //
1469 //    - Function returns TRUE   - class exists and we successfully found/created the containing Module. See below
1470 //                                for how to deconstruct the results.
1471 //    - Function returns FALSE  - class affirmatively NOT found (that means it doesn't exist as a regular type although
1472 //                                  it could also be a parameterized type)
1473 //    - Function throws         - OOM or some other reason we couldn't do the job (if it's a case-sensitive search
1474 //                                  and you're looking for already loaded type or you've set the TokenNotToLoad.
1475 //                                  we are guaranteed not to find a reason to throw.)
1476 //
1477 //
1478 // If it succeeds (returns TRUE), one of the following will occur. Check (*pType)->IsNull() to discriminate.
1479 //
1480 //     1. *pType: set to the null TypeHandle()
1481 //        *ppModule: set to the owning Module
1482 //        *pmdClassToken: set to the typedef
1483 //        *pmdFoundExportedType: if this name bound to an ExportedType, this contains the mdtExportedType token (otherwise,
1484 //                               it's set to mdTokenNil.) You need this because in this case, *pmdClassToken is just
1485 //                               a best guess and you need to verify it. (The division of labor between this
1486 //                               and LoadTypeHandle could definitely be better!)
1487 //
1488 //     2. *pType: set to non-null TypeHandle()
1489 //        This means someone else had already done this same lookup before you and caused the actual
1490 //        TypeHandle to be cached. Since we know that's what you *really* wanted, we'll just forget the
1491 //        Module/typedef stuff and give you the actual TypeHandle.
1492 //
1493 //
1494 BOOL ClassLoader::FindClassModuleThrowing(
1495     const NameHandle *    pName, 
1496     TypeHandle *          pType, 
1497     mdToken *             pmdClassToken, 
1498     Module **             ppModule, 
1499     mdToken *             pmdFoundExportedType, 
1500     HashedTypeEntry *     pFoundEntry,
1501     Module *              pLookInThisModuleOnly, 
1502     Loader::LoadFlag      loadFlag)
1503 {
1504     CONTRACTL
1505     {
1506         INSTANCE_CHECK;
1507         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1508         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1509         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1510         PRECONDITION(CheckPointer(pName));
1511         PRECONDITION(CheckPointer(ppModule));
1512         MODE_ANY;
1513         SUPPORTS_DAC;
1514     }
1515     CONTRACTL_END
1516
1517     // Note that the type name is expected to be lower-cased by the caller for case-insensitive lookups
1518
1519     NameHandleTable nhTable = pName->GetTable();
1520
1521     // Remember if there are any unhashed modules.  We must do this before
1522     // the actual look to avoid a race condition with other threads doing lookups.
1523 #ifdef LOGGING
1524     BOOL incomplete = (m_cUnhashedModules > 0);
1525 #endif
1526
1527     HashDatum Data;
1528     EEClassHashTable * pTable = NULL;
1529     HashedTypeEntry foundEntry;
1530     BOOL needsToBuildHashtable;
1531     GetClassValue(nhTable, pName, &Data, &pTable, pLookInThisModuleOnly, &foundEntry, loadFlag, needsToBuildHashtable);
1532
1533     // In the case of R2R modules, the search is only performed in the hashtable saved in the 
1534     // R2R image, and this is why we return (whether we found a valid typedef token or not).
1535     // Note: case insensitive searches are not used/supported in R2R images.
1536     if (foundEntry.GetEntryType() == HashedTypeEntry::EntryType::IsHashedTokenEntry)
1537     {
1538         *pType = TypeHandle();
1539         HashedTypeEntry::TokenTypeEntry tokenAndModulePair = foundEntry.GetTokenBasedEntryValue();
1540         switch (TypeFromToken(tokenAndModulePair.m_TypeToken))
1541         {
1542         case mdtTypeDef:
1543             *pmdClassToken = tokenAndModulePair.m_TypeToken;
1544             *pmdFoundExportedType = mdTokenNil;
1545             break;
1546         case mdtExportedType:
1547             *pmdClassToken = mdTokenNil;
1548             *pmdFoundExportedType = tokenAndModulePair.m_TypeToken;
1549             break;
1550         default:
1551             _ASSERT(false);
1552             return FALSE;
1553         }
1554         *ppModule = tokenAndModulePair.m_pModule;
1555         if (pFoundEntry != NULL)
1556             *pFoundEntry = foundEntry;
1557
1558         return TRUE;
1559     }
1560
1561     EEClassHashEntry_t * pBucket = foundEntry.GetClassHashBasedEntryValue();
1562
1563     if (pBucket == NULL)
1564     {
1565         AvailableClasses_LockHolder lh(this);
1566
1567         // Try again with the lock.  This will protect against another thread reallocating
1568         // the hash table underneath us
1569         GetClassValue(nhTable, pName, &Data, &pTable, pLookInThisModuleOnly, &foundEntry, loadFlag, needsToBuildHashtable);
1570         pBucket = foundEntry.GetClassHashBasedEntryValue();
1571
1572 #ifndef DACCESS_COMPILE
1573         if (needsToBuildHashtable && (pBucket == NULL) && (m_cUnhashedModules > 0))
1574         {
1575             _ASSERT(needsToBuildHashtable);
1576
1577             if (nhTable == nhCaseInsensitive)
1578             {
1579                 LazyPopulateCaseInsensitiveHashTables();
1580             }
1581             else
1582             {
1583                 // Note: This codepath is only valid for R2R scenarios
1584                 LazyPopulateCaseSensitiveHashTables();
1585             }
1586
1587             // Try yet again with the new classes added
1588             GetClassValue(nhTable, pName, &Data, &pTable, pLookInThisModuleOnly, &foundEntry, loadFlag, needsToBuildHashtable);
1589             pBucket = foundEntry.GetClassHashBasedEntryValue();
1590             _ASSERT(!needsToBuildHashtable);
1591         }
1592 #endif
1593     }
1594
1595     // Same check as above, but this time we've checked with the lock so the table will be populated
1596     if (pBucket == NULL)
1597     {
1598 #if defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
1599         LPCUTF8 szName = pName->GetName();
1600         if (szName == NULL)
1601             szName = "<UNKNOWN>";
1602         LOG((LF_CLASSLOADER, LL_INFO10, "Failed to find type \"%s\", assembly \"%ws\" in hash table. Incomplete = %d\n",
1603             szName, GetAssembly()->GetDebugName(), incomplete));
1604 #endif
1605         return FALSE;
1606     }
1607
1608     if (pName->GetTable() == nhCaseInsensitive)
1609     {
1610         _ASSERTE(Data);
1611         pBucket = PTR_EEClassHashEntry(Data);
1612         Data = pBucket->GetData();
1613     }
1614
1615     // Lower bit is a discriminator.  If the lower bit is NOT SET, it means we have
1616     // a TypeHandle. Otherwise, we have a Module/CL.
1617     if ((dac_cast<TADDR>(Data) & EECLASSHASH_TYPEHANDLE_DISCR) == 0)
1618     {
1619         TypeHandle t = TypeHandle::FromPtr(Data);
1620         _ASSERTE(!t.IsNull());
1621
1622         *pType = t;
1623         if (pFoundEntry != NULL)
1624         {
1625             pFoundEntry->SetClassHashBasedEntryValue(pBucket);
1626         }
1627         return TRUE;
1628     }
1629
1630     // We have a Module/CL
1631     if (!pTable->UncompressModuleAndClassDef(Data, 
1632                                              loadFlag, 
1633                                              ppModule, 
1634                                              pmdClassToken, 
1635                                              pmdFoundExportedType))
1636     {
1637         _ASSERTE(loadFlag != Loader::Load);
1638         return FALSE;
1639     }
1640
1641     *pType = TypeHandle();
1642     if (pFoundEntry != NULL)
1643     {
1644         pFoundEntry->SetClassHashBasedEntryValue(pBucket);
1645     }
1646     return TRUE;
1647 } // ClassLoader::FindClassModuleThrowing
1648
1649 #ifndef DACCESS_COMPILE
1650 // Returns true if the full name (namespace+name) of pName matches that
1651 // of typeHnd; otherwise false. Because this is nothrow, it will default
1652 // to false for all exceptions (such as OOM).
1653 bool CompareNameHandleWithTypeHandleNoThrow(
1654     const NameHandle * pName, 
1655     TypeHandle         typeHnd)
1656 {
1657     bool fRet = false;
1658     
1659     EX_TRY
1660     {
1661         // This block is specifically designed to handle transient faults such
1662         // as OOM exceptions.
1663         CONTRACT_VIOLATION(FaultViolation | ThrowsViolation);
1664         StackSString ssBuiltName;
1665         ns::MakePath(ssBuiltName,
1666                      StackSString(SString::Utf8, pName->GetNameSpace()),
1667                      StackSString(SString::Utf8, pName->GetName()));
1668         StackSString ssName;
1669         typeHnd.GetName(ssName);
1670         fRet = ssName.Equals(ssBuiltName) == TRUE;
1671     }
1672     EX_CATCH
1673     {
1674         // Technically, the above operations should never result in a non-OOM
1675         // exception, but we'll put the rethrow line in there just in case.
1676         CONSISTENCY_CHECK(!GET_EXCEPTION()->IsTerminal());
1677         RethrowTerminalExceptions;
1678     }
1679     EX_END_CATCH(SwallowAllExceptions);
1680     
1681     return fRet;
1682 }
1683 #endif // #ifndef DACCESS_COMPILE
1684
1685 // 1024 seems like a good bet at detecting a loop in the type forwarding.
1686 static const UINT32 const_cMaxTypeForwardingChainSize = 1024;
1687
1688 // Does not throw an exception if the type was not found.  Use LoadTypeHandleThrowIfFailed()
1689 // instead if you need that.
1690 // 
1691 // Returns:
1692 //  pName->m_pBucket 
1693 //    Will be set to the 'final' TypeDef bucket if pName->GetTokenType() is mdtBaseType.
1694 // 
1695 TypeHandle 
1696 ClassLoader::LoadTypeHandleThrowing(
1697     NameHandle * pName, 
1698     ClassLoadLevel level, 
1699     Module *       pLookInThisModuleOnly /*=NULL*/)
1700 {
1701     CONTRACT(TypeHandle) {
1702         INSTANCE_CHECK;
1703         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1704         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1705         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1706         DAC_LOADS_TYPE(level, !pName->OKToLoad()); 
1707         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1708         PRECONDITION(CheckPointer(pName));
1709         POSTCONDITION(RETVAL.IsNull() || RETVAL.GetLoadLevel() >= level);
1710         MODE_ANY;
1711         SUPPORTS_DAC;
1712     } CONTRACT_END
1713
1714     TypeHandle typeHnd;
1715     Module * pFoundModule = NULL;
1716     mdToken FoundCl;
1717     HashedTypeEntry foundEntry;
1718     mdExportedType FoundExportedType = mdTokenNil;
1719
1720     UINT32 cLoopIterations = 0;
1721
1722     ClassLoader * pClsLdr = this;
1723
1724     while (true)
1725     {
1726         if (cLoopIterations++ >= const_cMaxTypeForwardingChainSize)
1727         {   // If we've looped too many times due to type forwarding, return null TypeHandle
1728             // Would prefer to return a format exception, but the original behaviour
1729             // was to detect a stack overflow possibility and return a null, and
1730             // so we need to maintain this.
1731             typeHnd = TypeHandle();
1732             break;
1733         }
1734         
1735         // Look outside the lock (though we're actually still a long way from the
1736         // lock at this point...).  This may discover that the type is actually
1737         // defined in another module...
1738         
1739         if (!pClsLdr->FindClassModuleThrowing(
1740                 pName, 
1741                 &typeHnd, 
1742                 &FoundCl, 
1743                 &pFoundModule, 
1744                 &FoundExportedType, 
1745                 &foundEntry,
1746                 pLookInThisModuleOnly, 
1747                 pName->OKToLoad() ? Loader::Load 
1748                                   : Loader::DontLoad))
1749         {   // Didn't find anything, no point looping indefinitely
1750             break;
1751         }
1752         _ASSERTE(!foundEntry.IsNull());
1753
1754         if (pName->GetTypeToken() == mdtBaseType)
1755         {   // We should return the found bucket in the pName
1756             pName->SetBucket(foundEntry);
1757         }
1758
1759         if (!typeHnd.IsNull())
1760         {   // Found the cached value, or a constructedtype
1761             if (typeHnd.GetLoadLevel() < level)
1762             {
1763                 typeHnd = pClsLdr->LoadTypeDefThrowing(
1764                     typeHnd.GetModule(),
1765                     typeHnd.GetCl(),
1766                     ClassLoader::ReturnNullIfNotFound, 
1767                     ClassLoader::PermitUninstDefOrRef, // When loading by name we always permit naked type defs/refs
1768                     pName->GetTokenNotToLoad(), 
1769                     level);
1770             }
1771             break;
1772         }
1773         
1774         // Found a cl, pModule pair            
1775         
1776         // If the found module's class loader is not the same as the current class loader,
1777         // then this is a forwarded type and we want to do something else (see 
1778         // code:#LoadTypeHandle_TypeForwarded).
1779         if (pFoundModule->GetClassLoader() == pClsLdr)
1780         {
1781             BOOL fTrustTD = TRUE;
1782 #ifndef DACCESS_COMPILE
1783             CONTRACT_VIOLATION(ThrowsViolation);
1784             BOOL fVerifyTD = FALSE;
1785             
1786             // If this is an exported type with a mdTokenNil class token, then then
1787             // exported type did not give a typedefID hint. We won't be able to trust the typedef
1788             // here.
1789             if ((FoundExportedType != mdTokenNil) && (FoundCl == mdTokenNil))
1790             {
1791                 fVerifyTD = TRUE;
1792                 fTrustTD = FALSE;
1793             }
1794             // verify that FoundCl is a valid token for pFoundModule, because
1795             // it may be just the hint saved in an ExportedType in another scope
1796             else if (fVerifyTD)
1797             {
1798                 fTrustTD = pFoundModule->GetMDImport()->IsValidToken(FoundCl);
1799             }                    
1800 #endif // #ifndef DACCESS_COMPILE
1801                 
1802             if (fTrustTD)
1803             {
1804                 typeHnd = pClsLdr->LoadTypeDefThrowing(
1805                     pFoundModule, 
1806                     FoundCl, 
1807                     ClassLoader::ReturnNullIfNotFound, 
1808                     ClassLoader::PermitUninstDefOrRef, // when loading by name we always permit naked type defs/refs
1809                     pName->GetTokenNotToLoad(), 
1810                     level);
1811             }                
1812 #ifndef DACCESS_COMPILE
1813             // If we used a TypeDef saved in a ExportedType, if we didn't verify
1814             // the hash for this internal module, don't trust the TD value.
1815             if (fVerifyTD)
1816             {
1817                 if (typeHnd.IsNull() || !CompareNameHandleWithTypeHandleNoThrow(pName, typeHnd))
1818                 {
1819                     if (SUCCEEDED(pClsLdr->FindTypeDefByExportedType(
1820                             pClsLdr->GetAssembly()->GetManifestImport(), 
1821                             FoundExportedType, 
1822                             pFoundModule->GetMDImport(), 
1823                             &FoundCl)))
1824                     {
1825                         typeHnd = pClsLdr->LoadTypeDefThrowing(
1826                             pFoundModule, 
1827                             FoundCl, 
1828                             ClassLoader::ReturnNullIfNotFound, 
1829                             ClassLoader::PermitUninstDefOrRef, 
1830                             pName->GetTokenNotToLoad(), 
1831                             level);
1832                     }
1833                     else
1834                     {
1835                         typeHnd = TypeHandle();
1836                     }
1837                 }
1838             }
1839 #endif // #ifndef DACCESS_COMPILE
1840             break;
1841         }
1842         else
1843         {   //#LoadTypeHandle_TypeForwarded
1844             // pName is a host instance so it's okay to set fields in it in a DAC build
1845             const HashedTypeEntry& bucket = pName->GetBucket();
1846
1847             // Reset pName's bucket entry
1848             if (bucket.GetEntryType() == HashedTypeEntry::IsHashedClassEntry && bucket.GetClassHashBasedEntryValue()->GetEncloser())
1849             {
1850                 // We will be searching for the type name again, so set the nesting/context type to the 
1851                 // encloser of just found type
1852                 pName->SetBucket(HashedTypeEntry().SetClassHashBasedEntryValue(bucket.GetClassHashBasedEntryValue()->GetEncloser()));
1853             }
1854             else
1855             {
1856                 pName->SetBucket(HashedTypeEntry());
1857             }
1858
1859             // Update the class loader for the new module/token pair.
1860             pClsLdr = pFoundModule->GetClassLoader();
1861             pLookInThisModuleOnly = NULL;
1862         }
1863
1864 #ifndef DACCESS_COMPILE
1865         // Replace AvailableClasses Module entry with found TypeHandle
1866         if (!typeHnd.IsNull() && 
1867             typeHnd.IsRestored() && 
1868             foundEntry.GetEntryType() == HashedTypeEntry::EntryType::IsHashedClassEntry &&
1869             (foundEntry.GetClassHashBasedEntryValue() != NULL) && 
1870             (foundEntry.GetClassHashBasedEntryValue()->GetData() != typeHnd.AsPtr()))
1871         {
1872             foundEntry.GetClassHashBasedEntryValue()->SetData(typeHnd.AsPtr());
1873         }
1874 #endif // !DACCESS_COMPILE
1875     }
1876
1877     RETURN typeHnd;
1878 } // ClassLoader::LoadTypeHandleThrowing
1879
1880 /* static */
1881 TypeHandle ClassLoader::LoadPointerOrByrefTypeThrowing(CorElementType typ, 
1882                                                        TypeHandle baseType,
1883                                                        LoadTypesFlag fLoadTypes/*=LoadTypes*/, 
1884                                                        ClassLoadLevel level/*=CLASS_LOADED*/)
1885 {
1886     CONTRACT(TypeHandle)
1887     {
1888         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1889         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1890         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1891         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
1892         MODE_ANY;
1893         PRECONDITION(CheckPointer(baseType));
1894         PRECONDITION(typ == ELEMENT_TYPE_BYREF || typ == ELEMENT_TYPE_PTR);
1895         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1896         POSTCONDITION(CheckPointer(RETVAL, ((fLoadTypes == LoadTypes) ? NULL_NOT_OK : NULL_OK)));
1897         SUPPORTS_DAC;
1898     }
1899     CONTRACT_END
1900
1901     TypeKey key(typ, baseType);
1902     RETURN(LoadConstructedTypeThrowing(&key, fLoadTypes, level));
1903 }
1904
1905 /* static */
1906 TypeHandle ClassLoader::LoadNativeValueTypeThrowing(TypeHandle baseType,
1907                                                     LoadTypesFlag fLoadTypes/*=LoadTypes*/, 
1908                                                     ClassLoadLevel level/*=CLASS_LOADED*/)
1909 {
1910     CONTRACT(TypeHandle)
1911     {
1912         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1913         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1914         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1915         MODE_ANY;
1916         PRECONDITION(CheckPointer(baseType));
1917         PRECONDITION(baseType.AsMethodTable()->IsValueType());
1918         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1919         POSTCONDITION(CheckPointer(RETVAL, ((fLoadTypes == LoadTypes) ? NULL_NOT_OK : NULL_OK)));
1920     }
1921     CONTRACT_END
1922
1923     TypeKey key(ELEMENT_TYPE_VALUETYPE, baseType);
1924     RETURN(LoadConstructedTypeThrowing(&key, fLoadTypes, level));
1925 }
1926
1927 /* static */
1928 TypeHandle ClassLoader::LoadFnptrTypeThrowing(BYTE callConv,
1929                                               DWORD ntypars,
1930                                               TypeHandle* inst, 
1931                                               LoadTypesFlag fLoadTypes/*=LoadTypes*/,
1932                                               ClassLoadLevel level/*=CLASS_LOADED*/)
1933 {
1934     CONTRACT(TypeHandle)
1935     {
1936         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1937         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1938         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
1939         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
1940         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1941         POSTCONDITION(CheckPointer(RETVAL, ((fLoadTypes == LoadTypes) ? NULL_NOT_OK : NULL_OK)));
1942         MODE_ANY;
1943         SUPPORTS_DAC;
1944     }
1945     CONTRACT_END
1946
1947     TypeKey key(callConv, ntypars, inst);
1948     RETURN(LoadConstructedTypeThrowing(&key, fLoadTypes, level));
1949 }
1950
1951 // Find an instantiation of a generic type if it has already been created.
1952 // If typeDef is not a generic type or is already instantiated then throw an exception.
1953 // If its arity does not match ntypars then throw an exception.
1954 // Value will be non-null if we're loading types.
1955 /* static */
1956 TypeHandle ClassLoader::LoadGenericInstantiationThrowing(Module *pModule,
1957                                                          mdTypeDef typeDef,
1958                                                          Instantiation inst,
1959                                                          LoadTypesFlag fLoadTypes/*=LoadTypes*/,
1960                                                          ClassLoadLevel level/*=CLASS_LOADED*/,
1961                                                          const InstantiationContext *pInstContext/*=NULL*/,
1962                                                          BOOL fFromNativeImage /*=FALSE*/)
1963 {
1964     // This can be called in FORBIDGC_LOADER_USE mode by the debugger to find
1965     // a particular generic type instance that is already loaded.
1966     CONTRACT(TypeHandle)
1967     {
1968         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
1969         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
1970         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
1971         PRECONDITION(CheckPointer(pModule));
1972         MODE_ANY;
1973         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
1974         PRECONDITION(CheckPointer(pInstContext, NULL_OK));
1975         POSTCONDITION(CheckPointer(RETVAL, ((fLoadTypes == LoadTypes) ? NULL_NOT_OK : NULL_OK)));
1976         SUPPORTS_DAC;
1977     }
1978     CONTRACT_END
1979
1980     // Essentially all checks to determine if a generic instantiation of a type
1981     // is well-formed go in this method, i.e. this is the 
1982     // "choke" point through which all attempts
1983     // to create an instantiation flow.  There is a similar choke point for generic
1984     // methods in genmeth.cpp.
1985
1986     if (inst.IsEmpty() || ClassLoader::IsTypicalInstantiation(pModule, typeDef, inst))
1987     {
1988         TypeHandle th = LoadTypeDefThrowing(pModule, typeDef, 
1989                                             ThrowIfNotFound,
1990                                             PermitUninstDefOrRef,
1991                                             fLoadTypes == DontLoadTypes ? tdAllTypes : tdNoTypes, 
1992                                             level, 
1993                                             fFromNativeImage ? NULL : &inst);
1994         _ASSERTE(th.GetNumGenericArgs() == inst.GetNumArgs());
1995         RETURN th;
1996     }
1997
1998     if (!fFromNativeImage)
1999     {
2000         TypeHandle th = ClassLoader::LoadTypeDefThrowing(pModule, typeDef, 
2001                                          ThrowIfNotFound,
2002                                          PermitUninstDefOrRef,
2003                                          fLoadTypes == DontLoadTypes ? tdAllTypes : tdNoTypes, 
2004                                          level, 
2005                                          fFromNativeImage ? NULL : &inst);
2006         _ASSERTE(th.GetNumGenericArgs() == inst.GetNumArgs());
2007     }
2008
2009     TypeKey key(pModule, typeDef, inst);
2010
2011 #ifndef DACCESS_COMPILE
2012     // To avoid loading useless shared instantiations, normalize shared instantiations to the canonical form 
2013     // (e.g. Dictionary<String,_Canon> -> Dictionary<_Canon,_Canon>)
2014     // The denormalized shared instantiations should be needed only during JITing, so it is fine to skip this
2015     // for DACCESS_COMPILE.
2016     if (TypeHandle::IsCanonicalSubtypeInstantiation(inst) && !IsCanonicalGenericInstantiation(inst))
2017     {
2018         RETURN(ClassLoader::LoadCanonicalGenericInstantiation(&key, fLoadTypes, level));
2019     }
2020 #endif
2021
2022     RETURN(LoadConstructedTypeThrowing(&key, fLoadTypes, level, pInstContext));
2023 }
2024
2025 //   For non-nested classes, gets the ExportedType name and finds the corresponding
2026 // TypeDef.
2027 //   For nested classes, gets the name of the ExportedType and its encloser.
2028 // Recursively gets and keeps the name for each encloser until we have the top
2029 // level one.  Gets the TypeDef token for that.  Then, returns from the
2030 // recursion, using the last found TypeDef token in order to find the
2031 // next nested level down TypeDef token.  Finally, returns the TypeDef
2032 // token for the type we care about.
2033 /*static*/
2034 HRESULT ClassLoader::FindTypeDefByExportedType(IMDInternalImport *pCTImport, mdExportedType mdCurrent,
2035                                                IMDInternalImport *pTDImport, mdTypeDef *mtd)
2036 {
2037     CONTRACTL
2038     {
2039         NOTHROW;
2040         GC_NOTRIGGER;
2041         FORBID_FAULT;
2042         MODE_ANY;
2043         SUPPORTS_DAC;
2044     }
2045     CONTRACTL_END
2046     
2047     mdToken mdImpl;
2048     LPCSTR szcNameSpace;
2049     LPCSTR szcName;
2050     HRESULT hr;
2051     
2052     IfFailRet(pCTImport->GetExportedTypeProps(
2053         mdCurrent,
2054         &szcNameSpace,
2055         &szcName,
2056         &mdImpl,
2057         NULL, //binding
2058         NULL)); //flags
2059     
2060     if ((TypeFromToken(mdImpl) == mdtExportedType) &&
2061         (mdImpl != mdExportedTypeNil)) {
2062         // mdCurrent is a nested ExportedType
2063         IfFailRet(FindTypeDefByExportedType(pCTImport, mdImpl, pTDImport, mtd));
2064         
2065         // Get TypeDef token for this nested type
2066         return pTDImport->FindTypeDef(szcNameSpace, szcName, *mtd, mtd);
2067     }
2068     
2069     // Get TypeDef token for this top-level type
2070     return pTDImport->FindTypeDef(szcNameSpace, szcName, mdTokenNil, mtd);
2071 }
2072
2073 #ifndef DACCESS_COMPILE
2074
2075 VOID ClassLoader::CreateCanonicallyCasedKey(LPCUTF8 pszNameSpace, LPCUTF8 pszName, __out LPUTF8 *ppszOutNameSpace, __out LPUTF8 *ppszOutName)
2076 {
2077     CONTRACTL
2078     {
2079         INSTANCE_CHECK;
2080         THROWS;
2081         GC_NOTRIGGER;
2082         INJECT_FAULT(COMPlusThrowOM(););
2083         MODE_ANY;
2084     }
2085     CONTRACTL_END
2086
2087     StackSString nameSpace(SString::Utf8, pszNameSpace);
2088     nameSpace.LowerCase();
2089
2090     StackScratchBuffer nameSpaceBuffer;
2091     pszNameSpace = nameSpace.GetUTF8(nameSpaceBuffer);
2092
2093
2094     StackSString name(SString::Utf8, pszName);
2095     name.LowerCase();
2096
2097     StackScratchBuffer nameBuffer;
2098     pszName = name.GetUTF8(nameBuffer);
2099
2100
2101    size_t iNSLength = strlen(pszNameSpace);
2102    size_t iNameLength = strlen(pszName);
2103
2104     //Calc & allocate path length
2105     //Includes terminating null
2106     S_SIZE_T allocSize = S_SIZE_T(iNSLength) + S_SIZE_T(iNameLength) + S_SIZE_T(2);
2107     AllocMemHolder<char> alloc(GetAssembly()->GetHighFrequencyHeap()->AllocMem(allocSize));
2108
2109     memcpy(*ppszOutNameSpace = (char*)alloc, pszNameSpace, iNSLength + 1);
2110     memcpy(*ppszOutName = (char*)alloc + iNSLength + 1, pszName, iNameLength + 1);
2111     
2112     alloc.SuppressRelease();
2113 }
2114
2115 #endif // #ifndef DACCESS_COMPILE
2116
2117
2118 //
2119 // Return a class that is already loaded
2120 // Only for type refs and type defs (not type specs)
2121 //
2122 /*static*/
2123 TypeHandle ClassLoader::LookupTypeDefOrRefInModule(Module *pModule, mdToken cl, ClassLoadLevel *pLoadLevel)
2124 {
2125     CONTRACT(TypeHandle)
2126     {
2127         NOTHROW;
2128         GC_NOTRIGGER;
2129         FORBID_FAULT;
2130         MODE_ANY;
2131         PRECONDITION(CheckPointer(pModule));
2132         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
2133         SUPPORTS_DAC;
2134     }
2135     CONTRACT_END
2136
2137     BAD_FORMAT_NOTHROW_ASSERT((TypeFromToken(cl) == mdtTypeRef ||
2138                        TypeFromToken(cl) == mdtTypeDef ||
2139                        TypeFromToken(cl) == mdtTypeSpec));
2140
2141     TypeHandle typeHandle;
2142
2143     if (TypeFromToken(cl) == mdtTypeDef)
2144         typeHandle = pModule->LookupTypeDef(cl, pLoadLevel);
2145     else if (TypeFromToken(cl) == mdtTypeRef)
2146     {
2147         typeHandle = pModule->LookupTypeRef(cl);
2148
2149         if (pLoadLevel && !typeHandle.IsNull())
2150         {
2151             *pLoadLevel = typeHandle.GetLoadLevel();
2152         }
2153     }
2154
2155     RETURN(typeHandle);
2156 }
2157
2158 DomainAssembly *ClassLoader::GetDomainAssembly()
2159 {
2160     WRAPPER_NO_CONTRACT;
2161     return GetAssembly()->GetDomainAssembly();
2162 }
2163
2164 #ifndef DACCESS_COMPILE
2165
2166 //
2167 // Free all modules associated with this loader
2168 //
2169 void ClassLoader::FreeModules()
2170 {
2171     CONTRACTL
2172     {
2173         INSTANCE_CHECK;
2174         NOTHROW;
2175         GC_TRIGGERS;
2176         MODE_PREEMPTIVE;
2177         DISABLED(FORBID_FAULT);  //Lots of crud to clean up to make this work
2178     }
2179     CONTRACTL_END;
2180
2181     Module *pManifest = NULL;
2182     if (GetAssembly() && (NULL != (pManifest = GetAssembly()->GetManifestModule()))) {
2183         // Unload the manifest last, since it contains the module list in its rid map
2184         ModuleIterator i = GetAssembly()->IterateModules();
2185         while (i.Next()) {
2186             // Have the module free its various tables and some of the EEClass links
2187             if (i.GetModule() != pManifest)
2188                 i.GetModule()->Destruct();
2189         }
2190         
2191         // Now do the manifest module.
2192         pManifest->Destruct();
2193     }
2194
2195 }
2196
2197 ClassLoader::~ClassLoader()
2198 {
2199     CONTRACTL
2200     {
2201         NOTHROW;
2202         DESTRUCTOR_CHECK;
2203         GC_TRIGGERS;
2204         MODE_PREEMPTIVE;
2205         DISABLED(FORBID_FAULT);  //Lots of crud to clean up to make this work
2206     }
2207     CONTRACTL_END
2208
2209 #ifdef _DEBUG
2210     // Do not walk m_pUnresolvedClassHash at destruct time as it is loaderheap allocated memory
2211     // and may already have been deallocated via an AllocMemTracker.
2212     m_pUnresolvedClassHash = (PendingTypeLoadTable*)(UINT_PTR)0xcccccccc;
2213 #endif
2214
2215 #ifdef _DEBUG
2216 //     LOG((
2217 //         LF_CLASSLOADER,
2218 //         INFO3,
2219 //         "Deleting classloader %x\n"
2220 //         "  >EEClass data:     %10d bytes\n"
2221 //         "  >Classname hash:   %10d bytes\n"
2222 //         "  >FieldDesc data:   %10d bytes\n"
2223 //         "  >MethodDesc data:  %10d bytes\n"
2224 //         "  >GCInfo:           %10d bytes\n"
2225 //         "  >Interface maps:   %10d bytes\n"
2226 //         "  >MethodTables:     %10d bytes\n"
2227 //         "  >Vtables:          %10d bytes\n"
2228 //         "  >Static fields:    %10d bytes\n"
2229 //         "# methods:           %10d\n"
2230 //         "# field descs:       %10d\n"
2231 //         "# classes:           %10d\n"
2232 //         "# dup intf slots:    %10d\n"
2233 //         "# array classrefs:   %10d\n"
2234 //         "Array class overhead:%10d bytes\n",
2235 //         this,
2236 //             m_dwEEClassData,
2237 //             m_pAvailableClasses->m_dwDebugMemory,
2238 //             m_dwFieldDescData,
2239 //             m_dwMethodDescData,
2240 //             m_dwGCSize,
2241 //             m_dwInterfaceMapSize,
2242 //             m_dwMethodTableSize,
2243 //             m_dwVtableData,
2244 //             m_dwStaticFieldData,
2245 //         m_dwDebugMethods,
2246 //         m_dwDebugFieldDescs,
2247 //         m_dwDebugClasses,
2248 //         m_dwDebugDuplicateInterfaceSlots,
2249 //     ));
2250 #endif
2251
2252     FreeModules();
2253
2254     m_UnresolvedClassLock.Destroy();
2255     m_AvailableClassLock.Destroy();
2256     m_AvailableTypesLock.Destroy();
2257 }
2258
2259
2260 //----------------------------------------------------------------------------
2261 // The constructor should only initialize enough to ensure that the destructor doesn't
2262 // crash. It cannot allocate or do anything that might fail as that would leave
2263 // the ClassLoader undestructable. Any such tasks should be done in ClassLoader::Init().
2264 //----------------------------------------------------------------------------
2265 ClassLoader::ClassLoader(Assembly *pAssembly)
2266 {
2267     CONTRACTL
2268     {
2269         CONSTRUCTOR_CHECK;
2270         NOTHROW;
2271         GC_NOTRIGGER;
2272         MODE_ANY;
2273         FORBID_FAULT;
2274     }
2275     CONTRACTL_END
2276
2277     m_pAssembly = pAssembly;
2278
2279     m_pUnresolvedClassHash          = NULL;
2280     m_cUnhashedModules              = 0;
2281
2282 #ifdef _DEBUG
2283     m_dwDebugMethods        = 0;
2284     m_dwDebugFieldDescs     = 0;
2285     m_dwDebugClasses        = 0;
2286     m_dwDebugDuplicateInterfaceSlots = 0;
2287     m_dwGCSize              = 0;
2288     m_dwInterfaceMapSize    = 0;
2289     m_dwMethodTableSize     = 0;
2290     m_dwVtableData          = 0;
2291     m_dwStaticFieldData     = 0;
2292     m_dwFieldDescData       = 0;
2293     m_dwMethodDescData      = 0;
2294     m_dwEEClassData         = 0;
2295 #endif
2296 }
2297
2298
2299 //----------------------------------------------------------------------------
2300 // This function completes the initialization of the ClassLoader. It can
2301 // assume the constructor is run and that the function is entered with
2302 // ClassLoader in a safely destructable state. This function can throw
2303 // but whether it throws or succeeds, it must leave the ClassLoader in a safely
2304 // destructable state.
2305 //----------------------------------------------------------------------------
2306 VOID ClassLoader::Init(AllocMemTracker *pamTracker)
2307 {
2308     STANDARD_VM_CONTRACT;
2309
2310     m_pUnresolvedClassHash = PendingTypeLoadTable::Create(GetAssembly()->GetLowFrequencyHeap(), 
2311                                                           UNRESOLVED_CLASS_HASH_BUCKETS, 
2312                                                           pamTracker);
2313
2314     m_UnresolvedClassLock.Init(CrstUnresolvedClassLock);
2315
2316     // This lock is taken within the classloader whenever we have to enter a
2317     // type in one of the modules governed by the loader.
2318     // The process of creating these types may be reentrant.  The ordering has
2319     // not yet been sorted out, and when we sort it out we should also modify the
2320     // ordering for m_AvailableTypesLock in BaseDomain.
2321     m_AvailableClassLock.Init(
2322                              CrstAvailableClass,
2323                              CRST_REENTRANCY);
2324
2325     // This lock is taken within the classloader whenever we have to insert a new param. type into the table
2326     // This lock also needs to be taken for a read operation in a GC_NOTRIGGER scope, thus the ANYMODE flag.
2327     m_AvailableTypesLock.Init(
2328                                   CrstAvailableParamTypes,
2329                                   (CrstFlags)(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD));
2330
2331 #ifdef _DEBUG
2332     CorTypeInfo::CheckConsistency();
2333 #endif
2334
2335 }
2336
2337 #endif // #ifndef DACCESS_COMPILE
2338
2339 /*static*/
2340 TypeHandle ClassLoader::LoadTypeDefOrRefOrSpecThrowing(Module *pModule,
2341                                                        mdToken typeDefOrRefOrSpec,
2342                                                        const SigTypeContext *pTypeContext,
2343                                                        NotFoundAction fNotFoundAction /* = ThrowIfNotFound */ ,
2344                                                        PermitUninstantiatedFlag fUninstantiated /* = FailIfUninstDefOrRef */,
2345                                                        LoadTypesFlag fLoadTypes/*=LoadTypes*/ ,
2346                                                        ClassLoadLevel level /* = CLASS_LOADED */,
2347                                                        BOOL dropGenericArgumentLevel /* = FALSE */,
2348                                                        const Substitution *pSubst)
2349 {
2350     CONTRACT(TypeHandle)
2351     {
2352         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
2353         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
2354         MODE_ANY;
2355         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
2356         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
2357         PRECONDITION(CheckPointer(pModule));
2358         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
2359         PRECONDITION(FORBIDGC_LOADER_USE_ENABLED() || GetAppDomain()->CheckCanLoadTypes(pModule->GetAssembly()));
2360         POSTCONDITION(CheckPointer(RETVAL, (fNotFoundAction == ThrowIfNotFound)? NULL_NOT_OK : NULL_OK));
2361     }
2362     CONTRACT_END
2363
2364     if (TypeFromToken(typeDefOrRefOrSpec) == mdtTypeSpec) 
2365     {
2366         ULONG cSig;
2367         PCCOR_SIGNATURE pSig;
2368         
2369         IMDInternalImport *pInternalImport = pModule->GetMDImport();
2370         if (FAILED(pInternalImport->GetTypeSpecFromToken(typeDefOrRefOrSpec, &pSig, &cSig)))
2371         {
2372 #ifndef DACCESS_COMPILE
2373             if (fNotFoundAction == ThrowIfNotFound)
2374             {
2375                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, typeDefOrRefOrSpec, IDS_CLASSLOAD_BADFORMAT);
2376             }
2377 #endif //!DACCESS_COMPILE
2378             RETURN (TypeHandle());
2379         }
2380         SigPointer sigptr(pSig, cSig);
2381         TypeHandle typeHnd = sigptr.GetTypeHandleThrowing(pModule, pTypeContext, fLoadTypes, 
2382                                                           level, dropGenericArgumentLevel, pSubst);
2383 #ifndef DACCESS_COMPILE
2384         if ((fNotFoundAction == ThrowIfNotFound) && typeHnd.IsNull())
2385             pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, typeDefOrRefOrSpec,
2386                                                            IDS_CLASSLOAD_GENERAL);
2387 #endif
2388         RETURN (typeHnd);
2389     }
2390     else
2391     {
2392         RETURN (LoadTypeDefOrRefThrowing(pModule, typeDefOrRefOrSpec, 
2393                                          fNotFoundAction, 
2394                                          fUninstantiated,
2395                                          ((fLoadTypes == LoadTypes) ? tdNoTypes : tdAllTypes), 
2396                                          level));
2397     }
2398 } // ClassLoader::LoadTypeDefOrRefOrSpecThrowing
2399
2400 // Given a token specifying a typeDef, and a module in which to
2401 // interpret that token, find or load the corresponding type handle.
2402 //
2403 //
2404 /*static*/
2405 TypeHandle ClassLoader::LoadTypeDefThrowing(Module *pModule,
2406                                             mdToken typeDef,
2407                                             NotFoundAction fNotFoundAction /* = ThrowIfNotFound */ ,
2408                                             PermitUninstantiatedFlag fUninstantiated /* = FailIfUninstDefOrRef */,
2409                                             mdToken tokenNotToLoad,
2410                                             ClassLoadLevel level, 
2411                                             Instantiation * pTargetInstantiation)
2412 {
2413
2414     CONTRACT(TypeHandle)
2415     {
2416         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
2417         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
2418         MODE_ANY;
2419         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
2420         DAC_LOADS_TYPE(level, !NameHandle::OKToLoad(typeDef, tokenNotToLoad));
2421         PRECONDITION(CheckPointer(pModule));
2422         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
2423         PRECONDITION(FORBIDGC_LOADER_USE_ENABLED()
2424                      || GetAppDomain()->CheckCanLoadTypes(pModule->GetAssembly()));
2425
2426         POSTCONDITION(CheckPointer(RETVAL, NameHandle::OKToLoad(typeDef, tokenNotToLoad) && (fNotFoundAction == ThrowIfNotFound) ? NULL_NOT_OK : NULL_OK));
2427         POSTCONDITION(RETVAL.IsNull() || RETVAL.GetCl() == typeDef);
2428         SUPPORTS_DAC;
2429     }
2430     CONTRACT_END;
2431
2432     TypeHandle typeHnd;
2433
2434     // First, attempt to find the class if it is already loaded
2435     ClassLoadLevel existingLoadLevel = CLASS_LOAD_BEGIN;
2436     typeHnd = pModule->LookupTypeDef(typeDef, &existingLoadLevel);
2437     if (!typeHnd.IsNull())
2438     {
2439 #ifndef DACCESS_COMPILE
2440         // If the type is loaded, we can do cheap arity verification
2441         if (pTargetInstantiation != NULL && pTargetInstantiation->GetNumArgs() != typeHnd.AsMethodTable()->GetNumGenericArgs())
2442             pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_TYPEWRONGNUMGENERICARGS);
2443 #endif
2444
2445         if (existingLoadLevel >= level)
2446             RETURN(typeHnd);
2447     }
2448
2449     IMDInternalImport *pInternalImport = pModule->GetMDImport();
2450
2451 #ifndef DACCESS_COMPILE
2452     if (typeHnd.IsNull() && pTargetInstantiation != NULL)
2453     {
2454         // If the type is not loaded yet, we have to do heavy weight arity verification based on metadata
2455         HENUMInternal hEnumGenericPars;
2456         HRESULT hr = pInternalImport->EnumInit(mdtGenericParam, typeDef, &hEnumGenericPars);
2457         if (FAILED(hr))
2458             pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, typeDef, IDS_CLASSLOAD_BADFORMAT);
2459         DWORD nGenericClassParams = pInternalImport->EnumGetCount(&hEnumGenericPars);
2460         pInternalImport->EnumClose(&hEnumGenericPars);
2461
2462         if (pTargetInstantiation->GetNumArgs() != nGenericClassParams)
2463             pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, typeDef, IDS_CLASSLOAD_TYPEWRONGNUMGENERICARGS);
2464     }
2465 #endif
2466
2467     if (IsNilToken(typeDef) || TypeFromToken(typeDef) != mdtTypeDef || !pInternalImport->IsValidToken(typeDef) )
2468     {
2469         LOG((LF_CLASSLOADER, LL_INFO10, "Bogus class token to load: 0x%08x\n", typeDef));
2470         typeHnd = TypeHandle();
2471     }
2472     else 
2473     {
2474         // *****************************************************************************
2475         //
2476         //             Important invariant:
2477         //
2478         // The rule here is that we never go to LoadTypeHandleForTypeKey if a Find should succeed.
2479         // This is vital, because otherwise a stack crawl will open up opportunities for
2480         // GC.  Since operations like setting up a GCFrame will trigger a crawl in stress
2481         // mode, a GC at that point would be disastrous.  We can't assert this, because
2482         // of race conditions.  (In other words, the type could suddently be find-able
2483         // because another thread loaded it while we were in this method.
2484
2485         // Not found - try to load it unless we are told not to
2486
2487 #ifndef DACCESS_COMPILE
2488         if ( !NameHandle::OKToLoad(typeDef, tokenNotToLoad) )
2489         {
2490             typeHnd = TypeHandle();
2491         }
2492         else
2493         {
2494             // Anybody who puts himself in a FORBIDGC_LOADER state has promised
2495             // to use us only for resolving, not loading. We are now transitioning into
2496             // loading.
2497 #ifdef _DEBUG_IMPL
2498             _ASSERTE(!FORBIDGC_LOADER_USE_ENABLED());
2499 #endif
2500             TRIGGERSGC();
2501
2502             if (pModule->IsReflection())
2503             {
2504                 // Don't try to load types that are not in available table, when this
2505                 // is an in-memory module.  Raise the type-resolve event instead.
2506                 typeHnd = TypeHandle();
2507
2508                 // Avoid infinite recursion
2509                 if (tokenNotToLoad != tdAllAssemblies)
2510                 {
2511                     AppDomain* pDomain = SystemDomain::GetCurrentDomain();
2512
2513                     LPUTF8 pszFullName;
2514                     LPCUTF8 className;
2515                     LPCUTF8 nameSpace;
2516                     if (FAILED(pInternalImport->GetNameOfTypeDef(typeDef, &className, &nameSpace)))
2517                     {
2518                         LOG((LF_CLASSLOADER, LL_INFO10, "Bogus TypeDef record while loading: 0x%08x\n", typeDef));
2519                         typeHnd = TypeHandle();
2520                     }
2521                     else
2522                     {
2523                         MAKE_FULL_PATH_ON_STACK_UTF8(pszFullName,
2524                                                         nameSpace,
2525                                                         className);
2526                         GCX_COOP();
2527                         ASSEMBLYREF asmRef = NULL;
2528                         DomainAssembly *pDomainAssembly = NULL;
2529                         GCPROTECT_BEGIN(asmRef);
2530
2531                         pDomainAssembly = pDomain->RaiseTypeResolveEventThrowing(
2532                             pModule->GetAssembly()->GetDomainAssembly(), 
2533                             pszFullName, &asmRef);
2534
2535                         if (asmRef != NULL)
2536                         {
2537                             _ASSERTE(pDomainAssembly != NULL);
2538                             if (pDomainAssembly->GetAssembly()->GetLoaderAllocator()->IsCollectible())
2539                             {
2540                                 if (!pModule->GetLoaderAllocator()->IsCollectible())
2541                                 {
2542                                     LOG((LF_CLASSLOADER, LL_INFO10, "Bad result from TypeResolveEvent while loader TypeDef record: 0x%08x\n", typeDef));
2543                                     COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
2544                                 }
2545
2546                                 pModule->GetLoaderAllocator()->EnsureReference(pDomainAssembly->GetAssembly()->GetLoaderAllocator());
2547                             }
2548                         }
2549                         GCPROTECT_END();
2550                         if (pDomainAssembly != NULL)
2551                         {
2552                             Assembly *pAssembly = pDomainAssembly->GetAssembly();
2553                                 
2554                             NameHandle name(nameSpace, className);
2555                             name.SetTypeToken(pModule, typeDef);
2556                             name.SetTokenNotToLoad(tdAllAssemblies);
2557                             typeHnd = pAssembly->GetLoader()->LoadTypeHandleThrowing(&name, level);
2558                         }
2559                     }
2560                 }
2561             }
2562             else
2563             {
2564                 TypeKey typeKey(pModule, typeDef);
2565                 typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, 
2566                                                                               typeHnd,
2567                                                                               level);
2568             }
2569         }
2570 #endif // !DACCESS_COMPILE
2571     }
2572
2573 #ifndef DACCESS_COMPILE
2574     if ((fUninstantiated == FailIfUninstDefOrRef) && !typeHnd.IsNull() && typeHnd.IsGenericTypeDefinition())
2575     {
2576         typeHnd = TypeHandle();
2577     }
2578
2579     if ((fNotFoundAction == ThrowIfNotFound) && typeHnd.IsNull() && (tokenNotToLoad != tdAllTypes))
2580     {
2581         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), 
2582                                                        typeDef,
2583                                                        IDS_CLASSLOAD_GENERAL);
2584     }
2585 #endif
2586     ;
2587     
2588     RETURN(typeHnd);
2589 }
2590
2591 // Given a token specifying a typeDef or typeRef, and a module in
2592 // which to interpret that token, find or load the corresponding type
2593 // handle.
2594 //
2595 /*static*/
2596 TypeHandle ClassLoader::LoadTypeDefOrRefThrowing(Module *pModule,
2597                                                  mdToken typeDefOrRef,
2598                                                  NotFoundAction fNotFoundAction /* = ThrowIfNotFound */ ,
2599                                                  PermitUninstantiatedFlag fUninstantiated /* = FailIfUninstDefOrRef */,
2600                                                  mdToken tokenNotToLoad,
2601                                                  ClassLoadLevel level)
2602 {
2603
2604     CONTRACT(TypeHandle)
2605     {
2606         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
2607         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
2608         MODE_ANY;
2609         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
2610         PRECONDITION(CheckPointer(pModule));
2611         PRECONDITION(level > CLASS_LOAD_BEGIN && level <= CLASS_LOADED);
2612         PRECONDITION(FORBIDGC_LOADER_USE_ENABLED()
2613                      || GetAppDomain()->CheckCanLoadTypes(pModule->GetAssembly()));
2614
2615         POSTCONDITION(CheckPointer(RETVAL, NameHandle::OKToLoad(typeDefOrRef, tokenNotToLoad) && (fNotFoundAction == ThrowIfNotFound) ? NULL_NOT_OK : NULL_OK));
2616         POSTCONDITION(level <= CLASS_LOAD_UNRESTORED || RETVAL.IsNull() || RETVAL.IsRestored());
2617         SUPPORTS_DAC;
2618     }
2619     CONTRACT_END;
2620
2621     // NotFoundAction could be the bizarre 'ThrowButNullV11McppWorkaround', 
2622     //  which means ThrowIfNotFound EXCEPT if this might be the Everett MCPP 
2623     //  Nil-token ResolutionScope for value type.  In that case, it means 
2624     //  ReturnNullIfNotFound.
2625     // If we have ThrowButNullV11McppWorkaround, remember that NULL *might*
2626     //  be OK if there is no resolution scope, but change the value to
2627     //  ThrowIfNotFound.
2628     BOOLEAN bReturnNullOkWhenNoResolutionScope = false;
2629     if (fNotFoundAction == ThrowButNullV11McppWorkaround)
2630     {
2631         bReturnNullOkWhenNoResolutionScope = true;
2632         fNotFoundAction = ThrowIfNotFound;
2633     }
2634
2635     // First, attempt to find the class if it is already loaded
2636     ClassLoadLevel existingLoadLevel = CLASS_LOAD_BEGIN;
2637     TypeHandle typeHnd = LookupTypeDefOrRefInModule(pModule, typeDefOrRef, &existingLoadLevel);
2638     if (!typeHnd.IsNull())
2639     {
2640         if (existingLoadLevel < level)
2641         {
2642             pModule = typeHnd.GetModule();
2643             typeDefOrRef = typeHnd.GetCl();
2644         }
2645     }
2646
2647     if (!typeHnd.IsNull() && existingLoadLevel >= level)
2648     {
2649         // perform the check that it's not an uninstantiated TypeDef/TypeRef
2650         // being used inappropriately.
2651         if (!((fUninstantiated == FailIfUninstDefOrRef) && !typeHnd.IsNull() && typeHnd.IsGenericTypeDefinition()))
2652         {
2653             RETURN(typeHnd);
2654         }
2655     }
2656     else
2657     {
2658         // otherwise try to resolve the TypeRef and/or load the corresponding TypeDef
2659         IMDInternalImport *pInternalImport = pModule->GetMDImport();
2660         mdToken tokType = TypeFromToken(typeDefOrRef);
2661         
2662         if (IsNilToken(typeDefOrRef) || ((tokType != mdtTypeDef)&&(tokType != mdtTypeRef))
2663             || !pInternalImport->IsValidToken(typeDefOrRef) ) 
2664         {
2665 #ifdef _DEBUG
2666             LOG((LF_CLASSLOADER, LL_INFO10, "Bogus class token to load: 0x%08x\n", typeDefOrRef));
2667 #endif
2668             
2669             typeHnd = TypeHandle();
2670         }
2671         
2672         else if (tokType == mdtTypeRef) 
2673         {
2674             BOOL fNoResolutionScope;
2675             Module *pFoundModule = Assembly::FindModuleByTypeRef(pModule, typeDefOrRef,
2676                                                                   tokenNotToLoad==tdAllTypes ? 
2677                                                                                   Loader::DontLoad :
2678                                                                                   Loader::Load,
2679                                                                  &fNoResolutionScope);
2680
2681             if (pFoundModule != NULL)
2682             {
2683                 
2684                 // Not in my module, have to look it up by name.  This is the primary path
2685                 // taken by the TypeRef case, i.e. we've resolve a TypeRef to a TypeDef/Module
2686                 // pair.
2687                 LPCUTF8 pszNameSpace;
2688                 LPCUTF8 pszClassName;
2689                 if (FAILED(pInternalImport->GetNameOfTypeRef(
2690                     typeDefOrRef, 
2691                     &pszNameSpace, 
2692                     &pszClassName)))
2693                 {
2694                     typeHnd = TypeHandle();
2695                 }
2696                 else
2697                 {
2698                     if (fNoResolutionScope)
2699                     {
2700                         // Everett C++ compiler can generate a TypeRef with RS=0
2701                         // without respective TypeDef for unmanaged valuetypes,
2702                         // referenced only by pointers to them,
2703                         // so we can fail to load legally w/ no exception
2704                         typeHnd = ClassLoader::LoadTypeByNameThrowing(pFoundModule->GetAssembly(),
2705                                                                       pszNameSpace,
2706                                                                       pszClassName,
2707                                                                       ClassLoader::ReturnNullIfNotFound,
2708                                                                       tokenNotToLoad==tdAllTypes ? ClassLoader::DontLoadTypes : ClassLoader::LoadTypes,
2709                                                                       level);
2710                         
2711                         if(typeHnd.IsNull() && bReturnNullOkWhenNoResolutionScope)
2712                         {
2713                             fNotFoundAction = ReturnNullIfNotFound;
2714                             RETURN(typeHnd);
2715                         }
2716                     }
2717                     else
2718                     {
2719                         NameHandle nameHandle(pModule, typeDefOrRef);
2720                         nameHandle.SetName(pszNameSpace, pszClassName);
2721                         nameHandle.SetTokenNotToLoad(tokenNotToLoad);
2722                         typeHnd = pFoundModule->GetClassLoader()->
2723                             LoadTypeHandleThrowIfFailed(&nameHandle, level,
2724                                                         pFoundModule->IsReflection() ? NULL : pFoundModule);
2725                     }
2726                 }
2727                 
2728 #ifndef DACCESS_COMPILE
2729                 if (!(typeHnd.IsNull()))
2730                     pModule->StoreTypeRef(typeDefOrRef, typeHnd);
2731 #endif
2732             }
2733         }
2734         else
2735         {
2736             // This is the mdtTypeDef case...
2737             typeHnd = LoadTypeDefThrowing(pModule, typeDefOrRef, 
2738                                           fNotFoundAction, 
2739                                           fUninstantiated, 
2740                                           tokenNotToLoad, 
2741                                           level);
2742         }
2743     }
2744     TypeHandle thRes = typeHnd;
2745     
2746     // reject the load if it's an uninstantiated TypeDef/TypeRef
2747     // being used inappropriately.  
2748     if ((fUninstantiated == FailIfUninstDefOrRef) && !typeHnd.IsNull() && typeHnd.IsGenericTypeDefinition())
2749         thRes = TypeHandle();
2750
2751     // perform the check to throw when the thing is not found
2752     if ((fNotFoundAction == ThrowIfNotFound) && thRes.IsNull() && (tokenNotToLoad != tdAllTypes))
2753     {
2754 #ifndef DACCESS_COMPILE
2755         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(),
2756                                                        typeDefOrRef,
2757                                                        IDS_CLASSLOAD_GENERAL);
2758 #else
2759         DacNotImpl();
2760 #endif
2761     }
2762
2763     RETURN(thRes);
2764 }
2765
2766 /*static*/
2767 BOOL 
2768 ClassLoader::ResolveTokenToTypeDefThrowing(
2769     Module *         pTypeRefModule, 
2770     mdTypeRef        typeRefToken, 
2771     Module **        ppTypeDefModule, 
2772     mdTypeDef *      pTypeDefToken, 
2773     Loader::LoadFlag loadFlag,
2774     BOOL *           pfUsesTypeForwarder) // The semantic of this parameter: TRUE if a type forwarder is found. It is never set to FALSE.
2775 {
2776     CONTRACT(BOOL)
2777     {
2778         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
2779         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
2780         MODE_ANY;
2781         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
2782         PRECONDITION(CheckPointer(pTypeRefModule));
2783         SUPPORTS_DAC;
2784     }
2785     CONTRACT_END;
2786     
2787     // It's a TypeDef already
2788     if (TypeFromToken(typeRefToken) == mdtTypeDef)
2789     {
2790         if (ppTypeDefModule != NULL)
2791             *ppTypeDefModule = pTypeRefModule;
2792         if (pTypeDefToken != NULL)
2793             *pTypeDefToken = typeRefToken;
2794         RETURN TRUE;
2795     }
2796     
2797     TypeHandle typeHnd = pTypeRefModule->LookupTypeRef(typeRefToken);
2798     
2799     // Type is already (partially) loaded and cached in the module's TypeRef table
2800     // Do not return here if we are checking for type forwarders
2801     if (!typeHnd.IsNull() && (pfUsesTypeForwarder == NULL))
2802     {
2803         if (ppTypeDefModule != NULL)
2804             *ppTypeDefModule = typeHnd.GetModule();
2805         if (pTypeDefToken != NULL)
2806             *pTypeDefToken = typeHnd.GetCl();
2807         RETURN TRUE;
2808     }
2809     
2810     BOOL fNoResolutionScope; //not used
2811     Module * pFoundRefModule = Assembly::FindModuleByTypeRef(
2812         pTypeRefModule, 
2813         typeRefToken, 
2814         loadFlag, 
2815         &fNoResolutionScope);
2816     
2817     if (pFoundRefModule == NULL) 
2818     {   // We didn't find the TypeRef anywhere
2819         RETURN FALSE;
2820     }
2821     
2822     // If checking for type forwarders, then we can see if a type forwarder was used based on the output of 
2823     // pFoundRefModule and typeHnd (if typeHnd is set)
2824     if (!typeHnd.IsNull() && (pfUsesTypeForwarder != NULL))
2825     {
2826         if (typeHnd.GetModule() != pFoundRefModule)
2827         {
2828             *pfUsesTypeForwarder = TRUE;
2829         }
2830
2831         if (ppTypeDefModule != NULL)
2832             *ppTypeDefModule = typeHnd.GetModule();
2833         if (pTypeDefToken != NULL)
2834             *pTypeDefToken = typeHnd.GetCl();
2835         RETURN TRUE;
2836     }
2837
2838     // Not in my module, have to look it up by name
2839     LPCUTF8 pszNameSpace;
2840     LPCUTF8 pszClassName;
2841     if (FAILED(pTypeRefModule->GetMDImport()->GetNameOfTypeRef(typeRefToken, &pszNameSpace, &pszClassName)))
2842     {
2843         RETURN FALSE;
2844     }
2845     NameHandle nameHandle(pTypeRefModule, typeRefToken);
2846     nameHandle.SetName(pszNameSpace, pszClassName);
2847     if (loadFlag != Loader::Load)
2848     {
2849         nameHandle.SetTokenNotToLoad(tdAllTypes);
2850     }
2851
2852     return ResolveNameToTypeDefThrowing(pFoundRefModule, &nameHandle, ppTypeDefModule, pTypeDefToken, loadFlag, pfUsesTypeForwarder);
2853 }
2854
2855 /*static*/
2856 BOOL
2857 ClassLoader::ResolveNameToTypeDefThrowing(
2858     Module *         pModule,
2859     const NameHandle * pName,
2860     Module **        ppTypeDefModule,
2861     mdTypeDef *      pTypeDefToken,
2862     Loader::LoadFlag loadFlag,
2863     BOOL *           pfUsesTypeForwarder) // The semantic of this parameter: TRUE if a type forwarder is found. It is never set to FALSE.
2864 {    
2865     CONTRACT(BOOL)
2866     {
2867         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
2868         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
2869         MODE_ANY;
2870         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
2871         PRECONDITION(CheckPointer(pModule));
2872         PRECONDITION(CheckPointer(pName));
2873         SUPPORTS_DAC;
2874     }
2875     CONTRACT_END;
2876
2877     TypeHandle typeHnd;
2878     mdToken  foundTypeDef;
2879     Module * pFoundModule;
2880     mdExportedType foundExportedType;
2881     Module * pSourceModule = pModule;
2882     Module * pFoundRefModule = pModule;
2883     
2884     for (UINT32 nTypeForwardingChainSize = 0; nTypeForwardingChainSize < const_cMaxTypeForwardingChainSize; nTypeForwardingChainSize++)
2885     {
2886         foundTypeDef = mdTokenNil;
2887         pFoundModule = NULL;
2888         foundExportedType = mdTokenNil;
2889         if (!pSourceModule->GetClassLoader()->FindClassModuleThrowing(
2890             pName,
2891             &typeHnd, 
2892             &foundTypeDef, 
2893             &pFoundModule, 
2894             &foundExportedType, 
2895             NULL, 
2896             pSourceModule->IsReflection() ? NULL : pSourceModule, 
2897             loadFlag))
2898         {
2899             RETURN FALSE;
2900         }
2901         
2902         // Type is already loaded and cached in the loader's by-name table
2903         if (!typeHnd.IsNull())
2904         {
2905             if ((typeHnd.GetModule() != pFoundRefModule) && (pfUsesTypeForwarder != NULL))
2906             {   // We followed at least one type forwarder to resolve the type
2907                 *pfUsesTypeForwarder = TRUE;
2908             }
2909             if (ppTypeDefModule != NULL)
2910                 *ppTypeDefModule = typeHnd.GetModule();
2911             if (pTypeDefToken != NULL)
2912                 *pTypeDefToken = typeHnd.GetCl();
2913             RETURN TRUE;
2914         }
2915         
2916         if (pFoundModule == NULL)
2917         {   // Module was probably not loaded
2918             RETURN FALSE;
2919         }
2920         
2921         if (TypeFromToken(foundExportedType) != mdtExportedType)
2922         {   // It's not exported type
2923             _ASSERTE(foundExportedType == mdTokenNil);
2924             
2925             if ((pFoundModule != pFoundRefModule) && (pfUsesTypeForwarder != NULL))
2926             {   // We followed at least one type forwarder to resolve the type
2927                 *pfUsesTypeForwarder = TRUE;
2928             }
2929             if (pTypeDefToken != NULL)
2930                 *pTypeDefToken = foundTypeDef;
2931             if (ppTypeDefModule != NULL)
2932                 *ppTypeDefModule = pFoundModule;
2933             RETURN TRUE;
2934         }
2935         // It's exported type
2936         
2937         // Repeat the search for the type in the newly found module
2938         pSourceModule = pFoundModule;
2939     }
2940     // Type forwarding chain is too long
2941     RETURN FALSE;
2942 } // ClassLoader::ResolveTokenToTypeDefThrowing
2943
2944 #ifndef DACCESS_COMPILE
2945
2946 //---------------------------------------------------------------------------------------
2947 // 
2948 //static
2949 VOID 
2950 ClassLoader::GetEnclosingClassThrowing(
2951     IMDInternalImport * pInternalImport, 
2952     Module *            pModule, 
2953     mdTypeDef           cl, 
2954     mdTypeDef *         tdEnclosing)
2955 {
2956     CONTRACTL
2957     {
2958         THROWS;
2959         GC_TRIGGERS;
2960         INJECT_FAULT(COMPlusThrowOM());
2961         MODE_ANY;
2962     }
2963     CONTRACTL_END;
2964
2965     _ASSERTE(tdEnclosing);
2966     *tdEnclosing = mdTypeDefNil;
2967
2968     HRESULT hr = pInternalImport->GetNestedClassProps(cl, tdEnclosing);
2969
2970     if (FAILED(hr))
2971     {
2972         if (hr != CLDB_E_RECORD_NOTFOUND)
2973             COMPlusThrowHR(hr);
2974         return;
2975     }
2976
2977     if (TypeFromToken(*tdEnclosing) != mdtTypeDef)
2978         pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_ENCLOSING);
2979 } // ClassLoader::GetEnclosingClassThrowing
2980
2981
2982 //---------------------------------------------------------------------------------------
2983 // 
2984 // Load a parent type or implemented interface type.
2985 //
2986 // If this is an instantiated type represented by a type spec, then instead of attempting to load the
2987 // exact type, load an approximate instantiation in which all reference types are replaced by Object.
2988 // The exact instantiated types will be loaded later by LoadInstantiatedInfo.
2989 // We do this to avoid cycles early in class loading caused by definitions such as
2990 //   struct M : ICloneable<M>                     // load ICloneable<object>
2991 //   class C<T> : D<C<T>,int> for any T           // load D<object,int>
2992 // 
2993 //static
2994 TypeHandle 
2995 ClassLoader::LoadApproxTypeThrowing(
2996     Module *               pModule, 
2997     mdToken                tok, 
2998     SigPointer *           pSigInst, 
2999     const SigTypeContext * pClassTypeContext)
3000 {
3001     CONTRACT(TypeHandle)
3002     {
3003         THROWS;
3004         GC_TRIGGERS;
3005         INJECT_FAULT(COMPlusThrowOM());
3006         MODE_ANY;
3007         PRECONDITION(CheckPointer(pSigInst, NULL_OK));
3008         PRECONDITION(CheckPointer(pModule));
3009         POSTCONDITION(CheckPointer(RETVAL));
3010     }
3011     CONTRACT_END;
3012
3013     IMDInternalImport * pInternalImport = pModule->GetMDImport();
3014
3015     if (TypeFromToken(tok) == mdtTypeSpec)
3016     {
3017         ULONG cSig;
3018         PCCOR_SIGNATURE pSig;
3019         IfFailThrowBF(pInternalImport->GetTypeSpecFromToken(tok, &pSig, &cSig), BFA_METADATA_CORRUPT, pModule);
3020
3021         SigPointer sigptr = SigPointer(pSig, cSig);
3022         CorElementType type = ELEMENT_TYPE_END;
3023         IfFailThrowBF(sigptr.GetElemType(&type), BFA_BAD_SIGNATURE, pModule);
3024
3025         // The only kind of type specs that we recognise are instantiated types
3026         if (type != ELEMENT_TYPE_GENERICINST)
3027             pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, tok, IDS_CLASSLOAD_GENERAL);
3028
3029         // Of these, we outlaw instantiated value classes (they can't be interfaces and can't be subclassed)
3030         IfFailThrowBF(sigptr.GetElemType(&type), BFA_BAD_SIGNATURE, pModule);
3031      
3032         if (type != ELEMENT_TYPE_CLASS)
3033             pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, tok, IDS_CLASSLOAD_GENERAL);
3034
3035         mdToken genericTok = 0;
3036         IfFailThrowBF(sigptr.GetToken(&genericTok), BFA_BAD_SIGNATURE, pModule);
3037         IfFailThrowBF(sigptr.GetData(NULL), BFA_BAD_SIGNATURE, pModule);
3038
3039         if (pSigInst != NULL)
3040             *pSigInst = sigptr;
3041
3042         // Try to load the generic type itself
3043         THROW_BAD_FORMAT_MAYBE(
3044             ((TypeFromToken(genericTok) == mdtTypeRef) || (TypeFromToken(genericTok) == mdtTypeDef)), 
3045             BFA_UNEXPECTED_GENERIC_TOKENTYPE, 
3046             pModule);
3047         TypeHandle genericTypeTH = LoadTypeDefOrRefThrowing(
3048             pModule, 
3049             genericTok, 
3050             ClassLoader::ThrowIfNotFound, 
3051             ClassLoader::PermitUninstDefOrRef, 
3052             tdNoTypes, 
3053             CLASS_LOAD_APPROXPARENTS);
3054
3055         // We load interfaces at very approximate types - the generic
3056         // interface itself.  We fix this up in LoadInstantiatedInfo.
3057         // This allows us to load recursive interfaces on structs such
3058         // as "struct VC : I<VC>".  The details of the interface
3059         // are not currently needed during the first phase
3060         // of setting up the method table.
3061         if (genericTypeTH.IsInterface())
3062         {
3063             RETURN genericTypeTH;
3064         }
3065         else            
3066         {
3067             // approxTypes, i.e. approximate reference types by Object, i.e. load the canonical type
3068             RETURN SigPointer(pSig, cSig).GetTypeHandleThrowing(
3069                 pModule, 
3070                 pClassTypeContext, 
3071                 ClassLoader::LoadTypes, 
3072                 CLASS_LOAD_APPROXPARENTS, 
3073                 TRUE /*dropGenericArgumentLevel*/);
3074         }
3075     }
3076     else 
3077     {
3078         if (pSigInst != NULL)
3079             *pSigInst = SigPointer();
3080         RETURN LoadTypeDefOrRefThrowing(
3081             pModule, 
3082             tok, 
3083             ClassLoader::ThrowIfNotFound, 
3084             ClassLoader::FailIfUninstDefOrRef, 
3085             tdNoTypes, 
3086             CLASS_LOAD_APPROXPARENTS);
3087     }
3088 } // ClassLoader::LoadApproxTypeThrowing
3089
3090
3091 //---------------------------------------------------------------------------------------
3092 // 
3093 //static
3094 MethodTable * 
3095 ClassLoader::LoadApproxParentThrowing(
3096     Module *               pModule, 
3097     mdToken                cl, 
3098     SigPointer *           pParentInst, 
3099     const SigTypeContext * pClassTypeContext)
3100 {
3101     CONTRACTL
3102     {
3103         THROWS;
3104         GC_TRIGGERS;
3105         INJECT_FAULT(COMPlusThrowOM());
3106         MODE_ANY;
3107     }
3108     CONTRACTL_END;
3109
3110     mdTypeRef     crExtends;
3111     MethodTable * pParentMethodTable = NULL;
3112     TypeHandle    parentType;
3113     DWORD         dwAttrClass;
3114     Assembly *    pAssembly = pModule->GetAssembly();
3115     IMDInternalImport * pInternalImport = pModule->GetMDImport();
3116     
3117     // Initialize the return value;
3118     *pParentInst = SigPointer();
3119     
3120     // Now load all dependencies of this class
3121     if (FAILED(pInternalImport->GetTypeDefProps(
3122         cl,
3123         &dwAttrClass, // AttrClass
3124         &crExtends)))
3125     {
3126         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
3127     }
3128     
3129     if (RidFromToken(crExtends) != mdTokenNil)
3130     {
3131         // Do an "approximate" load of the parent, replacing reference types in the instantiation by Object
3132         // This is to avoid cycles in the loader e.g. on class C : D<C> or class C<T> : D<C<T>>
3133         // We fix up the exact parent later in LoadInstantiatedInfo
3134         parentType = LoadApproxTypeThrowing(pModule, crExtends, pParentInst, pClassTypeContext);
3135
3136         pParentMethodTable = parentType.GetMethodTable();
3137
3138         if (pParentMethodTable == NULL)
3139             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_PARENTNULL);
3140
3141         // cannot inherit from an interface
3142         if (pParentMethodTable->IsInterface())
3143             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_PARENTINTERFACE);
3144
3145         if (IsTdInterface(dwAttrClass))
3146         {
3147             // Interfaces must extend from Object
3148             if (! pParentMethodTable->IsObjectClass())
3149                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACEOBJECT);
3150         }
3151     }
3152
3153     return pParentMethodTable;
3154 } // ClassLoader::LoadApproxParentThrowing
3155
3156 // Perform a single phase of class loading
3157 // It is the caller's responsibility to lock
3158 /*static*/
3159 TypeHandle ClassLoader::DoIncrementalLoad(TypeKey *pTypeKey, TypeHandle typeHnd, ClassLoadLevel currentLevel)
3160 {
3161     CONTRACTL
3162     {
3163         STANDARD_VM_CHECK;
3164         PRECONDITION(CheckPointer(pTypeKey));
3165         PRECONDITION(currentLevel >= CLASS_LOAD_BEGIN && currentLevel < CLASS_LOADED);
3166         MODE_ANY;
3167     }
3168     CONTRACTL_END;
3169
3170 #ifdef _DEBUG
3171     if (LoggingOn(LF_CLASSLOADER, LL_INFO10000))
3172     {
3173         SString name;
3174         TypeString::AppendTypeKeyDebug(name, pTypeKey);
3175         LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: About to do incremental load of type %S (%p) from level %s\n", name.GetUnicode(), typeHnd.AsPtr(), classLoadLevelName[currentLevel]));
3176     }
3177 #endif
3178
3179     // Level is BEGIN if and only if type handle is null
3180     CONSISTENCY_CHECK((currentLevel == CLASS_LOAD_BEGIN) == typeHnd.IsNull());
3181
3182     switch (currentLevel)
3183     {
3184         // Attain at least level CLASS_LOAD_UNRESTORED (if just locating type in ngen image)
3185         // or at least level CLASS_LOAD_APPROXPARENTS (if creating type for the first time)
3186         case CLASS_LOAD_BEGIN :
3187             {
3188                 IBCLoggerAwareAllocMemTracker amTracker;
3189                 typeHnd = CreateTypeHandleForTypeKey(pTypeKey, &amTracker);
3190                 CONSISTENCY_CHECK(!typeHnd.IsNull());
3191                 TypeHandle published = PublishType(pTypeKey, typeHnd);
3192                 if (published == typeHnd)
3193                     amTracker.SuppressRelease();
3194                 typeHnd = published;
3195             }
3196             break;
3197
3198         case CLASS_LOAD_UNRESTOREDTYPEKEY :
3199 #ifdef FEATURE_PREJIT
3200             typeHnd.DoRestoreTypeKey();
3201 #endif
3202             break;
3203
3204         // Attain level CLASS_LOAD_APPROXPARENTS, starting with unrestored class
3205         case CLASS_LOAD_UNRESTORED :
3206 #ifdef FEATURE_PREJIT
3207             {
3208                 CONSISTENCY_CHECK(!typeHnd.IsRestored_NoLogging());
3209                 if (typeHnd.IsTypeDesc())
3210                     typeHnd.AsTypeDesc()->Restore();
3211                 else
3212                     typeHnd.AsMethodTable()->Restore();
3213             }
3214 #endif
3215             break;
3216
3217         // Attain level CLASS_LOAD_EXACTPARENTS
3218         case CLASS_LOAD_APPROXPARENTS :
3219             if (!typeHnd.IsTypeDesc())
3220             {
3221                 LoadExactParents(typeHnd.AsMethodTable());
3222             }
3223             break;
3224
3225         case CLASS_LOAD_EXACTPARENTS :
3226         case CLASS_DEPENDENCIES_LOADED :
3227         case CLASS_LOADED :
3228             break;
3229
3230     }
3231
3232     if (typeHnd.GetLoadLevel() >= CLASS_LOAD_EXACTPARENTS)
3233     {
3234         Notify(typeHnd);
3235     }
3236
3237     return typeHnd;
3238 }
3239
3240 /*static*/
3241 // For non-canonical instantiations of generic types, create a fresh type by replicating the canonical instantiation
3242 // For canonical instantiations of generic types, create a brand new method table
3243 // For other constructed types, create a type desc and template method table if necessary
3244 // For all other types, create a method table
3245 TypeHandle ClassLoader::CreateTypeHandleForTypeKey(TypeKey* pKey, AllocMemTracker* pamTracker)
3246 {
3247     CONTRACT(TypeHandle)
3248     {
3249         STANDARD_VM_CHECK;
3250         PRECONDITION(CheckPointer(pKey));
3251       
3252         POSTCONDITION(RETVAL.CheckMatchesKey(pKey));
3253         MODE_ANY;
3254     }
3255     CONTRACT_END
3256
3257     TypeHandle typeHnd = TypeHandle();
3258     
3259     if (!pKey->IsConstructed())
3260     {
3261         typeHnd = CreateTypeHandleForTypeDefThrowing(pKey->GetModule(),
3262                                                      pKey->GetTypeToken(),
3263                                                      pKey->GetInstantiation(),
3264                                                      pamTracker);
3265     }
3266     else if (pKey->HasInstantiation())
3267     {
3268         if (IsCanonicalGenericInstantiation(pKey->GetInstantiation()))
3269         {
3270             typeHnd = CreateTypeHandleForTypeDefThrowing(pKey->GetModule(),
3271                                                             pKey->GetTypeToken(),
3272                                                             pKey->GetInstantiation(),
3273                                                             pamTracker);
3274         }
3275         else 
3276         {
3277             typeHnd = CreateTypeHandleForNonCanonicalGenericInstantiation(pKey,
3278                                                                                         pamTracker);
3279         }
3280 #if defined(_DEBUG) && !defined(CROSSGEN_COMPILE)
3281         if (Nullable::IsNullableType(typeHnd)) 
3282             Nullable::CheckFieldOffsets(typeHnd);
3283 #endif
3284     }
3285     else if (pKey->GetKind() == ELEMENT_TYPE_FNPTR) 
3286     {
3287         Module *pLoaderModule = ComputeLoaderModule(pKey);
3288         pLoaderModule->GetLoaderAllocator()->EnsureInstantiation(NULL, Instantiation(pKey->GetRetAndArgTypes(), pKey->GetNumArgs() + 1));
3289
3290         PREFIX_ASSUME(pLoaderModule!=NULL);
3291         DWORD numArgs = pKey->GetNumArgs();
3292         BYTE* mem = (BYTE*) pamTracker->Track(pLoaderModule->GetAssembly()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(FnPtrTypeDesc)) + S_SIZE_T(sizeof(TypeHandle)) * S_SIZE_T(numArgs)));
3293             
3294         typeHnd = TypeHandle(new(mem)  FnPtrTypeDesc(pKey->GetCallConv(), numArgs, pKey->GetRetAndArgTypes()));
3295     }
3296     else
3297     {
3298         Module *pLoaderModule = ComputeLoaderModule(pKey);
3299         PREFIX_ASSUME(pLoaderModule!=NULL);
3300
3301         CorElementType kind = pKey->GetKind();
3302         TypeHandle paramType = pKey->GetElementType();
3303         MethodTable *templateMT;
3304
3305         // Create a new type descriptor and insert into constructed type table
3306         if (CorTypeInfo::IsArray(kind)) 
3307         {
3308             DWORD rank = pKey->GetRank();
3309             THROW_BAD_FORMAT_MAYBE((kind != ELEMENT_TYPE_ARRAY) || rank > 0, BFA_MDARRAY_BADRANK, pLoaderModule);
3310             THROW_BAD_FORMAT_MAYBE((kind != ELEMENT_TYPE_SZARRAY) || rank == 1, BFA_SDARRAY_BADRANK, pLoaderModule);
3311
3312             // Arrays of BYREFS not allowed
3313             if (paramType.GetInternalCorElementType() == ELEMENT_TYPE_BYREF)
3314             {
3315                 ThrowTypeLoadException(pKey, IDS_CLASSLOAD_BYREFARRAY);
3316             }
3317
3318             // Arrays of ByRefLike types not allowed
3319             MethodTable* pMT = paramType.GetMethodTable();
3320             if (pMT != NULL)
3321             {
3322                 if (pMT->IsByRefLike())
3323                 {
3324                     ThrowTypeLoadException(pKey, IDS_CLASSLOAD_BYREFLIKEARRAY);
3325                 }
3326             }
3327
3328             // We really don't need this check anymore.
3329             if (rank > MAX_RANK)
3330             {
3331                 ThrowTypeLoadException(pKey, IDS_CLASSLOAD_RANK_TOOLARGE);
3332             }
3333
3334             templateMT = pLoaderModule->CreateArrayMethodTable(paramType, kind, rank, pamTracker);
3335
3336             BYTE* mem = (BYTE*) pamTracker->Track(pLoaderModule->GetAssembly()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(ArrayTypeDesc))));
3337             typeHnd = TypeHandle(new(mem)  ArrayTypeDesc(templateMT, paramType));
3338         }
3339         else 
3340         {
3341             // no parameterized type allowed on a reference
3342             if (paramType.GetInternalCorElementType() == ELEMENT_TYPE_BYREF ||
3343                 paramType.GetInternalCorElementType() == ELEMENT_TYPE_TYPEDBYREF)
3344             {
3345                 ThrowTypeLoadException(pKey, IDS_CLASSLOAD_GENERAL);
3346             }
3347
3348             // We do allow parametrized types of ByRefLike types. Languages may restrict them to produce safe or verifiable code, 
3349             // but there is not a good reason for restricting them in the runtime.
3350
3351             // let <Type>* type have a method table
3352             // System.UIntPtr's method table is used for types like int*, void *, string * etc.
3353             if (kind == ELEMENT_TYPE_PTR)
3354                 templateMT = MscorlibBinder::GetElementType(ELEMENT_TYPE_U);
3355             else 
3356                 templateMT = NULL;
3357
3358             BYTE* mem = (BYTE*) pamTracker->Track(pLoaderModule->GetAssembly()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(ParamTypeDesc))));
3359             typeHnd = TypeHandle(new(mem)  ParamTypeDesc(kind, templateMT, paramType));
3360         }
3361     }
3362
3363     RETURN typeHnd;
3364 }
3365
3366 // Publish a type (and possibly member information) in the loader's
3367 // tables Types are published before they are fully loaded. In
3368 // particular, exact parent info (base class and interfaces) is loaded
3369 // in a later phase
3370 /*static*/
3371 TypeHandle ClassLoader::PublishType(TypeKey *pTypeKey, TypeHandle typeHnd)
3372 {
3373     CONTRACTL
3374     {
3375         STANDARD_VM_CHECK;
3376         PRECONDITION(CheckPointer(typeHnd));
3377         PRECONDITION(CheckPointer(pTypeKey));
3378
3379         // Key must match that of the handle
3380         PRECONDITION(typeHnd.CheckMatchesKey(pTypeKey));
3381
3382         // Don't publish array template method tables; these are accessed only through type descs
3383         PRECONDITION(typeHnd.IsTypeDesc() || !typeHnd.AsMethodTable()->IsArray());
3384     }
3385     CONTRACTL_END;
3386
3387
3388     if (pTypeKey->IsConstructed())
3389     {
3390         Module *pLoaderModule = ComputeLoaderModule(pTypeKey);
3391         EETypeHashTable *pTable = pLoaderModule->GetAvailableParamTypes();
3392
3393         // m_AvailableTypesLock has to be taken in cooperative mode to avoid deadlocks during GC
3394         GCX_COOP();
3395
3396         CrstHolder ch(&pLoaderModule->GetClassLoader()->m_AvailableTypesLock);
3397
3398         // The type could have been loaded by a different thread as side-effect of avoiding deadlocks caused by LoadsTypeViolation
3399         TypeHandle existing = pTable->GetValue(pTypeKey);
3400         if (!existing.IsNull())
3401             return existing;
3402
3403         pTable->InsertValue(typeHnd);
3404
3405 #ifdef _DEBUG
3406         // Checks to help ensure that the CoreLib in the ngen process does not get contaminated with pointers to the compilation domains.
3407         if (pLoaderModule->IsSystem() && IsCompilationProcess() && pLoaderModule->HasNativeImage())
3408         {
3409             CorElementType kind = pTypeKey->GetKind();
3410             MethodTable *typeHandleMethodTable = typeHnd.GetMethodTable();
3411             if ((typeHandleMethodTable != NULL) && (typeHandleMethodTable->GetLoaderAllocator() != pLoaderModule->GetLoaderAllocator()))
3412             {
3413                 _ASSERTE(!"MethodTable of type loaded into CoreLib during NGen is not from CoreLib!");
3414             }
3415             if ((kind != ELEMENT_TYPE_FNPTR) && (kind != ELEMENT_TYPE_VAR) && (kind != ELEMENT_TYPE_MVAR))
3416             {
3417                 if ((kind == ELEMENT_TYPE_SZARRAY) || (kind == ELEMENT_TYPE_ARRAY) || (kind == ELEMENT_TYPE_BYREF) || (kind == ELEMENT_TYPE_PTR) || (kind == ELEMENT_TYPE_VALUETYPE))
3418                 {
3419                     // Check to ensure param value is also part of CoreLib.
3420                     if (pTypeKey->GetElementType().GetLoaderAllocator() != pLoaderModule->GetLoaderAllocator())
3421                     {
3422                         _ASSERTE(!"Param value of type key used to load type during NGEN not located within CoreLib yet type is placed into CoreLib");
3423                     }
3424                 }
3425                 else if (kind == ELEMENT_TYPE_FNPTR)
3426                 {
3427                     // Check to ensure the parameter types of fnptr are in CoreLib
3428                     for (DWORD i = 0; i <= pTypeKey->GetNumArgs(); i++)
3429                     {
3430                         if (pTypeKey->GetRetAndArgTypes()[i].GetLoaderAllocator() != pLoaderModule->GetLoaderAllocator())
3431                         {
3432                             _ASSERTE(!"Ret or Arg type of function pointer type key used to load type during NGEN not located within CoreLib yet type is placed into CoreLib");
3433                         }
3434                     }
3435                 }
3436                 else if (kind == ELEMENT_TYPE_CLASS)
3437                 {
3438                     // Check to ensure that the generic parameters are all within CoreLib
3439                     for (DWORD i = 0; i < pTypeKey->GetNumGenericArgs(); i++)
3440                     {
3441                         if (pTypeKey->GetInstantiation()[i].GetLoaderAllocator() != pLoaderModule->GetLoaderAllocator())
3442                         {
3443                             _ASSERTE(!"Instantiation parameter of generic class type key used to load type during NGEN not located within CoreLib yet type is placed into CoreLib");
3444                         }
3445                     }
3446                 }
3447                 else
3448                 {
3449                     // Should not be able to get here
3450                     _ASSERTE(!"Unknown type key type");
3451                 }
3452             }
3453         }
3454 #endif // DEBUG 
3455     }
3456     else
3457     {
3458         Module *pModule = pTypeKey->GetModule();
3459         mdTypeDef typeDef = pTypeKey->GetTypeToken();
3460
3461         // m_AvailableTypesLock has to be taken in cooperative mode to avoid deadlocks during GC
3462         GCX_COOP();
3463
3464         CrstHolder ch(&pModule->GetClassLoader()->m_AvailableTypesLock);
3465
3466         // ! We cannot fail after this point.
3467         CANNOTTHROWCOMPLUSEXCEPTION();
3468         FAULT_FORBID();
3469
3470         // The type could have been loaded by a different thread as side-effect of avoiding deadlocks caused by LoadsTypeViolation
3471         TypeHandle existing = pModule->LookupTypeDef(typeDef);
3472         if (!existing.IsNull())
3473             return existing;
3474
3475         MethodTable *pMT = typeHnd.AsMethodTable();
3476
3477         MethodTable::IntroducedMethodIterator it(pMT);
3478         for (; it.IsValid(); it.Next())
3479         {
3480             MethodDesc * pMD = it.GetMethodDesc();
3481             CONSISTENCY_CHECK(pMD != NULL && pMD->GetMethodTable() == pMT);
3482             if (!pMD->IsUnboxingStub())
3483             {
3484                 pModule->EnsuredStoreMethodDef(pMD->GetMemberDef(), pMD);
3485             }
3486         }
3487
3488         ApproxFieldDescIterator fdIterator(pMT, ApproxFieldDescIterator::ALL_FIELDS);
3489         FieldDesc* pFD;
3490
3491         while ((pFD = fdIterator.Next()) != NULL)
3492         {
3493             if (pFD->GetEnclosingMethodTable() == pMT)
3494             {
3495                 pModule->EnsuredStoreFieldDef(pFD->GetMemberDef(), pFD);
3496             }
3497         }
3498
3499         // Publish the type last - to ensure that nobody can see it until all the method and field RID maps are filled in
3500         pModule->EnsuredStoreTypeDef(typeDef, typeHnd);
3501     }
3502
3503     return typeHnd;
3504 }
3505
3506 // Notify profiler and debugger that a type load has completed
3507 // Also adjust perf counters
3508 /*static*/
3509 void ClassLoader::Notify(TypeHandle typeHnd)
3510 {
3511     CONTRACTL
3512     {
3513         STANDARD_VM_CHECK;
3514         PRECONDITION(CheckPointer(typeHnd));
3515     }
3516     CONTRACTL_END;
3517
3518     LOG((LF_CLASSLOADER, LL_INFO1000, "Notify: %p %s\n", typeHnd.AsPtr(), typeHnd.IsTypeDesc() ? "typedesc" : typeHnd.AsMethodTable()->GetDebugClassName()));
3519
3520     if (typeHnd.IsTypeDesc())
3521         return;
3522
3523     MethodTable * pMT = typeHnd.AsMethodTable();
3524
3525 #ifdef PROFILING_SUPPORTED
3526     {
3527         BEGIN_PIN_PROFILER(CORProfilerTrackClasses());
3528         // We don't tell profilers about typedescs, as per IF above.  Also, we don't
3529         // tell profilers about:
3530         if (
3531             // ...generics with unbound variables
3532             (!pMT->ContainsGenericVariables()) &&
3533             // ...or array method tables
3534             // (This check is mainly for NGEN restore, as JITted code won't hit
3535             // this code path for array method tables anyway)
3536             (!pMT->IsArray()))
3537         {
3538             LOG((LF_CLASSLOADER, LL_INFO1000, "Notifying profiler of Started1 %p %s\n", pMT, pMT->GetDebugClassName()));
3539             // Record successful load of the class for the profiler
3540             g_profControlBlock.pProfInterface->ClassLoadStarted(TypeHandleToClassID(typeHnd));
3541
3542             //
3543             // Profiler can turn off TrackClasses during the Started() callback.  Need to
3544             // retest the flag here.
3545             //
3546             if (CORProfilerTrackClasses()) 
3547             {
3548                 LOG((LF_CLASSLOADER, LL_INFO1000, "Notifying profiler of Finished1 %p %s\n", pMT, pMT->GetDebugClassName()));
3549                 g_profControlBlock.pProfInterface->ClassLoadFinished(TypeHandleToClassID(typeHnd),
3550                     S_OK);
3551             }
3552         }
3553         END_PIN_PROFILER();
3554     }
3555 #endif //PROFILING_SUPPORTED
3556
3557     g_IBCLogger.LogMethodTableAccess(pMT);
3558
3559     if (pMT->IsTypicalTypeDefinition())
3560     {
3561         LOG((LF_CLASSLOADER, LL_INFO100, "Successfully loaded class %s\n", pMT->GetDebugClassName()));
3562
3563 #ifdef DEBUGGING_SUPPORTED
3564         {
3565             Module * pModule = pMT->GetModule();
3566             // Update metadata for dynamic module.
3567             pModule->UpdateDynamicMetadataIfNeeded();
3568         }
3569
3570         if (CORDebuggerAttached()) 
3571         {
3572             LOG((LF_CORDB, LL_EVERYTHING, "NotifyDebuggerLoad clsload 2239 class %s\n", pMT->GetDebugClassName()));
3573             typeHnd.NotifyDebuggerLoad(NULL, FALSE);
3574         }
3575 #endif // DEBUGGING_SUPPORTED
3576     }
3577 }
3578
3579
3580 //-----------------------------------------------------------------------------
3581 // Common helper for LoadTypeHandleForTypeKey and LoadTypeHandleForTypeKeyNoLock.
3582 // Makes the root level call to kick off the transitive closure walk for
3583 // the final level pushes.
3584 //-----------------------------------------------------------------------------
3585 static void PushFinalLevels(TypeHandle typeHnd, ClassLoadLevel targetLevel, const InstantiationContext *pInstContext)
3586 {
3587     CONTRACTL
3588     {
3589         STANDARD_VM_CHECK;
3590         LOADS_TYPE(targetLevel);
3591     }
3592     CONTRACTL_END
3593
3594
3595     // This phase brings the type and all its transitive dependencies to their
3596     // final state, sans the IsFullyLoaded bit.
3597     if (targetLevel >= CLASS_DEPENDENCIES_LOADED)
3598     {
3599         BOOL fBailed = FALSE;
3600         typeHnd.DoFullyLoad(NULL, CLASS_DEPENDENCIES_LOADED, NULL, &fBailed, pInstContext);
3601     }
3602
3603     // This phase does access/constraint and other type-safety checks on the type
3604     // and on its transitive dependencies.
3605     if (targetLevel == CLASS_LOADED)
3606     {
3607         DFLPendingList pendingList;
3608         BOOL           fBailed = FALSE;
3609     
3610         typeHnd.DoFullyLoad(NULL, CLASS_LOADED, &pendingList, &fBailed, pInstContext);
3611
3612
3613         // In the case of a circular dependency, one or more types will have
3614         // had their promotions deferred.
3615         //
3616         // If we got to this point, all checks have successfully passed on
3617         // the transitive closure (otherwise, DoFullyLoad would have thrown.)
3618         //
3619         // So we can go ahead and mark everyone as fully loaded.
3620         //
3621         UINT numTH = pendingList.Count();
3622         TypeHandle *pTHPending = pendingList.Table();
3623         for (UINT i = 0; i < numTH; i++)
3624         {
3625             // NOTE: It is possible for duplicates to appear in this list so
3626             // don't do any operation that isn't idempodent.
3627
3628             pTHPending[i].SetIsFullyLoaded();
3629         }
3630     }
3631 }
3632
3633
3634 // 
3635 TypeHandle ClassLoader::LoadTypeHandleForTypeKey(TypeKey *pTypeKey,
3636                                                  TypeHandle typeHnd,
3637                                                  ClassLoadLevel targetLevel/*=CLASS_LOADED*/,
3638                                                  const InstantiationContext *pInstContext/*=NULL*/)
3639 {
3640
3641     CONTRACTL
3642     {
3643         INSTANCE_CHECK;
3644         THROWS;
3645         GC_TRIGGERS;
3646         MODE_ANY;
3647         LOADS_TYPE(targetLevel);
3648     }
3649     CONTRACTL_END
3650
3651     GCX_PREEMP();
3652
3653 #ifdef _DEBUG
3654     if (LoggingOn(LF_CLASSLOADER, LL_INFO1000))
3655     {
3656         SString name;
3657         TypeString::AppendTypeKeyDebug(name, pTypeKey);
3658         LOG((LF_CLASSLOADER, LL_INFO10000, "PHASEDLOAD: LoadTypeHandleForTypeKey for type %S to level %s\n", name.GetUnicode(), classLoadLevelName[targetLevel]));
3659         CrstHolder unresolvedClassLockHolder(&m_UnresolvedClassLock);
3660         m_pUnresolvedClassHash->Dump();
3661     }
3662 #endif
3663
3664     // When using domain neutral assemblies (and not eagerly propagating dependency loads), 
3665     // it's possible to get here without having injected the module into the current app domain.
3666     // GetDomainFile will accomplish that.
3667     
3668     if (!pTypeKey->IsConstructed())
3669     {
3670         pTypeKey->GetModule()->GetDomainFile();
3671     }
3672     
3673     ClassLoadLevel currentLevel = typeHnd.IsNull() ? CLASS_LOAD_BEGIN : typeHnd.GetLoadLevel();
3674     ClassLoadLevel targetLevelUnderLock = targetLevel < CLASS_DEPENDENCIES_LOADED ? targetLevel : (ClassLoadLevel) (CLASS_DEPENDENCIES_LOADED-1);
3675     if (currentLevel < targetLevelUnderLock)
3676     {
3677         typeHnd = LoadTypeHandleForTypeKey_Body(pTypeKey, 
3678                                                 typeHnd,
3679                                                 targetLevelUnderLock);
3680         _ASSERTE(!typeHnd.IsNull());
3681     }
3682     _ASSERTE(typeHnd.GetLoadLevel() >= targetLevelUnderLock);
3683
3684     PushFinalLevels(typeHnd, targetLevel, pInstContext);
3685
3686     return typeHnd;
3687 }
3688
3689 // 
3690 TypeHandle ClassLoader::LoadTypeHandleForTypeKeyNoLock(TypeKey *pTypeKey,
3691                                                        ClassLoadLevel targetLevel/*=CLASS_LOADED*/,
3692                                                        const InstantiationContext *pInstContext/*=NULL*/)
3693 {
3694
3695     CONTRACTL
3696     {
3697         INSTANCE_CHECK;
3698         THROWS;
3699         GC_TRIGGERS;
3700         MODE_ANY;
3701         LOADS_TYPE(targetLevel);
3702         PRECONDITION(CheckPointer(pTypeKey));
3703         PRECONDITION(targetLevel >= 0 && targetLevel <= CLASS_LOADED);
3704     }
3705     CONTRACTL_END
3706
3707     GCX_PREEMP();
3708
3709     TypeHandle typeHnd = TypeHandle();
3710
3711     ClassLoadLevel currentLevel = CLASS_LOAD_BEGIN;
3712     ClassLoadLevel targetLevelUnderLock = targetLevel < CLASS_DEPENDENCIES_LOADED ? targetLevel : (ClassLoadLevel) (CLASS_DEPENDENCIES_LOADED-1);
3713     while (currentLevel < targetLevelUnderLock)
3714     {
3715         typeHnd = DoIncrementalLoad(pTypeKey, typeHnd, currentLevel);
3716         CONSISTENCY_CHECK(typeHnd.GetLoadLevel() > currentLevel);
3717         currentLevel = typeHnd.GetLoadLevel();
3718     }
3719
3720     PushFinalLevels(typeHnd, targetLevel, pInstContext);
3721
3722     return typeHnd;
3723 }
3724
3725 //---------------------------------------------------------------------------------------
3726 // 
3727 class PendingTypeLoadHolder
3728 {
3729     Thread * m_pThread;
3730     PendingTypeLoadEntry * m_pEntry;
3731     PendingTypeLoadHolder * m_pPrevious;
3732
3733 public:
3734     PendingTypeLoadHolder(PendingTypeLoadEntry * pEntry)
3735     {
3736         LIMITED_METHOD_CONTRACT;
3737
3738         m_pThread = GetThread();
3739         m_pEntry = pEntry;
3740
3741         m_pPrevious = m_pThread->GetPendingTypeLoad();
3742         m_pThread->SetPendingTypeLoad(this);
3743     }
3744
3745     ~PendingTypeLoadHolder()
3746     {
3747         LIMITED_METHOD_CONTRACT;
3748
3749         _ASSERTE(m_pThread->GetPendingTypeLoad() == this);
3750         m_pThread->SetPendingTypeLoad(m_pPrevious);
3751     }
3752
3753     static bool CheckForDeadLockOnCurrentThread(PendingTypeLoadEntry * pEntry)
3754     {
3755         LIMITED_METHOD_CONTRACT;
3756
3757         PendingTypeLoadHolder * pCurrent = GetThread()->GetPendingTypeLoad();
3758
3759         while (pCurrent != NULL)
3760         {
3761             if (pCurrent->m_pEntry == pEntry)
3762                 return true;
3763
3764             pCurrent = pCurrent->m_pPrevious;
3765         }
3766
3767         return false;
3768     }
3769 };
3770
3771 //---------------------------------------------------------------------------------------
3772 // 
3773 TypeHandle 
3774 ClassLoader::LoadTypeHandleForTypeKey_Body(
3775     TypeKey *                         pTypeKey, 
3776     TypeHandle                        typeHnd, 
3777     ClassLoadLevel                    targetLevel)
3778 {
3779     CONTRACT(TypeHandle)
3780     {
3781         STANDARD_VM_CHECK;
3782         POSTCONDITION(!typeHnd.IsNull() && typeHnd.GetLoadLevel() >= targetLevel);
3783     }
3784     CONTRACT_END
3785
3786     if (!pTypeKey->IsConstructed())
3787     {
3788         Module *pModule = pTypeKey->GetModule();
3789         mdTypeDef cl = pTypeKey->GetTypeToken();
3790
3791         STRESS_LOG2(LF_CLASSLOADER,  LL_INFO100000, "LoadTypeHandle: Loading Class from Module %p token %x\n", pModule, cl);
3792
3793 #ifdef _DEBUG
3794         IMDInternalImport* pInternalImport = pModule->GetMDImport();
3795         LPCUTF8 className;
3796         LPCUTF8 nameSpace;
3797         if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &className, &nameSpace)))
3798         {
3799             className = nameSpace = "Invalid TypeDef record";
3800         }
3801         if (g_pConfig->ShouldBreakOnClassLoad(className))
3802             CONSISTENCY_CHECK_MSGF(false, ("BreakOnClassLoad: typename '%s' ", className));
3803 #endif
3804     }
3805
3806     ReleaseHolder<PendingTypeLoadEntry> pLoadingEntry;
3807     CrstHolderWithState unresolvedClassLockHolder(&m_UnresolvedClassLock, false);
3808
3809 retry:
3810     unresolvedClassLockHolder.Acquire();    
3811
3812     // Is it in the hash of classes currently being loaded?
3813     pLoadingEntry = m_pUnresolvedClassHash->GetValue(pTypeKey);
3814     if (pLoadingEntry)
3815     {
3816         pLoadingEntry->AddRef();
3817
3818         // It is in the hash, which means that another thread is waiting for it (or that we are
3819         // already loading this class on this thread, which should never happen, since that implies
3820         // a recursive dependency).
3821         unresolvedClassLockHolder.Release();
3822
3823         //
3824         // Check one last time before waiting that the type handle is not sufficiently loaded to 
3825         // prevent deadlocks
3826         //
3827         {
3828             if (typeHnd.IsNull())
3829             {
3830                 typeHnd = LookupTypeHandleForTypeKey(pTypeKey);
3831             }
3832
3833             if (!typeHnd.IsNull())
3834             {
3835                 if (typeHnd.GetLoadLevel() >= targetLevel)
3836                     RETURN typeHnd;
3837             }
3838         }
3839
3840         if (PendingTypeLoadHolder::CheckForDeadLockOnCurrentThread(pLoadingEntry))
3841         {
3842             // Attempting recursive load
3843             ClassLoader::ThrowTypeLoadException(pTypeKey, IDS_CLASSLOAD_GENERAL);
3844         }
3845
3846         //
3847         // Violation of type loadlevel ordering rules depends on type load failing in case of cyclic dependency that would
3848         // otherwise lead to deadlock. We will speculatively proceed with the type load to make it fail in the right spot,
3849         // in backward compatible way. In case the type load succeeds, we will only let one type win in PublishType.
3850         //
3851         if (typeHnd.IsNull() && GetThread()->HasThreadStateNC(Thread::TSNC_LoadsTypeViolation))
3852         {
3853             PendingTypeLoadHolder ptlh(pLoadingEntry);
3854             typeHnd = DoIncrementalLoad(pTypeKey, TypeHandle(), CLASS_LOAD_BEGIN);
3855             goto retry;
3856         }
3857
3858         {
3859             // Wait for class to be loaded by another thread.  This is where we start tracking the
3860             // entry, so there is an implicit Acquire in our use of Assign here.
3861             CrstHolder loadingEntryLockHolder(&pLoadingEntry->m_Crst);
3862             _ASSERTE(pLoadingEntry->HasLock());
3863         }
3864
3865         // Result of other thread loading the class
3866         HRESULT hr = pLoadingEntry->m_hrResult;
3867
3868         if (FAILED(hr)) {
3869
3870             //
3871             // Redo the lookup one more time and return a valid type if possible. The other thread could
3872             // have hit error while loading the type to higher level than we need.
3873             // 
3874             {
3875                 if (typeHnd.IsNull())
3876                 {
3877                     typeHnd = LookupTypeHandleForTypeKey(pTypeKey);
3878                 }
3879
3880                 if (!typeHnd.IsNull())
3881                 {
3882                     if (typeHnd.GetLoadLevel() >= targetLevel)
3883                         RETURN typeHnd;
3884                 }
3885             }
3886
3887             if (hr == E_ABORT) {
3888                 LOG((LF_CLASSLOADER, LL_INFO10, "need to retry LoadTypeHandle: %x\n", hr));
3889                 goto retry;
3890             }
3891
3892             LOG((LF_CLASSLOADER, LL_INFO10, "Failed to load in other entry: %x\n", hr));
3893
3894             if (hr == E_OUTOFMEMORY) {
3895                 COMPlusThrowOM();
3896             }
3897
3898             pLoadingEntry->ThrowException();
3899         }
3900
3901         // Get a pointer to the EEClass being loaded
3902         typeHnd = pLoadingEntry->m_typeHandle;
3903
3904         if (!typeHnd.IsNull())
3905         {
3906             // If the type load on the other thread loaded the type to the needed level, return it here.
3907             if (typeHnd.GetLoadLevel() >= targetLevel)
3908                 RETURN typeHnd;
3909         }
3910
3911         // The type load on the other thread did not load the type "enough". Begin the type load
3912         // process again to cause us to load to the needed level.
3913         goto retry;
3914     }
3915
3916     if (typeHnd.IsNull())
3917     {
3918         // The class was not being loaded.  However, it may have already been loaded after our
3919         // first LoadTypeHandleThrowIfFailed() and before taking the lock.
3920         typeHnd = LookupTypeHandleForTypeKey(pTypeKey);
3921     }
3922
3923     ClassLoadLevel currentLevel = CLASS_LOAD_BEGIN;
3924     if (!typeHnd.IsNull())
3925     {
3926         currentLevel = typeHnd.GetLoadLevel();
3927         if (currentLevel >= targetLevel)
3928             RETURN typeHnd;
3929     }
3930
3931     // It was not loaded, and it is not being loaded, so we must load it.  Create a new LoadingEntry
3932     // and acquire it immediately so that other threads will block. 
3933     pLoadingEntry = new PendingTypeLoadEntry(*pTypeKey, typeHnd);  // this atomically creates a crst and acquires it
3934
3935     if (!(m_pUnresolvedClassHash->InsertValue(pLoadingEntry)))
3936     {
3937         COMPlusThrowOM();
3938     }
3939
3940     // Leave the global lock, so that other threads may now start waiting on our class's lock
3941     unresolvedClassLockHolder.Release();
3942
3943     EX_TRY
3944     {
3945         PendingTypeLoadHolder ptlh(pLoadingEntry);
3946
3947         TRIGGERS_TYPELOAD();
3948
3949         while (currentLevel < targetLevel)
3950         {
3951             typeHnd = DoIncrementalLoad(pTypeKey, typeHnd, currentLevel);
3952             CONSISTENCY_CHECK(typeHnd.GetLoadLevel() > currentLevel);
3953             currentLevel = typeHnd.GetLoadLevel();
3954
3955             // If other threads are waiting for this load, unblock them as soon as possible to prevent deadlocks.
3956             if (pLoadingEntry->HasWaiters())
3957                 break;
3958         }
3959
3960         _ASSERTE(!typeHnd.IsNull());
3961         pLoadingEntry->SetResult(typeHnd);
3962     }
3963     EX_HOOK
3964     {
3965         LOG((LF_CLASSLOADER, LL_INFO10, "Caught an exception loading: %x, %0x (Module)\n", pTypeKey->GetTypeToken(), pTypeKey->GetModule()));
3966
3967         if (!GetThread()->HasThreadStateNC(Thread::TSNC_LoadsTypeViolation))
3968         {
3969             // Fix up the loading entry.
3970             Exception *pException = GET_EXCEPTION();
3971             pLoadingEntry->SetException(pException);
3972         }
3973
3974         // Unlink this class from the unresolved class list.
3975         unresolvedClassLockHolder.Acquire();
3976         m_pUnresolvedClassHash->DeleteValue(pTypeKey);
3977
3978         // Release the lock before proceeding. The unhandled exception filters take number of locks that
3979         // have ordering violations with this lock.
3980         unresolvedClassLockHolder.Release();
3981         
3982         // Unblock any thread waiting to load same type as in TypeLoadEntry
3983         pLoadingEntry->UnblockWaiters();
3984     }
3985     EX_END_HOOK;
3986
3987     // Unlink this class from the unresolved class list.
3988     unresolvedClassLockHolder.Acquire();
3989     m_pUnresolvedClassHash->DeleteValue(pTypeKey);
3990     unresolvedClassLockHolder.Release();
3991
3992     // Unblock any thread waiting to load same type as in TypeLoadEntry. This should be done
3993     // after pLoadingEntry is removed from m_pUnresolvedClassHash. Otherwise the other thread
3994     // (which was waiting) will keep spinning for a while after waking up, till the current thread removes 
3995     //  pLoadingEntry from m_pUnresolvedClassHash. This can cause hang in situation when the current 
3996     // thread is a background thread and so will get very less processor cycle to perform subsequent
3997     // operations to remove the entry from hash later. 
3998     pLoadingEntry->UnblockWaiters();
3999
4000     if (currentLevel < targetLevel)
4001         goto retry;
4002
4003     RETURN typeHnd;
4004 } // ClassLoader::LoadTypeHandleForTypeKey_Body
4005
4006 #endif //!DACCESS_COMPILE
4007
4008 //---------------------------------------------------------------------------------------
4009 // 
4010 //static
4011 TypeHandle 
4012 ClassLoader::LoadArrayTypeThrowing(
4013     TypeHandle     elemType, 
4014     CorElementType arrayKind, 
4015     unsigned       rank,        //=0
4016     LoadTypesFlag  fLoadTypes,  //=LoadTypes
4017     ClassLoadLevel level)
4018 {
4019     CONTRACT(TypeHandle)
4020     {
4021         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
4022         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
4023         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
4024         if (FORBIDGC_LOADER_USE_ENABLED() || fLoadTypes != LoadTypes) { LOADS_TYPE(CLASS_LOAD_BEGIN); } else { LOADS_TYPE(level); }
4025         MODE_ANY;
4026         SUPPORTS_DAC;
4027         POSTCONDITION(CheckPointer(RETVAL, ((fLoadTypes == LoadTypes) ? NULL_NOT_OK : NULL_OK)));
4028     }
4029     CONTRACT_END
4030
4031     CorElementType predefinedElementType = ELEMENT_TYPE_END;
4032
4033     // Try finding it in our cache of primitive SD arrays
4034     if (arrayKind == ELEMENT_TYPE_SZARRAY) {
4035         predefinedElementType = elemType.GetSignatureCorElementType();
4036         if (predefinedElementType <= ELEMENT_TYPE_R8) {
4037             ArrayTypeDesc* typeDesc = g_pPredefinedArrayTypes[predefinedElementType];
4038             if (typeDesc != 0)
4039                 RETURN(TypeHandle(typeDesc));
4040         }
4041         // This call to AsPtr is somewhat bogus and only used
4042         // as an optimization.  If the TypeHandle is really a TypeDesc
4043         // then the equality checks for the optimizations below will 
4044         // fail.  Thus ArrayMT should not be used elsewhere in this function
4045         else if (elemType.AsPtr() == PTR_VOID(g_pObjectClass)) {
4046             // Code duplicated because Object[]'s SigCorElementType is E_T_CLASS, not OBJECT
4047             ArrayTypeDesc* typeDesc = g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT];
4048             if (typeDesc != 0)
4049                 RETURN(TypeHandle(typeDesc));
4050             predefinedElementType = ELEMENT_TYPE_OBJECT;
4051         }
4052         else if (elemType.AsPtr() == PTR_VOID(g_pStringClass)) {
4053             // Code duplicated because String[]'s SigCorElementType is E_T_CLASS, not STRING
4054             ArrayTypeDesc* typeDesc = g_pPredefinedArrayTypes[ELEMENT_TYPE_STRING];
4055             if (typeDesc != 0)
4056                 RETURN(TypeHandle(typeDesc));
4057             predefinedElementType = ELEMENT_TYPE_STRING;
4058         }
4059         else {
4060             predefinedElementType = ELEMENT_TYPE_END;
4061         }
4062         rank = 1;
4063     }
4064
4065 #ifndef DACCESS_COMPILE
4066     // To avoid loading useless shared instantiations, normalize shared instantiations to the canonical form 
4067     // (e.g. List<_Canon>[] -> _Canon[])
4068     // The denormalized shared instantiations should be needed only during JITing, so it is fine to skip this
4069     // for DACCESS_COMPILE.
4070     if (elemType.IsCanonicalSubtype())
4071     {
4072         elemType = ClassLoader::CanonicalizeGenericArg(elemType);
4073     }
4074 #endif
4075
4076     TypeKey key(arrayKind, elemType, FALSE, rank);
4077     TypeHandle th = LoadConstructedTypeThrowing(&key, fLoadTypes, level);
4078
4079     if (predefinedElementType != ELEMENT_TYPE_END && !th.IsNull() && th.IsFullyLoaded())
4080     {
4081         g_pPredefinedArrayTypes[predefinedElementType] = th.AsArray();
4082     }
4083
4084     RETURN(th);
4085 } // ClassLoader::LoadArrayTypeThrowing
4086
4087 #ifndef DACCESS_COMPILE
4088
4089 VOID ClassLoader::AddAvailableClassDontHaveLock(Module *pModule,
4090                                                 mdTypeDef classdef,
4091                                                 AllocMemTracker *pamTracker)
4092 {
4093     CONTRACTL
4094     {
4095         INSTANCE_CHECK;
4096         THROWS;
4097         GC_TRIGGERS;
4098         MODE_ANY;
4099         INJECT_FAULT(COMPlusThrowOM(););
4100     }
4101     CONTRACTL_END
4102     
4103 #ifdef FEATURE_COMINTEROP
4104     _ASSERTE(!pModule->GetAssembly()->IsWinMD());   // WinMD files should never get into this path, otherwise provide szWinRtNamespacePrefix
4105 #endif
4106
4107     CrstHolder ch(&m_AvailableClassLock);
4108
4109     AddAvailableClassHaveLock(
4110         pModule, 
4111         classdef, 
4112         pamTracker, 
4113         NULL,   // szWinRtNamespacePrefix
4114         0);     // cchWinRtNamespacePrefix
4115 }
4116
4117 // This routine must be single threaded!  The reason is that there are situations which allow
4118 // the same class name to have two different mdTypeDef tokens (for example, we load two different DLLs
4119 // simultaneously, and they have some common class files, or we convert the same class file
4120 // simultaneously on two threads).  The problem is that we do not want to overwrite the old
4121 // <classname> -> pModule mapping with the new one, because this may cause identity problems.
4122 //
4123 // This routine assumes you already have the lock.  Use AddAvailableClassDontHaveLock() if you
4124 // don't have it.
4125 // 
4126 // Also validates that TypeDef namespace begins with szWinRTNamespacePrefix (if it is not NULL).
4127 // The prefix should be NULL for normal non-WinRT .NET assemblies.
4128 // 
4129 VOID ClassLoader::AddAvailableClassHaveLock(
4130     Module *          pModule, 
4131     mdTypeDef         classdef, 
4132     AllocMemTracker * pamTracker, 
4133     LPCSTR            szWinRtNamespacePrefix, 
4134     DWORD             cchWinRtNamespacePrefix)  // Optimization for faster prefix comparison implementation
4135 {
4136     CONTRACTL
4137     {
4138         INSTANCE_CHECK;
4139         THROWS;
4140         GC_TRIGGERS;
4141         MODE_ANY;
4142         INJECT_FAULT(COMPlusThrowOM(););
4143     }
4144     CONTRACTL_END
4145
4146     EEClassHashTable *pClassHash = pModule->GetAvailableClassHash();
4147     EEClassHashTable *pClassCaseInsHash = pModule->GetAvailableClassCaseInsHash();
4148
4149     LPCUTF8        pszName;
4150     LPCUTF8        pszNameSpace;
4151     HashDatum      ThrowawayData;
4152     IMDInternalImport *pMDImport = pModule->GetMDImport();
4153     if (FAILED(pMDImport->GetNameOfTypeDef(classdef, &pszName, &pszNameSpace)))
4154     {
4155         pszName = pszNameSpace = "Invalid TypeDef token";
4156         pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_INVALID_TOKEN);
4157     }
4158     
4159     EEClassHashEntry_t *pBucket;
4160     mdTypeDef      enclosing;
4161     if (SUCCEEDED(pMDImport->GetNestedClassProps(classdef, &enclosing))) {
4162         // nested type
4163
4164         LPCUTF8 pszEnclosingName;
4165         LPCUTF8 pszEnclosingNameSpace;
4166         mdTypeDef enclEnclosing;
4167
4168         // Find this type's encloser's entry in the available table.
4169         // We'll save a pointer to it in the new hash entry for this type.
4170         BOOL fNestedEncl = SUCCEEDED(pMDImport->GetNestedClassProps(enclosing, &enclEnclosing));
4171
4172         EEClassHashTable::LookupContext sContext;
4173         if (FAILED(pMDImport->GetNameOfTypeDef(enclosing, &pszEnclosingName, &pszEnclosingNameSpace)))
4174         {
4175             pszName = pszNameSpace = "Invalid TypeDef token";
4176             pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_INVALID_TOKEN);
4177         }
4178         if ((pBucket = pClassHash->GetValue(pszEnclosingNameSpace,
4179                                             pszEnclosingName,
4180                                             &ThrowawayData,
4181                                             fNestedEncl,
4182                                             &sContext)) != NULL) {
4183             if (fNestedEncl) {
4184                 // Find entry for enclosing class - NOTE, this assumes that the
4185                 // enclosing class's TypeDef or ExportedType was inserted previously,
4186                 // which assumes that, when enuming TD's, we get the enclosing class first
4187                 while ((!CompareNestedEntryWithTypeDef(pMDImport,
4188                                                        enclEnclosing,
4189                                                        pClassHash,
4190                                                        pBucket->GetEncloser())) &&
4191                        (pBucket = pClassHash->FindNextNestedClass(pszEnclosingNameSpace,
4192                                                                   pszEnclosingName,
4193                                                                   &ThrowawayData,
4194                                                                   &sContext)) != NULL);
4195             }
4196
4197             if (!pBucket) // Enclosing type not found in hash table
4198                 pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_ENCLOSING_TYPE_NOT_FOUND);
4199
4200             // In this hash table, if the lower bit is set, it means a Module, otherwise it means EEClass*
4201             ThrowawayData = EEClassHashTable::CompressClassDef(classdef);
4202             InsertValue(pClassHash, pClassCaseInsHash, pszNameSpace, pszName, ThrowawayData, pBucket, pamTracker);
4203         }
4204     }
4205     else {
4206         // Don't add duplicate top-level classes.  Top-level classes are
4207         // added to the beginning of the bucket, while nested classes are
4208         // added to the end.  So, a duplicate top-level class could hide
4209         // the previous type's EEClass* entry in the hash table.
4210         EEClassHashEntry_t *pCaseInsEntry = NULL;
4211         LPUTF8 pszLowerCaseNS = NULL;
4212         LPUTF8 pszLowerCaseName = NULL;
4213
4214         if (pClassCaseInsHash) {
4215             CreateCanonicallyCasedKey(pszNameSpace, pszName, &pszLowerCaseNS, &pszLowerCaseName);
4216             pCaseInsEntry = pClassCaseInsHash->AllocNewEntry(pamTracker);
4217         }
4218
4219         EEClassHashEntry_t *pEntry = pClassHash->FindItem(pszNameSpace, pszName, FALSE, NULL);
4220         if (pEntry) {
4221             HashDatum Data = pEntry->GetData();
4222
4223             if (((size_t)Data & EECLASSHASH_TYPEHANDLE_DISCR) &&
4224                 ((size_t)Data & EECLASSHASH_MDEXPORT_DISCR)) {
4225
4226                 // it's an ExportedType - check the 'already seen' bit and if on, report a class loading exception
4227                 // otherwise, set it
4228                 if ((size_t)Data & EECLASSHASH_ALREADYSEEN)
4229                     pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_MULT_TYPE_SAME_NAME);
4230                 else {
4231                     Data = (HashDatum)((size_t)Data | EECLASSHASH_ALREADYSEEN);
4232                     pEntry->SetData(Data);
4233                 }
4234             }
4235             else {
4236                 // We want to throw an exception for a duplicate typedef.
4237                 // However, this used to be allowed in 1.0/1.1, and some third-party DLLs have
4238                 // been obfuscated so that they have duplicate private typedefs.
4239                 // We must allow this for old assemblies for app compat reasons
4240                 pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_MULT_TYPE_SAME_NAME);
4241             }
4242         }
4243         else {
4244             pEntry = pClassHash->AllocNewEntry(pamTracker);
4245
4246             CANNOTTHROWCOMPLUSEXCEPTION();
4247             FAULT_FORBID();
4248
4249             pClassHash->InsertValueUsingPreallocatedEntry(pEntry, pszNameSpace, pszName, EEClassHashTable::CompressClassDef(classdef), NULL);
4250
4251             if (pClassCaseInsHash)
4252                 pClassCaseInsHash->InsertValueUsingPreallocatedEntry(pCaseInsEntry, pszLowerCaseNS, pszLowerCaseName, pEntry, pEntry->GetEncloser());
4253         }
4254         
4255 #ifdef FEATURE_COMINTEROP
4256         // Check WinRT namespace prefix if required
4257         if (szWinRtNamespacePrefix != NULL)
4258         {
4259             DWORD dwAttr;
4260             if (FAILED(pMDImport->GetTypeDefProps(classdef, &dwAttr, NULL)))
4261             {
4262                 pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_INVALID_TOKEN);
4263             }
4264             
4265             // Check only public WinRT types that are not nested (i.e. only types available for binding, excluding NoPIA)
4266             if (IsTdPublic(dwAttr) && IsTdWindowsRuntime(dwAttr))
4267             {
4268                 // Guaranteed by the caller - code:ClassLoader::PopulateAvailableClassHashTable
4269                 _ASSERTE(cchWinRtNamespacePrefix == strlen(szWinRtNamespacePrefix));
4270                 
4271                 // Now make sure namespace is, or begins with the namespace-prefix (note: 'MyN' should not match namespace 'MyName')
4272                 // Note: Case insensitive comparison function has to be in sync with Win8 implementation 
4273                 // (ExtractExactCaseNamespaceSegmentFromMetadataFile in com\WinRT\WinTypes\TypeResolution\NamespaceResolution.cpp)
4274                 BOOL fIsNamespaceSubstring = (pszNameSpace != NULL) && 
4275                                               ((strncmp(pszNameSpace, szWinRtNamespacePrefix, cchWinRtNamespacePrefix) == 0) || 
4276                                                (_strnicmp(pszNameSpace, szWinRtNamespacePrefix, cchWinRtNamespacePrefix) == 0));
4277                 BOOL fIsSubNamespace = fIsNamespaceSubstring && 
4278                                        ((pszNameSpace[cchWinRtNamespacePrefix] == '\0') || 
4279                                         (pszNameSpace[cchWinRtNamespacePrefix] == '.'));
4280                 if (!fIsSubNamespace)
4281                 {
4282                     pModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_WINRT_INVALID_NAMESPACE_FOR_TYPE);
4283                 }
4284             }
4285         }
4286 #endif // FEATURE_COMINTEROP
4287     }
4288 }
4289
4290 VOID ClassLoader::AddExportedTypeDontHaveLock(Module *pManifestModule,
4291     mdExportedType cl,
4292     AllocMemTracker *pamTracker)
4293 {
4294     CONTRACTL
4295     {
4296         INSTANCE_CHECK;
4297         THROWS;
4298         GC_TRIGGERS;
4299         MODE_ANY;
4300         INJECT_FAULT(COMPlusThrowOM(););
4301     }
4302     CONTRACTL_END
4303
4304     CrstHolder ch(&m_AvailableClassLock);
4305
4306     AddExportedTypeHaveLock(
4307         pManifestModule,
4308         cl,
4309         pamTracker);
4310 }
4311
4312 VOID ClassLoader::AddExportedTypeHaveLock(Module *pManifestModule,
4313                                           mdExportedType cl,
4314                                           AllocMemTracker *pamTracker)
4315 {
4316     CONTRACTL
4317     {
4318         INSTANCE_CHECK;
4319         THROWS;
4320         GC_TRIGGERS;
4321         MODE_ANY;
4322         INJECT_FAULT(COMPlusThrowOM(););
4323     }
4324     CONTRACTL_END
4325
4326
4327     mdToken mdImpl;
4328     LPCSTR pszName;
4329     LPCSTR pszNameSpace;
4330     IMDInternalImport* pAsmImport = pManifestModule->GetMDImport();
4331     if (FAILED(pAsmImport->GetExportedTypeProps(
4332         cl,
4333         &pszNameSpace,
4334         &pszName,
4335         &mdImpl,
4336         NULL,   // type def
4337         NULL))) // flags
4338     {
4339         pManifestModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_INVALID_TOKEN);
4340     }
4341     
4342     HashDatum ThrowawayData;
4343     
4344     if (TypeFromToken(mdImpl) == mdtExportedType)
4345     {
4346         // nested class
4347         LPCUTF8 pszEnclosingNameSpace;
4348         LPCUTF8 pszEnclosingName;
4349         mdToken nextImpl;
4350         if (FAILED(pAsmImport->GetExportedTypeProps(
4351             mdImpl, 
4352             &pszEnclosingNameSpace, 
4353             &pszEnclosingName, 
4354             &nextImpl, 
4355             NULL,   // type def
4356             NULL))) // flags
4357         {
4358             pManifestModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_INVALID_TOKEN);
4359         }
4360         
4361         // Find entry for enclosing class - NOTE, this assumes that the
4362         // enclosing class's ExportedType was inserted previously, which assumes that,
4363         // when enuming ExportedTypes, we get the enclosing class first
4364         EEClassHashEntry_t *pBucket;
4365         EEClassHashTable::LookupContext sContext;
4366         if ((pBucket = pManifestModule->GetAvailableClassHash()->GetValue(pszEnclosingNameSpace,
4367                                                                           pszEnclosingName,
4368                                                                           &ThrowawayData,
4369                                                                           TypeFromToken(nextImpl) == mdtExportedType,
4370                                                                           &sContext)) != NULL) {
4371             do {
4372                 // check to see if this is the correct class
4373                 if (EEClassHashTable::UncompressModuleAndClassDef(ThrowawayData) == mdImpl) {
4374                     ThrowawayData = EEClassHashTable::CompressClassDef(cl);
4375
4376                     // we explicitly don't check for the case insensitive hash table because we know it can't have been created yet
4377                     pManifestModule->GetAvailableClassHash()->InsertValue(pszNameSpace, pszName, ThrowawayData, pBucket, pamTracker);
4378                 }
4379                 pBucket = pManifestModule->GetAvailableClassHash()->FindNextNestedClass(pszEnclosingNameSpace, pszEnclosingName, &ThrowawayData, &sContext);
4380             } while (pBucket);
4381         }
4382
4383         // If the encloser is not in the hash table, this nested class
4384         // was defined in the manifest module, so it doesn't need to be added
4385         return;
4386     }
4387     else {
4388         // Defined in the manifest module - add to the hash table by TypeDef instead
4389         if (mdImpl == mdFileNil)
4390             return;
4391
4392         // Don't add duplicate top-level classes
4393         // In this hash table, if the lower bit is set, it means a Module, otherwise it means EEClass*
4394         ThrowawayData = EEClassHashTable::CompressClassDef(cl);
4395         // ThrowawayData is an IN OUT param. Going in its the pointer to the new value if the entry needs
4396         // to be inserted. The OUT param points to the value stored in the hash table.
4397         BOOL bFound;
4398         pManifestModule->GetAvailableClassHash()->InsertValueIfNotFound(pszNameSpace, pszName, &ThrowawayData, NULL, FALSE, &bFound, pamTracker);
4399         if (bFound) {
4400
4401             // Check for duplicate ExportedTypes
4402             // Let it slide if it's pointing to the same type
4403             mdToken foundTypeImpl;
4404             if ((size_t)ThrowawayData & EECLASSHASH_MDEXPORT_DISCR)
4405             {
4406                 mdExportedType foundExportedType = EEClassHashTable::UncompressModuleAndClassDef(ThrowawayData);
4407                 if (FAILED(pAsmImport->GetExportedTypeProps(
4408                     foundExportedType,
4409                     NULL,   // namespace
4410                     NULL,   // name
4411                     &foundTypeImpl, 
4412                     NULL,   // TypeDef
4413                     NULL))) // flags
4414                 {
4415                     pManifestModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_INVALID_TOKEN);
4416                 }
4417             }
4418             else
4419             {
4420                 foundTypeImpl = mdFileNil;
4421             }
4422
4423             if (mdImpl != foundTypeImpl)
4424             {
4425                 pManifestModule->GetAssembly()->ThrowBadImageException(pszNameSpace, pszName, BFA_MULT_TYPE_SAME_NAME);
4426             }
4427         }
4428     }
4429 }
4430
4431 static MethodTable* GetEnclosingMethodTable(MethodTable *pMT)
4432 {
4433     CONTRACT(MethodTable*)
4434     {
4435         THROWS;
4436         GC_TRIGGERS;
4437         INJECT_FAULT(COMPlusThrowOM(););
4438         MODE_ANY;
4439         PRECONDITION(CheckPointer(pMT));
4440         POSTCONDITION(RETVAL == NULL || RETVAL->IsTypicalTypeDefinition());
4441     }
4442     CONTRACT_END;
4443
4444     RETURN pMT->LoadEnclosingMethodTable();
4445 }
4446
4447 StaticAccessCheckContext::StaticAccessCheckContext(MethodDesc* pCallerMethod)
4448 {
4449     CONTRACTL
4450     {
4451         LIMITED_METHOD_CONTRACT;
4452         PRECONDITION(CheckPointer(pCallerMethod));
4453     }
4454     CONTRACTL_END;
4455
4456     m_pCallerMethod = pCallerMethod;
4457     m_pCallerMT = m_pCallerMethod->GetMethodTable();
4458     m_pCallerAssembly = m_pCallerMT->GetAssembly();
4459 }
4460
4461 StaticAccessCheckContext::StaticAccessCheckContext(MethodDesc* pCallerMethod, MethodTable* pCallerType)
4462 {
4463     CONTRACTL
4464     {
4465         LIMITED_METHOD_CONTRACT;
4466         PRECONDITION(CheckPointer(pCallerMethod, NULL_OK));
4467         PRECONDITION(CheckPointer(pCallerType));
4468     }
4469     CONTRACTL_END;
4470
4471     m_pCallerMethod = pCallerMethod;
4472     m_pCallerMT = pCallerType;
4473     m_pCallerAssembly = pCallerType->GetAssembly();
4474 }
4475
4476 //******************************************************************************
4477
4478 // static
4479 AccessCheckOptions* AccessCheckOptions::s_pNormalAccessChecks;
4480
4481 //******************************************************************************
4482
4483 void AccessCheckOptions::Startup()
4484 {
4485     STANDARD_VM_CONTRACT;
4486
4487     s_pNormalAccessChecks = new AccessCheckOptions(
4488                                     AccessCheckOptions::kNormalAccessibilityChecks, 
4489                                     NULL, 
4490                                     FALSE, 
4491                                     (MethodTable *)NULL);
4492 }
4493
4494 //******************************************************************************
4495 AccessCheckOptions::AccessCheckOptions(
4496     const AccessCheckOptions & templateOptions,
4497     BOOL                       throwIfTargetIsInaccessible) :
4498     m_pAccessContext(templateOptions.m_pAccessContext)
4499 {
4500     WRAPPER_NO_CONTRACT;
4501
4502     Initialize(
4503         templateOptions.m_accessCheckType,
4504         throwIfTargetIsInaccessible,
4505         templateOptions.m_pTargetMT,
4506         templateOptions.m_pTargetMethod, 
4507         templateOptions.m_pTargetField);
4508 }
4509
4510 //******************************************************************************
4511 // This function should only be called when normal accessibility is not possible.
4512 // It returns TRUE if the target can be accessed.
4513 // Otherwise, it either returns FALSE or throws an exception, depending on the value of throwIfTargetIsInaccessible.
4514
4515 BOOL AccessCheckOptions::DemandMemberAccess(AccessCheckContext *pContext, MethodTable * pTargetMT, BOOL visibilityCheck) const
4516 {
4517     CONTRACTL
4518     {
4519         THROWS;
4520         GC_TRIGGERS;
4521         MODE_ANY;
4522         PRECONDITION(m_accessCheckType != kNormalAccessibilityChecks);
4523         PRECONDITION(CheckPointer(pContext));
4524     }
4525     CONTRACTL_END;
4526
4527     _ASSERTE(m_accessCheckType != kNormalAccessibilityChecks);
4528
4529     if (NingenEnabled())
4530     {
4531         // NinGen should always perform normal accessibility checks
4532         _ASSERTE(false);
4533
4534         if (m_fThrowIfTargetIsInaccessible)
4535         {
4536             ThrowAccessException(pContext, pTargetMT, NULL);
4537         }
4538
4539         return FALSE;
4540     }
4541     
4542     if (pTargetMT && pTargetMT->GetAssembly()->IsDisabledPrivateReflection())
4543     {
4544         if (m_fThrowIfTargetIsInaccessible)
4545         {
4546             ThrowAccessException(pContext, pTargetMT, NULL);
4547         }
4548
4549         return FALSE;
4550     }
4551
4552     BOOL canAccessTarget = FALSE;
4553
4554 #ifndef CROSSGEN_COMPILE
4555
4556     // In CoreCLR kRestrictedMemberAccess means that one can access private/internal
4557     // classes/members in app code.
4558     if (m_accessCheckType != kMemberAccess && pTargetMT)
4559     {
4560         // We allow all transparency checks to succeed in LCG methods and reflection invocation.
4561         if (m_accessCheckType == kNormalAccessNoTransparency || m_accessCheckType == kRestrictedMemberAccessNoTransparency)
4562             return TRUE;
4563     }
4564
4565     // Always allow interop (NULL) callers full access.
4566     if (pContext->IsCalledFromInterop())
4567         return TRUE;
4568
4569     // No Access
4570     if (m_fThrowIfTargetIsInaccessible)
4571     {
4572         ThrowAccessException(pContext, pTargetMT, NULL);
4573     }
4574
4575 #endif // CROSSGEN_COMPILE
4576
4577     return canAccessTarget;
4578 }
4579
4580 //******************************************************************************
4581 // pFailureMT - the MethodTable that we were trying to access. It can be null
4582 //              if the failure is not because of a specific type. This will be a
4583 //              a component of the instantiation of m_pTargetMT/m_pTargetMethod/m_pTargetField.
4584
4585 void AccessCheckOptions::ThrowAccessException(
4586     AccessCheckContext* pContext,
4587     MethodTable*        pFailureMT,             /* = NULL  */
4588     Exception*          pInnerException         /* = NULL  */) const
4589 {
4590     CONTRACTL
4591     {
4592         THROWS;
4593         GC_TRIGGERS;
4594         MODE_ANY;
4595         PRECONDITION(CheckPointer(pContext));
4596         PRECONDITION(CheckPointer(pInnerException, NULL_OK));
4597         PRECONDITION(m_fThrowIfTargetIsInaccessible);
4598     }
4599     CONTRACTL_END;
4600
4601     GCX_COOP();
4602
4603     MethodDesc* pCallerMD = pContext->GetCallerMethod();
4604
4605     if (m_pTargetMT != NULL)
4606     {
4607         // If we know the specific type that caused the failure, display it.
4608         // Else display the whole type that we are trying to access.
4609         MethodTable * pMT = (pFailureMT != NULL) ? pFailureMT : m_pTargetMT;
4610         ThrowTypeAccessException(pContext, pMT, 0, pInnerException);
4611     }
4612     else if (m_pTargetMethod != NULL) 
4613     {
4614         // If the caller and target method are non-null and the same, then this means that we're checking to see
4615         // if the method has access to itself in order to validate that it has access to its parameter types,
4616         // containing type, and return type.  In this case, throw a more informative TypeAccessException to
4617         // describe the error that occurred (for instance, "this method doesn't have access to one of its
4618         // parameter types", rather than "this method doesn't have access to itself").
4619         // We only want to do this if we know the exact type that caused the problem, otherwise fall back to
4620         // throwing the standard MethodAccessException.
4621         if (pCallerMD != NULL && m_pTargetMethod == pCallerMD && pFailureMT != NULL)
4622         {
4623             ThrowTypeAccessException(pContext, pFailureMT, 0, pInnerException);
4624         }
4625         else
4626         {
4627             ThrowMethodAccessException(pContext, m_pTargetMethod, 0, pInnerException);
4628         }
4629     }
4630     else
4631     {
4632         _ASSERTE(m_pTargetField != NULL);
4633         ThrowFieldAccessException(pContext, m_pTargetField, 0, pInnerException);
4634     }
4635 }
4636
4637 //******************************************************************************
4638 // This will do a security demand if appropriate.
4639 // If access is not possible, this will either throw an exception or return FALSE
4640 BOOL AccessCheckOptions::DemandMemberAccessOrFail(AccessCheckContext *pContext, MethodTable * pTargetMT, BOOL visibilityCheck) const
4641 {
4642     CONTRACTL
4643     {
4644         THROWS;
4645         GC_TRIGGERS;
4646         MODE_ANY;
4647     }
4648     CONTRACTL_END;
4649
4650     if (DoNormalAccessibilityChecks())
4651     {
4652         if (pContext->GetCallerAssembly()->IgnoresAccessChecksTo(pTargetMT->GetAssembly()))
4653         {
4654             return TRUE;
4655         }
4656
4657         if (m_fThrowIfTargetIsInaccessible)
4658         {
4659             ThrowAccessException(pContext, pTargetMT);
4660         }
4661
4662         return FALSE;
4663     }
4664
4665     return DemandMemberAccess(pContext, pTargetMT, visibilityCheck);
4666 }
4667
4668 //******************************************************************************
4669 // This should be called if access to the target is not possible.
4670 // This will either throw an exception or return FALSE.
4671 BOOL AccessCheckOptions::FailOrThrow(AccessCheckContext *pContext) const
4672 {
4673     CONTRACTL
4674     {
4675         THROWS;
4676         GC_TRIGGERS;
4677         MODE_ANY;
4678         PRECONDITION(CheckPointer(pContext));
4679     }
4680     CONTRACTL_END;
4681
4682     if (m_fThrowIfTargetIsInaccessible)
4683     {
4684         ThrowAccessException(pContext);
4685     }
4686
4687     return FALSE;
4688 }
4689
4690 void DECLSPEC_NORETURN ThrowFieldAccessException(AccessCheckContext* pContext,
4691                                                  FieldDesc *pFD,
4692                                                  UINT messageID /* = 0 */,
4693                                                  Exception *pInnerException /* = NULL */)
4694 {
4695     CONTRACTL
4696     {
4697         THROWS;
4698         GC_TRIGGERS;
4699         MODE_ANY;
4700         PRECONDITION(CheckPointer(pContext));
4701         PRECONDITION(CheckPointer(pFD));
4702     }
4703     CONTRACTL_END;
4704
4705     MethodDesc* pCallerMD = pContext->GetCallerMethod();
4706     
4707     ThrowFieldAccessException(pCallerMD,
4708                               pFD,
4709                               messageID,
4710                               pInnerException);
4711 }
4712
4713 void DECLSPEC_NORETURN ThrowFieldAccessException(MethodDesc* pCallerMD,
4714                                                  FieldDesc *pFD,
4715                                                  UINT messageID /* = 0 */,
4716                                                  Exception *pInnerException /* = NULL */)
4717 {
4718     CONTRACTL
4719     {
4720         THROWS;
4721         GC_TRIGGERS;
4722         MODE_ANY;
4723         PRECONDITION(CheckPointer(pCallerMD, NULL_OK));
4724         PRECONDITION(CheckPointer(pFD));
4725     }
4726     CONTRACTL_END;
4727
4728     if (pCallerMD != NULL)
4729     {
4730         if (messageID == 0)
4731         {
4732             messageID = IDS_E_FIELDACCESS;
4733         }
4734
4735         EX_THROW_WITH_INNER(EEFieldException, (pFD, pCallerMD, SString::Empty(), messageID), pInnerException);
4736     }
4737     else
4738     {
4739         EX_THROW_WITH_INNER(EEFieldException, (pFD), pInnerException);
4740     }
4741 }
4742
4743 void DECLSPEC_NORETURN ThrowMethodAccessException(AccessCheckContext* pContext,
4744                                                   MethodDesc *pCalleeMD,
4745                                                   UINT messageID /* = 0 */,
4746                                                   Exception *pInnerException /* = NULL */)
4747 {
4748     CONTRACTL
4749     {
4750         THROWS;
4751         GC_TRIGGERS;
4752         MODE_ANY;
4753         PRECONDITION(CheckPointer(pContext));
4754         PRECONDITION(CheckPointer(pCalleeMD));
4755     }
4756     CONTRACTL_END;
4757
4758     MethodDesc* pCallerMD = pContext->GetCallerMethod();
4759     
4760     ThrowMethodAccessException(pCallerMD,
4761                                pCalleeMD,
4762                                messageID,
4763                                pInnerException);
4764 }
4765
4766 void DECLSPEC_NORETURN ThrowMethodAccessException(MethodDesc* pCallerMD,
4767                                                   MethodDesc *pCalleeMD,
4768                                                   UINT messageID /* = 0 */,
4769                                                   Exception *pInnerException /* = NULL */)
4770 {
4771     CONTRACTL
4772     {
4773         THROWS;
4774         GC_TRIGGERS;
4775         MODE_ANY;
4776         PRECONDITION(CheckPointer(pCallerMD, NULL_OK));
4777         PRECONDITION(CheckPointer(pCalleeMD));
4778     }
4779     CONTRACTL_END;
4780
4781     if (pCallerMD != NULL)
4782     {
4783         if (messageID == 0)
4784         {
4785             messageID = IDS_E_METHODACCESS;
4786         }
4787
4788         EX_THROW_WITH_INNER(EEMethodException, (pCalleeMD, pCallerMD, SString::Empty(), messageID), pInnerException);
4789     }
4790     else
4791     {
4792         EX_THROW_WITH_INNER(EEMethodException, (pCalleeMD), pInnerException);
4793     }
4794 }
4795
4796 void DECLSPEC_NORETURN ThrowTypeAccessException(AccessCheckContext* pContext,
4797                                                 MethodTable *pMT,
4798                                                 UINT messageID /* = 0 */,
4799                                                 Exception *pInnerException /* = NULL */)
4800 {
4801     CONTRACTL
4802     {
4803         THROWS;
4804         GC_TRIGGERS;
4805         MODE_ANY;
4806         PRECONDITION(CheckPointer(pContext));
4807         PRECONDITION(CheckPointer(pMT));
4808     }
4809     CONTRACTL_END;
4810
4811     MethodDesc* pCallerMD = pContext->GetCallerMethod();
4812     
4813     ThrowTypeAccessException(pCallerMD,
4814                              pMT,
4815                              messageID,
4816                              pInnerException);
4817 }
4818
4819 void DECLSPEC_NORETURN ThrowTypeAccessException(MethodDesc* pCallerMD,
4820                                                 MethodTable *pMT,
4821                                                 UINT messageID /* = 0 */,
4822                                                 Exception *pInnerException /* = NULL */)
4823 {
4824     CONTRACTL
4825     {
4826         THROWS;
4827         GC_TRIGGERS;
4828         MODE_ANY;
4829         PRECONDITION(CheckPointer(pCallerMD, NULL_OK));
4830         PRECONDITION(CheckPointer(pMT));
4831     }
4832     CONTRACTL_END;
4833
4834     if (pCallerMD != NULL)
4835     {
4836         if (messageID == 0)
4837         {
4838             messageID = IDS_E_TYPEACCESS;
4839         }
4840
4841         EX_THROW_WITH_INNER(EETypeAccessException, (pMT, pCallerMD, SString::Empty(), messageID), pInnerException);
4842     }
4843     else
4844     {
4845         EX_THROW_WITH_INNER(EETypeAccessException, (pMT), pInnerException);
4846     }
4847 }
4848
4849 //---------------------------------------------------------------------------------------
4850 //
4851 // Checks to see if access to a member with assembly visiblity is allowed.
4852 //
4853 // Arguments:
4854 //    pAccessingAssembly    - The assembly requesting access to the internal member
4855 //    pTargetAssembly       - The assembly which contains the target member
4856 //    pOptionalTargetField  - Internal field being accessed OR
4857 //    pOptionalTargetMethod - Internal type being accessed OR
4858 //    pOptionalTargetType   - Internal type being accessed
4859 //
4860 // Return Value:
4861 //    TRUE if pTargetAssembly is pAccessingAssembly, or if pTargetAssembly allows
4862 //    pAccessingAssembly friend access to the target. FALSE otherwise.
4863 //
4864
4865 static BOOL AssemblyOrFriendAccessAllowed(Assembly       *pAccessingAssembly,
4866                                           Assembly       *pTargetAssembly,
4867                                           FieldDesc      *pOptionalTargetField,
4868                                           MethodDesc     *pOptionalTargetMethod,
4869                                           MethodTable    *pOptionalTargetType)
4870 {
4871     CONTRACTL
4872     {
4873         THROWS;
4874         GC_TRIGGERS;
4875         PRECONDITION(CheckPointer(pAccessingAssembly));
4876         PRECONDITION(CheckPointer(pTargetAssembly));
4877         PRECONDITION(pOptionalTargetField != NULL || pOptionalTargetMethod != NULL || pOptionalTargetType != NULL);
4878         PRECONDITION(pOptionalTargetField == NULL || pOptionalTargetMethod == NULL);
4879     }
4880     CONTRACTL_END;
4881
4882     if (pAccessingAssembly == pTargetAssembly)
4883     {
4884         return TRUE;
4885     }
4886
4887     if (pAccessingAssembly->IgnoresAccessChecksTo(pTargetAssembly))
4888     {
4889         return TRUE;
4890     }
4891
4892     else if (pOptionalTargetField != NULL)
4893     {
4894         return pTargetAssembly->GrantsFriendAccessTo(pAccessingAssembly, pOptionalTargetField);
4895     }
4896     else if (pOptionalTargetMethod != NULL)
4897     {
4898         return pTargetAssembly->GrantsFriendAccessTo(pAccessingAssembly, pOptionalTargetMethod);
4899     }
4900     else
4901     {
4902         return pTargetAssembly->GrantsFriendAccessTo(pAccessingAssembly, pOptionalTargetType);
4903     }
4904 }
4905
4906 //******************************************************************************
4907 // This function determines whether a target class is accessible from 
4908 //  some given class.
4909 /* static */
4910 BOOL ClassLoader::CanAccessMethodInstantiation( // True if access is legal, false otherwise. 
4911     AccessCheckContext* pContext,
4912     MethodDesc*         pOptionalTargetMethod,  // The desired method; if NULL, return TRUE (or)
4913     const AccessCheckOptions & accessCheckOptions)
4914 {                                           
4915     CONTRACTL
4916     {
4917         THROWS;
4918         GC_TRIGGERS;
4919         INJECT_FAULT(COMPlusThrowOM(););
4920         MODE_ANY;
4921         PRECONDITION(CheckPointer(pContext));
4922     }
4923     CONTRACTL_END
4924
4925     // If there is no target method just allow access.
4926     // NB: the caller may just be checking access to a field or class, so we allow for NULL.
4927     if (!pOptionalTargetMethod)
4928         return TRUE;
4929
4930     // Is the desired target an instantiated generic method?
4931     if (pOptionalTargetMethod->HasMethodInstantiation())
4932     {   // check that the current class has access
4933         // to all of the instantiating classes.
4934         Instantiation inst = pOptionalTargetMethod->GetMethodInstantiation();
4935         for (DWORD i = 0; i < inst.GetNumArgs(); i++)
4936         {   
4937             TypeHandle th = inst[i];
4938
4939             MethodTable* pMT = th.GetMethodTableOfElementType();
4940
4941             // Either a TypeVarTypeDesc or a FnPtrTypeDesc. No access check needed.
4942             if (pMT == NULL)
4943                 continue;
4944
4945             if (!CanAccessClass(
4946                     pContext, 
4947                     pMT, 
4948                     th.GetAssembly(), 
4949                     accessCheckOptions))
4950             {
4951                 return FALSE;
4952             }
4953         }
4954         //  If we are here, the current class has access to all of the target's instantiating args,
4955     }
4956     return TRUE;
4957 }
4958
4959 //******************************************************************************
4960 // This function determines whether a target class is accessible from 
4961 //  some given class.
4962 // CanAccessClass does the following checks:
4963 //   1. Transparency check on the target class
4964 //   2. Recursively calls CanAccessClass on the generic arguments of the target class if it is generic.
4965 //   3. Visibility check on the target class, if the target class is nested, this will be translated
4966 //      to a member access check on the enclosing type (calling CanAccess with appropriate dwProtection.
4967 //
4968 /* static */
4969 BOOL ClassLoader::CanAccessClass(                   // True if access is legal, false otherwise. 
4970     AccessCheckContext* pContext,                   // The caller context
4971     MethodTable*        pTargetClass,               // The desired target class.
4972     Assembly*           pTargetAssembly,            // Assembly containing the target class.    
4973     const AccessCheckOptions & accessCheckOptions)// = TRUE
4974 {                                           
4975     CONTRACTL
4976     {
4977         THROWS;
4978         GC_TRIGGERS;
4979         INJECT_FAULT(COMPlusThrowOM(););
4980         MODE_ANY;
4981         PRECONDITION(CheckPointer(pContext));
4982         PRECONDITION(CheckPointer(pTargetClass));
4983     }
4984     CONTRACTL_END
4985
4986     // If there is no target class, allow access.
4987     // @todo: what does that mean?
4988     //if (!pTargetClass)
4989     //    return TRUE;
4990
4991     // Step 2: Recursively call CanAccessClass on the generic type arguments
4992     // Is the desired target a generic instantiation?
4993     if (pTargetClass->HasInstantiation())
4994     {   // Yes, so before going any further, check that the current class has access
4995         //  to all of the instantiating classes.
4996         Instantiation inst = pTargetClass->GetInstantiation();
4997         for (DWORD i = 0; i < inst.GetNumArgs(); i++)
4998         {   
4999             TypeHandle th = inst[i];
5000
5001             MethodTable* pMT = th.GetMethodTableOfElementType();
5002
5003             // Either a TypeVarTypeDesc or a FnPtrTypeDesc. No access check needed.
5004             if (pMT == NULL)
5005                 continue;
5006
5007             if (!CanAccessClass(
5008                     pContext, 
5009                     pMT, 
5010                     th.GetAssembly(), 
5011                     accessCheckOptions))
5012             {
5013                 // no need to call accessCheckOptions.DemandMemberAccessOrFail here because the base case in
5014                 // CanAccessClass does that already
5015                 return FALSE;
5016             }
5017         }
5018         // If we are here, the current class has access to all of the desired target's instantiating args.
5019         //  Now, check whether the current class has access to the desired target itself.
5020     }
5021
5022     // Step 3: Visibility Check
5023     if (!pTargetClass->GetClass()->IsNested()) 
5024     {   // a non-nested class can be either all public or accessible only from its own assembly (and friends).
5025         if (IsTdPublic(pTargetClass->GetClass()->GetProtection()))
5026         {
5027             return TRUE;
5028         }
5029         else
5030         {
5031             // Always allow interop callers full access.
5032             if (pContext->IsCalledFromInterop())
5033                 return TRUE;
5034
5035             Assembly* pCurrentAssembly = pContext->GetCallerAssembly();
5036             _ASSERTE(pCurrentAssembly != NULL);
5037
5038             if (AssemblyOrFriendAccessAllowed(pCurrentAssembly,
5039                                               pTargetAssembly,
5040                                               NULL,
5041                                               NULL,
5042                                               pTargetClass))
5043             {
5044                 return TRUE;
5045             }
5046             else
5047             {
5048                 return accessCheckOptions.DemandMemberAccessOrFail(pContext, pTargetClass, TRUE /*visibilityCheck*/);
5049             }
5050         }
5051     }
5052
5053     // If we are here, the desired target class is nested.  Translate the type flags 
5054     //  to corresponding method access flags. We need to make a note if friend access was allowed to the
5055     //  type being checked since we're not passing it directly to the recurisve call to CanAccess, and
5056     //  instead are just passing in the dwProtectionFlags.
5057     DWORD dwProtection = pTargetClass->GetClass()->GetProtection();
5058
5059     switch(dwProtection) {
5060         case tdNestedPublic:
5061             dwProtection = mdPublic;
5062             break;
5063         case tdNestedFamily:
5064             dwProtection = mdFamily;
5065             break;
5066         case tdNestedPrivate:
5067             dwProtection = mdPrivate;
5068             break;
5069         case tdNestedFamORAssem:
5070             // If we can access the class because we have assembly or friend access, we have satisfied the
5071             // FamORAssem accessibility, so we we can simplify it down to public. Otherwise we require that
5072             // family access be allowed to grant access.
5073         case tdNestedFamANDAssem:
5074             // If we don't grant assembly or friend access to the target class, then there is no way we
5075             // could satisfy the FamANDAssem requirement.  Otherwise, since we have satsified the Assm
5076             // portion, we only need to check for the Fam portion.
5077         case tdNestedAssembly:
5078             // If we don't grant assembly or friend access to the target class, and that class has assembly
5079             // protection, we can fail the request now.  Otherwise we can check to make sure a public member
5080             // of the outer class is allowed, since we have satisfied the target's accessibility rules.
5081
5082             // Always allow interop callers full access.
5083             if (pContext->IsCalledFromInterop())
5084                 return TRUE;
5085
5086             if (AssemblyOrFriendAccessAllowed(pContext->GetCallerAssembly(), pTargetAssembly, NULL, NULL, pTargetClass))
5087                 dwProtection = (dwProtection == tdNestedFamANDAssem) ? mdFamily : mdPublic;
5088             else if (dwProtection == tdNestedFamORAssem)
5089                 dwProtection = mdFamily;
5090             else
5091                 return accessCheckOptions.DemandMemberAccessOrFail(pContext, pTargetClass, TRUE /*visibilityCheck*/);
5092
5093             break;
5094
5095         default:
5096             THROW_BAD_FORMAT_MAYBE(!"Unexpected class visibility flag value", BFA_BAD_VISIBILITY, pTargetClass); 
5097     }
5098
5099     // The desired target class is nested, so translate the class access request into
5100     //  a member access request.  That is, if the current class is trying to access A::B, 
5101     //  check if it can access things in A with the visibility of B.
5102     // So, pass A as the desired target class and visibility of B within A as the member access
5103     // We've already done transparency check above. No need to do it again.
5104     return ClassLoader::CanAccess(
5105         pContext,
5106         GetEnclosingMethodTable(pTargetClass),
5107         pTargetAssembly,
5108         dwProtection,
5109         NULL,
5110         NULL,
5111         accessCheckOptions);
5112 } // BOOL ClassLoader::CanAccessClass()
5113
5114 //******************************************************************************
5115 // This is a front-end to CheckAccessMember that handles the nested class scope. If can't access
5116 // from the current point and are a nested class, then try from the enclosing class.
5117 // In addition to CanAccessMember, if the caller class doesn't have access to the caller, see if the enclosing class does.
5118 //
5119 /* static */
5120 BOOL ClassLoader::CanAccess(                            // TRUE if access is allowed, FALSE otherwise.
5121     AccessCheckContext* pContext,                       // The caller context
5122     MethodTable*        pTargetMT,                      // The class containing the desired target member.
5123     Assembly*           pTargetAssembly,                // Assembly containing that class.
5124     DWORD               dwMemberAccess,                 // Member access flags of the desired target member (as method bits).
5125     MethodDesc*         pOptionalTargetMethod,          // The target method; NULL if the target is a not a method or
5126                                                         // there is no need to check the method's instantiation.
5127     FieldDesc*          pOptionalTargetField,           // or The desired field; if NULL, return TRUE
5128     const AccessCheckOptions & accessCheckOptions)      // = s_NormalAccessChecks
5129 {
5130     CONTRACT(BOOL)
5131     {
5132         THROWS;
5133         GC_TRIGGERS;
5134         INJECT_FAULT(COMPlusThrowOM(););
5135         PRECONDITION(CheckPointer(pContext));
5136         MODE_ANY;
5137     }
5138     CONTRACT_END;
5139
5140     AccessCheckOptions accessCheckOptionsNoThrow(accessCheckOptions, FALSE);
5141
5142     if (!CheckAccessMember(pContext,
5143                            pTargetMT,
5144                            pTargetAssembly,
5145                            dwMemberAccess,
5146                            pOptionalTargetMethod,
5147                            pOptionalTargetField,
5148                            // Suppress exceptions for nested classes since this is not a hard-failure,
5149                            // and we can do additional checks
5150                            accessCheckOptionsNoThrow))
5151     {
5152         // If we're here, CheckAccessMember didn't allow access.
5153         BOOL canAccess = FALSE;
5154
5155         // If the current class is nested, there may be an enclosing class that might have access
5156         // to the target. And if the pCurrentMT == NULL, the current class is global, and so there 
5157         // is no enclosing class.
5158         MethodTable* pCurrentMT = pContext->GetCallerMT();
5159
5160         // if this is called from interop, the CheckAccessMember call above should have already succeeded.
5161         _ASSERTE(!pContext->IsCalledFromInterop());
5162         
5163         BOOL isNestedClass = (pCurrentMT && pCurrentMT->GetClass()->IsNested());
5164
5165         if (isNestedClass)
5166         {
5167             // A nested class also has access to anything that the enclosing class does, so 
5168             //  recursively check whether the enclosing class can access the desired target member.
5169             MethodTable * pEnclosingMT = GetEnclosingMethodTable(pCurrentMT);
5170
5171             StaticAccessCheckContext accessContext(pContext->GetCallerMethod(),
5172                                                    pEnclosingMT,
5173                                                    pContext->GetCallerAssembly());
5174
5175             // On failure, do not throw from inside this call since that will cause the exception message 
5176             // to refer to the enclosing type.
5177             canAccess = ClassLoader::CanAccess(
5178                                  &accessContext,
5179                                  pTargetMT,
5180                                  pTargetAssembly,
5181                                  dwMemberAccess,
5182                                  pOptionalTargetMethod,
5183                                  pOptionalTargetField,
5184                                  accessCheckOptionsNoThrow);
5185         }
5186
5187         if (!canAccess)
5188         {
5189             BOOL fail = accessCheckOptions.FailOrThrow(pContext);
5190             RETURN(fail);
5191         }
5192     }
5193
5194     RETURN(TRUE);
5195 } // BOOL ClassLoader::CanAccess()
5196
5197 //******************************************************************************
5198 // This is the helper function for the corresponding CanAccess()
5199 // It does the following checks:
5200 //   1. CanAccessClass on pTargetMT
5201 //   2. CanAccessMethodInstantiation if the pOptionalTargetMethod is provided and is generic.
5202 //   3. Transparency check on pTargetMT, pOptionalTargetMethod and pOptionalTargetField.
5203 //   4. Visibility check on dwMemberAccess (on pTargetMT)
5204
5205 /* static */
5206 BOOL ClassLoader::CheckAccessMember(                // TRUE if access is allowed, false otherwise.
5207     AccessCheckContext*     pContext,
5208     MethodTable*            pTargetMT,              // The class containing the desired target member.
5209     Assembly*               pTargetAssembly,        // Assembly containing that class.                                   
5210     DWORD                   dwMemberAccess,         // Member access flags of the desired target member (as method bits). 
5211     MethodDesc*             pOptionalTargetMethod,  // The target method; NULL if the target is a not a method or
5212                                                     // there is no need to check the method's instantiation.
5213     FieldDesc*              pOptionalTargetField,   // target field, NULL if there is no Target field
5214     const AccessCheckOptions & accessCheckOptions
5215     )             
5216 {
5217     CONTRACTL
5218     {
5219         THROWS;
5220         GC_TRIGGERS;
5221         INJECT_FAULT(COMPlusThrowOM(););
5222         PRECONDITION(CheckPointer(pContext));
5223         MODE_ANY;
5224     }
5225     CONTRACTL_END
5226
5227     // we're trying to access a member that is contained in the class pTargetClass, so need to
5228     // check if have access to pTargetClass itself from the current point before worry about
5229     // having access to the member within the class
5230     if (!CanAccessClass(pContext,
5231                         pTargetMT,
5232                         pTargetAssembly,
5233                         accessCheckOptions))
5234     {
5235         return FALSE;
5236     }
5237     
5238     // If we are trying to access a generic method, we have to ensure its instantiation is accessible.
5239     // Note that we need to perform transparency checks on the instantiation even if we have
5240     if (!CanAccessMethodInstantiation(
5241             pContext, 
5242             pOptionalTargetMethod, 
5243             accessCheckOptions))
5244     {
5245         return FALSE;
5246     }
5247
5248     // pOptionalTargetMethod and pOptionalTargetField can never be NULL at the same time.
5249     _ASSERTE(pOptionalTargetMethod == NULL || pOptionalTargetField == NULL);
5250
5251     // Perform transparency checks
5252     // We don't need to do transparency check against pTargetMT here because
5253     // it was already done in CanAccessClass above.
5254
5255     if (IsMdPublic(dwMemberAccess))
5256     {
5257         return TRUE;
5258     }
5259
5260     // Always allow interop callers full access.
5261     if (pContext->IsCalledFromInterop())
5262         return TRUE;
5263
5264     MethodTable* pCurrentMT = pContext->GetCallerMT();
5265
5266     if (IsMdPrivateScope(dwMemberAccess))
5267     {        
5268         if (pCurrentMT != NULL && pCurrentMT->GetModule() == pTargetMT->GetModule())
5269         {
5270             return TRUE;
5271         }
5272         else
5273         {
5274             return accessCheckOptions.DemandMemberAccessOrFail(pContext, pTargetMT, TRUE /*visibilityCheck*/);
5275         }
5276     }
5277
5278
5279 #ifdef _DEBUG
5280     if (pTargetMT == NULL &&
5281         (IsMdFamORAssem(dwMemberAccess) ||
5282          IsMdFamANDAssem(dwMemberAccess) ||
5283          IsMdFamily(dwMemberAccess))) {
5284         THROW_BAD_FORMAT_MAYBE(!"Family flag is not allowed on global functions", BFA_FAMILY_ON_GLOBAL, pTargetMT); 
5285     }
5286 #endif
5287
5288     if (pTargetMT == NULL || 
5289         IsMdAssem(dwMemberAccess) || 
5290         IsMdFamORAssem(dwMemberAccess) || 
5291         IsMdFamANDAssem(dwMemberAccess))
5292     {
5293         // If the member has Assembly accessibility, grant access if the current
5294         //  class is in the same assembly as the desired target member, or if the
5295         //  desired target member's assembly grants friend access to the current 
5296         //  assembly.
5297         // @todo: What does it mean for the target class to be NULL?
5298
5299         Assembly* pCurrentAssembly = pContext->GetCallerAssembly();
5300
5301         // pCurrentAssembly should never be NULL, unless we are called from interop,
5302         // in which case we should have already returned TRUE.
5303         _ASSERTE(pCurrentAssembly != NULL);
5304         
5305         const BOOL fAssemblyOrFriendAccessAllowed = AssemblyOrFriendAccessAllowed(pCurrentAssembly,
5306                                                                                   pTargetAssembly,
5307                                                                                   pOptionalTargetField,
5308                                                                                   pOptionalTargetMethod,
5309                                                                                   pTargetMT);
5310
5311         if ((pTargetMT == NULL || IsMdAssem(dwMemberAccess) || IsMdFamORAssem(dwMemberAccess)) && 
5312             fAssemblyOrFriendAccessAllowed)
5313         {
5314             return TRUE;
5315         }
5316         else if (IsMdFamANDAssem(dwMemberAccess) && 
5317                  !fAssemblyOrFriendAccessAllowed)
5318         {
5319             return accessCheckOptions.DemandMemberAccessOrFail(pContext, pTargetMT, TRUE /*visibilityCheck*/);
5320         }
5321     }
5322
5323     // Nested classes can access all members of the parent class.
5324     while(pCurrentMT != NULL)
5325     {
5326         //@GENERICSVER:
5327         if (pTargetMT->HasSameTypeDefAs(pCurrentMT))
5328             return TRUE;
5329
5330         if (IsMdPrivate(dwMemberAccess))
5331         {
5332             if (!pCurrentMT->GetClass()->IsNested())
5333             {
5334                 return accessCheckOptions.DemandMemberAccessOrFail(pContext, pTargetMT, TRUE /*visibilityCheck*/);
5335             }
5336         }
5337         else if (IsMdFamORAssem(dwMemberAccess) || IsMdFamily(dwMemberAccess) || IsMdFamANDAssem(dwMemberAccess))
5338         {
5339             if (CanAccessFamily(pCurrentMT, pTargetMT))
5340             {
5341                 return TRUE;
5342             }
5343         }
5344
5345         pCurrentMT = GetEnclosingMethodTable(pCurrentMT);
5346     }
5347
5348     return accessCheckOptions.DemandMemberAccessOrFail(pContext, pTargetMT, TRUE /*visibilityCheck*/);
5349 }
5350
5351 // The family check is actually in two parts (Partition I, 8.5.3.2).  The first part:
5352 //
5353 //              ...accessible to referents that support the same type
5354 //              (i.e., an exact type and all of the types that inherit
5355 //              from it).
5356 //
5357 // Translation: pCurrentClass must be the same type as pTargetClass or a derived class.  (i.e. Derived
5358 // can access Base.protected but Unrelated cannot access Base.protected).
5359 //
5360 // The second part:
5361 //
5362 //              For verifiable code (see Section 8.8), there is an additional
5363 //              requirement that can require a runtime check: the reference
5364 //              shall be made through an item whose exact type supports
5365 //              the exact type of the referent. That is, the item whose
5366 //              member is being accessed shall inherit from the type
5367 //              performing the access.
5368 //
5369 // Translation: The C++ protected rule.  For those unfamiliar, it means that:
5370 //  if you have:
5371 //  GrandChild : Child
5372 //      and
5373 //  Child : Parent
5374 //      and
5375 //  Parent {
5376 //  protected:
5377 //      int protectedField;
5378 //  }
5379 //
5380 //  Child::function(GrandChild * o) {
5381 //      o->protectedField; //This access is legal.
5382 //  }
5383 //
5384 //  GrandChild:function2(Child * o) {
5385 //      o->protectedField; //This access is illegal.
5386 //  }
5387 //
5388 //  The reason for this rule is that if you had:
5389 //  Sibling : Parent
5390 //  
5391 //  Child::function3( Sibling * o ) {
5392 //      o->protectedField; //This access is illegal
5393 //  }
5394 //
5395 //  This is intuitively correct.  However, you need to prevent:
5396 //  Child::function4( Sibling * o ) {
5397 //      ((Parent*)o)->protectedField;
5398 //  }
5399 //
5400 //  Which means that you must access protected fields through a type that is yourself or one of your
5401 //  derived types.
5402
5403 //This checks the first part of the rule above.
5404 /* static */
5405 BOOL ClassLoader::CanAccessFamily(
5406                                  MethodTable *pCurrentClass,
5407                                  MethodTable *pTargetClass)
5408 {
5409     CONTRACTL
5410     {
5411         THROWS;
5412         GC_TRIGGERS;
5413         INJECT_FAULT(COMPlusThrowOM(););
5414         MODE_ANY;
5415         PRECONDITION(CheckPointer(pTargetClass));
5416     }
5417     CONTRACTL_END
5418
5419     _ASSERTE(pCurrentClass);
5420     _ASSERTE(pTargetClass);
5421
5422     BOOL bIsInterface = pTargetClass->IsInterface();
5423
5424     //Look to see if Current is a child of the Target.
5425     while (pCurrentClass) {
5426         if (bIsInterface)
5427         {
5428             // Calling a protected interface member
5429             MethodTable::InterfaceMapIterator it = pCurrentClass->IterateInterfaceMap();
5430             while (it.Next())
5431             {
5432                 // We only loosely check if they are of the same generic type
5433                 if (it.GetInterface()->HasSameTypeDefAs(pTargetClass))
5434                     return TRUE;
5435             }
5436         }
5437         else
5438         {
5439             MethodTable *pCurInstance = pCurrentClass;
5440
5441             while (pCurInstance) {
5442                 //This is correct.  csc is incredibly lax about generics.  Essentially if you are a subclass of
5443                 //any type of generic it lets you access it.  Since the standard is totally unclear, mirror that
5444                 //behavior here.
5445                 if (pCurInstance->HasSameTypeDefAs(pTargetClass)) {
5446                     return TRUE;
5447                 }
5448
5449                 pCurInstance = pCurInstance->GetParentMethodTable();
5450             }
5451         }
5452
5453         ///Looking at 8.5.3, it looks like a protected member of a nested class in a parent type is also
5454         //accessible.
5455         pCurrentClass = GetEnclosingMethodTable(pCurrentClass);
5456     }
5457
5458     return FALSE;
5459 }
5460
5461 //If instance is an inner class, this also succeeds if the outer class conforms to 8.5.3.2.  A nested class
5462 //is enclosed inside of the enclosing class' open type.  So we need to ignore generic variables.  That also
5463 //helps us with:
5464 /*
5465 class Base {
5466     protected int m_family;
5467 }
5468 class Derived<T> : Base {
5469     class Inner {
5470         public int function(Derived<T> d) {
5471             return d.m_family;
5472         }
5473     }
5474 }
5475 */
5476
5477 //Since the inner T is not the same T as the enclosing T (since accessing generic variables is a CLS rule,
5478 //not a CLI rule), we see that as a comparison between Derived<T> and Derived<T'>.  CanCastTo rejects that.
5479 //Instead we just check against the typedef of the two types.  This ignores all generic parameters (formal
5480 //or not).
5481
5482 BOOL CanAccessFamilyVerificationEnclosingHelper(MethodTable * pMTCurrentEnclosingClass,
5483                                                 TypeHandle thInstanceClass)
5484 {
5485     CONTRACTL
5486     {
5487         THROWS;
5488         GC_TRIGGERS;
5489         MODE_ANY;
5490     }
5491     CONTRACTL_END
5492
5493     _ASSERTE(pMTCurrentEnclosingClass);
5494
5495     if (thInstanceClass.IsGenericVariable())
5496     {
5497         //In this case it is a TypeVarTypeDesc (i.e. T).  If this access would be legal due to a
5498         //constraint:
5499         //
5500         /*
5501         public class My<T>
5502         {
5503             public class Inner<U> where U : My<T>
5504             {
5505                 public int foo(U u)
5506                 {
5507                     return u.field;
5508                 }
5509             }
5510             protected int field;
5511         }
5512         */
5513         //We need to find the generic class constraint.  (The above is legal because U must be a My<T> which makes this
5514         //legal by 8.5.3.2)
5515         // There may only be 1 class constraint on a generic parameter
5516
5517         // Get the constraints on this generic variable
5518         // At most 1 of them is a class constraint.
5519         // That class constraint methodtable can go through the normal search for matching typedef logic below
5520         TypeVarTypeDesc *tyvar = thInstanceClass.AsGenericVariable();
5521         DWORD numConstraints;
5522         TypeHandle *constraints = tyvar->GetConstraints(&numConstraints, CLASS_DEPENDENCIES_LOADED);
5523         if (constraints == NULL)
5524         {
5525             // If we did not find a class constraint, we cannot generate a methodtable to search for
5526             return FALSE;
5527         }
5528         else
5529         {
5530             for (DWORD i = 0; i < numConstraints; i++)
5531             {
5532                 if (!constraints[i].IsInterface())
5533                 {
5534                     // We have found the class constraint on this TypeVarTypeDesc
5535                     // Recurse on the found class constraint. It is possible that this constraint may also be a TypeVarTypeDesc
5536 //class Outer4<T>
5537 //{
5538 //    protected int field;
5539 //
5540 //    public class Inner<U,V> where V:U where U : Outer4<T>
5541 //    {
5542 //        public int Method(V param) { return (++param.field); }
5543 //    }
5544 //}
5545                     return CanAccessFamilyVerificationEnclosingHelper(pMTCurrentEnclosingClass, constraints[i]);
5546                 }
5547             }
5548             // If we did not find a class constraint, we cannot generate a methodtable to search for
5549             return FALSE;
5550         }
5551     }
5552     do
5553     {
5554         MethodTable * pAccessor = pMTCurrentEnclosingClass;
5555         //If thInstanceClass is a MethodTable, we should only be doing the TypeDef comparison (see
5556         //above).
5557         if (!thInstanceClass.IsTypeDesc())
5558         {
5559             MethodTable *pInstanceMT = thInstanceClass.AsMethodTable();
5560
5561             // This is a CanCastTo implementation for classes, assuming we should ignore generic instantiation parameters.
5562             do
5563             {
5564                 if (pAccessor->HasSameTypeDefAs(pInstanceMT))
5565                     return TRUE;
5566                 pInstanceMT = pInstanceMT->GetParentMethodTable();
5567             }while(pInstanceMT);
5568         }
5569         else
5570         {
5571             // Leave this logic in place for now, as I'm not fully confident it can't happen, and we are very close to RTM
5572             // This logic was originally written to handle TypeVarTypeDescs, but those are now handled above.
5573             _ASSERTE(FALSE);
5574             if (thInstanceClass.CanCastTo(TypeHandle(pAccessor)))
5575                 return TRUE;
5576         }
5577
5578         pMTCurrentEnclosingClass = GetEnclosingMethodTable(pMTCurrentEnclosingClass);
5579     }while(pMTCurrentEnclosingClass);
5580     return FALSE;
5581 }
5582
5583
5584 //This checks the verification only part of the rule above.
5585 //From the example above:
5586 //  GrandChild::function2(Child * o) {
5587 //      o->protectedField; //This access is illegal.
5588 //  }
5589 // pCurrentClass is GrandChild and pTargetClass is Child.  This check is completely unnecessary for statics,
5590 // but by legacy convention you can use GrandChild for pTargetClass in that case.
5591
5592 BOOL ClassLoader::CanAccessFamilyVerification(TypeHandle thCurrentClass,
5593                                               TypeHandle thInstanceClass)
5594 {
5595     CONTRACTL
5596     {
5597         THROWS;
5598         GC_TRIGGERS;
5599         INJECT_FAULT(COMPlusThrowOM(););
5600         MODE_ANY;
5601         PRECONDITION(!thCurrentClass.IsNull());
5602         PRECONDITION(!thCurrentClass.IsTypeDesc());
5603     }
5604     CONTRACTL_END
5605     
5606     //Check to see if Instance is equal to or derived from pCurrentClass.
5607     //
5608     //In some cases the type we have for the instance type is actually a TypeVarTypeDesc.  In those cases we
5609     //need to check against the constraints (You're accessing a member through a 'T' with a type constraint
5610     //that makes this legal).  For those cases, CanCastTo does what I want.  
5611     MethodTable * pAccessor = thCurrentClass.GetMethodTable();
5612     if (thInstanceClass.CanCastTo(TypeHandle(pAccessor)))
5613         return TRUE;
5614
5615     //ArrayTypeDescs are the only typedescs that have methods, and their methods don't have IL.  All other
5616     //TypeDescs don't need to be here.  So only run this on MethodTables.
5617     if (!thInstanceClass.IsNull())
5618     {
5619         return CanAccessFamilyVerificationEnclosingHelper(pAccessor, thInstanceClass);
5620     }
5621     return FALSE;
5622 }
5623
5624 #endif // #ifndef DACCESS_COMPILE
5625
5626 #ifdef DACCESS_COMPILE
5627
5628 void
5629 ClassLoader::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
5630 {
5631     WRAPPER_NO_CONTRACT;
5632     SUPPORTS_DAC;
5633     DAC_ENUM_DTHIS();
5634
5635     EMEM_OUT(("MEM: %p ClassLoader\n", dac_cast<TADDR>(this)));
5636
5637     if (m_pAssembly.IsValid())
5638     {
5639         ModuleIterator modIter = GetAssembly()->IterateModules();
5640
5641         while (modIter.Next())
5642         {
5643             modIter.GetModule()->EnumMemoryRegions(flags, true);
5644         }
5645     }
5646 }
5647
5648 #endif // #ifdef DACCESS_COMPILE