Deal with cross-bitness compilation warnings Pt.2 (#19781)
[platform/upstream/coreclr.git] / src / vm / ceeload.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: CEELOAD.CPP
6 // 
7
8 //
9
10 // CEELOAD reads in the PE file format using LoadLibrary
11 // ===========================================================================
12
13
14 #include "common.h"
15
16 #include "array.h"
17 #include "ceeload.h"
18 #include "hash.h"
19 #include "vars.hpp"
20 #include "reflectclasswriter.h"
21 #include "method.hpp"
22 #include "stublink.h"
23 #include "cgensys.h"
24 #include "excep.h"
25 #include "dbginterface.h"
26 #include "dllimport.h"
27 #include "eeprofinterfaces.h"
28 #include "perfcounters.h"
29 #include "encee.h"
30 #include "jitinterface.h"
31 #include "eeconfig.h"
32 #include "dllimportcallback.h"
33 #include "contractimpl.h"
34 #include "typehash.h"
35 #include "instmethhash.h"
36 #include "virtualcallstub.h"
37 #include "typestring.h"
38 #include "stringliteralmap.h"
39 #include <formattype.h>
40 #include "fieldmarshaler.h"
41 #include "sigbuilder.h"
42 #include "metadataexports.h"
43 #include "inlinetracking.h"
44
45
46 #ifdef FEATURE_PREJIT
47 #include "exceptionhandling.h"
48 #include "corcompile.h"
49 #include "compile.h"
50 #include "nibblestream.h"
51 #include "zapsig.h"
52 #endif //FEATURE_PREJIT
53
54 #ifdef FEATURE_COMINTEROP 
55 #include "runtimecallablewrapper.h"
56 #include "comcallablewrapper.h"
57 #endif //FEATURE_COMINTEROP 
58
59 #ifdef _MSC_VER
60 #pragma warning(push)
61 #pragma warning(disable:4724)
62 #endif // _MSC_VER
63
64 #include "ngenhash.inl"
65
66 #ifdef _MSC_VER
67 #pragma warning(pop)
68 #endif // _MSC_VER
69
70
71 #include "perflog.h"
72 #include "ecall.h"
73 #include "../md/compiler/custattr.h"
74 #include "typekey.h"
75 #include "peimagelayout.inl"
76 #include "ildbsymlib.h"
77
78
79 #if defined(PROFILING_SUPPORTED)
80 #include "profilermetadataemitvalidator.h"
81 #endif
82
83 #ifdef _MSC_VER
84 #pragma warning(push)
85 #pragma warning(disable:4244)
86 #endif // _MSC_VER
87
88 #ifdef _TARGET_64BIT_
89 #define COR_VTABLE_PTRSIZED     COR_VTABLE_64BIT
90 #define COR_VTABLE_NOT_PTRSIZED COR_VTABLE_32BIT
91 #else // !_TARGET_64BIT_
92 #define COR_VTABLE_PTRSIZED     COR_VTABLE_32BIT
93 #define COR_VTABLE_NOT_PTRSIZED COR_VTABLE_64BIT
94 #endif // !_TARGET_64BIT_
95
96 #define CEE_FILE_GEN_GROWTH_COLLECTIBLE 2048
97
98 #define NGEN_STATICS_ALLCLASSES_WERE_LOADED -1
99
100 BOOL Module::HasInlineTrackingMap()
101 {
102     LIMITED_METHOD_DAC_CONTRACT;
103 #ifdef FEATURE_READYTORUN
104         if (IsReadyToRun() && GetReadyToRunInfo()->GetInlineTrackingMap() != NULL)
105         {
106                 return TRUE;
107         }
108 #endif
109     return (m_pPersistentInlineTrackingMapNGen != NULL);
110 }
111
112 COUNT_T Module::GetInliners(PTR_Module inlineeOwnerMod, mdMethodDef inlineeTkn, COUNT_T inlinersSize, MethodInModule inliners[], BOOL *incompleteData)
113 {
114     WRAPPER_NO_CONTRACT;
115 #ifdef FEATURE_READYTORUN
116     if(IsReadyToRun() && GetReadyToRunInfo()->GetInlineTrackingMap() != NULL)
117     {
118         return GetReadyToRunInfo()->GetInlineTrackingMap()->GetInliners(inlineeOwnerMod, inlineeTkn, inlinersSize, inliners, incompleteData);
119     }
120 #endif
121     if(m_pPersistentInlineTrackingMapNGen != NULL)
122     {
123         return m_pPersistentInlineTrackingMapNGen->GetInliners(inlineeOwnerMod, inlineeTkn, inlinersSize, inliners, incompleteData);
124     }
125     return 0;
126 }
127
128
129 #ifndef DACCESS_COMPILE 
130
131
132
133 // ===========================================================================
134 // Module
135 // ===========================================================================
136
137 //---------------------------------------------------------------------------------------------------
138 // This wrapper just invokes the real initialization inside a try/hook.
139 // szName is not null only for dynamic modules
140 //---------------------------------------------------------------------------------------------------
141 void Module::DoInit(AllocMemTracker *pamTracker, LPCWSTR szName)
142 {
143     CONTRACTL
144     {
145         INSTANCE_CHECK;
146         STANDARD_VM_CHECK;
147     }
148     CONTRACTL_END;
149
150 #ifdef PROFILING_SUPPORTED
151     {
152         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
153         GCX_COOP();
154         g_profControlBlock.pProfInterface->ModuleLoadStarted((ModuleID) this);
155         END_PIN_PROFILER();
156     }
157     // Need TRY/HOOK instead of holder so we can get HR of exception thrown for profiler callback
158     EX_TRY
159 #endif
160     {
161         Initialize(pamTracker, szName);
162     }
163 #ifdef PROFILING_SUPPORTED
164     
165
166     EX_HOOK
167     {
168         {
169             BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
170             g_profControlBlock.pProfInterface->ModuleLoadFinished((ModuleID) this, GET_EXCEPTION()->GetHR());
171             END_PIN_PROFILER();
172         }
173     }
174     EX_END_HOOK;
175
176 #endif
177 }
178
179 // Set the given bit on m_dwTransientFlags. Return true if we won the race to set the bit.
180 BOOL Module::SetTransientFlagInterlocked(DWORD dwFlag)
181 {
182     LIMITED_METHOD_CONTRACT;
183
184     for (;;)
185     {
186         DWORD dwTransientFlags = m_dwTransientFlags;
187         if ((dwTransientFlags & dwFlag) != 0)
188             return FALSE;
189         if ((DWORD)FastInterlockCompareExchange((LONG*)&m_dwTransientFlags, dwTransientFlags | dwFlag, dwTransientFlags) == dwTransientFlags)
190             return TRUE;
191     }
192 }
193
194 #if PROFILING_SUPPORTED 
195 void Module::NotifyProfilerLoadFinished(HRESULT hr)
196 {
197     CONTRACTL
198     {
199         INSTANCE_CHECK;
200         THROWS;
201         GC_TRIGGERS;
202         INJECT_FAULT(COMPlusThrowOM());
203         MODE_ANY;
204     }
205     CONTRACTL_END;
206
207     // Note that in general we wil reuse shared modules.  So we need to make sure we only notify
208     // the profiler once.
209     if (SetTransientFlagInterlocked(IS_PROFILER_NOTIFIED))
210     {
211         // Record how many types are already present
212         DWORD countTypesOrig = 0;
213         DWORD countExportedTypesOrig = 0;
214         if (!IsResource())
215         {
216             countTypesOrig = GetMDImport()->GetCountWithTokenKind(mdtTypeDef);
217             countExportedTypesOrig = GetMDImport()->GetCountWithTokenKind(mdtExportedType);
218         }
219
220         // Notify the profiler, this may cause metadata to be updated
221         {
222             BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
223             {
224                 GCX_PREEMP();
225                 g_profControlBlock.pProfInterface->ModuleLoadFinished((ModuleID) this, hr);
226
227                 if (SUCCEEDED(hr))
228                 {
229                     g_profControlBlock.pProfInterface->ModuleAttachedToAssembly((ModuleID) this,
230                                                                                 (AssemblyID)m_pAssembly);
231                 }
232             }
233             END_PIN_PROFILER();
234         }
235
236         // If there are more types than before, add these new types to the
237         // assembly
238         if (!IsResource())
239         {
240             DWORD countTypesAfterProfilerUpdate = GetMDImport()->GetCountWithTokenKind(mdtTypeDef);
241             DWORD countExportedTypesAfterProfilerUpdate = GetMDImport()->GetCountWithTokenKind(mdtExportedType);
242             // typeDefs rids 0 and 1 aren't included in the count, thus X typeDefs before means rid X+1 was valid and our incremental addition should start at X+2
243             for (DWORD typeDefRid = countTypesOrig + 2; typeDefRid < countTypesAfterProfilerUpdate + 2; typeDefRid++)
244             {
245                 GetAssembly()->AddType(this, TokenFromRid(typeDefRid, mdtTypeDef));
246             }
247             // exportedType rid 0 isn't included in the count, thus X exportedTypes before means rid X was valid and our incremental addition should start at X+1
248             for (DWORD exportedTypeDef = countExportedTypesOrig + 1; exportedTypeDef < countExportedTypesAfterProfilerUpdate + 1; exportedTypeDef++)
249             {
250                 GetAssembly()->AddExportedType(TokenFromRid(exportedTypeDef, mdtExportedType));
251             }
252         }
253
254         {
255             BEGIN_PIN_PROFILER(CORProfilerTrackAssemblyLoads());
256             if (IsManifest())
257             {
258                 GCX_COOP();
259                 g_profControlBlock.pProfInterface->AssemblyLoadFinished((AssemblyID) m_pAssembly, hr);
260             }
261             END_PIN_PROFILER();
262         }
263     }
264 }
265
266 #ifndef CROSSGEN_COMPILE
267 IMetaDataEmit *Module::GetValidatedEmitter()
268 {
269     CONTRACTL
270     {
271         INSTANCE_CHECK;
272         THROWS;
273         GC_NOTRIGGER;
274         INJECT_FAULT(COMPlusThrowOM());
275         MODE_ANY;
276     }
277     CONTRACTL_END;
278
279     if (m_pValidatedEmitter.Load() == NULL)
280     {
281         // In the past profilers could call any API they wanted on the the IMetaDataEmit interface and we didn't
282         // verify anything. To ensure we don't break back-compat the verifications are not enabled by default.
283         // Right now I have only added verifications for NGEN images, but in the future we might want verifications
284         // for all modules.
285         IMetaDataEmit* pEmit = NULL;
286         if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation) && HasNativeImage())
287         {
288             ProfilerMetadataEmitValidator* pValidator = new ProfilerMetadataEmitValidator(GetEmitter());
289             pValidator->QueryInterface(IID_IMetaDataEmit, (void**)&pEmit);
290         }
291         else
292         {
293             pEmit = GetEmitter();
294             pEmit->AddRef();
295         }
296         // Atomically swap it into the field (release it if we lose the race)
297         if (FastInterlockCompareExchangePointer(&m_pValidatedEmitter, pEmit, NULL) != NULL)
298         {
299             pEmit->Release();
300         }
301     }
302     return m_pValidatedEmitter.Load();
303 }
304 #endif // CROSSGEN_COMPILE
305 #endif // PROFILING_SUPPORTED
306
307 void Module::NotifyEtwLoadFinished(HRESULT hr)
308 {
309     CONTRACTL
310     {
311         NOTHROW;
312         GC_TRIGGERS;
313     }
314     CONTRACTL_END
315
316     // we report only successful loads
317     if (SUCCEEDED(hr) &&
318         ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, 
319                                      TRACE_LEVEL_INFORMATION, 
320                                      KEYWORDZERO))
321     {
322         BOOL fSharedModule = !SetTransientFlagInterlocked(IS_ETW_NOTIFIED);
323         ETW::LoaderLog::ModuleLoad(this, fSharedModule);
324     }
325 }
326
327 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
328 //
329 // The constructor phase initializes just enough so that Destruct() can be safely called.
330 // It cannot throw or fail.
331 //
332 Module::Module(Assembly *pAssembly, mdFile moduleRef, PEFile *file)
333 {
334     CONTRACTL
335     {
336         NOTHROW;
337         GC_TRIGGERS;
338         FORBID_FAULT;
339     }
340     CONTRACTL_END
341
342     PREFIX_ASSUME(pAssembly != NULL);
343
344     m_pAssembly = pAssembly;
345     m_moduleRef = moduleRef;
346     m_file      = file;
347     m_dwTransientFlags = CLASSES_FREED;
348
349     if (!m_file->HasNativeImage())
350     {
351         // Memory allocated on LoaderHeap is zero-filled. Spot-check it here.
352         _ASSERTE(m_pBinder == NULL);
353         _ASSERTE(m_symbolFormat == eSymbolFormatNone);
354     }
355     
356     file->AddRef();
357 }
358
359 void Module::InitializeForProfiling()
360 {
361     CONTRACTL
362     {
363         INSTANCE_CHECK;
364         THROWS;
365         GC_TRIGGERS;
366         MODE_PREEMPTIVE;
367         PRECONDITION(HasNativeOrReadyToRunImage());
368     }
369     CONTRACTL_END;
370
371     COUNT_T  cbProfileList = 0;
372
373     m_nativeImageProfiling = FALSE;
374
375     if (HasNativeImage())
376     {
377         PEImageLayout * pNativeImage = GetNativeImage();
378         CORCOMPILE_VERSION_INFO * pNativeVersionInfo = pNativeImage->GetNativeVersionInfoMaybeNull();
379         if ((pNativeVersionInfo != NULL) && (pNativeVersionInfo->wConfigFlags & CORCOMPILE_CONFIG_INSTRUMENTATION))
380         {
381             m_nativeImageProfiling = GetAssembly()->IsInstrumented();
382         }
383
384         // Link the module to the profile data list if available.
385         m_methodProfileList = pNativeImage->GetNativeProfileDataList(&cbProfileList);
386     }
387     else // ReadyToRun image
388     {
389 #ifdef FEATURE_READYTORUN
390         // We already setup the m_methodProfileList in the ReadyToRunInfo constructor
391         if (m_methodProfileList != nullptr)
392         {
393             ReadyToRunInfo * pInfo = GetReadyToRunInfo();
394             PEImageLayout *  pImage = pInfo->GetImage();
395
396             // Enable profiling if the ZapBBInstr value says to
397             m_nativeImageProfiling = GetAssembly()->IsInstrumented();
398         }
399 #endif
400     }
401
402 #ifdef FEATURE_LAZY_COW_PAGES
403     // When running a IBC tuning image to gather profile data 
404     // we increment the block counts contained in this area.
405     //
406     if (cbProfileList)
407         EnsureWritablePages(m_methodProfileList, cbProfileList);
408 #endif
409 }
410
411 #ifdef FEATURE_PREJIT 
412
413 void Module::InitializeNativeImage(AllocMemTracker* pamTracker)
414 {
415     CONTRACTL
416     {
417         INSTANCE_CHECK;
418         THROWS;
419         GC_TRIGGERS;
420         MODE_PREEMPTIVE;
421         PRECONDITION(HasNativeImage());
422     }
423     CONTRACTL_END;
424
425     PEImageLayout * pNativeImage = GetNativeImage();
426
427     ExecutionManager::AddNativeImageRange(dac_cast<TADDR>(pNativeImage->GetBase()), pNativeImage->GetVirtualSize(), this);
428
429 #ifndef CROSSGEN_COMPILE
430     LoadTokenTables();
431     LoadHelperTable();
432 #endif // CROSSGEN_COMPILE
433
434 #if defined(HAVE_GCCOVER)
435     if (GCStress<cfg_instr_ngen>::IsEnabled())
436     {
437         // Setting up gc coverage requires the base system classes
438         //  to be initialized. So we must defer this for mscorlib.
439         if(!IsSystem())
440         {
441             SetupGcCoverageForNativeImage(this);
442         }
443     }
444 #endif // defined(HAVE_GCCOVER)
445 }
446
447 void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssembly)
448 {
449     CONTRACTL
450     {
451         THROWS;
452         GC_TRIGGERS;
453         MODE_ANY;
454     }
455     CONTRACTL_END;
456
457     if (m_NativeMetadataAssemblyRefMap == NULL)
458     {
459         IMDInternalImport* pImport = GetNativeAssemblyImport();
460         DWORD dwMaxRid = pImport->GetCountWithTokenKind(mdtAssemblyRef);
461         _ASSERTE(dwMaxRid > 0);
462
463         S_SIZE_T dwAllocSize = S_SIZE_T(sizeof(PTR_Assembly)) * S_SIZE_T(dwMaxRid);
464
465         AllocMemTracker amTracker;
466         PTR_Assembly * NativeMetadataAssemblyRefMap = (PTR_Assembly *) amTracker.Track( GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(dwAllocSize) );
467
468         // Note: Memory allocated on loader heap is zero filled
469
470         if (InterlockedCompareExchangeT<PTR_Assembly *>(&m_NativeMetadataAssemblyRefMap, NativeMetadataAssemblyRefMap, NULL) == NULL)
471             amTracker.SuppressRelease();
472     }
473     _ASSERTE(m_NativeMetadataAssemblyRefMap != NULL);
474
475     _ASSERTE(rid <= GetNativeAssemblyImport()->GetCountWithTokenKind(mdtAssemblyRef));
476     m_NativeMetadataAssemblyRefMap[rid-1] = pAssembly;
477
478 #else // FEATURE_PREJIT 
479 BOOL Module::IsPersistedObject(void *address)
480 {
481     LIMITED_METHOD_CONTRACT;
482     return FALSE;
483 }
484
485 #endif // FEATURE_PREJIT 
486
487 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
488 //
489 // The Initialize() phase completes the initialization after the constructor has run.
490 // It can throw exceptions but whether it throws or succeeds, it must leave the Module
491 // in a state where Destruct() can be safely called.
492 // 
493 // szName is only used by dynamic modules, see ReflectionModule::Initialize
494 // 
495 //
496 void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
497 {
498     CONTRACTL
499     {
500         INSTANCE_CHECK;
501         STANDARD_VM_CHECK;
502         PRECONDITION(szName == NULL);
503     }
504     CONTRACTL_END;
505
506     m_pSimpleName = m_file->GetSimpleName();
507
508     m_Crst.Init(CrstModule);
509     m_LookupTableCrst.Init(CrstModuleLookupTable, CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD));
510     m_FixupCrst.Init(CrstModuleFixup, (CrstFlags)(CRST_HOST_BREAKABLE|CRST_REENTRANCY));
511     m_InstMethodHashTableCrst.Init(CrstInstMethodHashTable, CRST_REENTRANCY);
512     m_ISymUnmanagedReaderCrst.Init(CrstISymUnmanagedReader, CRST_DEBUGGER_THREAD);
513
514     if (!m_file->HasNativeImage())
515     {
516         AllocateMaps();
517
518         if (IsSystem() ||
519             (strcmp(m_pSimpleName, "System") == 0) ||
520             (strcmp(m_pSimpleName, "System.Core") == 0) ||
521             (strcmp(m_pSimpleName, "Windows.Foundation") == 0))
522         {
523             FastInterlockOr(&m_dwPersistedFlags, LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME);
524         }
525     }
526
527     m_dwTransientFlags &= ~((DWORD)CLASSES_FREED);  // Set flag indicating LookupMaps are now in a consistent and destructable state
528
529 #ifdef FEATURE_READYTORUN
530     if (!HasNativeImage() && !IsResource())
531         m_pReadyToRunInfo = ReadyToRunInfo::Initialize(this, pamTracker);
532 #endif
533
534     // Initialize the instance fields that we need for all non-Resource Modules
535     if (!IsResource())
536     {
537         if (m_pAvailableClasses == NULL && !IsReadyToRun())
538         {
539             m_pAvailableClasses = EEClassHashTable::Create(this,
540                 GetAssembly()->IsCollectible() ? AVAILABLE_CLASSES_HASH_BUCKETS_COLLECTIBLE : AVAILABLE_CLASSES_HASH_BUCKETS,
541                                                            FALSE /* bCaseInsensitive */, pamTracker);
542         }
543
544         if (m_pAvailableParamTypes == NULL)
545         {
546             m_pAvailableParamTypes = EETypeHashTable::Create(GetLoaderAllocator(), this, PARAMTYPES_HASH_BUCKETS, pamTracker);
547         }
548
549         if (m_pInstMethodHashTable == NULL)
550         {
551             m_pInstMethodHashTable = InstMethodHashTable::Create(GetLoaderAllocator(), this, PARAMMETHODS_HASH_BUCKETS, pamTracker);
552         }
553
554         if(m_pMemberRefToDescHashTable == NULL)
555         {
556             if (IsReflection())
557             {
558                 m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, MEMBERREF_MAP_INITIAL_SIZE, pamTracker);
559             }
560             else
561             {
562                                 IMDInternalImport * pImport = GetMDImport();
563
564                 // Get #MemberRefs and create memberrefToDesc hash table
565                 m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, pImport->GetCountWithTokenKind(mdtMemberRef)+1, pamTracker);
566             }
567         }
568
569 #ifdef FEATURE_COMINTEROP
570         if (IsCompilationProcess() && m_pGuidToTypeHash == NULL)
571         {
572             // only allocate this during NGEN-ing
573             m_pGuidToTypeHash = GuidToMethodTableHashTable::Create(this, GUID_TO_TYPE_HASH_BUCKETS, pamTracker);
574         }
575 #endif // FEATURE_COMINTEROP
576     }
577
578     if (GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())
579     {
580         m_ModuleIndex = Module::AllocateModuleIndex();
581         m_ModuleID = (DomainLocalModule*)Module::IndexToID(m_ModuleIndex);
582     }
583     else
584     {
585         // this will be initialized a bit later.
586         m_ModuleID = NULL;
587         m_ModuleIndex.m_dwIndex = (SIZE_T)-1;
588     }
589
590 #ifdef FEATURE_COLLECTIBLE_TYPES
591     if (GetAssembly()->IsCollectible())
592     {
593         FastInterlockOr(&m_dwPersistedFlags, COLLECTIBLE_MODULE);
594     }
595 #endif // FEATURE_COLLECTIBLE_TYPES
596
597     // Prepare statics that are known at module load time
598     AllocateStatics(pamTracker);
599
600 #ifdef FEATURE_PREJIT 
601     // Set up native image
602     if (HasNativeImage())
603     {
604         InitializeNativeImage(pamTracker);
605     }
606 #endif // FEATURE_PREJIT
607
608     if (HasNativeOrReadyToRunImage())
609     {
610         InitializeForProfiling();
611     }
612
613 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
614     if (g_CorCompileVerboseLevel)
615         m_pNgenStats = new NgenStats();
616 #endif
617
618     if (!IsResource() && (m_AssemblyRefByNameTable == NULL))
619     {
620         Module::CreateAssemblyRefByNameTable(pamTracker);
621     }
622     
623     // If the program has the "ForceEnc" env variable set we ensure every eligible
624     // module has EnC turned on.
625     if (g_pConfig->ForceEnc() && IsEditAndContinueCapable())
626         EnableEditAndContinue();
627
628     LOG((LF_CLASSLOADER, LL_INFO10, "Loaded pModule: \"%ws\".\n", GetDebugName()));
629
630 }
631
632 #endif // DACCESS_COMPILE
633
634
635 #ifdef FEATURE_COMINTEROP
636
637 #ifndef DACCESS_COMPILE
638
639 // static
640 GuidToMethodTableHashTable* GuidToMethodTableHashTable::Create(Module* pModule, DWORD cInitialBuckets, 
641                         AllocMemTracker *pamTracker)
642 {
643     CONTRACTL
644     {
645         THROWS;
646         GC_TRIGGERS;
647         MODE_ANY;
648         INJECT_FAULT(COMPlusThrowOM(););
649         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
650     }
651     CONTRACTL_END;
652
653     LoaderHeap *pHeap = pModule->GetAssembly()->GetLowFrequencyHeap();
654     GuidToMethodTableHashTable *pThis = (GuidToMethodTableHashTable*)pamTracker->Track(pHeap->AllocMem((S_SIZE_T)sizeof(GuidToMethodTableHashTable)));
655
656     // The base class get initialized through chaining of constructors. We allocated the hash instance via the
657     // loader heap instead of new so use an in-place new to call the constructors now.
658     new (pThis) GuidToMethodTableHashTable(pModule, pHeap, cInitialBuckets);
659
660     return pThis;
661 }
662
663 GuidToMethodTableEntry *GuidToMethodTableHashTable::InsertValue(PTR_GUID pGuid, PTR_MethodTable pMT, 
664                         BOOL bReplaceIfFound, AllocMemTracker *pamTracker)
665 {
666     CONTRACTL
667     {
668         THROWS;
669         GC_NOTRIGGER;
670         MODE_ANY;
671         INJECT_FAULT(COMPlusThrowOM(););
672         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
673     }
674     CONTRACTL_END;
675
676     GuidToMethodTableEntry *pEntry = NULL;
677
678     if (bReplaceIfFound)
679     {
680         pEntry = FindItem(pGuid, NULL);
681     }
682
683     if (pEntry != NULL)
684     {
685         pEntry->m_pMT = pMT;
686     }
687     else
688     {
689         pEntry = BaseAllocateEntry(pamTracker);
690         pEntry->m_Guid = pGuid;
691         pEntry->m_pMT = pMT;
692
693         DWORD hash = Hash(pGuid);
694         BaseInsertEntry(hash, pEntry);
695     }
696
697     return pEntry;
698 }
699
700 #endif // !DACCESS_COMPILE
701
702 PTR_MethodTable GuidToMethodTableHashTable::GetValue(const GUID * pGuid, LookupContext *pContext)
703 {
704     CONTRACTL
705     {
706         NOTHROW;
707         GC_NOTRIGGER;
708         MODE_ANY;
709         SUPPORTS_DAC;
710         PRECONDITION(CheckPointer(pGuid));
711     }
712     CONTRACTL_END;
713
714     GuidToMethodTableEntry * pEntry = FindItem(pGuid, pContext);
715     if (pEntry != NULL)
716     {
717         return pEntry->m_pMT;
718     }
719
720     return NULL;
721 }
722
723 GuidToMethodTableEntry *GuidToMethodTableHashTable::FindItem(const GUID * pGuid, LookupContext *pContext)
724 {
725     CONTRACTL
726     {
727         NOTHROW;
728         GC_NOTRIGGER;
729         MODE_ANY;
730         SUPPORTS_DAC;
731         PRECONDITION(CheckPointer(pGuid));
732     }
733     CONTRACTL_END;
734
735     // It's legal for the caller not to pass us a LookupContext, but we might need to iterate
736     // internally (since we lookup via hash and hashes may collide). So substitute our own 
737     // private context if one was not provided.
738     LookupContext sAltContext;
739     if (pContext == NULL)
740         pContext = &sAltContext;
741
742     // The base class provides the ability to enumerate all entries with the same hash code. 
743     // We further check which of these entries actually match the full key.
744     PTR_GuidToMethodTableEntry pSearch = BaseFindFirstEntryByHash(Hash(pGuid), pContext);
745     while (pSearch)
746     {
747         if (CompareKeys(pSearch, pGuid)) 
748         {
749             return pSearch;
750         }
751
752         pSearch = BaseFindNextEntryByHash(pContext);
753     }
754
755     return NULL;
756 }
757
758 BOOL GuidToMethodTableHashTable::CompareKeys(PTR_GuidToMethodTableEntry pEntry, const GUID * pGuid)
759 {
760     LIMITED_METHOD_DAC_CONTRACT;
761     return *pGuid == *(pEntry->m_Guid);
762 }
763
764 DWORD GuidToMethodTableHashTable::Hash(const GUID * pGuid)
765 {
766     LIMITED_METHOD_DAC_CONTRACT;
767     static_assert_no_msg(sizeof(GUID) % sizeof(DWORD) == 0);
768     static_assert_no_msg(sizeof(GUID) / sizeof(DWORD) == 4);
769     DWORD * pSlice = (DWORD*) pGuid;
770     return pSlice[0] ^ pSlice[1] ^ pSlice[2] ^ pSlice[3];
771 }
772
773
774 BOOL GuidToMethodTableHashTable::FindNext(Iterator *it, GuidToMethodTableEntry **ppEntry)
775 {
776     LIMITED_METHOD_DAC_CONTRACT;
777
778     if (!it->m_fIterating)
779     {
780         BaseInitIterator(&it->m_sIterator);
781         it->m_fIterating = true;
782     }
783
784     *ppEntry = it->m_sIterator.Next();
785     return *ppEntry ? TRUE : FALSE;
786 }
787
788 DWORD GuidToMethodTableHashTable::GetCount()
789 {
790     LIMITED_METHOD_DAC_CONTRACT;
791     return BaseGetElementCount();
792 }
793
794 #if defined(FEATURE_NATIVE_IMAGE_GENERATION) && !defined(DACCESS_COMPILE)
795
796 void GuidToMethodTableHashTable::Save(DataImage *pImage, CorProfileData *pProfileData)
797 {
798     WRAPPER_NO_CONTRACT;
799     Base_t::BaseSave(pImage, pProfileData);
800 }
801
802 void GuidToMethodTableHashTable::Fixup(DataImage *pImage)
803 {
804     WRAPPER_NO_CONTRACT;
805     Base_t::BaseFixup(pImage);
806 }
807
808 bool GuidToMethodTableHashTable::SaveEntry(DataImage *pImage, CorProfileData *pProfileData, 
809                     GuidToMethodTableEntry *pOldEntry, GuidToMethodTableEntry *pNewEntry, 
810                     EntryMappingTable *pMap)
811
812     LIMITED_METHOD_CONTRACT;
813     return false;
814 }
815
816 void GuidToMethodTableHashTable::FixupEntry(DataImage *pImage, GuidToMethodTableEntry *pEntry, void *pFixupBase, DWORD cbFixupOffset)
817 {
818     WRAPPER_NO_CONTRACT;
819     pImage->FixupField(pFixupBase, cbFixupOffset + offsetof(GuidToMethodTableEntry, m_pMT), pEntry->m_pMT);
820     pImage->FixupField(pFixupBase, cbFixupOffset + offsetof(GuidToMethodTableEntry, m_Guid), pEntry->m_Guid);
821 }
822     
823 #endif // FEATURE_NATIVE_IMAGE_GENERATION && !DACCESS_COMPILE
824
825
826 #ifdef FEATURE_PREJIT
827
828 #ifndef DACCESS_COMPILE
829 BOOL Module::CanCacheWinRTTypeByGuid(MethodTable *pMT)
830 {
831     CONTRACTL
832     {
833         THROWS;
834         GC_NOTRIGGER;
835         MODE_ANY;
836         PRECONDITION(IsCompilationProcess());
837     }
838     CONTRACTL_END;
839
840     // Don't cache mscorlib-internal declarations of WinRT types.
841     if (IsSystem() && pMT->IsProjectedFromWinRT())
842         return FALSE;
843
844     // Don't cache redirected WinRT types.
845     if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
846         return FALSE;
847
848 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
849     // Don't cache in a module that's not the NGen target, since the result
850     // won't be saved, and since the such a module might be read-only.
851     if (GetAppDomain()->ToCompilationDomain()->GetTargetModule() != this)
852         return FALSE;
853 #endif
854
855     return TRUE;
856 }
857
858 void Module::CacheWinRTTypeByGuid(PTR_MethodTable pMT, PTR_GuidInfo pgi /*= NULL*/)
859 {
860     CONTRACTL
861     {
862         STANDARD_VM_CHECK;
863         PRECONDITION(CheckPointer(pMT));
864         PRECONDITION(pMT->IsLegalNonArrayWinRTType());
865         PRECONDITION(pgi != NULL || pMT->GetGuidInfo() != NULL);
866         PRECONDITION(IsCompilationProcess());
867     }
868     CONTRACTL_END;
869
870     if (pgi == NULL)
871     {
872         pgi = pMT->GetGuidInfo();
873     }
874
875     AllocMemTracker amt;
876     m_pGuidToTypeHash->InsertValue(&pgi->m_Guid, pMT, TRUE, &amt);
877     amt.SuppressRelease();
878 }
879
880 #endif // !DACCESS_COMPILE
881
882 PTR_MethodTable Module::LookupTypeByGuid(const GUID & guid)
883 {
884     WRAPPER_NO_CONTRACT;
885     // Triton ni images do not have this hash.
886     if (m_pGuidToTypeHash != NULL)
887         return m_pGuidToTypeHash->GetValue(&guid, NULL);
888     else
889         return NULL;
890 }
891
892 void Module::GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids)
893 {
894     CONTRACTL
895     {
896         STANDARD_VM_CHECK;
897         SUPPORTS_DAC;
898     }
899     CONTRACTL_END;
900
901     // Triton ni images do not have this hash.
902     if (m_pGuidToTypeHash != NULL)
903     {
904         GuidToMethodTableHashTable::Iterator it(m_pGuidToTypeHash);
905         GuidToMethodTableEntry *pEntry;
906         while (m_pGuidToTypeHash->FindNext(&it, &pEntry))
907         {
908             pTypes->Append(pEntry->m_pMT);
909             pGuids->Append(*pEntry->m_Guid);
910         }
911     }
912 }
913
914 #endif // FEATURE_PREJIT
915
916 #endif // FEATURE_COMINTEROP
917
918 #ifndef DACCESS_COMPILE
919 MemberRefToDescHashTable* MemberRefToDescHashTable::Create(Module *pModule, DWORD cInitialBuckets, AllocMemTracker *pamTracker)
920 {
921     CONTRACTL
922     {
923         THROWS;
924         GC_TRIGGERS;
925         MODE_ANY;
926         INJECT_FAULT(COMPlusThrowOM(););
927         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
928     }
929     CONTRACTL_END;
930
931     LoaderHeap *pHeap = pModule->GetAssembly()->GetLowFrequencyHeap();
932     MemberRefToDescHashTable *pThis = (MemberRefToDescHashTable*)pamTracker->Track(pHeap->AllocMem((S_SIZE_T)sizeof(MemberRefToDescHashTable)));
933
934     // The base class get initialized through chaining of constructors. We allocated the hash instance via the
935     // loader heap instead of new so use an in-place new to call the constructors now.
936     new (pThis) MemberRefToDescHashTable(pModule, pHeap, cInitialBuckets);
937
938     return pThis;
939 }
940
941 //Inserts FieldRef 
942 MemberRefToDescHashEntry* MemberRefToDescHashTable::Insert(mdMemberRef token , FieldDesc *value)
943 {
944     CONTRACTL
945     {
946         THROWS;
947         GC_NOTRIGGER;
948         MODE_ANY;
949         INJECT_FAULT(COMPlusThrowOM(););
950         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
951     }
952     CONTRACTL_END;
953
954     LookupContext sAltContext;
955
956     _ASSERTE((dac_cast<TADDR>(value) & IS_FIELD_MEMBER_REF) == 0);
957
958     MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(token), &sAltContext);
959     if (pEntry != NULL)
960     {
961         // If memberRef is hot token in that case entry for memberref is already persisted in ngen image. So entry for it will already be present in hash table.
962         // However its value will be null. We need to set its actual value.
963         if(pEntry->m_value == dac_cast<TADDR>(NULL))
964         {
965             EnsureWritablePages(&(pEntry->m_value));
966             pEntry->m_value = dac_cast<TADDR>(value)|IS_FIELD_MEMBER_REF;
967         }
968
969         _ASSERTE(pEntry->m_value == (dac_cast<TADDR>(value)|IS_FIELD_MEMBER_REF));
970         return pEntry;
971     }
972
973     // For non hot tokens insert new entry in hashtable
974     pEntry = BaseAllocateEntry(NULL);
975     pEntry->m_value = dac_cast<TADDR>(value)|IS_FIELD_MEMBER_REF;
976     BaseInsertEntry(RidFromToken(token), pEntry);
977
978     return pEntry;
979 }
980
981 // Insert MethodRef
982 MemberRefToDescHashEntry* MemberRefToDescHashTable::Insert(mdMemberRef token , MethodDesc *value)
983 {
984     CONTRACTL
985     {
986         THROWS;
987         GC_NOTRIGGER;
988         MODE_ANY;
989         INJECT_FAULT(COMPlusThrowOM(););
990         PRECONDITION(!FORBIDGC_LOADER_USE_ENABLED());
991     }
992     CONTRACTL_END;
993
994     LookupContext sAltContext;
995
996     MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(token), &sAltContext);
997     if (pEntry != NULL)
998     {
999         // If memberRef is hot token in that case entry for memberref is already persisted in ngen image. So entry for it will already be present in hash table.
1000         // However its value will be null. We need to set its actual value.
1001         if(pEntry->m_value == dac_cast<TADDR>(NULL))
1002         {
1003             EnsureWritablePages(&(pEntry->m_value));
1004             pEntry->m_value = dac_cast<TADDR>(value);
1005         }
1006
1007         _ASSERTE(pEntry->m_value == dac_cast<TADDR>(value));
1008         return pEntry;
1009     }
1010
1011     // For non hot tokens insert new entry in hashtable
1012     pEntry = BaseAllocateEntry(NULL);
1013     pEntry->m_value = dac_cast<TADDR>(value);
1014     BaseInsertEntry(RidFromToken(token), pEntry);
1015
1016     return pEntry;
1017 }
1018
1019 #if defined(FEATURE_NATIVE_IMAGE_GENERATION)
1020 void MemberRefToDescHashTable::Save(DataImage *pImage, CorProfileData *pProfileData)
1021 {
1022     STANDARD_VM_CONTRACT;
1023
1024     // Mark if the tokens are hot
1025     if (pProfileData)
1026     {
1027         DWORD numInTokenList = pProfileData->GetHotTokens(mdtMemberRef>>24, 1<<RidMap, 1<<RidMap, NULL, 0);
1028         
1029         if (numInTokenList > 0)
1030         {
1031             LookupContext sAltContext;
1032
1033             mdToken *tokenList = (mdToken*)(void*)pImage->GetModule()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(mdToken)) * S_SIZE_T(numInTokenList));
1034
1035             pProfileData->GetHotTokens(mdtMemberRef>>24, 1<<RidMap, 1<<RidMap, tokenList, numInTokenList);
1036             for (DWORD i = 0; i < numInTokenList; i++)
1037             {
1038                 DWORD rid = RidFromToken(tokenList[i]);
1039                 MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(tokenList[i]), &sAltContext);
1040                 if (pEntry != NULL)
1041                 {
1042                     _ASSERTE((pEntry->m_value & 0x1) == 0);
1043                     pEntry->m_value |= 0x1;
1044                 }
1045             }
1046         }
1047     }
1048
1049     BaseSave(pImage, pProfileData);
1050 }
1051
1052 void MemberRefToDescHashTable::FixupEntry(DataImage *pImage, MemberRefToDescHashEntry *pEntry, void *pFixupBase, DWORD cbFixupOffset)
1053 {
1054     //As there is no more hard binding initialize MemberRef* to NULL
1055     pImage->ZeroPointerField(pFixupBase, cbFixupOffset + offsetof(MemberRefToDescHashEntry, m_value));
1056 }
1057
1058 #endif // FEATURE_NATIVE_IMAGE_GENERATION
1059
1060 #endif // !DACCESS_COMPILE
1061
1062 PTR_MemberRef MemberRefToDescHashTable::GetValue(mdMemberRef token, BOOL *pfIsMethod)
1063 {
1064     CONTRACTL
1065     {
1066         NOTHROW;
1067         GC_NOTRIGGER;
1068         MODE_ANY;
1069         SUPPORTS_DAC;
1070     }
1071     CONTRACTL_END;
1072
1073     LookupContext sAltContext;
1074
1075     MemberRefToDescHashEntry *pEntry = (PTR_MemberRefToDescHashEntry) BaseFindFirstEntryByHash(RidFromToken(token), &sAltContext);
1076     if (pEntry != NULL)
1077     {
1078         if(pEntry->m_value & IS_FIELD_MEMBER_REF)
1079             *pfIsMethod = FALSE;
1080         else
1081             *pfIsMethod = TRUE;
1082         return (PTR_MemberRef)(pEntry->m_value & (~MEMBER_REF_MAP_ALL_FLAGS));
1083     }
1084
1085     return NULL;
1086 }
1087
1088
1089 void Module::SetDebuggerInfoBits(DebuggerAssemblyControlFlags newBits)
1090 {
1091     LIMITED_METHOD_CONTRACT;
1092     SUPPORTS_DAC;
1093
1094     _ASSERTE(((newBits << DEBUGGER_INFO_SHIFT_PRIV) &
1095               ~DEBUGGER_INFO_MASK_PRIV) == 0);
1096
1097     m_dwTransientFlags &= ~DEBUGGER_INFO_MASK_PRIV;
1098     m_dwTransientFlags |= (newBits << DEBUGGER_INFO_SHIFT_PRIV);
1099
1100 #ifdef DEBUGGING_SUPPORTED 
1101     BOOL setEnC = ((newBits & DACF_ENC_ENABLED) != 0) && IsEditAndContinueCapable();
1102
1103     // IsEditAndContinueCapable should already check !GetAssembly()->IsDomainNeutral
1104     _ASSERTE(!setEnC || !GetAssembly()->IsDomainNeutral());
1105
1106     // The only way can change Enc is through debugger override.
1107     if (setEnC)
1108     {
1109         EnableEditAndContinue();
1110     }
1111     else
1112     {
1113         if (!g_pConfig->ForceEnc())
1114             DisableEditAndContinue();
1115     }
1116 #endif // DEBUGGING_SUPPORTED
1117
1118 #if defined(DACCESS_COMPILE)
1119     // Now that we've changed m_dwTransientFlags, update that in the target too.
1120     // This will fail for read-only target.
1121     // If this fails, it will throw an exception.
1122     // @dbgtodo dac write: finalize on plans for how DAC writes to the target.
1123     HRESULT hrDac;
1124     hrDac = DacWriteHostInstance(this, true);
1125     _ASSERTE(SUCCEEDED(hrDac)); // would throw if there was an error.
1126 #endif // DACCESS_COMPILE
1127 }
1128
1129 #ifndef DACCESS_COMPILE
1130 /* static */
1131 Module *Module::Create(Assembly *pAssembly, mdFile moduleRef, PEFile *file, AllocMemTracker *pamTracker)
1132 {
1133     CONTRACT(Module *)
1134     {
1135         STANDARD_VM_CHECK;
1136         PRECONDITION(CheckPointer(pAssembly));
1137         PRECONDITION(CheckPointer(file));
1138         PRECONDITION(!IsNilToken(moduleRef) || file->IsAssembly());
1139         POSTCONDITION(CheckPointer(RETVAL));
1140         POSTCONDITION(RETVAL->GetFile() == file);
1141     }
1142     CONTRACT_END;
1143
1144     // Hoist CONTRACT into separate routine because of EX incompatibility
1145
1146     Module *pModule = NULL;
1147
1148     // Create the module
1149
1150 #ifdef FEATURE_PREJIT 
1151
1152     if (file->HasNativeImage())
1153     {
1154         pModule = file->GetLoadedNative()->GetPersistedModuleImage();
1155         PREFIX_ASSUME(pModule != NULL);
1156         CONSISTENCY_CHECK_MSG(pModule->m_pAssembly == NULL || !pModule->IsTenured(), // if the module is not tenured it could be our previous attempt
1157                               "Native image can only be used once per process\n");
1158         EnsureWritablePages(pModule);
1159         pModule = new ((void*) pModule) Module(pAssembly, moduleRef, file);
1160         PREFIX_ASSUME(pModule != NULL);
1161     }
1162
1163 #endif // FEATURE_PREJIT
1164
1165     if (pModule == NULL)
1166     {
1167 #ifdef EnC_SUPPORTED
1168         if (IsEditAndContinueCapable(pAssembly, file))
1169         {
1170             // IsEditAndContinueCapable should already check !pAssembly->IsDomainNeutral
1171             _ASSERTE(!pAssembly->IsDomainNeutral());
1172             
1173             // if file is EnCCapable, always create an EnC-module, but EnC won't necessarily be enabled.
1174             // Debugger enables this by calling SetJITCompilerFlags on LoadModule callback.
1175
1176             void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(EditAndContinueModule))));
1177             pModule = new (pMemory) EditAndContinueModule(pAssembly, moduleRef, file);
1178         }
1179         else
1180 #endif // EnC_SUPPORTED
1181         {
1182             void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(Module))));
1183             pModule = new (pMemory) Module(pAssembly, moduleRef, file);
1184         }
1185     }
1186
1187     PREFIX_ASSUME(pModule != NULL);
1188     ModuleHolder pModuleSafe(pModule);
1189     pModuleSafe->DoInit(pamTracker, NULL);
1190
1191     RETURN pModuleSafe.Extract();
1192 }
1193
1194 void Module::ApplyMetaData()
1195 {
1196     CONTRACTL
1197     {
1198         THROWS;
1199         GC_NOTRIGGER;
1200         MODE_ANY;
1201     }
1202     CONTRACTL_END;
1203
1204     LOG((LF_CLASSLOADER, LL_INFO100, "Module::ApplyNewMetaData %x\n", this));
1205
1206     HRESULT hr = S_OK;
1207     ULONG ulCount;
1208
1209     // Ensure for TypeRef
1210     ulCount = GetMDImport()->GetCountWithTokenKind(mdtTypeRef) + 1;
1211     EnsureTypeRefCanBeStored(TokenFromRid(ulCount, mdtTypeRef));
1212
1213     // Ensure for AssemblyRef
1214     ulCount = GetMDImport()->GetCountWithTokenKind(mdtAssemblyRef) + 1;
1215     EnsureAssemblyRefCanBeStored(TokenFromRid(ulCount, mdtAssemblyRef));
1216 }
1217
1218 //
1219 // Destructor for Module
1220 //
1221
1222 void Module::Destruct()
1223 {
1224     CONTRACTL
1225     {
1226         INSTANCE_CHECK;
1227         NOTHROW;
1228         GC_TRIGGERS;
1229         MODE_PREEMPTIVE;
1230     }
1231     CONTRACTL_END;
1232
1233     LOG((LF_EEMEM, INFO3, "Deleting module %x\n", this));
1234 #ifdef PROFILING_SUPPORTED
1235     {
1236         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
1237         if (!IsBeingUnloaded())
1238         {
1239             // Profiler is causing some peripheral class loads. Probably this just needs
1240             // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
1241             EX_TRY
1242             {
1243                 GCX_PREEMP();
1244                 g_profControlBlock.pProfInterface->ModuleUnloadStarted((ModuleID) this);
1245             }
1246             EX_CATCH
1247             {
1248             }
1249             EX_END_CATCH(SwallowAllExceptions);
1250         }
1251         END_PIN_PROFILER();
1252     }
1253 #endif // PROFILING_SUPPORTED
1254
1255
1256     DACNotify::DoModuleUnloadNotification(this);
1257
1258     // Free classes in the class table
1259     FreeClassTables();
1260     
1261
1262
1263 #ifdef DEBUGGING_SUPPORTED 
1264     if (g_pDebugInterface)
1265     {
1266         GCX_PREEMP();
1267         g_pDebugInterface->DestructModule(this);
1268     }
1269
1270 #endif // DEBUGGING_SUPPORTED
1271
1272     ReleaseISymUnmanagedReader();
1273
1274     // Clean up sig cookies
1275     VASigCookieBlock    *pVASigCookieBlock = m_pVASigCookieBlock;
1276     while (pVASigCookieBlock)
1277     {
1278         VASigCookieBlock    *pNext = pVASigCookieBlock->m_Next;
1279         delete pVASigCookieBlock;
1280
1281         pVASigCookieBlock = pNext;
1282     }
1283
1284     // Clean up the IL stub cache
1285     if (m_pILStubCache != NULL)
1286     {
1287         delete m_pILStubCache;
1288     }
1289
1290
1291
1292 #ifdef PROFILING_SUPPORTED 
1293     {
1294         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
1295         // Profiler is causing some peripheral class loads. Probably this just needs
1296         // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
1297         EX_TRY
1298         {
1299             GCX_PREEMP();
1300             g_profControlBlock.pProfInterface->ModuleUnloadFinished((ModuleID) this, S_OK);
1301         }
1302         EX_CATCH
1303         {
1304         }
1305         EX_END_CATCH(SwallowAllExceptions);
1306         END_PIN_PROFILER();
1307     }
1308
1309     if (m_pValidatedEmitter.Load() != NULL)
1310     {
1311         m_pValidatedEmitter->Release();
1312     }
1313 #endif // PROFILING_SUPPORTED
1314
1315     //
1316     // Warning - deleting the zap file will cause the module to be unmapped
1317     //
1318     ClearInMemorySymbolStream();
1319
1320     m_Crst.Destroy();
1321     m_FixupCrst.Destroy();
1322     m_LookupTableCrst.Destroy();
1323     m_InstMethodHashTableCrst.Destroy();
1324     m_ISymUnmanagedReaderCrst.Destroy();
1325
1326
1327     if (m_debuggerSpecificData.m_pDynamicILCrst)
1328     {
1329         delete m_debuggerSpecificData.m_pDynamicILCrst;
1330     }
1331
1332     if (m_debuggerSpecificData.m_pDynamicILBlobTable)
1333     {
1334         delete m_debuggerSpecificData.m_pDynamicILBlobTable;
1335     }
1336
1337     if (m_debuggerSpecificData.m_pTemporaryILBlobTable)
1338     {
1339         delete m_debuggerSpecificData.m_pTemporaryILBlobTable;
1340     }
1341
1342     if (m_debuggerSpecificData.m_pILOffsetMappingTable)
1343     {
1344         for (ILOffsetMappingTable::Iterator pCurElem = m_debuggerSpecificData.m_pILOffsetMappingTable->Begin(),
1345                                             pEndElem = m_debuggerSpecificData.m_pILOffsetMappingTable->End();
1346              pCurElem != pEndElem;
1347              pCurElem++)
1348         {
1349             ILOffsetMappingEntry entry = *pCurElem;
1350             entry.m_mapping.Clear();
1351         }
1352         delete m_debuggerSpecificData.m_pILOffsetMappingTable;
1353     }
1354
1355 #ifdef FEATURE_PREJIT 
1356
1357     if (HasNativeImage())
1358     {
1359         m_file->Release();
1360     }
1361     else
1362 #endif // FEATURE_PREJIT
1363     {
1364         m_file->Release();
1365     }
1366
1367     // If this module was loaded as domain-specific, then 
1368     // we must free its ModuleIndex so that it can be reused
1369     FreeModuleIndex();
1370 }
1371
1372 #ifdef  FEATURE_PREJIT
1373 void Module::DeleteNativeCodeRanges()
1374 {
1375     CONTRACTL
1376     {
1377         NOTHROW;
1378         GC_NOTRIGGER;
1379         MODE_PREEMPTIVE;
1380         FORBID_FAULT;
1381     }
1382     CONTRACTL_END;
1383
1384     if (HasNativeImage())
1385     {
1386         PEImageLayout * pNativeImage = GetNativeImage();
1387
1388         ExecutionManager::DeleteRange(dac_cast<TADDR>(pNativeImage->GetBase()));
1389     }
1390 }
1391 #endif
1392
1393 bool Module::NeedsGlobalMethodTable()
1394 {
1395     CONTRACTL
1396     {
1397         INSTANCE_CHECK;
1398         THROWS;
1399         GC_TRIGGERS;
1400         MODE_ANY;
1401     }
1402     CONTRACTL_END;
1403
1404     IMDInternalImport * pImport = GetMDImport();
1405     if (!IsResource() && pImport->IsValidToken(COR_GLOBAL_PARENT_TOKEN))
1406     {
1407         {
1408             HENUMInternalHolder funcEnum(pImport);
1409             funcEnum.EnumGlobalFunctionsInit();
1410             if (pImport->EnumGetCount(&funcEnum) != 0)
1411                 return true;
1412         }
1413
1414         {
1415             HENUMInternalHolder fieldEnum(pImport);
1416             fieldEnum.EnumGlobalFieldsInit();
1417             if (pImport->EnumGetCount(&fieldEnum) != 0)
1418                 return true;
1419         }
1420     }
1421
1422     // resource module or no global statics nor global functions
1423     return false;
1424 }
1425
1426
1427 MethodTable *Module::GetGlobalMethodTable()
1428 {
1429     CONTRACT (MethodTable *)
1430     {
1431         INSTANCE_CHECK;
1432         THROWS;
1433         GC_TRIGGERS;
1434         MODE_ANY;
1435         INJECT_FAULT(CONTRACT_RETURN NULL;);
1436         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
1437     }
1438     CONTRACT_END;
1439
1440
1441     if ((m_dwPersistedFlags & COMPUTED_GLOBAL_CLASS) == 0)
1442     {
1443         MethodTable *pMT = NULL;
1444
1445         if (NeedsGlobalMethodTable())
1446         {
1447             pMT = ClassLoader::LoadTypeDefThrowing(this, COR_GLOBAL_PARENT_TOKEN,
1448                                                    ClassLoader::ThrowIfNotFound,
1449                                                    ClassLoader::FailIfUninstDefOrRef).AsMethodTable();
1450         }
1451
1452         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_GLOBAL_CLASS);
1453         RETURN pMT;
1454     }
1455     else
1456     {
1457         RETURN LookupTypeDef(COR_GLOBAL_PARENT_TOKEN).AsMethodTable();
1458     }
1459 }
1460
1461
1462 #endif // !DACCESS_COMPILE
1463
1464 #ifdef FEATURE_PREJIT 
1465
1466 /*static*/
1467 BOOL Module::IsAlwaysSavedInPreferredZapModule(Instantiation classInst,     // the type arguments to the type (if any)
1468                                                Instantiation methodInst)    // the type arguments to the method (if any)
1469 {
1470     LIMITED_METHOD_CONTRACT;
1471
1472     return ClassLoader::IsTypicalSharedInstantiation(classInst) &&
1473            ClassLoader::IsTypicalSharedInstantiation(methodInst);
1474 }
1475
1476 //this gets called recursively for generics, so do a probe.
1477 PTR_Module Module::ComputePreferredZapModule(Module * pDefinitionModule,
1478                                              Instantiation classInst,
1479                                              Instantiation methodInst)
1480 {
1481     CONTRACTL
1482     {
1483         NOTHROW;
1484         GC_NOTRIGGER;
1485         MODE_ANY;
1486         SO_TOLERANT;
1487         SUPPORTS_DAC;
1488     }
1489     CONTRACTL_END;
1490
1491     PTR_Module  ret = NULL;
1492     INTERIOR_STACK_PROBE_NOTHROW_CHECK_THREAD(DontCallDirectlyForceStackOverflow());
1493
1494     ret = Module::ComputePreferredZapModuleHelper( pDefinitionModule,
1495                                                    classInst,
1496                                                    methodInst );
1497     END_INTERIOR_STACK_PROBE;
1498     return ret;
1499 }
1500
1501 //
1502 // Is pModule likely a dependency of pOtherModule? Heuristic used by preffered zap module algorithm.
1503 // It can return both false positives and negatives.
1504 //
1505 static bool IsLikelyDependencyOf(Module * pModule, Module * pOtherModule)
1506 {
1507     CONTRACTL
1508     {
1509         NOTHROW;
1510         GC_NOTRIGGER;
1511         FORBID_FAULT;
1512         MODE_ANY;
1513         SUPPORTS_DAC;
1514         PRECONDITION(CheckPointer(pOtherModule));
1515     }
1516     CONTRACTL_END
1517     
1518     // Every module has a dependency with itself
1519     if (pModule == pOtherModule)
1520         return true;
1521
1522     //
1523     // Explicit check for low level system assemblies is working around Win8P facades introducing extra layer between low level system assemblies
1524     // (System.dll or System.Core.dll) and the app assemblies. Because of this extra layer, the check below won't see the direct
1525     // reference between these low level system assemblies and the app assemblies. The prefererred zap module for instantiations of generic
1526     // collections from these low level system assemblies (like LinkedList<AppType>) should be module of AppType. It would be module of the generic 
1527     // collection without this check. On desktop (FEATURE_FULL_NGEN defined), it would result into inefficient code because of the instantiations 
1528     // would be speculative. On CoreCLR (FEATURE_FULL_NGEN not defined), it would result into the instantiations not getting saved into native
1529     // image at all.
1530     //
1531     // Similar problem exists for Windows.Foundation.winmd. There is a cycle between Windows.Foundation.winmd and Windows.Storage.winmd. This cycle
1532     // would cause prefererred zap module for instantiations of foundation types (like IAsyncOperation<StorageFolder>) to be Windows.Foundation.winmd.
1533     // It is a bad choice. It should be Windows.Storage.winmd instead. We explicitly push Windows.Foundation to lower level by treating it as 
1534     // low level system assembly to avoid this problem.
1535     //
1536     if (pModule->IsLowLevelSystemAssemblyByName())
1537     {
1538         if (!pOtherModule->IsLowLevelSystemAssemblyByName())
1539             return true;
1540
1541         // Every module depends upon mscorlib
1542         if (pModule->IsSystem())
1543             return true;
1544
1545         // mscorlib does not depend upon any other module
1546         if (pOtherModule->IsSystem())
1547             return false;
1548     }
1549     else
1550     {
1551         if (pOtherModule->IsLowLevelSystemAssemblyByName())
1552             return false;
1553     }
1554
1555     // At this point neither pModule or pOtherModule is mscorlib
1556
1557 #ifndef DACCESS_COMPILE 
1558     //
1559     // We will check to see if the pOtherModule has a reference to pModule
1560     //
1561
1562     // If we can match the assembly ref in the ManifestModuleReferencesMap we can early out.
1563     // This early out kicks in less than half of the time. It hurts performance on average.
1564     // if (!IsNilToken(pOtherModule->FindAssemblyRef(pModule->GetAssembly())))
1565     //     return true;
1566
1567     if (pOtherModule->HasReferenceByName(pModule->GetSimpleName()))
1568         return true;
1569 #endif // DACCESS_COMPILE
1570
1571     return false;
1572 }
1573
1574 // Determine the "preferred ngen home" for an instantiated type or method
1575 // * This is the first ngen module that the loader will look in;
1576 // * Also, we only hard bind to a type or method that lives in its preferred module
1577 // The following properties must hold of the preferred module:
1578 // - it must be one of the component type's declaring modules
1579 // - if the type or method is open then the preferred module must be that of one of the type parameters
1580 //   (this ensures that we can always hard bind to open types and methods created during ngen)
1581 // - for always-saved instantiations it must be the declaring module of the generic definition
1582 // Otherwise, we try to pick a module that is likely to reference the type or method
1583 //
1584 /* static */
1585 PTR_Module Module::ComputePreferredZapModuleHelper(
1586     Module * pDefinitionModule,    // the module that declares the generic type or method
1587     Instantiation classInst,       // the type arguments to the type (if any)
1588     Instantiation methodInst)      // the type arguments to the method (if any)
1589 {
1590     CONTRACT(PTR_Module)
1591     {
1592         NOTHROW;
1593         GC_NOTRIGGER;
1594         FORBID_FAULT;
1595         MODE_ANY;
1596         PRECONDITION(CheckPointer(pDefinitionModule, NULL_OK));
1597         // One of them will be non-null... Note we don't use CheckPointer
1598         // because that raises a breakpoint in the debugger
1599         PRECONDITION(pDefinitionModule != NULL || !classInst.IsEmpty() || !methodInst.IsEmpty());
1600         POSTCONDITION(CheckPointer(RETVAL));
1601         SUPPORTS_DAC;
1602     }
1603     CONTRACT_END
1604
1605     DWORD totalArgs = classInst.GetNumArgs() + methodInst.GetNumArgs();
1606
1607     // The open type parameters takes precendence over closed type parameters since
1608     // we always hardbind to open types.
1609     for (DWORD i = 0; i < totalArgs; i++)
1610     {
1611         TypeHandle thArg = (i < classInst.GetNumArgs()) ? classInst[i] : methodInst[i - classInst.GetNumArgs()];
1612
1613         // Encoded types are never open
1614         _ASSERTE(!thArg.IsEncodedFixup());
1615         Module * pOpenModule = thArg.GetDefiningModuleForOpenType();
1616         if (pOpenModule != NULL)
1617             RETURN dac_cast<PTR_Module>(pOpenModule);
1618     }
1619
1620     // The initial value of pCurrentPZM is the pDefinitionModule or mscorlib 
1621     Module* pCurrentPZM = (pDefinitionModule != NULL) ? pDefinitionModule : MscorlibBinder::GetModule();
1622     bool preferredZapModuleBasedOnValueType = false;
1623
1624     for (DWORD i = 0; i < totalArgs; i++)
1625     {
1626         TypeHandle pTypeParam = (i < classInst.GetNumArgs()) ? classInst[i] : methodInst[i - classInst.GetNumArgs()];
1627
1628         _ASSERTE(pTypeParam != NULL);
1629         _ASSERTE(!pTypeParam.IsEncodedFixup()); 
1630
1631         Module * pParamPZM = GetPreferredZapModuleForTypeHandle(pTypeParam);
1632
1633         //
1634         // If pCurrentPZM is not a dependency of pParamPZM
1635         // then we aren't going to update pCurrentPZM
1636         // 
1637         if (IsLikelyDependencyOf(pCurrentPZM, pParamPZM))
1638         {
1639             // If we have a type parameter that is a value type 
1640             // and we don't yet have a value type based pCurrentPZM
1641             // then we will select it's module as the new pCurrentPZM.
1642             //
1643             if (pTypeParam.IsValueType() && !preferredZapModuleBasedOnValueType)
1644             {
1645                 pCurrentPZM = pParamPZM;
1646                 preferredZapModuleBasedOnValueType = true;
1647             }
1648             else
1649             {
1650                 // The normal rule is to replace the pCurrentPZM only when 
1651                 // both of the following are true:
1652                 //     pCurrentPZM is a dependency of pParamPZM 
1653                 // and pParamPZM is not a dependency of pCurrentPZM
1654                 // 
1655                 // note that the second condition is alway true when pCurrentPZM is mscorlib
1656                 //
1657                 if (!IsLikelyDependencyOf(pParamPZM, pCurrentPZM))
1658                 {
1659                     pCurrentPZM = pParamPZM;
1660                 }
1661             }
1662         }
1663     }
1664
1665     RETURN dac_cast<PTR_Module>(pCurrentPZM);
1666 }
1667
1668 PTR_Module Module::ComputePreferredZapModule(TypeKey *pKey)
1669 {
1670     CONTRACTL
1671     {
1672         NOTHROW;
1673         GC_NOTRIGGER;
1674         SO_TOLERANT;
1675         MODE_ANY;
1676         SUPPORTS_DAC;
1677     }
1678     CONTRACTL_END;
1679
1680     if (pKey->GetKind() == ELEMENT_TYPE_CLASS)
1681     {
1682         return Module::ComputePreferredZapModule(pKey->GetModule(),
1683                                                  pKey->GetInstantiation());
1684     }
1685     else if (pKey->GetKind() != ELEMENT_TYPE_FNPTR)
1686         return Module::GetPreferredZapModuleForTypeHandle(pKey->GetElementType());
1687     else
1688         return NULL;
1689
1690 }
1691
1692 /* see code:Module::ComputePreferredZapModuleHelper for more */
1693 /*static*/
1694 PTR_Module Module::GetPreferredZapModuleForMethodTable(MethodTable *pMT)
1695 {
1696     CONTRACTL
1697     {
1698         NOTHROW;
1699         GC_NOTRIGGER;
1700         SO_TOLERANT;
1701         MODE_ANY;
1702         SUPPORTS_DAC;
1703     }
1704     CONTRACTL_END;
1705
1706     PTR_Module pRet=NULL;
1707
1708     INTERIOR_STACK_PROBE_FOR_NOTHROW_CHECK_THREAD(10, NO_FORBIDGC_LOADER_USE_ThrowSO(););
1709
1710     if (pMT->IsArray())
1711     {
1712         TypeHandle elemTH = pMT->GetApproxArrayElementTypeHandle();
1713         pRet= ComputePreferredZapModule(NULL, Instantiation(&elemTH, 1));
1714     }
1715     else if (pMT->HasInstantiation() && !pMT->IsGenericTypeDefinition())
1716     {
1717         pRet= ComputePreferredZapModule(pMT->GetModule(),
1718                                         pMT->GetInstantiation());
1719     }
1720     else
1721     {
1722         // If it is uninstantiated or it is the generic type definition itself
1723         // then its loader module is simply the module containing its TypeDef
1724         pRet= pMT->GetModule();
1725     }
1726     END_INTERIOR_STACK_PROBE;
1727     return pRet;
1728 }
1729
1730
1731 /*static*/
1732 PTR_Module Module::GetPreferredZapModuleForTypeDesc(PTR_TypeDesc pTD)
1733 {
1734     CONTRACTL
1735     {
1736         NOTHROW;
1737         GC_NOTRIGGER;
1738         SO_TOLERANT;
1739         MODE_ANY;
1740     }
1741     CONTRACTL_END;
1742     SUPPORTS_DAC;
1743     if (pTD->HasTypeParam())
1744         return GetPreferredZapModuleForTypeHandle(pTD->GetTypeParam());
1745     else if (pTD->IsGenericVariable())
1746         return pTD->GetModule();
1747
1748     _ASSERTE(pTD->GetInternalCorElementType() == ELEMENT_TYPE_FNPTR);
1749     PTR_FnPtrTypeDesc pFnPtrTD = dac_cast<PTR_FnPtrTypeDesc>(pTD);
1750
1751     // Result type of function type is used for preferred zap module
1752     return GetPreferredZapModuleForTypeHandle(pFnPtrTD->GetRetAndArgTypesPointer()[0]);
1753 }
1754
1755 /*static*/
1756 PTR_Module Module::GetPreferredZapModuleForTypeHandle(TypeHandle t)
1757 {
1758     CONTRACTL
1759     {
1760         NOTHROW;
1761         GC_NOTRIGGER;
1762         SO_TOLERANT;
1763         MODE_ANY;
1764     }
1765     CONTRACTL_END;
1766     SUPPORTS_DAC;
1767     if (t.IsTypeDesc())
1768         return GetPreferredZapModuleForTypeDesc(t.AsTypeDesc());
1769     else
1770         return GetPreferredZapModuleForMethodTable(t.AsMethodTable());
1771 }
1772
1773 /*static*/
1774 PTR_Module Module::GetPreferredZapModuleForMethodDesc(const MethodDesc *pMD)
1775 {
1776     CONTRACTL
1777     {
1778         NOTHROW;
1779         GC_NOTRIGGER;
1780         SO_TOLERANT;
1781         MODE_ANY;
1782     }
1783     CONTRACTL_END;
1784
1785     if (pMD->IsTypicalMethodDefinition())
1786     {
1787         return PTR_Module(pMD->GetModule());
1788     }
1789     else if (pMD->IsGenericMethodDefinition())
1790     {
1791         return GetPreferredZapModuleForMethodTable(pMD->GetMethodTable());
1792     }
1793     else
1794     {
1795         return ComputePreferredZapModule(pMD->GetModule(),
1796                                          pMD->GetClassInstantiation(), 
1797                                          pMD->GetMethodInstantiation());
1798     }
1799 }
1800
1801 /* see code:Module::ComputePreferredZapModuleHelper for more */
1802 /*static*/
1803 PTR_Module Module::GetPreferredZapModuleForFieldDesc(FieldDesc * pFD)
1804 {
1805     CONTRACTL
1806     {
1807         NOTHROW;
1808         GC_NOTRIGGER;
1809         SO_TOLERANT;
1810         MODE_ANY;
1811     }
1812     CONTRACTL_END;
1813
1814     // The approx MT is sufficient: it's always the one that owns the FieldDesc
1815     // data structure
1816     return GetPreferredZapModuleForMethodTable(pFD->GetApproxEnclosingMethodTable());
1817 }
1818 #endif // FEATURE_PREJIT
1819
1820 /*static*/
1821 BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEFile *file)
1822 {
1823     CONTRACTL
1824         {
1825             NOTHROW;
1826             GC_NOTRIGGER;
1827             SO_TOLERANT;
1828             MODE_ANY;
1829             SUPPORTS_DAC;
1830         }
1831     CONTRACTL_END;
1832
1833     _ASSERTE(pAssembly != NULL && file != NULL);
1834     
1835     // Some modules are never EnC-capable
1836     return ! (pAssembly->GetDebuggerInfoBits() & DACF_ALLOW_JIT_OPTS ||
1837               pAssembly->IsDomainNeutral() ||
1838               file->IsSystem() ||
1839               file->IsResource() ||
1840               file->HasNativeImage() ||
1841               file->IsDynamic());
1842 }
1843
1844 BOOL Module::IsManifest()
1845 {
1846     WRAPPER_NO_CONTRACT;
1847     return dac_cast<TADDR>(GetAssembly()->GetManifestModule()) ==
1848            dac_cast<TADDR>(this);
1849 }
1850
1851 DomainAssembly* Module::GetDomainAssembly(AppDomain *pDomain)
1852 {
1853     CONTRACT(DomainAssembly *)
1854     {
1855         INSTANCE_CHECK;
1856         PRECONDITION(CheckPointer(pDomain, NULL_OK));
1857         POSTCONDITION(CheckPointer(RETVAL));
1858         THROWS;
1859         GC_TRIGGERS;
1860         MODE_ANY;
1861     }
1862     CONTRACT_END;
1863
1864     if (IsManifest())
1865         RETURN (DomainAssembly *) GetDomainFile(pDomain);
1866     else
1867         RETURN (DomainAssembly *) m_pAssembly->GetDomainAssembly(pDomain);
1868 }
1869
1870 DomainFile *Module::GetDomainFile(AppDomain *pDomain)
1871 {
1872     CONTRACT(DomainFile *)
1873     {
1874         INSTANCE_CHECK;
1875         PRECONDITION(CheckPointer(pDomain));
1876         POSTCONDITION(CheckPointer(RETVAL));
1877         GC_TRIGGERS;
1878         THROWS;
1879         MODE_ANY;
1880         SUPPORTS_DAC;
1881     }
1882     CONTRACT_END;
1883
1884     if (Module::IsEncodedModuleIndex(GetModuleID()))
1885     {
1886         DomainLocalBlock *pLocalBlock = pDomain->GetDomainLocalBlock();
1887         DomainFile *pDomainFile =  pLocalBlock->TryGetDomainFile(GetModuleIndex());
1888
1889 #if !defined(DACCESS_COMPILE) && defined(FEATURE_LOADER_OPTIMIZATION)
1890         if (pDomainFile == NULL)
1891             pDomainFile = pDomain->LoadDomainNeutralModuleDependency(this, FILE_LOADED);
1892 #endif // !DACCESS_COMPILE
1893
1894         RETURN (PTR_DomainFile) pDomainFile;
1895     }
1896     else
1897     {
1898
1899         CONSISTENCY_CHECK(dac_cast<TADDR>(pDomain) == dac_cast<TADDR>(GetDomain()) || IsSingleAppDomain());
1900         RETURN dac_cast<PTR_DomainFile>(m_ModuleID->GetDomainFile());
1901     }
1902 }
1903
1904 DomainAssembly* Module::FindDomainAssembly(AppDomain *pDomain)
1905 {
1906     CONTRACT(DomainAssembly *)
1907     {
1908         INSTANCE_CHECK;
1909         PRECONDITION(CheckPointer(pDomain));
1910         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
1911         NOTHROW;
1912         GC_NOTRIGGER;
1913         MODE_ANY;
1914         SO_TOLERANT;
1915         SUPPORTS_DAC;
1916     }
1917     CONTRACT_END;
1918
1919     if (IsManifest())
1920         RETURN dac_cast<PTR_DomainAssembly>(FindDomainFile(pDomain));
1921     else
1922         RETURN m_pAssembly->FindDomainAssembly(pDomain);
1923 }
1924
1925 DomainModule *Module::GetDomainModule(AppDomain *pDomain)
1926 {
1927     CONTRACT(DomainModule *)
1928     {
1929         INSTANCE_CHECK;
1930         PRECONDITION(CheckPointer(pDomain));
1931         PRECONDITION(!IsManifest());
1932         POSTCONDITION(CheckPointer(RETVAL));
1933
1934         THROWS;
1935         GC_TRIGGERS;
1936         MODE_ANY;
1937     }
1938     CONTRACT_END;
1939
1940     RETURN (DomainModule *) GetDomainFile(pDomain);
1941 }
1942
1943 DomainFile *Module::FindDomainFile(AppDomain *pDomain)
1944 {
1945     CONTRACT(DomainFile *)
1946     {
1947         INSTANCE_CHECK;
1948         PRECONDITION(CheckPointer(pDomain));
1949         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
1950         NOTHROW;
1951         GC_NOTRIGGER;
1952         MODE_ANY;
1953         SO_TOLERANT;
1954         SUPPORTS_DAC;
1955     }
1956     CONTRACT_END;
1957
1958     if (Module::IsEncodedModuleIndex(GetModuleID()))
1959     {
1960         DomainLocalBlock *pLocalBlock = pDomain->GetDomainLocalBlock();
1961         RETURN pLocalBlock->TryGetDomainFile(GetModuleIndex());
1962     }
1963     else
1964     {
1965         if (dac_cast<TADDR>(pDomain) == dac_cast<TADDR>(GetDomain()) || IsSingleAppDomain())
1966             RETURN m_ModuleID->GetDomainFile();
1967         else
1968             RETURN NULL;
1969     }
1970 }
1971
1972 DomainModule *Module::FindDomainModule(AppDomain *pDomain)
1973 {
1974     CONTRACT(DomainModule *)
1975     {
1976         INSTANCE_CHECK;
1977         PRECONDITION(CheckPointer(pDomain));
1978         PRECONDITION(!IsManifest());
1979         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
1980         GC_NOTRIGGER;
1981         NOTHROW;
1982         MODE_ANY;
1983     }
1984     CONTRACT_END;
1985
1986     RETURN (DomainModule *) FindDomainFile(pDomain);
1987 }
1988
1989 #ifndef DACCESS_COMPILE 
1990 #include "staticallocationhelpers.inl"
1991
1992 // Parses metadata and initializes offsets of per-class static blocks.
1993 void Module::BuildStaticsOffsets(AllocMemTracker *pamTracker)
1994 {
1995     STANDARD_VM_CONTRACT;
1996
1997     // Trade off here. We want a slot for each type. That way we can get to 2 bits per class and
1998     // index directly and not need a mapping from ClassID to MethodTable (we will use the RID
1999     // as the mapping)
2000     IMDInternalImport *pImport = GetMDImport();
2001
2002     DWORD * pRegularStaticOffsets = NULL;
2003     DWORD * pThreadStaticOffsets = NULL;
2004
2005     // Get the number of types/classes defined in this module. Add 1 to count the module itself
2006     DWORD dwNumTypes   = pImport->GetCountWithTokenKind(mdtTypeDef) + 1; // +1 for module type
2007
2008     // [0] covers regular statics, [1] covers thread statics
2009     DWORD      dwGCHandles[2] = { 0, 0 };
2010
2011     // Organization in memory of the static block
2012     //
2013     //
2014     //                                       |  GC Statics             |
2015     //                                                  |
2016     //                                                  |
2017     //    | Class Data (one byte per class)  |   pointer to gc statics | primitive type statics |
2018     //
2019     //
2020 #ifndef CROSSBITNESS_COMPILE
2021     // The assertions must hold in every non-crossbitness scenario
2022     _ASSERTE(OFFSETOF__DomainLocalModule__m_pDataBlob_ == DomainLocalModule::OffsetOfDataBlob());
2023     _ASSERTE(OFFSETOF__ThreadLocalModule__m_pDataBlob  == ThreadLocalModule::OffsetOfDataBlob());
2024 #endif
2025
2026     DWORD      dwNonGCBytes[2] = { 
2027         DomainLocalModule::OffsetOfDataBlob() + sizeof(BYTE)*dwNumTypes, 
2028         ThreadLocalModule::OffsetOfDataBlob() + sizeof(BYTE)*dwNumTypes
2029     };
2030
2031     HENUMInternalHolder hTypeEnum(pImport);
2032     hTypeEnum.EnumAllInit(mdtTypeDef);
2033
2034     mdTypeDef type;
2035     // Parse each type of the class
2036     while (pImport->EnumNext(&hTypeEnum, &type))
2037     {
2038         // Set offset for this type
2039         DWORD dwIndex = RidFromToken(type) - 1;
2040
2041         // [0] covers regular statics, [1] covers thread statics
2042         DWORD dwAlignment[2] = { 1, 1 };
2043         DWORD dwClassNonGCBytes[2] = { 0, 0 };
2044         DWORD dwClassGCHandles[2]  = { 0, 0 };
2045
2046         // need to check if the type is generic and if so exclude it from iteration as we don't know the size
2047         HENUMInternalHolder hGenericEnum(pImport);
2048         hGenericEnum.EnumInit(mdtGenericParam, type);
2049         ULONG cGenericParams = pImport->EnumGetCount(&hGenericEnum);
2050         if (cGenericParams == 0)
2051         {
2052             HENUMInternalHolder hFieldEnum(pImport);
2053             hFieldEnum.EnumInit(mdtFieldDef, type);
2054
2055             mdFieldDef field;
2056             // Parse each field of the type
2057             while (pImport->EnumNext(&hFieldEnum, &field))
2058             {
2059                 BOOL fSkip = FALSE;
2060
2061                 CorElementType ElementType = ELEMENT_TYPE_END;
2062                 mdToken tkValueTypeToken = 0;
2063                 int kk; // Use one set of variables for regular statics, and the other set for thread statics
2064                 
2065                 fSkip = GetStaticFieldElementTypeForFieldDef(this, pImport, field, &ElementType, &tkValueTypeToken, &kk);
2066                 if (fSkip)
2067                     continue;
2068
2069                 // We account for "regular statics" and "thread statics" separately. 
2070                 // Currently we are lumping RVA and context statics into "regular statics",
2071                 // but we probably shouldn't.
2072                 switch (ElementType)
2073                 {
2074                     case ELEMENT_TYPE_I1:
2075                     case ELEMENT_TYPE_U1:
2076                     case ELEMENT_TYPE_BOOLEAN:
2077                         dwClassNonGCBytes[kk] += 1;
2078                         break;
2079                     case ELEMENT_TYPE_I2:
2080                     case ELEMENT_TYPE_U2:
2081                     case ELEMENT_TYPE_CHAR:
2082                         dwAlignment[kk] =  max(2, dwAlignment[kk]);
2083                         dwClassNonGCBytes[kk] += 2;
2084                         break;
2085                     case ELEMENT_TYPE_I4:
2086                     case ELEMENT_TYPE_U4:
2087                     case ELEMENT_TYPE_R4:
2088                         dwAlignment[kk] =  max(4, dwAlignment[kk]);
2089                         dwClassNonGCBytes[kk] += 4;
2090                         break;
2091                     case ELEMENT_TYPE_FNPTR:
2092                     case ELEMENT_TYPE_PTR:
2093                     case ELEMENT_TYPE_I:
2094                     case ELEMENT_TYPE_U:
2095                         dwAlignment[kk] =  max((1 << LOG2_PTRSIZE), dwAlignment[kk]);
2096                         dwClassNonGCBytes[kk] += (1 << LOG2_PTRSIZE);
2097                         break;
2098                     case ELEMENT_TYPE_I8:
2099                     case ELEMENT_TYPE_U8:
2100                     case ELEMENT_TYPE_R8:
2101                         dwAlignment[kk] =  max(8, dwAlignment[kk]);
2102                         dwClassNonGCBytes[kk] += 8;
2103                         break;
2104                     case ELEMENT_TYPE_VAR:
2105                     case ELEMENT_TYPE_MVAR:
2106                     case ELEMENT_TYPE_STRING:
2107                     case ELEMENT_TYPE_SZARRAY:
2108                     case ELEMENT_TYPE_ARRAY:
2109                     case ELEMENT_TYPE_CLASS:
2110                     case ELEMENT_TYPE_OBJECT:
2111                         dwClassGCHandles[kk]  += 1;
2112                         break;
2113                     case ELEMENT_TYPE_VALUETYPE:
2114                         // Statics for valuetypes where the valuetype is defined in this module are handled here. Other valuetype statics utilize the pessimistic model below.
2115                         dwClassGCHandles[kk]  += 1;
2116                         break;
2117                     case ELEMENT_TYPE_END:
2118                     default:
2119                         // The actual element type was ELEMENT_TYPE_VALUETYPE, but the as we don't want to load additional assemblies
2120                         // to determine these static offsets, we've fallen back to a pessimistic model.
2121                         if (tkValueTypeToken != 0)
2122                         {
2123                             // We'll have to be pessimistic here
2124                             dwClassNonGCBytes[kk] += MAX_PRIMITIVE_FIELD_SIZE;
2125                             dwAlignment[kk] = max(MAX_PRIMITIVE_FIELD_SIZE, dwAlignment[kk]);
2126
2127                             dwClassGCHandles[kk]  += 1;
2128                             break;
2129                         }
2130                         else
2131                         {
2132                             // field has an unexpected type
2133                             ThrowHR(VER_E_FIELD_SIG);
2134                             break;
2135                         }
2136                 }
2137             }
2138
2139             if (pRegularStaticOffsets == NULL && (dwClassGCHandles[0] != 0 || dwClassNonGCBytes[0] != 0))
2140             {
2141                 // Lazily allocate table for offsets. We need offsets for GC and non GC areas. We add +1 to use as a sentinel. 
2142                 pRegularStaticOffsets = (PTR_DWORD)pamTracker->Track(
2143                     GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
2144                         (S_SIZE_T(2 * sizeof(DWORD))*(S_SIZE_T(dwNumTypes)+S_SIZE_T(1)))));
2145
2146                 for (DWORD i = 0; i < dwIndex; i++) {
2147                     pRegularStaticOffsets[i * 2    ] = dwGCHandles[0]*TARGET_POINTER_SIZE;
2148                     pRegularStaticOffsets[i * 2 + 1] = dwNonGCBytes[0];                    
2149                 }
2150             }
2151
2152             if (pThreadStaticOffsets == NULL && (dwClassGCHandles[1] != 0 || dwClassNonGCBytes[1] != 0))
2153             {
2154                 // Lazily allocate table for offsets. We need offsets for GC and non GC areas. We add +1 to use as a sentinel. 
2155                 pThreadStaticOffsets = (PTR_DWORD)pamTracker->Track(
2156                     GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
2157                         (S_SIZE_T(2 * sizeof(DWORD))*(S_SIZE_T(dwNumTypes)+S_SIZE_T(1)))));
2158
2159                 for (DWORD i = 0; i < dwIndex; i++) {
2160                     pThreadStaticOffsets[i * 2    ] = dwGCHandles[1]*TARGET_POINTER_SIZE;
2161                     pThreadStaticOffsets[i * 2 + 1] = dwNonGCBytes[1];                    
2162                 }
2163             }
2164         }
2165
2166         if (pRegularStaticOffsets != NULL)
2167         {
2168             // Align the offset of non gc statics
2169             dwNonGCBytes[0] = (DWORD) ALIGN_UP(dwNonGCBytes[0], dwAlignment[0]);
2170
2171             // Save current offsets
2172             pRegularStaticOffsets[dwIndex*2]     = dwGCHandles[0]*TARGET_POINTER_SIZE;
2173             pRegularStaticOffsets[dwIndex*2 + 1] = dwNonGCBytes[0];
2174         
2175             // Increment for next class
2176             dwGCHandles[0]  += dwClassGCHandles[0];
2177             dwNonGCBytes[0] += dwClassNonGCBytes[0];
2178         }
2179
2180         if (pThreadStaticOffsets != NULL)
2181         {
2182             // Align the offset of non gc statics
2183             dwNonGCBytes[1] = (DWORD) ALIGN_UP(dwNonGCBytes[1], dwAlignment[1]);
2184
2185             // Save current offsets
2186             pThreadStaticOffsets[dwIndex*2]     = dwGCHandles[1]*TARGET_POINTER_SIZE;
2187             pThreadStaticOffsets[dwIndex*2 + 1] = dwNonGCBytes[1];
2188         
2189             // Increment for next class
2190             dwGCHandles[1]  += dwClassGCHandles[1];
2191             dwNonGCBytes[1] += dwClassNonGCBytes[1];
2192         }
2193     }
2194
2195     m_maxTypeRidStaticsAllocated = dwNumTypes;
2196
2197     if (pRegularStaticOffsets != NULL)
2198     {
2199         pRegularStaticOffsets[dwNumTypes*2]     = dwGCHandles[0]*TARGET_POINTER_SIZE;
2200         pRegularStaticOffsets[dwNumTypes*2 + 1] = dwNonGCBytes[0];
2201     }
2202
2203     if (pThreadStaticOffsets != NULL)
2204     {
2205         pThreadStaticOffsets[dwNumTypes*2]     = dwGCHandles[1]*TARGET_POINTER_SIZE;
2206         pThreadStaticOffsets[dwNumTypes*2 + 1] = dwNonGCBytes[1];
2207     }
2208
2209     m_pRegularStaticOffsets = pRegularStaticOffsets;
2210     m_pThreadStaticOffsets = pThreadStaticOffsets;
2211
2212     m_dwMaxGCRegularStaticHandles = dwGCHandles[0];
2213     m_dwMaxGCThreadStaticHandles = dwGCHandles[1];
2214
2215     m_dwRegularStaticsBlockSize = dwNonGCBytes[0];
2216     m_dwThreadStaticsBlockSize = dwNonGCBytes[1];
2217 }
2218
2219 void  Module::GetOffsetsForRegularStaticData(
2220                     mdToken cl,
2221                     BOOL bDynamic, DWORD dwGCStaticHandles,
2222                     DWORD dwNonGCStaticBytes,
2223                     DWORD * pOutStaticHandleOffset,
2224                     DWORD * pOutNonGCStaticOffset)
2225 {
2226     CONTRACTL
2227     {
2228         THROWS;
2229         GC_TRIGGERS;
2230         INJECT_FAULT(COMPlusThrowOM());
2231     }
2232     CONTRACTL_END
2233
2234     *pOutStaticHandleOffset = 0;
2235     *pOutNonGCStaticOffset  = 0;
2236
2237     if (!dwGCStaticHandles && !dwNonGCStaticBytes)
2238     {
2239         return;
2240     }
2241
2242 #ifndef CROSSBITNESS_COMPILE
2243     _ASSERTE(OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob == DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob());
2244 #endif
2245     // Statics for instantiated types are allocated dynamically per-instantiation
2246     if (bDynamic)
2247     {
2248         // Non GC statics are embedded in the Dynamic Entry.
2249         *pOutNonGCStaticOffset  = OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob;
2250         return;
2251     }
2252
2253     if (m_pRegularStaticOffsets == NULL)
2254     {
2255         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2256     }
2257     _ASSERTE(m_pRegularStaticOffsets != (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED);
2258
2259     // We allocate in the big blob.
2260     DWORD index = RidFromToken(cl) - 1;
2261
2262     *pOutStaticHandleOffset = m_pRegularStaticOffsets[index*2];
2263
2264     *pOutNonGCStaticOffset  = m_pRegularStaticOffsets[index*2 + 1];
2265 #ifdef CROSSBITNESS_COMPILE
2266     *pOutNonGCStaticOffset += OFFSETOF__DomainLocalModule__m_pDataBlob_ - DomainLocalModule::OffsetOfDataBlob();
2267 #endif
2268
2269     // Check we didnt go out of what we predicted we would need for the class
2270     if (*pOutStaticHandleOffset + TARGET_POINTER_SIZE*dwGCStaticHandles >
2271                 m_pRegularStaticOffsets[(index+1)*2] ||
2272         *pOutNonGCStaticOffset + dwNonGCStaticBytes >
2273                 m_pRegularStaticOffsets[(index+1)*2 + 1])
2274     {   // It's most likely that this is due to bad metadata, thus the exception. However, the
2275         // previous comments for this bit of code mentioned that this could be a corner case bug
2276         // with static field size estimation, though this is entirely unlikely since the code has
2277         // been this way for at least two releases.
2278         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2279     }
2280 }
2281
2282
2283 void  Module::GetOffsetsForThreadStaticData(
2284                     mdToken cl,
2285                     BOOL bDynamic, DWORD dwGCStaticHandles,
2286                     DWORD dwNonGCStaticBytes,
2287                     DWORD * pOutStaticHandleOffset,
2288                     DWORD * pOutNonGCStaticOffset)
2289 {
2290     CONTRACTL
2291     {
2292         THROWS;
2293         GC_TRIGGERS;
2294         INJECT_FAULT(COMPlusThrowOM());
2295     }
2296     CONTRACTL_END
2297
2298     *pOutStaticHandleOffset = 0;
2299     *pOutNonGCStaticOffset  = 0;
2300
2301     if (!dwGCStaticHandles && !dwNonGCStaticBytes)
2302     {
2303         return;
2304     }
2305
2306 #ifndef CROSSBITNESS_COMPILE
2307     _ASSERTE(OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob == ThreadLocalModule::DynamicEntry::GetOffsetOfDataBlob());
2308 #endif
2309     // Statics for instantiated types are allocated dynamically per-instantiation
2310     if (bDynamic)
2311     {
2312         // Non GC thread statics are embedded in the Dynamic Entry.
2313         *pOutNonGCStaticOffset  = OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob;
2314         return;
2315     }
2316
2317     if (m_pThreadStaticOffsets == NULL)
2318     {
2319         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2320     }
2321     _ASSERTE(m_pThreadStaticOffsets != (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED);
2322
2323     // We allocate in the big blob.
2324     DWORD index = RidFromToken(cl) - 1;
2325
2326     *pOutStaticHandleOffset = m_pThreadStaticOffsets[index*2];
2327
2328     *pOutNonGCStaticOffset  = m_pThreadStaticOffsets[index*2 + 1];
2329 #ifdef CROSSBITNESS_COMPILE
2330     *pOutNonGCStaticOffset += OFFSETOF__ThreadLocalModule__m_pDataBlob - ThreadLocalModule::GetOffsetOfDataBlob();
2331 #endif
2332
2333     // Check we didnt go out of what we predicted we would need for the class
2334     if (*pOutStaticHandleOffset + TARGET_POINTER_SIZE*dwGCStaticHandles >
2335                 m_pThreadStaticOffsets[(index+1)*2] ||
2336         *pOutNonGCStaticOffset + dwNonGCStaticBytes >
2337                 m_pThreadStaticOffsets[(index+1)*2 + 1])
2338     {
2339         // It's most likely that this is due to bad metadata, thus the exception. However, the
2340         // previous comments for this bit of code mentioned that this could be a corner case bug
2341         // with static field size estimation, though this is entirely unlikely since the code has
2342         // been this way for at least two releases.
2343         THROW_BAD_FORMAT(BFA_METADATA_CORRUPT, this);
2344     }
2345 }
2346
2347
2348 // initialize Crst controlling the Dynamic IL hashtable
2349 void Module::InitializeDynamicILCrst()
2350 {
2351     Crst * pCrst = new Crst(CrstDynamicIL, CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD));
2352     if (InterlockedCompareExchangeT(
2353             &m_debuggerSpecificData.m_pDynamicILCrst, pCrst, NULL) != NULL)
2354     {
2355         delete pCrst;
2356     }
2357 }
2358
2359 // Add a (token, address) pair to the table of IL blobs for reflection/dynamics
2360 // Arguments:
2361 //     Input:
2362 //         token        method token
2363 //         blobAddress  address of the start of the IL blob address, including the header
2364 //         fTemporaryOverride
2365 //                      is this a permanent override that should go in the
2366 //                      DynamicILBlobTable, or a temporary one?
2367 //     Output: not explicit, but if the pair was not already in the table it will be added.
2368 //             Does not add duplicate tokens to the table. 
2369
2370 void Module::SetDynamicIL(mdToken token, TADDR blobAddress, BOOL fTemporaryOverride)
2371 {
2372     DynamicILBlobEntry entry = {mdToken(token), TADDR(blobAddress)};
2373
2374     // Lazily allocate a Crst to serialize update access to the info structure.
2375     // Carefully synchronize to ensure we don't leak a Crst in race conditions.
2376     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2377     {
2378         InitializeDynamicILCrst();
2379     }
2380
2381     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2382    
2383     // Figure out which table to fill in
2384     PTR_DynamicILBlobTable &table(fTemporaryOverride ? m_debuggerSpecificData.m_pTemporaryILBlobTable 
2385                                                      : m_debuggerSpecificData.m_pDynamicILBlobTable);
2386
2387     // Lazily allocate the hash table.
2388     if (table == NULL)
2389     {
2390         table = PTR_DynamicILBlobTable(new DynamicILBlobTable);
2391     }
2392     table->AddOrReplace(entry);
2393 }
2394
2395 #endif // !DACCESS_COMPILE
2396
2397 // Get the stored address of the IL blob for reflection/dynamics
2398 // Arguments:
2399 //     Input:
2400 //         token        method token
2401 //         fAllowTemporary also check the temporary overrides
2402 // Return Value: starting (target) address of the IL blob corresponding to the input token
2403
2404 TADDR Module::GetDynamicIL(mdToken token, BOOL fAllowTemporary)
2405 {
2406     SUPPORTS_DAC;
2407
2408 #ifndef DACCESS_COMPILE
2409     // The Crst to serialize update access to the info structure is lazily allocated.
2410     // If it hasn't been allocated yet, then we don't have any IL blobs (temporary or otherwise)
2411     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2412     {
2413         return TADDR(NULL);
2414     }
2415
2416     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2417 #endif
2418  
2419     // Both hash tables are lazily allocated, so if they're NULL
2420     // then we have no IL blobs
2421
2422     if (fAllowTemporary && m_debuggerSpecificData.m_pTemporaryILBlobTable != NULL)
2423     {
2424         DynamicILBlobEntry entry = m_debuggerSpecificData.m_pTemporaryILBlobTable->Lookup(token);
2425
2426         // Only return a value if the lookup succeeded
2427         if (!DynamicILBlobTraits::IsNull(entry))
2428         {
2429             return entry.m_il;
2430         }
2431     }
2432  
2433     if (m_debuggerSpecificData.m_pDynamicILBlobTable == NULL)
2434     {
2435         return TADDR(NULL);
2436     }
2437
2438     DynamicILBlobEntry entry = m_debuggerSpecificData.m_pDynamicILBlobTable->Lookup(token);
2439     // If the lookup fails, it returns the 'NULL' entry
2440     // The 'NULL' entry has m_il set to NULL, so either way we're safe
2441     return entry.m_il;
2442 }
2443
2444 #if !defined(DACCESS_COMPILE)
2445 //---------------------------------------------------------------------------------------
2446 //
2447 // Add instrumented IL offset mapping for the specified method.
2448 //
2449 // Arguments:
2450 //    token   - the MethodDef token of the method in question
2451 //    mapping - the mapping information between original IL offsets and instrumented IL offsets
2452 //
2453 // Notes:
2454 //    * Once added, the mapping stays valid until the Module containing the method is destructed.
2455 //    * The profiler may potentially update the mapping more than once.
2456 //
2457
2458 void Module::SetInstrumentedILOffsetMapping(mdMethodDef token, InstrumentedILOffsetMapping mapping)
2459 {
2460     ILOffsetMappingEntry entry(token, mapping);
2461
2462     // Lazily allocate a Crst to serialize update access to the hash table.
2463     // Carefully synchronize to ensure we don't leak a Crst in race conditions.
2464     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2465     {
2466         InitializeDynamicILCrst();
2467     }
2468
2469     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2470    
2471     // Lazily allocate the hash table.
2472     if (m_debuggerSpecificData.m_pILOffsetMappingTable == NULL)
2473     {
2474         m_debuggerSpecificData.m_pILOffsetMappingTable = PTR_ILOffsetMappingTable(new ILOffsetMappingTable);
2475     }
2476
2477     ILOffsetMappingEntry currentEntry = m_debuggerSpecificData.m_pILOffsetMappingTable->Lookup(ILOffsetMappingTraits::GetKey(entry));
2478     if (!ILOffsetMappingTraits::IsNull(currentEntry))
2479         currentEntry.m_mapping.Clear();
2480
2481     m_debuggerSpecificData.m_pILOffsetMappingTable->AddOrReplace(entry);
2482 }
2483 #endif // DACCESS_COMPILE
2484
2485 //---------------------------------------------------------------------------------------
2486 //
2487 // Retrieve the instrumented IL offset mapping for the specified method.
2488 //
2489 // Arguments:
2490 //    token   - the MethodDef token of the method in question
2491 //
2492 // Return Value:
2493 //    Return the mapping information between original IL offsets and instrumented IL offsets.
2494 //    Check InstrumentedILOffsetMapping::IsNull() to see if any mapping is available.
2495 //
2496 // Notes:
2497 //    * Once added, the mapping stays valid until the Module containing the method is destructed.
2498 //    * The profiler may potentially update the mapping more than once.
2499 //
2500
2501 InstrumentedILOffsetMapping Module::GetInstrumentedILOffsetMapping(mdMethodDef token)
2502 {
2503     CONTRACTL
2504     {
2505         THROWS;
2506         GC_NOTRIGGER;
2507         MODE_ANY;
2508         SUPPORTS_DAC;
2509     }
2510     CONTRACTL_END;
2511
2512     // Lazily allocate a Crst to serialize update access to the hash table.
2513     // If the Crst is NULL, then we couldn't possibly have added any mapping yet, so just return NULL.
2514     if (m_debuggerSpecificData.m_pDynamicILCrst == NULL)
2515     {
2516         InstrumentedILOffsetMapping emptyMapping;
2517         return emptyMapping;
2518     }
2519
2520     CrstHolder ch(m_debuggerSpecificData.m_pDynamicILCrst);
2521  
2522     // If the hash table hasn't been created, then we couldn't possibly have added any mapping yet, 
2523     // so just return NULL.
2524     if (m_debuggerSpecificData.m_pILOffsetMappingTable == NULL)
2525     {
2526         InstrumentedILOffsetMapping emptyMapping;
2527         return emptyMapping;
2528     }
2529
2530     ILOffsetMappingEntry entry = m_debuggerSpecificData.m_pILOffsetMappingTable->Lookup(token);
2531     return entry.m_mapping;
2532 }
2533
2534 #undef DECODE_TYPEID
2535 #undef ENCODE_TYPEID
2536 #undef IS_ENCODED_TYPEID
2537
2538
2539
2540 #ifndef DACCESS_COMPILE 
2541
2542
2543 BOOL Module::IsNoStringInterning()
2544 {
2545     CONTRACTL
2546     {
2547         THROWS;
2548         GC_TRIGGERS;
2549     }
2550     CONTRACTL_END
2551
2552     if (!(m_dwPersistedFlags & COMPUTED_STRING_INTERNING))
2553     {
2554         // The flags should be precomputed in native images
2555         _ASSERTE(!HasNativeImage());
2556
2557         // Default is string interning
2558         BOOL fNoStringInterning = FALSE;
2559
2560         HRESULT hr;
2561         
2562         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
2563         // Thus, we should ever need it for manifest module only.
2564         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2565         _ASSERTE(mdImport);
2566         
2567         mdToken token;
2568         IfFailThrow(mdImport->GetAssemblyFromScope(&token));
2569         
2570         const BYTE *pVal;
2571         ULONG       cbVal;
2572         
2573         hr = mdImport->GetCustomAttributeByName(token,
2574                         COMPILATIONRELAXATIONS_TYPE,
2575                         (const void**)&pVal, &cbVal);
2576         
2577         // Parse the attribute
2578         if (hr == S_OK)
2579         {
2580             CustomAttributeParser cap(pVal, cbVal);
2581             IfFailThrow(cap.SkipProlog());
2582
2583             // Get Flags
2584             UINT32 flags;
2585             IfFailThrow(cap.GetU4(&flags));
2586
2587             if (flags & CompilationRelaxations_NoStringInterning)
2588             {
2589                 fNoStringInterning = TRUE;
2590             }
2591         }
2592
2593 #ifdef _DEBUG
2594         static ConfigDWORD g_NoStringInterning;
2595         DWORD dwOverride = g_NoStringInterning.val(CLRConfig::INTERNAL_NoStringInterning);
2596
2597         if (dwOverride == 0)
2598         {
2599             // Disabled
2600             fNoStringInterning = FALSE;
2601         }
2602         else if (dwOverride == 2)
2603         {
2604             // Always true (testing)
2605             fNoStringInterning = TRUE;
2606         }
2607 #endif // _DEBUG
2608
2609         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_STRING_INTERNING |
2610             (fNoStringInterning ? NO_STRING_INTERNING : 0));
2611     }
2612
2613     return !!(m_dwPersistedFlags & NO_STRING_INTERNING);
2614 }
2615
2616 BOOL Module::GetNeutralResourcesLanguage(LPCUTF8 * cultureName, ULONG * cultureNameLength, INT16 * fallbackLocation, BOOL cacheAttribute)
2617 {
2618     STANDARD_VM_CONTRACT;
2619
2620     BOOL retVal = FALSE;
2621     if (!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED))
2622     {
2623         const BYTE *pVal = NULL;
2624         ULONG cbVal = 0;
2625
2626         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
2627         // Thus, we should ever need it for manifest module only.
2628         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2629         _ASSERTE(mdImport);
2630
2631         mdToken token;
2632         IfFailThrow(mdImport->GetAssemblyFromScope(&token));
2633
2634         // Check for the existance of the attribute.
2635         HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal);
2636         if (hr == S_OK) {
2637
2638             // we should not have a native image (it would have been cached at ngen time)
2639             _ASSERTE(!HasNativeImage());
2640
2641             CustomAttributeParser cap(pVal, cbVal);
2642             IfFailThrow(cap.SkipProlog());
2643             IfFailThrow(cap.GetString(cultureName, cultureNameLength));
2644             IfFailThrow(cap.GetI2(fallbackLocation));
2645             // Should only be true on Module.Save(). Update flag to show we have the attribute cached
2646             if (cacheAttribute)
2647                 FastInterlockOr(&m_dwPersistedFlags, NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED);
2648
2649             retVal = TRUE;
2650         }
2651     }
2652     else 
2653     {
2654         *cultureName = m_pszCultureName;
2655         *cultureNameLength = m_CultureNameLength;
2656         *fallbackLocation = m_FallbackLocation;
2657         retVal = TRUE;
2658
2659 #ifdef _DEBUG
2660         // confirm that the NGENed attribute is correct
2661         LPCUTF8 pszCultureNameCheck = NULL;
2662         ULONG cultureNameLengthCheck = 0;
2663         INT16 fallbackLocationCheck = 0;
2664         const BYTE *pVal = NULL;
2665         ULONG cbVal = 0;
2666
2667         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2668         _ASSERTE(mdImport);
2669         mdToken token;
2670         IfFailThrow(mdImport->GetAssemblyFromScope(&token));
2671
2672         // Confirm that the attribute exists, and has the save value as when we ngen'd it
2673         HRESULT hr = mdImport->GetCustomAttributeByName(token,"System.Resources.NeutralResourcesLanguageAttribute",(const void **)&pVal, &cbVal);
2674         _ASSERTE(hr == S_OK);
2675         CustomAttributeParser cap(pVal, cbVal);
2676         IfFailThrow(cap.SkipProlog());
2677         IfFailThrow(cap.GetString(&pszCultureNameCheck, &cultureNameLengthCheck));
2678         IfFailThrow(cap.GetI2(&fallbackLocationCheck));
2679         _ASSERTE(cultureNameLengthCheck == m_CultureNameLength);
2680         _ASSERTE(fallbackLocationCheck == m_FallbackLocation);
2681         _ASSERTE(strncmp(pszCultureNameCheck,m_pszCultureName,m_CultureNameLength) == 0);
2682 #endif // _DEBUG
2683     }
2684
2685     return retVal;
2686 }
2687
2688
2689 BOOL Module::HasDefaultDllImportSearchPathsAttribute()
2690 {
2691     CONTRACTL
2692     {
2693         THROWS;
2694         GC_NOTRIGGER;
2695         MODE_ANY;
2696     }
2697     CONTRACTL_END;
2698
2699     if(IsDefaultDllImportSearchPathsAttributeCached())
2700     {
2701         return (m_dwPersistedFlags & DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS) != 0 ;
2702     }
2703     IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2704
2705     BOOL attributeIsFound = FALSE;
2706     attributeIsFound = GetDefaultDllImportSearchPathsAttributeValue(mdImport, TokenFromRid(1, mdtAssembly),&m_DefaultDllImportSearchPathsAttributeValue);
2707     if(attributeIsFound)
2708     {
2709         FastInterlockOr(&m_dwPersistedFlags, DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED | DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS);
2710     }
2711     else
2712     {
2713         FastInterlockOr(&m_dwPersistedFlags, DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED);
2714     }
2715
2716     return (m_dwPersistedFlags & DEFAULT_DLL_IMPORT_SEARCH_PATHS_STATUS) != 0 ;
2717 }
2718
2719 // Returns a BOOL to indicate if we have computed whether compiler has instructed us to
2720 // wrap the non-CLS compliant exceptions or not.
2721 BOOL Module::IsRuntimeWrapExceptionsStatusComputed()
2722 {
2723     LIMITED_METHOD_CONTRACT;
2724
2725     return (m_dwPersistedFlags & COMPUTED_WRAP_EXCEPTIONS);
2726 }
2727
2728 BOOL Module::IsRuntimeWrapExceptions()
2729 {
2730     CONTRACTL
2731     {
2732         THROWS;
2733         if (IsRuntimeWrapExceptionsStatusComputed()) GC_NOTRIGGER; else GC_TRIGGERS;
2734         MODE_ANY;
2735     }
2736     CONTRACTL_END
2737
2738     if (!(IsRuntimeWrapExceptionsStatusComputed()))
2739     {
2740         // The flags should be precomputed in native images
2741         _ASSERTE(!HasNativeImage());
2742         
2743         HRESULT hr;
2744         BOOL fRuntimeWrapExceptions = FALSE;
2745         
2746         // This flag applies to assembly, but it is stored on module so it can be cached in ngen image
2747         // Thus, we should ever need it for manifest module only.
2748         IMDInternalImport *mdImport = GetAssembly()->GetManifestImport();
2749         
2750         mdToken token;
2751         IfFailGo(mdImport->GetAssemblyFromScope(&token));
2752         
2753         const BYTE *pVal;
2754         ULONG       cbVal;
2755         
2756         hr = mdImport->GetCustomAttributeByName(token,
2757                         RUNTIMECOMPATIBILITY_TYPE,
2758                         (const void**)&pVal, &cbVal);
2759
2760         // Parse the attribute
2761         if (hr == S_OK)
2762         {
2763             CustomAttributeParser ca(pVal, cbVal);
2764             CaNamedArg namedArgs[1] = {{0}};
2765             
2766             // First, the void constructor:
2767             IfFailGo(ParseKnownCaArgs(ca, NULL, 0));
2768             
2769             // Then, find the named argument
2770             namedArgs[0].InitBoolField("WrapNonExceptionThrows");
2771             
2772             IfFailGo(ParseKnownCaNamedArgs(ca, namedArgs, lengthof(namedArgs)));
2773             
2774             if (namedArgs[0].val.boolean)
2775                 fRuntimeWrapExceptions = TRUE;
2776         }
2777 ErrExit:
2778         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_WRAP_EXCEPTIONS |
2779             (fRuntimeWrapExceptions ? WRAP_EXCEPTIONS : 0));
2780     }
2781     
2782     return !!(m_dwPersistedFlags & WRAP_EXCEPTIONS);
2783 }
2784
2785 BOOL Module::IsPreV4Assembly()
2786 {
2787     CONTRACTL
2788     {
2789         THROWS;
2790         GC_NOTRIGGER;
2791         SO_TOLERANT;
2792     }
2793     CONTRACTL_END
2794
2795     if (!(m_dwPersistedFlags & COMPUTED_IS_PRE_V4_ASSEMBLY))
2796     {
2797         // The flags should be precomputed in native images
2798         _ASSERTE(!HasNativeImage());
2799         
2800         IMDInternalImport *pImport = GetAssembly()->GetManifestImport();
2801         _ASSERTE(pImport);
2802         
2803         BOOL fIsPreV4Assembly = FALSE;
2804         LPCSTR szVersion = NULL;
2805         if (SUCCEEDED(pImport->GetVersionString(&szVersion)))
2806         {
2807             if (szVersion != NULL && strlen(szVersion) > 2)
2808             {
2809                 fIsPreV4Assembly = (szVersion[0] == 'v' || szVersion[0] == 'V') &&
2810                                    (szVersion[1] == '1' || szVersion[1] == '2');
2811             }
2812         }
2813
2814         FastInterlockOr(&m_dwPersistedFlags, COMPUTED_IS_PRE_V4_ASSEMBLY |
2815             (fIsPreV4Assembly ? IS_PRE_V4_ASSEMBLY : 0));
2816     }
2817
2818     return !!(m_dwPersistedFlags & IS_PRE_V4_ASSEMBLY);
2819 }
2820
2821
2822 ArrayDPTR(RelativeFixupPointer<PTR_MethodTable>) ModuleCtorInfo::GetGCStaticMTs(DWORD index)
2823 {
2824     LIMITED_METHOD_CONTRACT;
2825
2826     if (index < numHotGCStaticsMTs)
2827     {
2828         _ASSERTE(ppHotGCStaticsMTs != NULL);
2829
2830         return ppHotGCStaticsMTs + index;
2831     }
2832     else
2833     {
2834         _ASSERTE(ppColdGCStaticsMTs != NULL);
2835
2836         // shift the start of the cold table because all cold offsets are also shifted
2837         return ppColdGCStaticsMTs + (index - numHotGCStaticsMTs);
2838     }
2839 }
2840
2841 DWORD Module::AllocateDynamicEntry(MethodTable *pMT)
2842 {
2843     CONTRACTL
2844     {
2845         THROWS;
2846         GC_TRIGGERS;
2847         PRECONDITION(pMT->GetModuleForStatics() == this);
2848         PRECONDITION(pMT->IsDynamicStatics());
2849         PRECONDITION(!pMT->ContainsGenericVariables());
2850     }
2851     CONTRACTL_END;
2852
2853     DWORD newId = FastInterlockExchangeAdd((LONG*)&m_cDynamicEntries, 1);
2854
2855     if (newId >= m_maxDynamicEntries)
2856     {
2857         CrstHolder ch(&m_Crst);
2858
2859         if (newId >= m_maxDynamicEntries)
2860         {
2861             SIZE_T maxDynamicEntries = max(16, m_maxDynamicEntries);
2862             while (maxDynamicEntries <= newId)
2863             {
2864                 maxDynamicEntries *= 2;
2865             }
2866
2867             DynamicStaticsInfo* pNewDynamicStaticsInfo = (DynamicStaticsInfo*)
2868                 (void*)GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicStaticsInfo)) * S_SIZE_T(maxDynamicEntries));
2869
2870             if (m_pDynamicStaticsInfo)
2871                 memcpy(pNewDynamicStaticsInfo, m_pDynamicStaticsInfo, sizeof(DynamicStaticsInfo) * m_maxDynamicEntries);
2872
2873             m_pDynamicStaticsInfo = pNewDynamicStaticsInfo;
2874             m_maxDynamicEntries = maxDynamicEntries;
2875         }
2876     }
2877
2878     EnsureWritablePages(&(m_pDynamicStaticsInfo[newId]))->pEnclosingMT = pMT;
2879
2880     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Assigned dynamic ID %d to %s\n", newId, pMT->GetDebugClassName()));
2881
2882     return newId;
2883 }
2884
2885 void Module::FreeModuleIndex()
2886 {
2887     CONTRACTL
2888     {
2889         NOTHROW;
2890         GC_NOTRIGGER;
2891         MODE_ANY;
2892     }
2893     CONTRACTL_END;
2894     if (GetAssembly()->IsDomainNeutral())
2895     {
2896         // We do not recycle ModuleIndexes used by domain neutral Modules.
2897     }
2898     else 
2899     {
2900         if (m_ModuleID != NULL)
2901         {
2902             // Module's m_ModuleID should not contain the ID, it should 
2903             // contain a pointer to the DLM
2904             _ASSERTE(!Module::IsEncodedModuleIndex((SIZE_T)m_ModuleID));
2905             _ASSERTE(m_ModuleIndex == m_ModuleID->GetModuleIndex());
2906
2907             // Get the ModuleIndex from the DLM and free it
2908             Module::FreeModuleIndex(m_ModuleIndex);
2909         }
2910         else
2911         {
2912             // This was an empty, short-lived Module object that
2913             // was never assigned a ModuleIndex...
2914         }
2915     }
2916 }
2917
2918
2919
2920
2921 ModuleIndex Module::AllocateModuleIndex()
2922 {
2923     DWORD val;
2924     g_pModuleIndexDispenser->NewId(NULL, val);
2925
2926     // For various reasons, the IDs issued by the IdDispenser start at 1.
2927     // Domain neutral module IDs have historically started at 0, and we
2928     // have always assigned ID 0 to mscorlib. Thus, to make it so that
2929     // domain neutral module IDs start at 0, we will subtract 1 from the
2930     // ID that we got back from the ID dispenser.
2931     ModuleIndex index((SIZE_T)(val-1));
2932
2933     return index;
2934 }
2935
2936 void Module::FreeModuleIndex(ModuleIndex index)
2937 {
2938     WRAPPER_NO_CONTRACT;
2939     // We subtracted 1 after we allocated this ID, so we need to
2940     // add 1 before we free it.
2941     DWORD val = index.m_dwIndex + 1;
2942
2943     g_pModuleIndexDispenser->DisposeId(val);
2944 }
2945
2946
2947 void Module::AllocateRegularStaticHandles(AppDomain* pDomain)
2948 {
2949     CONTRACTL
2950     {
2951         THROWS;
2952         GC_TRIGGERS;
2953     }
2954     CONTRACTL_END;
2955
2956 #ifndef CROSSGEN_COMPILE
2957     if (NingenEnabled())
2958         return;
2959
2960     // Allocate the handles we will need. Note that AllocateStaticFieldObjRefPtrs will only
2961     // allocate if pModuleData->GetGCStaticsBasePointerAddress(pMT) != 0, avoiding creating
2962     // handles more than once for a given MT or module
2963
2964     DomainLocalModule *pModuleData = GetDomainLocalModule(pDomain);
2965
2966     _ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointerAddress() != NULL);
2967     if (this->m_dwMaxGCRegularStaticHandles > 0)
2968     {
2969         // If we're setting up a non-default domain, we want the allocation to look like it's
2970         // coming from the created domain.
2971
2972         // REVISIT_TODO: The comparison "pDomain != GetDomain()" will always be true for domain-neutral
2973         // modules, since GetDomain() will return the SharedDomain, which is NOT an AppDomain.
2974         // Was this intended? If so, there should be a clarifying comment. If not, then we should
2975         // probably do "pDomain != GetAppDomain()" instead.
2976
2977         if (pDomain != GetDomain() &&
2978             pDomain != SystemDomain::System()->DefaultDomain() &&
2979             IsSystem())
2980         {
2981             pDomain->AllocateStaticFieldObjRefPtrsCrossDomain(this->m_dwMaxGCRegularStaticHandles,
2982                                                pModuleData->GetPrecomputedGCStaticsBasePointerAddress());
2983         }
2984         else
2985         {
2986             pDomain->AllocateStaticFieldObjRefPtrs(this->m_dwMaxGCRegularStaticHandles,
2987                                                pModuleData->GetPrecomputedGCStaticsBasePointerAddress());
2988         }
2989
2990         // We should throw if we fail to allocate and never hit this assert
2991         _ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointer() != NULL);
2992     }
2993 #endif // CROSSGEN_COMPILE
2994 }
2995
2996 BOOL Module::IsStaticStoragePrepared(mdTypeDef tkType)
2997 {
2998     LIMITED_METHOD_CONTRACT;
2999
3000     // Right now the design is that we do one static allocation pass during NGEN,
3001     // and a 2nd pass for it at module init time for modules that weren't NGENed or the NGEN
3002     // pass was unsucessful. If we are loading types after that then we must use dynamic
3003     // static storage. These dynamic statics require an additional indirection so they
3004     // don't perform quite as well. 
3005     //
3006     // This check was created for the scenario where a profiler adds additional types
3007     // however it seems likely this check would also accurately handle other dynamic
3008     // scenarios such as ref.emit and EnC as long as they are adding new types and
3009     // not new statics to existing types.
3010     _ASSERTE(TypeFromToken(tkType) == mdtTypeDef);
3011     return m_maxTypeRidStaticsAllocated >= RidFromToken(tkType);
3012 }
3013
3014 void Module::AllocateStatics(AllocMemTracker *pamTracker)
3015 {
3016     STANDARD_VM_CONTRACT;
3017
3018     if (IsResource())
3019     {
3020         m_dwRegularStaticsBlockSize = DomainLocalModule::OffsetOfDataBlob();
3021         m_dwThreadStaticsBlockSize = ThreadLocalModule::OffsetOfDataBlob();
3022
3023         // If it has no code, we don't have to allocate anything
3024         LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Resource module %s. No statics neeeded\n", GetSimpleName()));
3025         _ASSERTE(m_maxTypeRidStaticsAllocated == 0);
3026         return;
3027     }
3028 #ifdef FEATURE_PREJIT
3029     if (m_pRegularStaticOffsets == (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED)
3030     {
3031         _ASSERTE(HasNativeImage());
3032
3033         // This is an ngen image and all the classes were loaded at ngen time, so we're done.
3034         LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: 'Complete' Native image found, no statics parsing needed for module %s.\n", GetSimpleName()));
3035         // typeDefs rids 0 and 1 aren't included in the count, thus X typeDefs means rid X+1 is valid
3036         _ASSERTE(m_maxTypeRidStaticsAllocated == GetMDImport()->GetCountWithTokenKind(mdtTypeDef) + 1);
3037         return;
3038     }
3039 #endif
3040     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Allocating statics for module %s\n", GetSimpleName()));
3041
3042     // Build the offset table, which will tell us what the offsets for the statics of each class are (one offset for gc handles, one offset
3043     // for non gc types)
3044     BuildStaticsOffsets(pamTracker);
3045 }
3046
3047 // This method will report GC static refs of the module. It doesn't have to be complete (ie, it's 
3048 // currently used to opportunistically get more concurrency in the marking of statics), so it currently
3049 // ignores any statics that are not preallocated (ie: won't report statics from IsDynamicStatics() MT)
3050 // The reason this function is in Module and not in DomainFile (together with DomainLocalModule is because
3051 // for shared modules we need a very fast way of getting to the DomainLocalModule. For that we use
3052 // a table in DomainLocalBlock that's indexed with a module ID
3053 //
3054 // This method is a secondary way for the GC to find statics, and it is only used when we are on
3055 // a multiproc machine and we are using the ServerHeap. The primary way used by the GC to find 
3056 // statics is through the handle table. Module::AllocateRegularStaticHandles() allocates a GC handle
3057 // from the handle table, and the GC will trace this handle and find the statics.
3058
3059 void Module::EnumRegularStaticGCRefs(AppDomain* pAppDomain, promote_func* fn, ScanContext* sc)
3060 {
3061     CONTRACT_VOID
3062     {
3063         NOTHROW;
3064         GC_NOTRIGGER;
3065     }
3066     CONTRACT_END;
3067
3068     _ASSERTE(GCHeapUtilities::IsGCInProgress() && 
3069          GCHeapUtilities::IsServerHeap() && 
3070          IsGCSpecialThread());
3071
3072
3073     DomainLocalModule *pModuleData = GetDomainLocalModule(pAppDomain);
3074     DWORD dwHandles                = m_dwMaxGCRegularStaticHandles;
3075
3076     if (IsResource())
3077     {
3078         RETURN;
3079     }
3080
3081     LOG((LF_GC, LL_INFO100, "Scanning statics for module %s\n", GetSimpleName()));
3082
3083     OBJECTREF* ppObjectRefs       = pModuleData->GetPrecomputedGCStaticsBasePointer();
3084     for (DWORD i = 0 ; i < dwHandles ; i++)
3085     {
3086         // Handles are allocated in SetDomainFile (except for bootstrapped mscorlib). In any
3087         // case, we shouldnt get called if the module hasn't had it's handles allocated (as we
3088         // only get here if IsActive() is true, which only happens after SetDomainFile(), which
3089         // is were we allocate handles.
3090         _ASSERTE(ppObjectRefs);
3091         fn((Object **)(ppObjectRefs+i), sc, 0);
3092     }
3093
3094     LOG((LF_GC, LL_INFO100, "Done scanning statics for module %s\n", GetSimpleName()));
3095
3096     RETURN;
3097 }
3098
3099 void Module::SetDomainFile(DomainFile *pDomainFile)
3100 {
3101     CONTRACTL
3102     {
3103         INSTANCE_CHECK;
3104         PRECONDITION(CheckPointer(pDomainFile));
3105         PRECONDITION(IsManifest() == pDomainFile->IsAssembly());
3106         THROWS;
3107         GC_TRIGGERS;
3108         MODE_ANY;
3109     }
3110     CONTRACTL_END;
3111
3112     DomainLocalModule* pModuleData = 0;
3113
3114     // Do we need to allocate memory for the non GC statics?
3115     if ((GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())|| m_ModuleID == NULL)
3116     {
3117         // Allocate memory for the module statics.
3118         LoaderAllocator *pLoaderAllocator = NULL;
3119         if (GetAssembly()->IsCollectible())
3120         {
3121             pLoaderAllocator = GetAssembly()->GetLoaderAllocator();
3122         }
3123         else
3124         {
3125             pLoaderAllocator = pDomainFile->GetAppDomain()->GetLoaderAllocator();
3126         }
3127
3128         SIZE_T size = GetDomainLocalModuleSize();
3129
3130         LOG((LF_CLASSLOADER, LL_INFO10, "STATICS: Allocating %i bytes for precomputed statics in module %S in LoaderAllocator %p\n",
3131             size, this->GetDebugName(), pLoaderAllocator));
3132
3133         // We guarantee alignment for 64-bit regular statics on 32-bit platforms even without FEATURE_64BIT_ALIGNMENT for performance reasons.
3134
3135         _ASSERTE(size >= DomainLocalModule::OffsetOfDataBlob());
3136
3137         pModuleData = (DomainLocalModule*)(void*)
3138             pLoaderAllocator->GetHighFrequencyHeap()->AllocAlignedMem(
3139                 size, MAX_PRIMITIVE_FIELD_SIZE);
3140
3141         // Note: Memory allocated on loader heap is zero filled
3142         // memset(pModuleData, 0, size);
3143
3144         // Verify that the space is really zero initialized
3145         _ASSERTE(pModuleData->GetPrecomputedGCStaticsBasePointer() == NULL);
3146
3147         // Make sure that the newly allocated DomainLocalModule gets 
3148         // a copy of the domain-neutral module ID. 
3149         if (GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())
3150         {
3151             // If the module was loaded as domain-neutral, we can find the ID by 
3152             // casting 'm_ModuleID'.
3153             
3154             _ASSERTE(Module::IDToIndex((SIZE_T)m_ModuleID) == this->m_ModuleIndex);
3155             pModuleData->m_ModuleIndex = Module::IDToIndex((SIZE_T)m_ModuleID);
3156
3157             // Eventually I want to just do this instead...
3158             //pModuleData->m_ModuleIndex = this->m_ModuleIndex;
3159         }
3160         else
3161         {
3162             // If the module was loaded as domain-specific, then we need to assign
3163             // this module a domain-neutral module ID.
3164             pModuleData->m_ModuleIndex = Module::AllocateModuleIndex();
3165             m_ModuleIndex = pModuleData->m_ModuleIndex;
3166         }
3167     }
3168     else
3169     {
3170         pModuleData = this->m_ModuleID;
3171         LOG((LF_CLASSLOADER, LL_INFO10, "STATICS: Allocation not needed for ngened non shared module %s in Appdomain %08x\n"));
3172     }
3173
3174     if (GetAssembly()->IsDomainNeutral() && !IsSingleAppDomain())
3175     {
3176         DomainLocalBlock *pLocalBlock;
3177         {
3178             pLocalBlock = pDomainFile->GetAppDomain()->GetDomainLocalBlock();
3179             pLocalBlock->SetModuleSlot(GetModuleIndex(), pModuleData);
3180         }
3181
3182         pLocalBlock->SetDomainFile(GetModuleIndex(), pDomainFile);
3183     }
3184     else
3185     {
3186         // Non shared case, module points directly to the statics. In ngen case
3187         // m_pDomainModule is already set for the non shared case
3188         if (m_ModuleID == NULL)
3189         {
3190             m_ModuleID = pModuleData;
3191         }
3192
3193         m_ModuleID->SetDomainFile(pDomainFile);
3194     }
3195
3196     // Allocate static handles now.
3197     // NOTE: Bootstrapping issue with mscorlib - we will manually allocate later
3198     // If the assembly is collectible, we don't initialize static handles for them
3199     // as it is currently initialized through the DomainLocalModule::PopulateClass in MethodTable::CheckRunClassInitThrowing
3200     // (If we don't do this, it would allocate here unused regular static handles that will be overridden later)
3201     if (g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] != NULL && !GetAssembly()->IsCollectible())
3202         AllocateRegularStaticHandles(pDomainFile->GetAppDomain());
3203 }
3204
3205 #ifndef CROSSGEN_COMPILE
3206 OBJECTREF Module::GetExposedObject()
3207 {
3208     CONTRACT(OBJECTREF)
3209     {
3210         INSTANCE_CHECK;
3211         POSTCONDITION(RETVAL != NULL);
3212         THROWS;
3213         GC_TRIGGERS;
3214         MODE_COOPERATIVE;
3215     }
3216     CONTRACT_END;
3217
3218     RETURN GetDomainFile()->GetExposedModuleObject();
3219 }
3220 #endif // CROSSGEN_COMPILE
3221
3222 //
3223 // AllocateMap allocates the RID maps based on the size of the current
3224 // metadata (if any)
3225 //
3226
3227 void Module::AllocateMaps()
3228 {
3229     CONTRACTL
3230     {
3231         INSTANCE_CHECK;
3232         THROWS;
3233         GC_NOTRIGGER;
3234         MODE_ANY;
3235     }
3236     CONTRACTL_END;
3237
3238     enum
3239     {
3240         TYPEDEF_MAP_INITIAL_SIZE = 5,
3241         TYPEREF_MAP_INITIAL_SIZE = 5,
3242         MEMBERDEF_MAP_INITIAL_SIZE = 10,
3243         GENERICPARAM_MAP_INITIAL_SIZE = 5,
3244         GENERICTYPEDEF_MAP_INITIAL_SIZE = 5,
3245         FILEREFERENCES_MAP_INITIAL_SIZE = 5,
3246         ASSEMBLYREFERENCES_MAP_INITIAL_SIZE = 5,
3247     };
3248
3249     PTR_TADDR pTable = NULL;
3250
3251     if (IsResource())
3252         return;
3253
3254     if (IsReflection())
3255     {
3256         // For dynamic modules, it is essential that we at least have a TypeDefToMethodTable
3257         // map with an initial block.  Otherwise, all the iterators will abort on an
3258         // initial empty table and we will e.g. corrupt the backpatching chains during
3259         // an appdomain unload.
3260         m_TypeDefToMethodTableMap.dwCount = TYPEDEF_MAP_INITIAL_SIZE;
3261
3262         // The above is essential.  The following ones are precautionary.
3263         m_TypeRefToMethodTableMap.dwCount = TYPEREF_MAP_INITIAL_SIZE;
3264         m_MethodDefToDescMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE;
3265         m_FieldDefToDescMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE;
3266         m_GenericParamToDescMap.dwCount = GENERICPARAM_MAP_INITIAL_SIZE;
3267         m_GenericTypeDefToCanonMethodTableMap.dwCount = TYPEDEF_MAP_INITIAL_SIZE;
3268         m_FileReferencesMap.dwCount = FILEREFERENCES_MAP_INITIAL_SIZE;
3269         m_ManifestModuleReferencesMap.dwCount = ASSEMBLYREFERENCES_MAP_INITIAL_SIZE;
3270         m_MethodDefToPropertyInfoMap.dwCount = MEMBERDEF_MAP_INITIAL_SIZE;
3271     }
3272     else
3273     {
3274         IMDInternalImport * pImport = GetMDImport();
3275
3276         // Get # TypeDefs (add 1 for COR_GLOBAL_PARENT_TOKEN)
3277         m_TypeDefToMethodTableMap.dwCount = pImport->GetCountWithTokenKind(mdtTypeDef)+2;
3278
3279         // Get # TypeRefs
3280         m_TypeRefToMethodTableMap.dwCount = pImport->GetCountWithTokenKind(mdtTypeRef)+1;
3281
3282         // Get # MethodDefs
3283         m_MethodDefToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtMethodDef)+1;
3284
3285         // Get # FieldDefs
3286         m_FieldDefToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtFieldDef)+1;
3287
3288         // Get # GenericParams
3289         m_GenericParamToDescMap.dwCount = pImport->GetCountWithTokenKind(mdtGenericParam)+1;
3290
3291         // Get the number of FileReferences in the map
3292         m_FileReferencesMap.dwCount = pImport->GetCountWithTokenKind(mdtFile)+1;
3293
3294         // Get the number of AssemblyReferences in the map
3295         m_ManifestModuleReferencesMap.dwCount = pImport->GetCountWithTokenKind(mdtAssemblyRef)+1;
3296
3297         // These maps are only added to during NGen, so for other scenarios leave them empty
3298         if (IsCompilationProcess())
3299         {
3300             m_GenericTypeDefToCanonMethodTableMap.dwCount = m_TypeDefToMethodTableMap.dwCount;
3301             m_MethodDefToPropertyInfoMap.dwCount = m_MethodDefToDescMap.dwCount;
3302         }
3303         else
3304         {
3305             m_GenericTypeDefToCanonMethodTableMap.dwCount = 0;
3306             m_MethodDefToPropertyInfoMap.dwCount = 0;
3307         }
3308     }
3309
3310     S_SIZE_T nTotal;
3311
3312     nTotal += m_TypeDefToMethodTableMap.dwCount;
3313     nTotal += m_TypeRefToMethodTableMap.dwCount;
3314     nTotal += m_MethodDefToDescMap.dwCount;
3315     nTotal += m_FieldDefToDescMap.dwCount;
3316     nTotal += m_GenericParamToDescMap.dwCount;
3317     nTotal += m_GenericTypeDefToCanonMethodTableMap.dwCount;
3318     nTotal += m_FileReferencesMap.dwCount;
3319     nTotal += m_ManifestModuleReferencesMap.dwCount;
3320     nTotal += m_MethodDefToPropertyInfoMap.dwCount;
3321
3322     _ASSERTE (m_pAssembly && m_pAssembly->GetLowFrequencyHeap());
3323     pTable = (PTR_TADDR)(void*)m_pAssembly->GetLowFrequencyHeap()->AllocMem(nTotal * S_SIZE_T(sizeof(TADDR)));
3324
3325     // Note: Memory allocated on loader heap is zero filled
3326     // memset(pTable, 0, nTotal * sizeof(void*));
3327
3328     m_TypeDefToMethodTableMap.pNext  = NULL;
3329     m_TypeDefToMethodTableMap.supportedFlags = TYPE_DEF_MAP_ALL_FLAGS;
3330     m_TypeDefToMethodTableMap.pTable = pTable;
3331
3332     m_TypeRefToMethodTableMap.pNext  = NULL;
3333     m_TypeRefToMethodTableMap.supportedFlags = TYPE_REF_MAP_ALL_FLAGS;
3334     m_TypeRefToMethodTableMap.pTable = &pTable[m_TypeDefToMethodTableMap.dwCount];
3335
3336     m_MethodDefToDescMap.pNext  = NULL;
3337     m_MethodDefToDescMap.supportedFlags = METHOD_DEF_MAP_ALL_FLAGS;
3338     m_MethodDefToDescMap.pTable = &m_TypeRefToMethodTableMap.pTable[m_TypeRefToMethodTableMap.dwCount];
3339
3340     m_FieldDefToDescMap.pNext  = NULL;
3341     m_FieldDefToDescMap.supportedFlags = FIELD_DEF_MAP_ALL_FLAGS;
3342     m_FieldDefToDescMap.pTable = &m_MethodDefToDescMap.pTable[m_MethodDefToDescMap.dwCount];
3343
3344     m_GenericParamToDescMap.pNext  = NULL;
3345     m_GenericParamToDescMap.supportedFlags = GENERIC_PARAM_MAP_ALL_FLAGS;
3346     m_GenericParamToDescMap.pTable = &m_FieldDefToDescMap.pTable[m_FieldDefToDescMap.dwCount];
3347
3348     m_GenericTypeDefToCanonMethodTableMap.pNext  = NULL;
3349     m_GenericTypeDefToCanonMethodTableMap.supportedFlags = GENERIC_TYPE_DEF_MAP_ALL_FLAGS;
3350     m_GenericTypeDefToCanonMethodTableMap.pTable = &m_GenericParamToDescMap.pTable[m_GenericParamToDescMap.dwCount];
3351
3352     m_FileReferencesMap.pNext  = NULL;
3353     m_FileReferencesMap.supportedFlags = FILE_REF_MAP_ALL_FLAGS;
3354     m_FileReferencesMap.pTable = &m_GenericTypeDefToCanonMethodTableMap.pTable[m_GenericTypeDefToCanonMethodTableMap.dwCount];
3355
3356     m_ManifestModuleReferencesMap.pNext  = NULL;
3357     m_ManifestModuleReferencesMap.supportedFlags = MANIFEST_MODULE_MAP_ALL_FLAGS;
3358     m_ManifestModuleReferencesMap.pTable = &m_FileReferencesMap.pTable[m_FileReferencesMap.dwCount];
3359
3360     m_MethodDefToPropertyInfoMap.pNext = NULL;
3361     m_MethodDefToPropertyInfoMap.supportedFlags = PROPERTY_INFO_MAP_ALL_FLAGS;
3362     m_MethodDefToPropertyInfoMap.pTable = &m_ManifestModuleReferencesMap.pTable[m_ManifestModuleReferencesMap.dwCount];
3363 }
3364
3365
3366 //
3367 // FreeClassTables frees the classes in the module
3368 //
3369
3370 void Module::FreeClassTables()
3371 {
3372     CONTRACTL
3373     {
3374         INSTANCE_CHECK;
3375         NOTHROW;
3376         GC_TRIGGERS;
3377         MODE_ANY;
3378     }
3379     CONTRACTL_END;
3380
3381     if (m_dwTransientFlags & CLASSES_FREED)
3382         return;
3383
3384     FastInterlockOr(&m_dwTransientFlags, CLASSES_FREED);
3385
3386     // disable ibc here because it can cause errors during the destruction of classes
3387     IBCLoggingDisabler disableLogging;
3388             
3389 #if _DEBUG 
3390     DebugLogRidMapOccupancy();
3391 #endif
3392
3393     //
3394     // Free the types filled out in the TypeDefToEEClass map
3395     //
3396
3397     // Go through each linked block
3398     LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
3399     while (typeDefIter.Next())
3400     {
3401         MethodTable * pMT = typeDefIter.GetElement();
3402
3403         if (pMT != NULL && pMT->IsRestored())
3404         {
3405             pMT->GetClass()->Destruct(pMT);
3406         }
3407     }
3408
3409     // Now do the same for constructed types (arrays and instantiated generic types)
3410     if (IsTenured())  // If we're destructing because of an error during the module's creation, we'll play it safe and not touch this table as its memory is freed by a
3411     {                 // separate AllocMemTracker. Though you're supposed to destruct everything else before destructing the AllocMemTracker, this is an easy invariant to break so
3412                       // we'll play extra safe on this end.
3413         if (m_pAvailableParamTypes != NULL)
3414         {
3415             EETypeHashTable::Iterator it(m_pAvailableParamTypes);
3416             EETypeHashEntry *pEntry;
3417             while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
3418             {
3419                 TypeHandle th = pEntry->GetTypeHandle();
3420
3421                 if (!th.IsRestored())
3422                     continue;
3423
3424 #ifdef FEATURE_COMINTEROP
3425                 // Some MethodTables/TypeDescs have COM interop goo attached to them which must be released
3426                 if (!th.IsTypeDesc())
3427                 {
3428                     MethodTable *pMT = th.AsMethodTable();
3429                     if (pMT->HasCCWTemplate() && (!pMT->IsZapped() || pMT->GetZapModule() == this))
3430                     {
3431                         // code:MethodTable::GetComCallWrapperTemplate() may go through canonical methodtable indirection cell.
3432                         // The module load could be aborted before completing code:FILE_LOAD_EAGER_FIXUPS phase that's responsible 
3433                         // for resolving pre-restored indirection cells, so we have to check for it here explicitly.
3434                         if (CORCOMPILE_IS_POINTER_TAGGED(pMT->GetCanonicalMethodTableFixup()))
3435                             continue;
3436
3437                         ComCallWrapperTemplate *pTemplate = pMT->GetComCallWrapperTemplate();
3438                         if (pTemplate != NULL)
3439                         {
3440                             pTemplate->Release();
3441                         }
3442                     }
3443                 }
3444                 else if (th.IsArray())
3445                 {
3446                     ComCallWrapperTemplate *pTemplate = th.AsArray()->GetComCallWrapperTemplate();
3447                     if (pTemplate != NULL)
3448                     {
3449                         pTemplate->Release();
3450                     }
3451                 }
3452 #endif // FEATURE_COMINTEROP
3453
3454                 // We need to call destruct on instances of EEClass whose "canonical" dependent lives in this table
3455                 // There is nothing interesting to destruct on array EEClass
3456                 if (!th.IsTypeDesc())
3457                 {
3458                     MethodTable * pMT = th.AsMethodTable();
3459                     if (pMT->IsCanonicalMethodTable() && (!pMT->IsZapped() || pMT->GetZapModule() == this))
3460                         pMT->GetClass()->Destruct(pMT);
3461                 }
3462             }
3463         }
3464     }
3465 }
3466
3467 #endif // !DACCESS_COMPILE
3468
3469 ClassLoader *Module::GetClassLoader()
3470 {
3471     WRAPPER_NO_CONTRACT;
3472     SUPPORTS_DAC;
3473     _ASSERTE(m_pAssembly != NULL);
3474     return m_pAssembly->GetLoader();
3475 }
3476
3477 PTR_BaseDomain Module::GetDomain()
3478 {
3479     WRAPPER_NO_CONTRACT;
3480     SUPPORTS_DAC;
3481     _ASSERTE(m_pAssembly != NULL);
3482     return m_pAssembly->GetDomain();
3483 }
3484
3485 #ifndef DACCESS_COMPILE 
3486
3487 #ifndef CROSSGEN_COMPILE
3488 void Module::StartUnload()
3489 {
3490     WRAPPER_NO_CONTRACT;
3491 #ifdef PROFILING_SUPPORTED 
3492     {
3493         BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads());
3494         if (!IsBeingUnloaded())
3495         {
3496             // Profiler is causing some peripheral class loads. Probably this just needs
3497             // to be turned into a Fault_not_fatal and moved to a specific place inside the profiler.
3498             EX_TRY
3499             {
3500                 GCX_PREEMP();
3501                 g_profControlBlock.pProfInterface->ModuleUnloadStarted((ModuleID) this);
3502             }
3503             EX_CATCH
3504             {
3505             }
3506             EX_END_CATCH(SwallowAllExceptions);
3507         }
3508         END_PIN_PROFILER();
3509     }
3510 #endif // PROFILING_SUPPORTED
3511 #ifdef FEATURE_PREJIT 
3512     if (g_IBCLogger.InstrEnabled())
3513     {
3514         Thread * pThread = GetThread();
3515         ThreadLocalIBCInfo* pInfo = pThread->GetIBCInfo();
3516
3517         // Acquire the Crst lock before creating the IBCLoggingDisabler object.
3518         // Only one thread at a time can be processing an IBC logging event.
3519         CrstHolder lock(g_IBCLogger.GetSync());
3520         {
3521             IBCLoggingDisabler disableLogging( pInfo );  // runs IBCLoggingDisabler::DisableLogging
3522
3523             // Write out the method profile data
3524             /*hr=*/WriteMethodProfileDataLogFile(true);
3525         }
3526     }
3527 #endif // FEATURE_PREJIT
3528     SetBeingUnloaded();
3529 }
3530 #endif // CROSSGEN_COMPILE
3531
3532 void Module::ReleaseILData(void)
3533 {
3534     WRAPPER_NO_CONTRACT;
3535
3536     ReleaseISymUnmanagedReader();
3537 }
3538
3539
3540
3541 //---------------------------------------------------------------------------------------
3542 //
3543 // Simple wrapper around calling IsAfContentType_WindowsRuntime() against the flags
3544 // returned from the PEAssembly's GetFlagsNoTrigger()
3545 //
3546 // Return Value:
3547 //     nonzero iff we successfully determined pModule is a WinMD. FALSE if pModule is not
3548 //     a WinMD, or we fail trying to find out.
3549 //
3550 BOOL Module::IsWindowsRuntimeModule()
3551 {
3552     CONTRACTL 
3553     {
3554         NOTHROW;
3555         GC_NOTRIGGER;
3556         CAN_TAKE_LOCK;     // Accesses metadata directly, which takes locks
3557         MODE_ANY;
3558     } 
3559     CONTRACTL_END;
3560
3561     BOOL fRet = FALSE;
3562
3563     DWORD dwFlags;
3564
3565     if (FAILED(GetAssembly()->GetManifestFile()->GetFlagsNoTrigger(&dwFlags)))
3566         return FALSE;
3567
3568     return IsAfContentType_WindowsRuntime(dwFlags);
3569 }
3570
3571 BOOL Module::IsInCurrentVersionBubble()
3572 {
3573     LIMITED_METHOD_CONTRACT;
3574
3575 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
3576     if (!IsCompilationProcess())
3577         return TRUE;
3578
3579     // The module being compiled is always part of the current version bubble
3580     AppDomain * pAppDomain = GetAppDomain();
3581     if (pAppDomain->IsCompilationDomain() && pAppDomain->ToCompilationDomain()->GetTargetModule() == this)
3582         return TRUE;
3583
3584     if (IsReadyToRunCompilation())
3585         return FALSE;
3586
3587 #ifdef FEATURE_COMINTEROP
3588     if (g_fNGenWinMDResilient)
3589         return !GetAssembly()->IsWinMD();
3590 #endif
3591
3592     return TRUE;
3593 #else // FEATURE_NATIVE_IMAGE_GENERATION
3594     return TRUE;
3595 #endif // FEATURE_NATIVE_IMAGE_GENERATION
3596 }
3597
3598 //---------------------------------------------------------------------------------------
3599 //
3600 // WinMD-aware helper to grab a readable public metadata interface. Any place that thinks
3601 // it wants to use Module::GetRWImporter + QI now should use this wrapper instead.
3602 //
3603 // Arguments:
3604 //      * dwOpenFlags - Combo from CorOpenFlags. Better not contain ofWrite!
3605 //      * riid - Public IID requested
3606 //      * ppvInterface - [out] Requested interface. On success, *ppvInterface is returned
3607 //          refcounted; caller responsible for Release.
3608 //
3609 // Return Value:
3610 //      HRESULT indicating success or failure.
3611 //
3612 HRESULT Module::GetReadablePublicMetaDataInterface(DWORD dwOpenFlags, REFIID riid, LPVOID * ppvInterface)
3613 {
3614     CONTRACTL 
3615     {
3616         NOTHROW;
3617         GC_NOTRIGGER;
3618         CAN_TAKE_LOCK;     // IsWindowsRuntimeModule accesses metadata directly, which takes locks
3619         MODE_ANY;
3620     } 
3621     CONTRACTL_END;
3622
3623     _ASSERTE((dwOpenFlags & ofWrite) == 0);
3624
3625     // Temporary place to store public, AddRef'd interface pointers
3626     ReleaseHolder<IUnknown> pIUnkPublic;
3627
3628     // Temporary place to store the IUnknown from which we'll do the final QI to get the
3629     // requested public interface.  Any assignment to pIUnk assumes pIUnk does not need
3630     // to do a Release() (either the interface was internal and not AddRef'd, or was
3631     // public and will be released by the above holder).
3632     IUnknown * pIUnk = NULL;
3633     
3634     HRESULT hr = S_OK;
3635
3636     // Normally, we just get an RWImporter to do the QI on, and we're on our way.
3637     EX_TRY
3638     {
3639         pIUnk = GetRWImporter();
3640     }
3641     EX_CATCH_HRESULT_NO_ERRORINFO(hr);
3642
3643     if (FAILED(hr) && IsWindowsRuntimeModule())
3644     {
3645         // WinMD modules don't like creating RW importers.   They also (currently)
3646         // have no plumbing to get to their public metadata interfaces from the
3647         // Module.  So we actually have to start from scratch at the dispenser.
3648
3649         // To start with, get a dispenser, and get the metadata memory blob we've
3650         // already loaded.  If either of these fail, just return the error HRESULT
3651         // from the above GetRWImporter() call.
3652
3653         // We'll get an addref'd IMetaDataDispenser, so use a holder to release it
3654         ReleaseHolder<IMetaDataDispenser> pDispenser;
3655         if (FAILED(InternalCreateMetaDataDispenser(IID_IMetaDataDispenser, &pDispenser)))
3656         {
3657             _ASSERTE(FAILED(hr));
3658             return hr;
3659         }
3660
3661         COUNT_T cbMetadata = 0;
3662         PTR_CVOID pvMetadata = GetAssembly()->GetManifestFile()->GetLoadedMetadata(&cbMetadata);
3663         if ((pvMetadata == NULL) || (cbMetadata == 0))
3664         {
3665             _ASSERTE(FAILED(hr));
3666             return hr;
3667         }
3668
3669         // Now that the pieces are ready, we can use the riid specified by the
3670         // profiler in this call to the dispenser to get the requested interface. If
3671         // this fails, then this is the interesting HRESULT for the caller to see.
3672         // 
3673         // We'll get an AddRef'd public interface, so use a holder to release it
3674         hr = pDispenser->OpenScopeOnMemory(
3675             pvMetadata, 
3676             cbMetadata, 
3677             (dwOpenFlags | ofReadOnly),         // Force ofReadOnly on behalf of the profiler
3678             riid, 
3679             &pIUnkPublic);
3680         if (FAILED(hr))
3681             return hr;
3682
3683         // Set pIUnk so we can do the final QI from it below as we do in the other
3684         // cases.
3685         pIUnk = pIUnkPublic;
3686     }
3687
3688     // Get the requested interface
3689     if (SUCCEEDED(hr) && (ppvInterface != NULL))
3690     {
3691         _ASSERTE(pIUnk != NULL);
3692         hr = pIUnk->QueryInterface(riid, (void **) ppvInterface);
3693     }
3694
3695     return hr;
3696 }
3697
3698 // a special token that indicates no reader could be created - don't try again
3699 static ISymUnmanagedReader* const k_pInvalidSymReader = (ISymUnmanagedReader*)0x1;
3700
3701 #if defined(FEATURE_ISYM_READER) && !defined(CROSSGEN_COMPILE)
3702 ISymUnmanagedReader *Module::GetISymUnmanagedReaderNoThrow(void)
3703 {
3704     CONTRACT(ISymUnmanagedReader *)
3705     {
3706         INSTANCE_CHECK;
3707         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
3708         NOTHROW;
3709         WRAPPER(GC_TRIGGERS);
3710         MODE_ANY;
3711     }
3712     CONTRACT_END;
3713
3714     ISymUnmanagedReader *ret = NULL;
3715
3716     EX_TRY
3717     {
3718         ret = GetISymUnmanagedReader();
3719     }
3720     EX_CATCH
3721     {
3722         // We swallow any exception and say that we simply couldn't get a reader by returning NULL.
3723         // The only type of error that should be possible here is OOM.
3724         /* DISABLED due to Dev10 bug 619495 
3725         CONSISTENCY_CHECK_MSG(
3726             GET_EXCEPTION()->GetHR() == E_OUTOFMEMORY, 
3727             "Exception from GetISymUnmanagedReader");
3728          */
3729     }
3730     EX_END_CATCH(RethrowTerminalExceptions);
3731
3732     RETURN (ret);
3733 }
3734
3735 ISymUnmanagedReader *Module::GetISymUnmanagedReader(void)
3736 {
3737     CONTRACT(ISymUnmanagedReader *)
3738     {
3739         INSTANCE_CHECK;
3740         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
3741         THROWS;
3742         WRAPPER(GC_TRIGGERS);
3743         MODE_ANY;
3744     }
3745     CONTRACT_END;
3746
3747     // No symbols for resource modules
3748     if (IsResource())
3749         RETURN NULL;
3750
3751     if (g_fEEShutDown)
3752         RETURN NULL;
3753
3754     // Verify that symbol reading is permitted for this module.
3755     // If we know we've already created a symbol reader, don't bother checking.  There is
3756     // no advantage to allowing symbol reading to be turned off if we've already created the reader.
3757     // Note that we can't just put this code in the creation block below because we might have to
3758     // call managed code to resolve security policy, and we can't do that while holding a lock.
3759     // There is no disadvantage other than a minor perf cost to calling this unnecessarily, so the
3760     // race on m_pISymUnmanagedReader here is OK.  The perf cost is minor because the only real
3761     // work is done by the security system which caches the result.
3762     if( m_pISymUnmanagedReader == NULL && !IsSymbolReadingEnabled() )
3763         RETURN NULL;
3764     
3765     // Take the lock for the m_pISymUnmanagedReader
3766     // This ensures that we'll only ever attempt to create one reader at a time, and we won't
3767     // create a reader if we're in the middle of destroying one that has become stale.
3768     // Actual access to the reader can safely occur outside the lock as long as it has its own
3769     // AddRef which we take inside the lock at the bottom of this method.
3770     CrstHolder holder(&m_ISymUnmanagedReaderCrst);
3771
3772     UINT lastErrorMode = 0;
3773
3774     // If we haven't created a reader yet, do so now
3775     if (m_pISymUnmanagedReader == NULL)
3776     {
3777         // Mark our reader as invalid so that if we fail to create the reader
3778         // (including if an exception is thrown), we won't keep trying.
3779         m_pISymUnmanagedReader = k_pInvalidSymReader;
3780
3781         // There are 4 main cases here:
3782         //  1. Assembly is on disk and we'll get the symbols from a file next to the assembly
3783         //  2. Assembly is provided by the host and we'll get the symbols from the host
3784         //  3. Assembly was loaded in-memory (by byte array or ref-emit), and symbols were
3785         //      provided along with it.
3786         //  4. Assembly was loaded in-memory but no symbols were provided.
3787
3788         // Determine whether we should be looking in memory for the symbols (cases 2 & 3)
3789         bool fInMemorySymbols = ( m_file->IsIStream() || GetInMemorySymbolStream() );
3790         if( !fInMemorySymbols && m_file->GetPath().IsEmpty() )
3791         {
3792             // Case 4.  We don't have a module path, an IStream or an in memory symbol stream, 
3793             // so there is no-where to try and get symbols from.
3794             RETURN (NULL);
3795         }
3796
3797         // Create a binder to find the reader.
3798         //
3799         // <REVISIT_TODO>@perf: this is slow, creating and destroying the binder every
3800         // time. We should cache this somewhere, but I'm not 100% sure
3801         // where right now...</REVISIT_TODO>
3802         HRESULT hr = S_OK;
3803
3804         SafeComHolder<ISymUnmanagedBinder> pBinder;
3805
3806         if (g_pDebugInterface == NULL)
3807         {
3808             // @TODO: this is reachable when debugging!
3809             UNREACHABLE_MSG("About to CoCreateInstance!  This code should not be "
3810                             "reachable or needs to be reimplemented for CoreCLR!");
3811         }
3812
3813         if (this->GetInMemorySymbolStreamFormat() == eSymbolFormatILDB)
3814         {
3815             // We've got in-memory ILDB symbols, create the ILDB symbol binder
3816             // Note that in this case, we must be very careful not to use diasymreader.dll
3817             // at all - we don't trust it, and shouldn't run any code in it
3818             IfFailThrow(IldbSymbolsCreateInstance(CLSID_CorSymBinder_SxS, IID_ISymUnmanagedBinder, (void**)&pBinder));
3819         }
3820         else
3821         {
3822             // We're going to be working with Windows PDB format symbols. Attempt to CoCreate the symbol binder.
3823             // CoreCLR supports not having a symbol reader installed, so CoCreate searches the PATH env var 
3824             // and then tries coreclr dll location.
3825             // On desktop, the framework installer is supposed to install diasymreader.dll as well
3826             // and so this shouldn't happen.
3827             hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, NATIVE_SYMBOL_READER_DLL, IID_ISymUnmanagedBinder, (void**)&pBinder, NULL);
3828             if (FAILED(hr))
3829             {
3830                 PathString symbolReaderPath;
3831                 hr = GetHModuleDirectory(GetModuleInst(), symbolReaderPath);
3832                 if (FAILED(hr))
3833                 {
3834                     RETURN (NULL);
3835                 }
3836                 symbolReaderPath.Append(NATIVE_SYMBOL_READER_DLL);
3837                 hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, symbolReaderPath.GetUnicode(), IID_ISymUnmanagedBinder, (void**)&pBinder, NULL);
3838                 if (FAILED(hr))
3839                 {
3840                     RETURN (NULL);
3841                 }
3842             }
3843         }
3844
3845         LOG((LF_CORDB, LL_INFO10, "M::GISUR: Created binder\n"));
3846
3847         // Note: we change the error mode here so we don't get any popups as the PDB symbol reader attempts to search the
3848         // hard disk for files.
3849         lastErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
3850
3851         SafeComHolder<ISymUnmanagedReader> pReader;
3852
3853         if (fInMemorySymbols) 
3854         {
3855             SafeComHolder<IStream> pIStream( NULL );
3856
3857             // If debug stream is already specified, don't bother to go through fusion
3858             // This is the common case for case 2 (hosted modules) and case 3 (Ref.Emit).
3859             if (GetInMemorySymbolStream() )
3860             {
3861                 
3862                 if( IsReflection() )
3863                 {
3864                     // If this is Reflection.Emit, we must clone the stream because another thread may 
3865                     // update it when someone is using the reader we create here leading to AVs.
3866                     // Note that the symbol stream should be up to date since we flush the writer
3867                     // after every addition in Module::AddClass.
3868                     IfFailThrow(GetInMemorySymbolStream()->Clone(&pIStream));
3869                 }
3870                 else
3871                 {
3872                     // The stream is not changing. Just add-ref to it.
3873                     pIStream = GetInMemorySymbolStream();
3874                     pIStream->AddRef();
3875                 }
3876             }
3877             if (SUCCEEDED(hr))
3878             {
3879                 hr = pBinder->GetReaderFromStream(GetRWImporter(), pIStream, &pReader);
3880             }
3881         }
3882         else
3883         {
3884             // The assembly is on disk, so try and load symbols based on the path to the assembly (case 1)
3885             const SString &path = m_file->GetPath();
3886
3887             // Call Fusion to ensure that any PDB's are shadow copied before
3888             // trying to get a symbol reader. This has to be done once per
3889             // Assembly.
3890             // for this to work with winmds we cannot simply call GetRWImporter() as winmds are RO
3891             // and thus don't implement the RW interface. so we call this wrapper function which knows 
3892             // how to get a IMetaDataImport interface regardless of the underlying module type.
3893             ReleaseHolder<IUnknown> pUnk = NULL;
3894             hr = GetReadablePublicMetaDataInterface(ofReadOnly, IID_IMetaDataImport, &pUnk);
3895             if (SUCCEEDED(hr))
3896                 hr = pBinder->GetReaderForFile(pUnk, path, NULL, &pReader);
3897         }
3898
3899         SetErrorMode(lastErrorMode);
3900
3901         if (SUCCEEDED(hr))
3902         {
3903             m_pISymUnmanagedReader = pReader.Extract();
3904             LOG((LF_CORDB, LL_INFO10, "M::GISUR: Loaded symbols for module %S\n", GetDebugName()));
3905         }
3906         else
3907         {
3908             // We failed to create the reader, don't try again next time
3909             LOG((LF_CORDB, LL_INFO10, "M::GISUR: Failed to load symbols for module %S\n", GetDebugName()));
3910             _ASSERTE( m_pISymUnmanagedReader == k_pInvalidSymReader );
3911         }
3912
3913     } // if( m_pISymUnmanagedReader == NULL )
3914
3915     // If we previously failed to create the reader, return NULL
3916     if (m_pISymUnmanagedReader == k_pInvalidSymReader)
3917     {
3918         RETURN (NULL);
3919     }
3920
3921     // Success - return an AddRef'd copy of the reader
3922     m_pISymUnmanagedReader->AddRef();
3923     RETURN (m_pISymUnmanagedReader);
3924 }
3925 #endif // FEATURE_ISYM_READER && !CROSSGEN_COMPILE
3926
3927 BOOL Module::IsSymbolReadingEnabled()
3928 {
3929     CONTRACTL
3930     {
3931         INSTANCE_CHECK;
3932         THROWS;
3933         GC_TRIGGERS;
3934         MODE_ANY;
3935     }
3936     CONTRACTL_END;
3937
3938     // The only time we need symbols available is for debugging and taking stack traces,
3939     // neither of which can be done if the assembly can't run. The advantage of being strict
3940     // is that there is a perf penalty adding types to a module if you must support reading
3941     // symbols at any time. If symbols don't need to be accesible then we can
3942     // optimize by only commiting symbols when the assembly is saved to disk. See DDB 671107.
3943     if(!GetAssembly()->HasRunAccess())
3944     {
3945         return FALSE;
3946     }
3947
3948     // If the module has symbols in-memory (eg. RefEmit) that are in ILDB
3949     // format, then there isn't any reason not to supply them.  The reader
3950     // code is always available, and we trust it's security.
3951     if (this->GetInMemorySymbolStreamFormat() == eSymbolFormatILDB)
3952     {
3953         return TRUE;
3954     }
3955
3956 #ifdef DEBUGGING_SUPPORTED 
3957     if (!g_pDebugInterface)
3958     {
3959         // if debugging is disabled (no debug pack installed), do not load symbols
3960         // This is done for two reasons.  We don't completely trust the security of
3961         // the diasymreader.dll code, so we don't want to use it in mainline scenarios.
3962         // Secondly, there's not reason that diasymreader.dll will even necssarily be
3963         // be on the machine if the debug pack isn't installed.
3964         return FALSE;
3965     }
3966 #endif // DEBUGGING_SUPPORTED
3967
3968
3969     return TRUE;
3970 }
3971
3972 // At this point, this is only called when we're creating an appdomain
3973 // out of an array of bytes, so we'll keep the IStream that we create
3974 // around in case the debugger attaches later (including detach & re-attach!)
3975 void Module::SetSymbolBytes(LPCBYTE pbSyms, DWORD cbSyms)
3976 {
3977     STANDARD_VM_CONTRACT;
3978
3979     // Create a IStream from the memory for the syms.
3980     SafeComHolder<CGrowableStream> pStream(new CGrowableStream());
3981
3982     // Do not need to AddRef the CGrowableStream because the constructor set it to 1
3983     // ref count already. The Module will keep a copy for its own use.
3984
3985     // Make sure to set the symbol stream on the module before
3986     // attempting to send UpdateModuleSyms messages up for it.
3987     SetInMemorySymbolStream(pStream, eSymbolFormatPDB);
3988
3989     // This can only be called when the module is being created.  No-one should have
3990     // tried to use the symbols yet, and so there should not be a reader.
3991     // If instead, we wanted to call this when a reader could have been created, we need to 
3992     // serialize access by taking the reader lock, and flush the old reader by calling 
3993     // code:Module.ReleaseISymUnmanagedReader
3994     _ASSERTE( m_pISymUnmanagedReader == NULL );
3995     
3996 #ifdef LOGGING 
3997     LPCWSTR pName = NULL;
3998     pName = GetDebugName();
3999 #endif // LOGGING
4000
4001     ULONG cbWritten;
4002     DWORD dwError = pStream->Write((const void *)pbSyms,
4003                                (ULONG)cbSyms,
4004                                                 &cbWritten);
4005     IfFailThrow(HRESULT_FROM_WIN32(dwError));
4006
4007 #if PROFILING_SUPPORTED && !defined(CROSSGEN_COMPILE)
4008     BEGIN_PIN_PROFILER(CORProfilerInMemorySymbolsUpdatesEnabled());
4009     {
4010         g_profControlBlock.pProfInterface->ModuleInMemorySymbolsUpdated((ModuleID) this);
4011     }
4012     END_PIN_PROFILER();
4013 #endif //PROFILING_SUPPORTED && !defined(CROSSGEN_COMPILE)
4014
4015     ETW::CodeSymbolLog::EmitCodeSymbols(this);
4016
4017     // Tell the debugger that symbols have been loaded for this
4018     // module.  We iterate through all domains which contain this
4019     // module's assembly, and send a debugger notify for each one.
4020     // <REVISIT_TODO>@perf: it would scale better if we directly knew which domains
4021     // the assembly was loaded in.</REVISIT_TODO>
4022     if (CORDebuggerAttached())
4023     {
4024         AppDomainIterator i(FALSE);
4025
4026         while (i.Next())
4027         {
4028             AppDomain *pDomain = i.GetDomain();
4029
4030             if (pDomain->IsDebuggerAttached() && (GetDomain() == SystemDomain::System() ||
4031                                                   pDomain->ContainsAssembly(m_pAssembly)))
4032             {
4033                 g_pDebugInterface->SendUpdateModuleSymsEventAndBlock(this, pDomain);
4034             }
4035         }
4036     }
4037 }
4038
4039 // Clear any cached symbol reader
4040 void Module::ReleaseISymUnmanagedReader(void)
4041 {
4042     CONTRACTL
4043     {
4044         NOTHROW;
4045         GC_NOTRIGGER;
4046         MODE_ANY;
4047         FORBID_FAULT;
4048     }
4049     CONTRACTL_END;
4050
4051     // Caller is responsible for taking the reader lock if the call could occur when
4052     // other threads are using or creating the reader
4053     if( m_pISymUnmanagedReader != NULL )
4054     {
4055         // If we previously failed to create a reader, don't attempt to release it
4056         // but do clear it out so that we can try again (eg. symbols may have changed)
4057         if( m_pISymUnmanagedReader != k_pInvalidSymReader )
4058         {
4059             m_pISymUnmanagedReader->Release();
4060         }
4061         m_pISymUnmanagedReader = NULL;
4062     }
4063 }
4064
4065 // Lazily creates a new IL stub cache for this module.
4066 ILStubCache* Module::GetILStubCache()
4067 {
4068     CONTRACTL
4069     {
4070         THROWS;
4071         GC_NOTRIGGER;
4072         MODE_ANY;
4073         INJECT_FAULT(COMPlusThrowOM(););
4074     }
4075     CONTRACTL_END;
4076
4077     // Use per-AD cache for domain specific modules when not NGENing
4078     BaseDomain *pDomain = GetDomain();
4079     if (!pDomain->IsSharedDomain() && !pDomain->AsAppDomain()->IsCompilationDomain())
4080         return pDomain->AsAppDomain()->GetILStubCache();
4081
4082     if (m_pILStubCache == NULL)
4083     {
4084         ILStubCache *pILStubCache = new ILStubCache(GetLoaderAllocator()->GetHighFrequencyHeap());
4085
4086         if (FastInterlockCompareExchangePointer(&m_pILStubCache, pILStubCache, NULL) != NULL)
4087         {
4088             // some thread swooped in and set the field
4089             delete pILStubCache;
4090         }
4091     }
4092     _ASSERTE(m_pILStubCache != NULL);
4093     return m_pILStubCache;
4094 }
4095
4096 // Called to finish the process of adding a new class with Reflection.Emit
4097 void Module::AddClass(mdTypeDef classdef)
4098 {
4099     CONTRACTL
4100     {
4101         INSTANCE_CHECK;
4102         THROWS;
4103         GC_TRIGGERS;
4104         MODE_PREEMPTIVE;
4105         PRECONDITION(!IsResource());
4106     }
4107     CONTRACTL_END;
4108
4109     // The fake class associated with the module (global fields & functions) needs to be initialized here
4110     // Normal classes are added to the available class hash when their typedef is first created.
4111     if (RidFromToken(classdef) == 0)
4112     {
4113         BuildClassForModule();
4114     }
4115
4116     // Since the module is being modified, the in-memory symbol stream 
4117     // (if any) has probably also been modified. If we support reading the symbols
4118     // then we need to commit the changes to the writer and flush any old readers
4119     // However if we don't support reading then we can skip this which will give
4120     // a substantial perf improvement. See DDB 671107.
4121     if(IsSymbolReadingEnabled())
4122     {
4123         CONSISTENCY_CHECK(IsReflection());   // this is only used for dynamic modules
4124         ISymUnmanagedWriter * pWriter = GetReflectionModule()->GetISymUnmanagedWriter();
4125         if (pWriter != NULL)
4126         {
4127             // Serialize with any concurrent reader creations
4128             // Specifically, if we started creating a reader on one thread, and then updated the
4129             // symbols on another thread, we need to wait until the initial reader creation has
4130             // completed and release it so we don't get stuck with a stale reader.
4131             // Also, if we commit to the stream while we're in the process of creating a reader,
4132             // the reader will get corrupted/incomplete data.
4133             // Note that we must also be in co-operative mode here to ensure the debugger helper
4134             // thread can't be simultaneously reading this stream while the process is synchronized
4135             // (code:Debugger::GetSymbolBytes)
4136             CrstHolder holder(&m_ISymUnmanagedReaderCrst);
4137
4138             // Flush writes to the symbol store to the symbol stream
4139             // Note that we do this when finishing the addition of the class, instead of 
4140             // on-demand in GetISymUnmanagedReader because the writer is not thread-safe.
4141             // Here, we're inside the lock of TypeBuilder.CreateType, and so it's safe to
4142             // manipulate the writer.
4143             SafeComHolderPreemp<ISymUnmanagedWriter3> pWriter3;
4144             HRESULT thr = pWriter->QueryInterface(IID_ISymUnmanagedWriter3, (void**)&pWriter3);
4145             CONSISTENCY_CHECK(SUCCEEDED(thr));
4146             if (SUCCEEDED(thr))
4147             {
4148                 thr = pWriter3->Commit();
4149                 if (SUCCEEDED(thr))
4150                 {
4151                     // Flush any cached symbol reader to ensure we pick up any new symbols
4152                     ReleaseISymUnmanagedReader();
4153                 }
4154             }
4155
4156             // If either the QI or Commit failed
4157             if (FAILED(thr))
4158             {
4159                 // The only way we expect this might fail is out-of-memory.  In that
4160                 // case we silently fail to update the symbol stream with new data, but
4161                 // we leave the existing reader intact.
4162                 CONSISTENCY_CHECK(thr==E_OUTOFMEMORY);
4163             }
4164         }
4165     }
4166 }
4167
4168 //---------------------------------------------------------------------------
4169 // For the global class this builds the table of MethodDescs an adds the rids
4170 // to the MethodDef map.
4171 //---------------------------------------------------------------------------
4172 void Module::BuildClassForModule()
4173 {
4174     CONTRACTL
4175     {
4176         INSTANCE_CHECK;
4177         THROWS;
4178         GC_TRIGGERS;
4179         MODE_ANY;
4180     }
4181     CONTRACTL_END;
4182
4183     IMDInternalImport * pImport = GetMDImport();
4184     DWORD           cFunctions, cFields;
4185
4186     {
4187         // Obtain count of global functions
4188         HENUMInternalHolder hEnum(pImport);
4189         hEnum.EnumGlobalFunctionsInit();
4190         cFunctions = pImport->EnumGetCount(&hEnum);
4191     }
4192
4193     {
4194         // Obtain count of global fields
4195         HENUMInternalHolder hEnum(pImport);
4196         hEnum.EnumGlobalFieldsInit();
4197         cFields = pImport->EnumGetCount(&hEnum);
4198     }
4199
4200     // If we have any work to do...
4201     if (cFunctions > 0 || cFields > 0)
4202     {
4203         COUNTER_ONLY(size_t _HeapSize = 0);
4204
4205         TypeKey typeKey(this, COR_GLOBAL_PARENT_TOKEN);
4206         TypeHandle typeHnd = GetClassLoader()->LoadTypeHandleForTypeKeyNoLock(&typeKey);
4207
4208 #ifdef ENABLE_PERF_COUNTERS 
4209
4210         _HeapSize = GetLoaderAllocator()->GetHighFrequencyHeap()->GetSize();
4211
4212         GetPerfCounters().m_Loading.cbLoaderHeapSize = _HeapSize;
4213 #endif // ENABLE_PERF_COUNTERS
4214
4215     }
4216 }
4217
4218 #endif // !DACCESS_COMPILE
4219
4220 // Returns true iff the debugger should be notified about this module
4221 // 
4222 // Notes:
4223 //   Debugger doesn't need to be notified about modules that can't be executed,
4224 //   like inspection and resource only. These are just pure data.
4225 //   
4226 //   This should be immutable for an instance of a module. That ensures that the debugger gets consistent
4227 //   notifications about it. It this value mutates, than the debugger may miss relevant notifications.
4228 BOOL Module::IsVisibleToDebugger()
4229 {
4230     WRAPPER_NO_CONTRACT; 
4231     SUPPORTS_DAC;
4232
4233     if (IsResource())
4234     {
4235         return FALSE;
4236     }
4237
4238     // If for whatever other reason, we can't run it, then don't notify the debugger about it.
4239     Assembly * pAssembly = GetAssembly();
4240     if (!pAssembly->HasRunAccess())
4241     {
4242         return FALSE;
4243     }
4244     return TRUE;
4245 }
4246
4247 BOOL            Module::HasNativeOrReadyToRunImage()
4248 {
4249 #ifdef FEATURE_READYTORUN
4250     if (IsReadyToRun())
4251         return TRUE;
4252 #endif
4253
4254     return HasNativeImage();
4255 }
4256
4257 PEImageLayout * Module::GetNativeOrReadyToRunImage()
4258 {
4259     LIMITED_METHOD_CONTRACT;
4260
4261 #ifdef FEATURE_READYTORUN
4262     if (IsReadyToRun())
4263         return GetReadyToRunInfo()->GetImage();
4264 #endif
4265
4266     return GetNativeImage();
4267 }
4268
4269 PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSections(COUNT_T *pCount)
4270 {
4271     CONTRACTL
4272     {
4273         NOTHROW;
4274         GC_NOTRIGGER;
4275     }
4276     CONTRACTL_END;
4277
4278 #ifdef FEATURE_READYTORUN
4279     if (IsReadyToRun())
4280         return GetReadyToRunInfo()->GetImportSections(pCount);
4281 #endif
4282
4283     return GetNativeImage()->GetNativeImportSections(pCount);
4284 }
4285
4286 PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionFromIndex(COUNT_T index)
4287 {
4288     CONTRACTL
4289     {
4290         NOTHROW;
4291         GC_NOTRIGGER;
4292     }
4293     CONTRACTL_END;
4294
4295 #ifdef FEATURE_READYTORUN
4296     if (IsReadyToRun())
4297         return GetReadyToRunInfo()->GetImportSectionFromIndex(index);
4298 #endif
4299
4300     return GetNativeImage()->GetNativeImportSectionFromIndex(index);
4301 }
4302
4303 PTR_CORCOMPILE_IMPORT_SECTION Module::GetImportSectionForRVA(RVA rva)
4304 {
4305     CONTRACTL
4306     {
4307         NOTHROW;
4308         GC_NOTRIGGER;
4309     }
4310     CONTRACTL_END;
4311
4312 #ifdef FEATURE_READYTORUN
4313     if (IsReadyToRun())
4314         return GetReadyToRunInfo()->GetImportSectionForRVA(rva);
4315 #endif
4316
4317     return GetNativeImage()->GetNativeImportSectionForRVA(rva);
4318 }
4319
4320 TADDR Module::GetIL(DWORD target)
4321 {
4322     WRAPPER_NO_CONTRACT;
4323     SUPPORTS_DAC;
4324
4325     if (target == 0)
4326         return NULL;
4327
4328     return m_file->GetIL(target);
4329 }
4330
4331 PTR_VOID Module::GetRvaField(DWORD rva, BOOL fZapped)
4332 {
4333     WRAPPER_NO_CONTRACT;
4334     SUPPORTS_DAC;
4335
4336 #ifdef FEATURE_PREJIT 
4337     if (fZapped && m_file->IsILOnly())
4338     {
4339         return dac_cast<PTR_VOID>(m_file->GetLoadedNative()->GetRvaData(rva,NULL_OK));
4340     }
4341 #endif // FEATURE_PREJIT
4342
4343     return m_file->GetRvaField(rva);
4344 }
4345
4346 #ifndef DACCESS_COMPILE 
4347
4348 CHECK Module::CheckRvaField(RVA field)
4349 {
4350     WRAPPER_NO_CONTRACT;
4351     if (!IsReflection())
4352         CHECK(m_file->CheckRvaField(field));
4353     CHECK_OK;
4354 }
4355
4356 CHECK Module::CheckRvaField(RVA field, COUNT_T size)
4357 {
4358     CONTRACTL
4359     {
4360         STANDARD_VM_CHECK;
4361         CAN_TAKE_LOCK;
4362     }
4363     CONTRACTL_END;
4364
4365     if (!IsReflection())
4366         CHECK(m_file->CheckRvaField(field, size));
4367     CHECK_OK;
4368 }
4369
4370 #endif // !DACCESS_COMPILE
4371
4372 BOOL Module::HasTls()
4373 {
4374     WRAPPER_NO_CONTRACT;
4375
4376     return m_file->HasTls();
4377 }
4378
4379 BOOL Module::IsRvaFieldTls(DWORD rva)
4380 {
4381     WRAPPER_NO_CONTRACT;
4382
4383     return m_file->IsRvaFieldTls(rva);
4384 }
4385
4386 UINT32 Module::GetFieldTlsOffset(DWORD rva)
4387 {
4388     WRAPPER_NO_CONTRACT;
4389
4390     return m_file->GetFieldTlsOffset(rva);
4391 }
4392
4393 UINT32 Module::GetTlsIndex()
4394 {
4395     WRAPPER_NO_CONTRACT;
4396
4397     return m_file->GetTlsIndex();
4398 }
4399
4400
4401 // In DAC builds this function was being called on host addresses which may or may not
4402 // have been marshalled from the target. Such addresses can't be reliably mapped back to
4403 // target addresses, which means we can't tell whether they came from the IL or not
4404 //
4405 // Security note: Any security which you might wish to gain by verifying the origin of
4406 // a signature isn't available in DAC. The attacker can provide a dump which spoofs all
4407 // module ranges. In other words the attacker can make the signature appear to come from
4408 // anywhere, but still violate all the rules that a signature from that location would
4409 // otherwise follow. I am removing this function from DAC in order to prevent anyone from
4410 // getting a false sense of security (in addition to its functional shortcomings)
4411
4412 #ifndef DACCESS_COMPILE
4413 BOOL Module::IsSigInIL(PCCOR_SIGNATURE signature)
4414 {
4415     CONTRACTL
4416     {
4417         INSTANCE_CHECK;
4418         FORBID_FAULT;
4419         MODE_ANY;
4420         NOTHROW;
4421         SO_TOLERANT;
4422         GC_NOTRIGGER;
4423     }
4424     CONTRACTL_END;
4425
4426     return m_file->IsPtrInILImage(signature);
4427 }
4428
4429 #ifdef FEATURE_PREJIT
4430 StubMethodHashTable *Module::GetStubMethodHashTable()
4431 {
4432     CONTRACTL
4433     {
4434         THROWS;
4435         GC_NOTRIGGER;
4436     }
4437     CONTRACTL_END
4438
4439     if (m_pStubMethodHashTable == NULL && SystemDomain::GetCurrentDomain()->IsCompilationDomain())
4440     {
4441         // we only need to create the hash table when NGENing, it is read-only at run-time
4442         AllocMemTracker amTracker;
4443         m_pStubMethodHashTable = StubMethodHashTable::Create(GetLoaderAllocator(), this, METHOD_STUBS_HASH_BUCKETS, &amTracker);
4444         amTracker.SuppressRelease();
4445     }
4446
4447     return m_pStubMethodHashTable;
4448 }
4449 #endif // FEATURE_PREJIT
4450
4451 void Module::InitializeStringData(DWORD token, EEStringData *pstrData, CQuickBytes *pqb)
4452 {
4453     CONTRACTL
4454     {
4455         INSTANCE_CHECK;
4456         THROWS;
4457         GC_TRIGGERS;
4458         MODE_ANY;
4459         INJECT_FAULT(COMPlusThrowOM());
4460         PRECONDITION(TypeFromToken(token) == mdtString);
4461     }
4462     CONTRACTL_END;
4463
4464     BOOL fIs80Plus;
4465     DWORD dwCharCount;
4466     LPCWSTR pString;
4467     if (FAILED(GetMDImport()->GetUserString(token, &dwCharCount, &fIs80Plus, &pString)) || 
4468         (pString == NULL))
4469     {
4470         THROW_BAD_FORMAT(BFA_BAD_STRING_TOKEN_RANGE, this);
4471     }
4472     
4473 #if !BIGENDIAN 
4474     pstrData->SetStringBuffer(pString);
4475 #else // !!BIGENDIAN
4476     _ASSERTE(pqb != NULL);
4477
4478     LPWSTR pSwapped;
4479
4480     pSwapped = (LPWSTR) pqb->AllocThrows(dwCharCount * sizeof(WCHAR));
4481     memcpy((void*)pSwapped, (void*)pString, dwCharCount*sizeof(WCHAR));
4482     SwapStringLength(pSwapped, dwCharCount);
4483
4484     pstrData->SetStringBuffer(pSwapped);
4485 #endif // !!BIGENDIAN
4486
4487         // MD and String look at this bit in opposite ways.  Here's where we'll do the conversion.
4488         // MD sets the bit to true if the string contains characters greater than 80.
4489         // String sets the bit to true if the string doesn't contain characters greater than 80.
4490
4491     pstrData->SetCharCount(dwCharCount);
4492     pstrData->SetIsOnlyLowChars(!fIs80Plus);
4493 }
4494
4495 #ifndef CROSSGEN_COMPILE
4496
4497 #ifdef FEATURE_PREJIT 
4498 OBJECTHANDLE Module::ResolveStringRefHelper(DWORD token, BaseDomain *pDomain, PTR_CORCOMPILE_IMPORT_SECTION pSection, EEStringData *pStrData)
4499 {        
4500     PEImageLayout *pNativeImage = GetNativeImage();
4501
4502     // Get the table
4503     COUNT_T tableSize;
4504     TADDR tableBase = pNativeImage->GetDirectoryData(&pSection->Section, &tableSize);
4505
4506     // Walk the handle table.
4507     // @TODO: If we ever care about the perf of this function, we could sort the tokens
4508     // using as a key the string they point to, so we could do a binary search
4509     for (SIZE_T * pEntry = (SIZE_T *)tableBase ; pEntry < (SIZE_T *)(tableBase + tableSize); pEntry++)
4510     {
4511         // Ensure that the compiler won't fetch the value twice
4512         SIZE_T entry = VolatileLoadWithoutBarrier(pEntry);
4513
4514         if (CORCOMPILE_IS_POINTER_TAGGED(entry))
4515         {
4516             BYTE * pBlob = (BYTE *) pNativeImage->GetRvaData(CORCOMPILE_UNTAG_TOKEN(entry));
4517
4518             // Note that we only care about strings from current module, and so we do not check ENCODE_MODULE_OVERRIDE
4519             if (*pBlob++ == ENCODE_STRING_HANDLE && 
4520                     TokenFromRid(CorSigUncompressData((PCCOR_SIGNATURE&) pBlob), mdtString) ==  token)
4521             {
4522                 EnsureWritablePages(pEntry);
4523
4524                 // This string hasn't been fixed up. Synchronize the update with the normal
4525                 // fixup logic
4526                 {
4527                     CrstHolder ch(this->GetFixupCrst());
4528
4529                     if (!CORCOMPILE_IS_POINTER_TAGGED(*pEntry))
4530                     {
4531                         // We lost the race, just return current entry
4532                     }
4533                     else
4534                     {
4535                         *pEntry = (SIZE_T) ResolveStringRef(token, pDomain, false);
4536                     }
4537                 }
4538
4539                 return (OBJECTHANDLE) *pEntry;
4540             }
4541         }
4542         else
4543         {
4544             OBJECTREF* pRef = (OBJECTREF*) entry;
4545             _ASSERTE((*pRef)->GetMethodTable() == g_pStringClass);
4546
4547             STRINGREF stringRef = (STRINGREF) *pRef;
4548
4549             // Is this the string we are trying to resolve?
4550             if (pStrData->GetCharCount() == stringRef->GetStringLength() &&
4551                 memcmp((void*)pStrData->GetStringBuffer(),
4552                         (void*) stringRef->GetBuffer(),
4553                         pStrData->GetCharCount()*sizeof(WCHAR)) == 0)
4554             {
4555                 // We found it, so we just have to return this instance
4556                 return (OBJECTHANDLE) entry;
4557             }
4558         }
4559     }
4560     return NULL;
4561 }
4562 #endif // FEATURE_PREJIT
4563
4564 OBJECTHANDLE Module::ResolveStringRef(DWORD token, BaseDomain *pDomain, bool bNeedToSyncWithFixups)
4565 {
4566     CONTRACTL
4567     {
4568         INSTANCE_CHECK;
4569         THROWS;
4570         GC_TRIGGERS;
4571         MODE_ANY;
4572         INJECT_FAULT(COMPlusThrowOM());
4573         PRECONDITION(TypeFromToken(token) == mdtString);
4574     }
4575     CONTRACTL_END;
4576
4577     EEStringData strData;
4578     OBJECTHANDLE string = NULL;
4579
4580 #if !BIGENDIAN 
4581     InitializeStringData(token, &strData, NULL);
4582 #else // !!BIGENDIAN
4583     CQuickBytes qb;
4584     InitializeStringData(token, &strData, &qb);
4585 #endif // !!BIGENDIAN
4586
4587     GCX_COOP();
4588
4589     // We can only do this for native images as they guarantee that resolvestringref will be
4590     // called only once per string from this module. @TODO: We really dont have any way of asserting
4591     // this, which would be nice... (and is needed to guarantee correctness)
4592 #ifdef FEATURE_PREJIT 
4593     if (HasNativeImage() && IsNoStringInterning())
4594     {
4595         if (bNeedToSyncWithFixups)
4596         {
4597             // In an ngen image, it is possible that we get here but not be coming from a fixup,
4598             // (FixupNativeEntry case). In that unfortunate case (ngen partial images, dynamic methods,
4599             // lazy string inits) we will have to troll through the fixup list, and in the case the string is there,
4600             // reuse it, if it's  there but hasn't been fixed up, fix it up now, and in the case it isn't
4601             // there at all, then go to our old style string interning. Going through this code path is
4602             // guaranteed to be slow. If necessary, we can further optimize it by sorting the token table,
4603             // Another way of solving this would be having a token to string table (would require knowing
4604             // all our posible stings in the ngen case (this is possible by looking at the IL))
4605
4606             PEImageLayout * pNativeImage = GetNativeImage();
4607
4608             COUNT_T nSections;
4609             PTR_CORCOMPILE_IMPORT_SECTION pSections = pNativeImage->GetNativeImportSections(&nSections);
4610
4611             for (COUNT_T iSection = 0; iSection < nSections; iSection++)
4612             {
4613                 PTR_CORCOMPILE_IMPORT_SECTION pSection = pSections + iSection;
4614
4615                 if (pSection->Type != CORCOMPILE_IMPORT_TYPE_STRING_HANDLE)
4616                     continue;
4617
4618                 OBJECTHANDLE oh = ResolveStringRefHelper(token, pDomain, pSection, &strData);
4619                 if (oh != NULL)
4620                     return oh;
4621             }
4622
4623             // The string is not in our fixup list, so just intern it old style (using hashtable)
4624             goto INTERN_OLD_STYLE;
4625
4626         }
4627         /* Unfortunately, this assert won't work in some cases of generics, consider the following scenario:
4628
4629             1) Generic type in mscorlib.
4630             2) Instantiation of generic (1) (via valuetype) in another module
4631             3) other module now holds a copy of the code of the generic for that particular instantiation
4632                however, it is resolving the string literals against mscorlib, which breaks the invariant
4633                this assert was based on (no string fixups against other modules). In fact, with NoStringInterning,
4634                our behavior is not very intuitive.
4635         */
4636         /*
4637         _ASSERTE(pDomain == GetAssembly()->GetDomain() && "If your are doing ldstr for a string"
4638         "in another module, either the JIT is very smart or you have a bug, check INLINE_NO_CALLEE_LDSTR");
4639
4640         */
4641         /*
4642         Dev10 804385 bugfix - 
4643            We should be using appdomain that the string token lives in (GetAssembly->GetDomain())
4644            to allocate the System.String object instead of the appdomain that first uses the ldstr <token> (pDomain).
4645
4646            Otherwise, it is possible to get into the situation that pDomain is unloaded but GetAssembly->GetDomain() is 
4647            still kicking around. Anything else that is still using that string will now be pointing to an object 
4648            that will be freed when the next GC happens.
4649         */
4650         pDomain = GetAssembly()->GetDomain();
4651
4652         // The caller is going to update an ngen fixup entry. The fixup entry
4653         // is used to reference the string and to ensure that the string is
4654         // allocated only once. Hence, this operation needs to be done under a lock.
4655         _ASSERTE(GetFixupCrst()->OwnedByCurrentThread());
4656
4657         // Allocate handle
4658         OBJECTREF* pRef = pDomain->AllocateObjRefPtrsInLargeTable(1);
4659
4660         STRINGREF str = AllocateStringObject(&strData);
4661         SetObjectReference(pRef, str, NULL);
4662
4663         #ifdef LOGGING 
4664         int length = strData.GetCharCount();
4665         length = min(length, 100);
4666         WCHAR *szString = (WCHAR *)_alloca((length + 1) * sizeof(WCHAR));
4667         memcpyNoGCRefs((void*)szString, (void*)strData.GetStringBuffer(), length * sizeof(WCHAR));
4668         szString[length] = '\0';
4669         LOG((LF_APPDOMAIN, LL_INFO10000, "String literal \"%S\" won't be interned due to NoInterningAttribute\n", szString));
4670         #endif // LOGGING
4671
4672         return (OBJECTHANDLE) pRef;
4673     }
4674
4675
4676 INTERN_OLD_STYLE:
4677 #endif
4678     // Retrieve the string from the either the appropriate LoaderAllocator
4679     LoaderAllocator *pLoaderAllocator;
4680
4681     if (this->IsCollectible())
4682         pLoaderAllocator = this->GetLoaderAllocator();
4683     else
4684         pLoaderAllocator = pDomain->GetLoaderAllocator();
4685         
4686     string = (OBJECTHANDLE)pLoaderAllocator->GetStringObjRefPtrFromUnicodeString(&strData);
4687
4688     return string;
4689 }
4690 #endif // CROSSGEN_COMPILE
4691
4692 //
4693 // Used by the verifier.  Returns whether this stringref is valid.
4694 //
4695 CHECK Module::CheckStringRef(DWORD token)
4696 {
4697     LIMITED_METHOD_CONTRACT;
4698     CHECK(TypeFromToken(token)==mdtString);
4699     CHECK(!IsNilToken(token));
4700     CHECK(GetMDImport()->IsValidToken(token));
4701     CHECK_OK;
4702 }
4703
4704 mdToken Module::GetEntryPointToken()
4705 {
4706     WRAPPER_NO_CONTRACT;
4707
4708     return m_file->GetEntryPointToken();
4709 }
4710
4711 BYTE *Module::GetProfilerBase()
4712 {
4713     CONTRACT(BYTE*)
4714     {
4715         NOTHROW;
4716         GC_NOTRIGGER;
4717         CANNOT_TAKE_LOCK;
4718     }
4719     CONTRACT_END;
4720
4721     if (m_file == NULL)  // I'd rather assert this is not the case...
4722     {
4723         RETURN NULL;
4724     }
4725     else if (HasNativeImage())
4726     {
4727         RETURN (BYTE*)(GetNativeImage()->GetBase());
4728     }
4729     else if (m_file->IsLoaded())
4730     {
4731         RETURN  (BYTE*)(m_file->GetLoadedIL()->GetBase());
4732     }
4733     else
4734     {
4735         RETURN NULL;
4736     }
4737 }
4738
4739 void Module::AddActiveDependency(Module *pModule, BOOL unconditional)
4740 {
4741     CONTRACT_VOID
4742     {
4743         THROWS;
4744         GC_TRIGGERS;
4745         PRECONDITION(CheckPointer(pModule));
4746         PRECONDITION(pModule != this);
4747         PRECONDITION(!IsSystem());
4748         PRECONDITION(!GetAssembly()->IsDomainNeutral() || pModule->GetAssembly()->IsDomainNeutral() || GetAppDomain()->IsDefaultDomain());
4749         POSTCONDITION(IsSingleAppDomain() || HasActiveDependency(pModule));
4750         POSTCONDITION(IsSingleAppDomain() || !unconditional || HasUnconditionalActiveDependency(pModule));
4751         // Postcondition about activation
4752     }
4753     CONTRACT_END;
4754
4755     // Activation tracking is not require in single domain mode. Activate the target immediately.
4756     if (IsSingleAppDomain())
4757     {
4758         pModule->EnsureActive();
4759         RETURN;
4760     }
4761
4762     // In the default AppDomain we delay a closure walk until a sharing attempt has been made
4763     // This might result in a situation where a domain neutral assembly from the default AppDomain 
4764     // depends on something resolved by assembly resolve event (even Ref.Emit assemblies) 
4765     // Since we won't actually share such assemblies, and the default AD itself cannot go away we 
4766     // do not need to assert for such assemblies, thus " || GetAppDomain()->IsDefaultDomain()"
4767
4768     CONSISTENCY_CHECK_MSG(!GetAssembly()->IsDomainNeutral() || pModule->GetAssembly()->IsDomainNeutral() || GetAppDomain()->IsDefaultDomain(),
4769                           "Active dependency from domain neutral to domain bound is illegal");
4770
4771     // We must track this dependency for multiple domains' use
4772     STRESS_LOG2(LF_CLASSLOADER, LL_INFO100000," %p -> %p\n",this,pModule);
4773
4774     _ASSERTE(!unconditional || pModule->HasNativeImage()); 
4775     _ASSERTE(!unconditional || HasNativeImage()); 
4776
4777     COUNT_T index;
4778
4779     // this function can run in parallel with DomainFile::Activate and sychronizes via GetNumberOfActivations()
4780     // because we expose dependency only in the end Domain::Activate might miss it, but it will increment a counter module
4781     // so we can realize we have to additionally propagate a dependency into that appdomain.
4782     // currently we do it just by rescanning al appdomains.
4783     // needless to say, updating the counter and checking counter+adding dependency to the list should be atomic
4784
4785
4786     BOOL propagate = FALSE;
4787     ULONG startCounter=0;
4788     ULONG endCounter=0;
4789     do
4790     {
4791         // First, add the dependency to the physical dependency list
4792         {
4793 #ifdef _DEBUG 
4794             CHECK check;
4795             if (unconditional)
4796                 check=DomainFile::CheckUnactivatedInAllDomains(this);
4797 #endif // _DEBUG
4798
4799             CrstHolder lock(&m_Crst);
4800             startCounter=GetNumberOfActivations();
4801
4802             index = m_activeDependencies.FindElement(0, pModule);
4803             if (index == (COUNT_T) ArrayList::NOT_FOUND)
4804             {
4805                 propagate = TRUE;
4806                 STRESS_LOG3(LF_CLASSLOADER, LL_INFO100,"Adding new module dependency %p -> %p, unconditional=%i\n",this,pModule,unconditional);
4807             }
4808
4809             if (unconditional)
4810             {
4811                 if (propagate)
4812                 {
4813                     CONSISTENCY_CHECK_MSG(check,
4814                                       "Unconditional dependency cannot be added after module has already been activated");
4815
4816                     index = m_activeDependencies.GetCount();
4817                     m_activeDependencies.Append(pModule);
4818                     m_unconditionalDependencies.SetBit(index);
4819                     STRESS_LOG2(LF_CLASSLOADER, LL_INFO100," Unconditional module dependency propagated %p -> %p\n",this,pModule);
4820                     // Now other threads can skip this dependency without propagating.
4821                 }
4822                 RETURN;
4823             }
4824
4825         }
4826
4827         // Now we have to propagate any module activations in the loader
4828
4829         if (propagate)
4830         {
4831
4832             _ASSERTE(!unconditional);
4833             DomainFile::PropagateNewActivation(this, pModule);
4834
4835             CrstHolder lock(&m_Crst);
4836             STRESS_LOG2(LF_CLASSLOADER, LL_INFO100," Conditional module dependency propagated %p -> %p\n",this,pModule);
4837             // Now other threads can skip this dependency without propagating.
4838             endCounter=GetNumberOfActivations();
4839             if(startCounter==endCounter)
4840                 m_activeDependencies.Append(pModule);
4841         }
4842         
4843     }while(propagate && startCounter!=endCounter); //need to retry if someone was activated in parallel
4844     RETURN;
4845 }
4846
4847 BOOL Module::HasActiveDependency(Module *pModule)
4848 {
4849     CONTRACTL
4850     {
4851         NOTHROW;
4852         GC_NOTRIGGER;
4853         MODE_ANY;
4854         PRECONDITION(CheckPointer(pModule));
4855     }
4856     CONTRACTL_END;
4857
4858     if (pModule == this)
4859         return TRUE;
4860
4861     DependencyIterator i = IterateActiveDependencies();
4862     while (i.Next())
4863     {
4864         if (i.GetDependency() == pModule)
4865             return TRUE;
4866     }
4867
4868     return FALSE;
4869 }
4870
4871 BOOL Module::HasUnconditionalActiveDependency(Module *pModule)
4872 {
4873     CONTRACTL
4874     {
4875         NOTHROW;
4876         CAN_TAKE_LOCK;
4877         MODE_ANY;
4878         PRECONDITION(CheckPointer(pModule));
4879     }
4880     CONTRACTL_END;
4881
4882     if (pModule == this)
4883         return TRUE;
4884
4885     DependencyIterator i = IterateActiveDependencies();
4886     while (i.Next())
4887     {
4888         if (i.GetDependency() == pModule
4889             && i.IsUnconditional())
4890             return TRUE;
4891     }
4892
4893     return FALSE;
4894 }
4895
4896 void Module::EnableModuleFailureTriggers(Module *pModuleTo, AppDomain *pDomain)
4897 {
4898     CONTRACTL
4899     {
4900         THROWS;
4901         GC_TRIGGERS;
4902         MODE_ANY;
4903     }
4904     CONTRACTL_END;
4905     // At this point we need to enable failure triggers we have placed in the code for this module.  However,
4906     // the failure trigger codegen logic is NYI.  To keep correctness, we just allow the exception to propagate
4907     // here.  Note that in general this will enforce the failure invariants, but will also result in some rude
4908     // behavior as these failures will be propagated too widely rather than constrained to the appropriate
4909     // assemblies/app domains.
4910     //
4911     // This should throw.
4912     STRESS_LOG2(LF_CLASSLOADER, LL_INFO100,"EnableModuleFailureTriggers for module %p in AppDomain %i\n",pModuleTo,pDomain->GetId().m_dwId);
4913     DomainFile *pDomainFileTo = pModuleTo->GetDomainFile(pDomain);
4914     pDomainFileTo->EnsureActive();
4915
4916     // @NYI: shouldn't get here yet since we propagate failures
4917     UNREACHABLE_MSG("Module failure triggers NYI");
4918 }
4919
4920 #endif //!DACCESS_COMPILE
4921
4922 //
4923 // an GetAssemblyIfLoadedAppDomainIterator is used to iterate over all domains that
4924 // are known to be walkable at the time GetAssemblyIfLoaded is executed.
4925 //
4926 // The iteration is guaranteed to include all domains that exist at the
4927 // start & end of the iteration that are safely accessible. This class is logically part
4928 // of GetAssemblyIfLoaded and logically has the same set of contracts.
4929 //
4930
4931 class GetAssemblyIfLoadedAppDomainIterator
4932 {
4933     enum IteratorType
4934     {
4935         StackwalkingThreadIterator,
4936         AllAppDomainWalkingIterator,
4937         CurrentAppDomainIterator
4938     }  m_iterType;
4939
4940 public:
4941     GetAssemblyIfLoadedAppDomainIterator() : 
4942       m_adIteratorAll(TRUE),
4943       m_appDomainCurrent(NULL),
4944       m_pFrame(NULL),
4945       m_fNextCalledForCurrentADIterator(FALSE)
4946     {
4947         LIMITED_METHOD_CONTRACT;
4948 #ifndef DACCESS_COMPILE
4949         if (IsStackWalkerThread())
4950         {
4951             Thread * pThread = (Thread *)ClrFlsGetValue(TlsIdx_StackWalkerWalkingThread);
4952             m_iterType = StackwalkingThreadIterator;
4953             m_pFrame = pThread->GetFrame();
4954             m_appDomainCurrent = pThread->GetDomain();
4955         }
4956         else if (IsGCThread())
4957         {
4958             m_iterType = AllAppDomainWalkingIterator;
4959             m_adIteratorAll.Init();
4960         }
4961         else
4962         {
4963             _ASSERTE(::GetAppDomain() != NULL);
4964             m_appDomainCurrent = ::GetAppDomain();
4965             m_iterType = CurrentAppDomainIterator;
4966         }
4967 #else //!DACCESS_COMPILE
4968         // We have to walk all AppDomains in debugger
4969         m_iterType = AllAppDomainWalkingIterator;
4970         m_adIteratorAll.Init();
4971 #endif //!DACCESS_COMPILE
4972     }
4973
4974     BOOL Next()
4975     {
4976         WRAPPER_NO_CONTRACT;
4977
4978         switch (m_iterType)
4979         {
4980 #ifndef DACCESS_COMPILE
4981         case StackwalkingThreadIterator:
4982             if (!m_fNextCalledForCurrentADIterator)
4983             {
4984                 m_fNextCalledForCurrentADIterator = TRUE;
4985
4986                 // Try searching frame chain if the current domain is NULL
4987                 if (m_appDomainCurrent == NULL)
4988                     return Next();
4989
4990                 return TRUE;
4991             }
4992             else
4993             {
4994                 while (m_pFrame != FRAME_TOP)
4995                 {
4996                     AppDomain * pDomain = m_pFrame->GetReturnDomain();
4997                     if ((pDomain != NULL) && (pDomain != m_appDomainCurrent))
4998                     {
4999                         m_appDomainCurrent = pDomain;
5000                         return TRUE;
5001                     }
5002                     m_pFrame = m_pFrame->PtrNextFrame();
5003                 }
5004
5005                 return FALSE;
5006             }
5007 #endif //!DACCESS_COMPILE
5008
5009         case AllAppDomainWalkingIterator:
5010             {
5011                 BOOL fSuccess = m_adIteratorAll.Next();
5012                 if (fSuccess)
5013                     m_appDomainCurrent = m_adIteratorAll.GetDomain();
5014                 return fSuccess;
5015             }
5016
5017 #ifndef DACCESS_COMPILE
5018         case CurrentAppDomainIterator:
5019             {
5020                 BOOL retVal;
5021                 retVal = !m_fNextCalledForCurrentADIterator;
5022                 m_fNextCalledForCurrentADIterator = TRUE;
5023                 return retVal;
5024             }
5025 #endif //!DACCESS_COMPILE
5026         
5027         default:
5028             _ASSERTE(FALSE);
5029             return FALSE;
5030         }
5031     }
5032
5033     AppDomain * GetDomain()
5034     {
5035         LIMITED_METHOD_CONTRACT;
5036
5037         return m_appDomainCurrent;
5038     }
5039
5040     BOOL UsingCurrentAD()
5041     {
5042         LIMITED_METHOD_CONTRACT;
5043         return m_iterType == CurrentAppDomainIterator;
5044     }
5045
5046   private:
5047
5048     UnsafeAppDomainIterator m_adIteratorAll;
5049     AppDomain *             m_appDomainCurrent;
5050     Frame *                 m_pFrame;
5051     BOOL                    m_fNextCalledForCurrentADIterator;
5052 };  // class GetAssemblyIfLoadedAppDomainIterator
5053
5054 #if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5055 // This function, given an AssemblyRef into the ngen generated native metadata section, will find the assembly referenced if
5056 // 1. The Assembly is defined with a different name than the AssemblyRef provides
5057 // 2. The Assembly has reached the stage of being loaded.
5058 // This function is used as a helper function to assist GetAssemblyIfLoaded with its tasks in the conditions
5059 // where GetAssemblyIfLoaded must succeed (or we violate various invariants in the system required for
5060 // correct implementation of GC, Stackwalking, and generic type loading.
5061 Assembly * Module::GetAssemblyIfLoadedFromNativeAssemblyRefWithRefDefMismatch(mdAssemblyRef kAssemblyRef, BOOL *pfDiscoveredAssemblyRefMatchesTargetDefExactly)
5062 {
5063     CONTRACT(Assembly *)
5064     {
5065         INSTANCE_CHECK;
5066         NOTHROW;
5067         GC_NOTRIGGER;
5068         FORBID_FAULT;
5069         MODE_ANY;
5070         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
5071     }
5072     CONTRACT_END;
5073
5074     _ASSERTE(HasNativeImage());
5075
5076     Assembly *pAssembly = NULL;
5077     IMDInternalImport *pImportFoundNativeImage = this->GetNativeAssemblyImport(FALSE);
5078
5079     if (!pImportFoundNativeImage)
5080     {
5081         RETURN NULL;
5082     }
5083
5084     if (kAssemblyRef != mdAssemblyRefNil)
5085     {
5086         // Scan CORCOMPILE_DEPENDENCIES tables
5087         PEImageLayout* pNativeLayout = this->GetNativeImage();
5088         COUNT_T dependencyCount;
5089         CORCOMPILE_DEPENDENCY *pDependencies = pNativeLayout->GetNativeDependencies(&dependencyCount);
5090
5091         // Find the assemblyDef that defines the exact target
5092         mdAssemblyRef foundAssemblyDef = mdAssemblyRefNil;
5093
5094         for (COUNT_T i = 0; i < dependencyCount; ++i)
5095         {
5096             CORCOMPILE_DEPENDENCY* pDependency = &(pDependencies[i]);
5097             if (pDependency->dwAssemblyRef == kAssemblyRef)
5098             {
5099                 foundAssemblyDef = pDependency->dwAssemblyDef;
5100                 break;
5101             }
5102         }
5103
5104         // In this case we know there is no assembly redirection involved. Skip any additional work.
5105         if (kAssemblyRef == foundAssemblyDef)
5106         {
5107             *pfDiscoveredAssemblyRefMatchesTargetDefExactly = true;
5108             RETURN NULL;
5109         }
5110
5111         if (foundAssemblyDef != mdAssemblyRefNil)
5112         {
5113             // Find out if THIS reference is satisfied
5114             // Specify fDoNotUtilizeExtraChecks to prevent recursion
5115             Assembly *pAssemblyCandidate = this->GetAssemblyIfLoaded(foundAssemblyDef, NULL, NULL, pImportFoundNativeImage, TRUE /*fDoNotUtilizeExtraChecks*/); 
5116
5117             // This extended check is designed only to find assemblies loaded via an AssemblySpecBindingCache based binder. Verify that's what we found.
5118             if(pAssemblyCandidate != NULL)
5119             {
5120                 if (!pAssemblyCandidate->GetManifestFile()->HasHostAssembly())
5121                 {
5122                     pAssembly = pAssemblyCandidate;
5123                 }
5124                 else
5125                 {
5126                     DWORD binderFlags = 0;
5127                     ICLRPrivAssembly * pPrivBinder = pAssemblyCandidate->GetManifestFile()->GetHostAssembly();
5128                     HRESULT hrBinderFlagCheck = pPrivBinder->GetBinderFlags(&binderFlags);
5129                     if (SUCCEEDED(hrBinderFlagCheck) && (binderFlags & BINDER_FINDASSEMBLYBYSPEC_REQUIRES_EXACT_MATCH))
5130                     {
5131                         pAssembly = pAssemblyCandidate;
5132                     }
5133                     else
5134                     {
5135                         // This should only happen in the generic instantiation case when multiple threads are racing and
5136                         // the assembly found is one which we will determine is the wrong assembly.
5137                         //
5138                         // We can't assert that (as its possible under stress); however it shouldn't happen in the stack walk or GC case, so we assert in those cases.
5139                         _ASSERTE("Non-AssemblySpecBindingCache based assembly found with extended search" && !(IsStackWalkerThread() || IsGCThread()) && IsGenericInstantiationLookupCompareThread());
5140                     }
5141                 }
5142             }
5143         }
5144     }
5145
5146     RETURN pAssembly;
5147 }
5148 #endif // !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5149
5150 // Fills ppContainingWinRtAppDomain only if WinRT type name is passed and if the assembly is found (return value != NULL).
5151 Assembly * 
5152 Module::GetAssemblyIfLoaded(
5153     mdAssemblyRef       kAssemblyRef, 
5154     LPCSTR              szWinRtNamespace,   // = NULL
5155     LPCSTR              szWinRtClassName,   // = NULL
5156     IMDInternalImport * pMDImportOverride,  // = NULL
5157     BOOL                fDoNotUtilizeExtraChecks, // = FALSE
5158     ICLRPrivBinder      *pBindingContextForLoadedAssembly // = NULL
5159 )    
5160 {
5161     CONTRACT(Assembly *)
5162     {
5163         INSTANCE_CHECK;
5164         NOTHROW;
5165         GC_NOTRIGGER;
5166         FORBID_FAULT;
5167         MODE_ANY;
5168         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
5169         SUPPORTS_DAC;
5170     }
5171     CONTRACT_END;
5172
5173     Assembly * pAssembly = NULL;
5174     BOOL fCanUseRidMap = ((pMDImportOverride == NULL) &&
5175                           (szWinRtNamespace == NULL));
5176
5177 #ifdef _DEBUG
5178     fCanUseRidMap = fCanUseRidMap && (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GetAssemblyIfLoadedIgnoreRidMap) == 0);
5179 #endif
5180
5181     // If we're here due to a generic instantiation, then we should only be querying information from the ngen image we're finding the generic instantiation in.
5182 #if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5183     _ASSERTE(!IsGenericInstantiationLookupCompareThread() || HasNativeImage());
5184 #endif
5185
5186     // Don't do a lookup if an override IMDInternalImport is provided, since the lookup is for the
5187     // standard IMDInternalImport and might result in an incorrect result.
5188     // WinRT references also do not update RID map, so don't try to look it up
5189     if (fCanUseRidMap)
5190     {
5191         pAssembly = LookupAssemblyRef(kAssemblyRef);
5192     }
5193     
5194 #ifndef DACCESS_COMPILE
5195     // Check if actually loaded, unless a GC is in progress or the current thread is
5196     // walking the stack (either its own stack, or another thread's stack) as that works
5197     // only with loaded assemblies
5198     //
5199     // NOTE: The case where the current thread is walking a stack can be problematic for
5200     // other reasons, as the remaining code of this function uses "GetAppDomain()", when
5201     // in fact the right AppDomain to use is the one corresponding to the frame being
5202     // traversed on the walked thread. Dev10 TFS bug# 762348 tracks that issue.
5203     if ((pAssembly != NULL) && !IsGCThread() && !IsStackWalkerThread())
5204     {
5205         _ASSERTE(::GetAppDomain() != NULL);
5206         DomainAssembly * pDomainAssembly = pAssembly->FindDomainAssembly(::GetAppDomain());
5207         if ((pDomainAssembly == NULL) || !pDomainAssembly->IsLoaded())
5208             pAssembly = NULL;
5209     }   
5210 #endif //!DACCESS_COMPILE
5211     
5212     if (pAssembly == NULL)
5213     {
5214         // If in stackwalking or gc mode
5215         // For each AppDomain that is on the stack being walked...
5216         // For each AppDomain in the process... if gc'ing
5217         // For the current AppDomain ... if none of the above
5218         GetAssemblyIfLoadedAppDomainIterator appDomainIter;
5219
5220         while (appDomainIter.Next())
5221         {
5222             AppDomain * pAppDomainExamine = appDomainIter.GetDomain();
5223             
5224             DomainAssembly * pCurAssemblyInExamineDomain = GetAssembly()->FindDomainAssembly(pAppDomainExamine);
5225             if (pCurAssemblyInExamineDomain == NULL)
5226             {
5227                 continue;
5228             }
5229
5230 #ifdef FEATURE_COMINTEROP
5231             if (szWinRtNamespace != NULL)
5232             {
5233                 _ASSERTE(szWinRtClassName != NULL);
5234                 
5235                 CLRPrivBinderWinRT * pWinRtBinder = pAppDomainExamine->GetWinRtBinder();
5236                 if (pWinRtBinder == nullptr)
5237                 {   // We are most likely in AppX mode (calling AppX::IsAppXProcess() for verification is painful in DACCESS)
5238 #ifndef DACCESS_COMPILE
5239                     // Note: We should also look
5240                     // Check designer binding context present (only in AppXDesignMode)
5241                     ICLRPrivBinder * pCurrentBinder = pAppDomainExamine->GetLoadContextHostBinder();
5242                     if (pCurrentBinder != nullptr)
5243                     {   // We have designer binding context, look for the type in it
5244                         ReleaseHolder<ICLRPrivWinRtTypeBinder> pCurrentWinRtTypeBinder;
5245                         HRESULT hr = pCurrentBinder->QueryInterface(__uuidof(ICLRPrivWinRtTypeBinder), (void **)&pCurrentWinRtTypeBinder);
5246                         
5247                         // The binder should be an instance of code:CLRPrivBinderAppX class that implements the interface
5248                         _ASSERTE(SUCCEEDED(hr) && (pCurrentWinRtTypeBinder != nullptr));
5249                         
5250                         if (SUCCEEDED(hr))
5251                         {
5252                             ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
5253                             pAssembly = (Assembly *)pCurrentWinRtTypeBinder->FindAssemblyForWinRtTypeIfLoaded(
5254                                 (void *)pAppDomainExamine, 
5255                                 szWinRtNamespace, 
5256                                 szWinRtClassName);
5257                         }
5258                     }
5259 #endif //!DACCESS_COMPILE
5260                     if (pAssembly == nullptr)
5261                     {   
5262                     }
5263                 }
5264                 
5265                 if (pWinRtBinder != nullptr)
5266                 {
5267                     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
5268                     pAssembly = pWinRtBinder->FindAssemblyForTypeIfLoaded(
5269                         dac_cast<PTR_AppDomain>(pAppDomainExamine), 
5270                         szWinRtNamespace, 
5271                         szWinRtClassName);
5272                 }
5273                 
5274                 // Never store WinMD AssemblyRefs into the rid map.
5275                 if (pAssembly != NULL)
5276                 {
5277                     break;
5278                 }
5279                 
5280                 // Never attemt to search the assembly spec binding cache for this form of WinRT assembly reference.
5281                 continue;
5282             }
5283 #endif // FEATURE_COMINTEROP
5284
5285 #ifndef DACCESS_COMPILE
5286             {
5287                 IMDInternalImport * pMDImport = (pMDImportOverride == NULL) ? (GetMDImport()) : (pMDImportOverride);
5288                 
5289                 //we have to be very careful here.
5290                 //we are using InitializeSpecInternal so we need to make sure that under no condition 
5291                 //the data we pass to it can outlive the assembly spec.
5292                 AssemblySpec spec;
5293                 if (FAILED(spec.InitializeSpecInternal(kAssemblyRef, 
5294                                                        pMDImport, 
5295                                                        pCurAssemblyInExamineDomain,
5296                                                        FALSE /*fAllowAllocation*/)))
5297                 {
5298                     continue;
5299                 }
5300
5301                 // If we have been passed the binding context for the loaded assembly that is being looked up in the 
5302                 // cache, then set it up in the AssemblySpec for the cache lookup to use it below.
5303                 if (pBindingContextForLoadedAssembly != NULL)
5304                 {
5305                     _ASSERTE(spec.GetBindingContext() == NULL);
5306                     spec.SetBindingContext(pBindingContextForLoadedAssembly);
5307                 }
5308                 DomainAssembly * pDomainAssembly = nullptr;
5309
5310                 {
5311                     pDomainAssembly = pAppDomainExamine->FindCachedAssembly(&spec, FALSE /*fThrow*/);
5312                 }
5313
5314                 if (pDomainAssembly && pDomainAssembly->IsLoaded())
5315                     pAssembly = pDomainAssembly->GetCurrentAssembly(); // <NOTE> Do not use GetAssembly - that may force the completion of a load
5316
5317                 // Only store in the rid map if working with the current AppDomain.
5318                 if (fCanUseRidMap && pAssembly && appDomainIter.UsingCurrentAD())
5319                     StoreAssemblyRef(kAssemblyRef, pAssembly);
5320
5321                 if (pAssembly != NULL)
5322                     break;
5323             }
5324 #endif //!DACCESS_COMPILE
5325         }
5326     }
5327
5328 #if !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5329     if (pAssembly == NULL && (IsStackWalkerThread() || IsGCThread() || IsGenericInstantiationLookupCompareThread()) && !fDoNotUtilizeExtraChecks)
5330     {
5331         // The GetAssemblyIfLoaded function must succeed in finding assemblies which have already been loaded in a series of interesting cases
5332         // (GC, Stackwalking, GenericInstantiationLookup). This logic is used to handle cases where the normal lookup done above
5333         // may fail, and more extensive (and slow) lookups are necessary. This logic is gated by a long series of checks to ensure it doesn't
5334         // run in cases which are not known to be problematic, or would not benefit from the logic here.
5335         //
5336         // This is logic which tries extra possibilities to find an assembly. It is believed this logic can only be hit in cases where an ngen
5337         // image depends on an assembly through some sort of binding version/public key token adjustment (due to binding policy, unification, or portability rules)
5338         // and the assembly depended on was loaded through a binder that utilizes the AssemblySpecBindingCache for binder caching. (The cache's in the other
5339         // binder's successfully answer the GetAssemblyIfLoaded question in the case of non-exact matches where the match was discovered during
5340         // ngen resolution.)
5341         // This restricts the scenario to a somewhat restricted case.
5342
5343         BOOL eligibleForAdditionalChecks = TRUE;
5344         if (szWinRtNamespace != NULL)
5345             eligibleForAdditionalChecks = FALSE; // WinRT binds do not support this scan
5346         else if (this->GetAssembly()->GetManifestFile()->IsDesignerBindingContext())
5347         {
5348             eligibleForAdditionalChecks = FALSE; 
5349             // assemblies loaded into leaf designer binding contexts cannot be ngen images, or be depended on by ngen assemblies that bind to different versions of assemblies.
5350             // However, in the shared designer binding context assemblies can be loaded with ngen images, and therefore can depend on assemblies in a designer binding context. (the shared context)
5351             // A more correct version of this check would probably allow assemblies loaded into the shared designer binding context to be eligibleForAdditionalChecks; however
5352             // there are problems. In particular, the logic below which scans through all native images is not strictly correct for scenarios involving a shared assembly context
5353             // as the shared assembly context may have different binding rules as compared to the root context. At this time, we prefer to not fix this scenario until
5354             // there is customer need for a fix.
5355         }
5356
5357         AssemblySpec specSearchAssemblyRef;
5358
5359         // Get the assembly ref information that we are attempting to satisfy.
5360         if (eligibleForAdditionalChecks)
5361         {
5362             IMDInternalImport * pMDImport = (pMDImportOverride == NULL) ? (GetMDImport()) : (pMDImportOverride);
5363
5364             if (FAILED(specSearchAssemblyRef.InitializeSpecInternal(kAssemblyRef, 
5365                                                     pMDImport, 
5366                                                     NULL,
5367                                                     FALSE /*fAllowAllocation*/)))
5368             {
5369                 eligibleForAdditionalChecks = FALSE; // If an assemblySpec can't be constructed then we're not going to succeed
5370                                                      // This should not ever happen, due to the above checks, but this logic 
5371                                                      // is intended to be defensive against unexpected behavior.
5372             }
5373             else if (specSearchAssemblyRef.IsContentType_WindowsRuntime())
5374             {
5375                 eligibleForAdditionalChecks = FALSE; // WinRT binds do not support this scan
5376             }
5377         }
5378
5379         if (eligibleForAdditionalChecks)
5380         {
5381             BOOL abortAdditionalChecks = false;
5382
5383             // When working with an ngenn'd assembly, as an optimization we can scan only that module for dependency info.
5384             bool onlyScanCurrentModule = HasNativeImage() && GetFile()->IsAssembly();
5385             mdAssemblyRef foundAssemblyRef = mdAssemblyRefNil;
5386
5387             GetAssemblyIfLoadedAppDomainIterator appDomainIter;
5388
5389             // In each AppDomain that might be interesting, scan for an ngen image that is loaded that has a dependency on the same 
5390             // assembly that is now being looked up. If that ngen image has the same dependency, then we can use the CORCOMPILE_DEPENDENCIES
5391             // table to find the exact AssemblyDef that defines the assembly, and attempt a load based on that information.
5392             // As this logic is expected to be used only in exceedingly rare situations, this code has not been tuned for performance
5393             // in any way.
5394             while (!abortAdditionalChecks && appDomainIter.Next())
5395             {
5396                 AppDomain * pAppDomainExamine = appDomainIter.GetDomain();
5397             
5398                 DomainAssembly * pCurAssemblyInExamineDomain = GetAssembly()->FindDomainAssembly(pAppDomainExamine);
5399                 if (pCurAssemblyInExamineDomain == NULL)
5400                 {
5401                     continue;
5402                 }
5403
5404                 DomainFile *pDomainFileNativeImage;
5405                 
5406                 if (onlyScanCurrentModule)
5407                 {
5408                     pDomainFileNativeImage = pCurAssemblyInExamineDomain;
5409                     // Do not reset foundAssemblyRef.
5410                     // This will allow us to avoid scanning for foundAssemblyRef in each domain we iterate through
5411                 }
5412                 else
5413                 {
5414                     foundAssemblyRef = mdAssemblyRefNil;
5415                     pDomainFileNativeImage = pAppDomainExamine->GetDomainFilesWithNativeImagesList();
5416                 }
5417
5418                 while (!abortAdditionalChecks && (pDomainFileNativeImage != NULL) && (pAssembly == NULL))
5419                 {
5420                     Module *pNativeImageModule = pDomainFileNativeImage->GetCurrentModule();
5421                     _ASSERTE(pNativeImageModule->HasNativeImage());
5422                     IMDInternalImport *pImportFoundNativeImage = pNativeImageModule->GetNativeAssemblyImport(FALSE);
5423                     if (pImportFoundNativeImage != NULL)
5424                     {
5425                         if (IsNilToken(foundAssemblyRef))
5426                         {
5427                             // Enumerate assembly refs in nmd space, and compare against held ref.
5428                             HENUMInternalHolder hAssemblyRefEnum(pImportFoundNativeImage);
5429                             if (FAILED(hAssemblyRefEnum.EnumInitNoThrow(mdtAssemblyRef, mdAssemblyRefNil)))
5430                             {
5431                                 continue;
5432                             }
5433
5434                             mdAssemblyRef assemblyRef = mdAssemblyRefNil;
5435
5436                             // Find if the native image has a matching assembly ref in its compile dependencies.
5437                             while (pImportFoundNativeImage->EnumNext(&hAssemblyRefEnum, &assemblyRef) && (pAssembly == NULL))
5438                             {
5439                                 AssemblySpec specFoundAssemblyRef;
5440                                 if (FAILED(specFoundAssemblyRef.InitializeSpecInternal(assemblyRef, 
5441                                                                         pImportFoundNativeImage, 
5442                                                                         NULL,
5443                                                                         FALSE /*fAllowAllocation*/)))
5444                                 {
5445                                     continue; // If the spec cannot be loaded, it isn't the one we're looking for
5446                                 }
5447
5448                                 // Check for AssemblyRef equality
5449                                 if (specSearchAssemblyRef.CompareEx(&specFoundAssemblyRef))
5450                                 {
5451                                     foundAssemblyRef = assemblyRef;
5452                                     break;
5453                                 }
5454                             }
5455                         }
5456
5457                         pAssembly = pNativeImageModule->GetAssemblyIfLoadedFromNativeAssemblyRefWithRefDefMismatch(foundAssemblyRef, &abortAdditionalChecks);
5458
5459                         if (fCanUseRidMap && pAssembly && appDomainIter.UsingCurrentAD())
5460                             StoreAssemblyRef(kAssemblyRef, pAssembly);
5461                     }
5462
5463                     // If we're only scanning one module for accurate dependency information, break the loop here.
5464                     if (onlyScanCurrentModule)
5465                         break;
5466
5467                     pDomainFileNativeImage = pDomainFileNativeImage->FindNextDomainFileWithNativeImage();
5468                 }
5469             }
5470         }
5471     }
5472 #endif // !defined(DACCESS_COMPILE) && defined(FEATURE_PREJIT)
5473
5474     // When walking the stack or computing GC information this function should never fail.
5475     _ASSERTE((pAssembly != NULL) || !(IsStackWalkerThread() || IsGCThread()));
5476
5477 #ifdef DACCESS_COMPILE
5478     
5479     // Note: In rare cases when debugger walks the stack, we could actually have pAssembly=NULL here.
5480     // To fix that we should DACize the AppDomain-iteration code above (especially AssemblySpec).
5481     _ASSERTE(pAssembly != NULL);
5482     
5483 #endif //DACCESS_COMPILE
5484     
5485     RETURN pAssembly;
5486 } // Module::GetAssemblyIfLoaded
5487
5488 DWORD 
5489 Module::GetAssemblyRefFlags(
5490     mdAssemblyRef tkAssemblyRef)
5491 {
5492     CONTRACTL
5493     {
5494         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
5495         GC_NOTRIGGER;
5496         MODE_ANY;
5497     }
5498     CONTRACTL_END;
5499     
5500     _ASSERTE(TypeFromToken(tkAssemblyRef) == mdtAssemblyRef);
5501     
5502     LPCSTR      pszAssemblyName;
5503     const void *pbPublicKeyOrToken;
5504     DWORD cbPublicKeyOrToken;
5505
5506     DWORD dwAssemblyRefFlags;
5507     IfFailThrow(GetMDImport()->GetAssemblyRefProps(
5508             tkAssemblyRef, 
5509             &pbPublicKeyOrToken, 
5510             &cbPublicKeyOrToken, 
5511             &pszAssemblyName, 
5512             NULL, 
5513             NULL, 
5514             NULL, 
5515             &dwAssemblyRefFlags));
5516     
5517     return dwAssemblyRefFlags;
5518 } // Module::GetAssemblyRefFlags
5519
5520 #ifndef DACCESS_COMPILE 
5521
5522 // Arguments:
5523 //   szWinRtTypeNamespace ... Namespace of WinRT type.
5524 //   szWinRtTypeClassName ... Name of WinRT type, NULL for non-WinRT (classic) types.
5525 DomainAssembly * Module::LoadAssembly(
5526     AppDomain *   pDomain, 
5527     mdAssemblyRef kAssemblyRef, 
5528     LPCUTF8       szWinRtTypeNamespace, 
5529     LPCUTF8       szWinRtTypeClassName)
5530 {
5531     CONTRACT(DomainAssembly *)
5532     {
5533         INSTANCE_CHECK;
5534         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
5535         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
5536         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM();); }
5537         MODE_ANY;
5538         PRECONDITION(CheckPointer(pDomain));
5539         POSTCONDITION(CheckPointer(RETVAL, NULL_NOT_OK));
5540         //POSTCONDITION((CheckPointer(GetAssemblyIfLoaded(kAssemblyRef, szWinRtTypeNamespace, szWinRtTypeClassName)), NULL_NOT_OK));
5541     }
5542     CONTRACT_END;
5543
5544     ETWOnStartup (LoaderCatchCall_V1, LoaderCatchCallEnd_V1);
5545
5546     DomainAssembly * pDomainAssembly;
5547
5548     //
5549     // Early out quickly if the result is cached
5550     //
5551     Assembly * pAssembly = LookupAssemblyRef(kAssemblyRef);
5552     if (pAssembly != NULL)
5553     {
5554         _ASSERTE(HasBindableIdentity(kAssemblyRef));
5555
5556         pDomainAssembly = pAssembly->FindDomainAssembly(pDomain);
5557
5558         if (pDomainAssembly == NULL)
5559             pDomainAssembly = pAssembly->GetDomainAssembly(pDomain);
5560         pDomain->LoadDomainFile(pDomainAssembly, FILE_LOADED);
5561
5562         RETURN pDomainAssembly;
5563     }
5564
5565     bool fHasBindableIdentity = HasBindableIdentity(kAssemblyRef);
5566     
5567     {
5568         PEAssemblyHolder pFile = GetDomainFile(GetAppDomain())->GetFile()->LoadAssembly(
5569                 kAssemblyRef, 
5570                 NULL, 
5571                 szWinRtTypeNamespace, 
5572                 szWinRtTypeClassName);
5573         AssemblySpec spec;
5574         spec.InitializeSpec(kAssemblyRef, GetMDImport(), GetDomainFile(GetAppDomain())->GetDomainAssembly());
5575         // Set the binding context in the AssemblySpec if one is available. This can happen if the LoadAssembly ended up
5576         // invoking the custom AssemblyLoadContext implementation that returned a reference to an assembly bound to a different
5577         // AssemblyLoadContext implementation.
5578         ICLRPrivBinder *pBindingContext = pFile->GetBindingContext();
5579         if (pBindingContext != NULL)
5580         {
5581             spec.SetBindingContext(pBindingContext);
5582         }
5583         if (szWinRtTypeClassName != NULL)
5584         {
5585             spec.SetWindowsRuntimeType(szWinRtTypeNamespace, szWinRtTypeClassName);
5586         }
5587         pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pFile, FILE_LOADED);
5588     }
5589
5590     if (pDomainAssembly != NULL)
5591     {
5592         _ASSERTE(
5593             !fHasBindableIdentity ||                        // GetAssemblyIfLoaded will not find non-bindable assemblies
5594             pDomainAssembly->IsSystem() ||                  // GetAssemblyIfLoaded will not find mscorlib (see AppDomain::FindCachedFile)
5595             !pDomainAssembly->IsLoaded() ||                 // GetAssemblyIfLoaded will not find not-yet-loaded assemblies
5596             GetAssemblyIfLoaded(kAssemblyRef, NULL, NULL, NULL, FALSE, pDomainAssembly->GetFile()->GetHostAssembly()) != NULL);     // GetAssemblyIfLoaded should find all remaining cases
5597
5598         // Note: We cannot cache WinRT AssemblyRef, because it is meaningless without the TypeRef context
5599         if (pDomainAssembly->GetCurrentAssembly() != NULL)
5600         {
5601             if (fHasBindableIdentity)
5602             {
5603                 StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetCurrentAssembly());
5604             }
5605         }
5606     }
5607
5608     RETURN pDomainAssembly;
5609 }
5610
5611 #endif // !DACCESS_COMPILE
5612
5613 Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL permitResources)
5614 {
5615     CONTRACT(Module *)
5616     {
5617         INSTANCE_CHECK;
5618         NOTHROW;
5619         GC_NOTRIGGER;
5620         MODE_ANY;
5621         PRECONDITION(TypeFromToken(kFile) == mdtFile
5622                      || TypeFromToken(kFile) == mdtModuleRef);
5623         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
5624         FORBID_FAULT;
5625         SUPPORTS_DAC;
5626     }
5627     CONTRACT_END;
5628
5629     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
5630
5631     // Handle the module ref case
5632     if (TypeFromToken(kFile) == mdtModuleRef)
5633     {
5634         LPCSTR moduleName;
5635         if (FAILED(GetMDImport()->GetModuleRefProps(kFile, &moduleName)))
5636         {
5637             RETURN NULL;
5638         }
5639         
5640         // This is required only because of some lower casing on the name
5641         kFile = GetAssembly()->GetManifestFileToken(moduleName);
5642         if (kFile == mdTokenNil)
5643             RETURN NULL;
5644         
5645         RETURN GetAssembly()->GetManifestModule()->GetModuleIfLoaded(kFile, onlyLoadedInAppDomain, permitResources);
5646     }
5647     
5648     Module *pModule = LookupFile(kFile);
5649     if (pModule == NULL)
5650     {
5651         if (IsManifest())
5652         {
5653             if (kFile == mdFileNil)
5654                 pModule = GetAssembly()->GetManifestModule();
5655         }
5656         else
5657         {
5658             // If we didn't find it there, look at the "master rid map" in the manifest file
5659             Assembly *pAssembly = GetAssembly();
5660             mdFile kMatch;
5661             
5662             // This is required only because of some lower casing on the name
5663             kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile);
5664             if (IsNilToken(kMatch))
5665             {
5666                 if (kMatch == mdFileNil)
5667                 {
5668                     pModule = pAssembly->GetManifestModule();
5669                 }
5670                 else
5671                 {
5672                     RETURN NULL;
5673                 }
5674             }
5675             else
5676             pModule = pAssembly->GetManifestModule()->LookupFile(kMatch);
5677         }
5678         
5679 #ifndef DACCESS_COMPILE
5680         if (pModule != NULL)
5681             StoreFileNoThrow(kFile, pModule);
5682 #endif
5683     }
5684     
5685     // We may not want to return a resource module
5686     if (!permitResources && pModule && pModule->IsResource())
5687         pModule = NULL;
5688
5689 #ifndef DACCESS_COMPILE
5690 #endif // !DACCESS_COMPILE
5691     RETURN pModule;
5692 }
5693
5694 #ifndef DACCESS_COMPILE
5695
5696 DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile,
5697                                BOOL permitResources/*=TRUE*/, BOOL bindOnly/*=FALSE*/)
5698 {
5699     CONTRACT(DomainFile *)
5700     {
5701         INSTANCE_CHECK;
5702         THROWS;
5703         GC_TRIGGERS;
5704         MODE_ANY;
5705         PRECONDITION(TypeFromToken(kFile) == mdtFile
5706                      || TypeFromToken(kFile) == mdtModuleRef);
5707         POSTCONDITION(CheckPointer(RETVAL, !permitResources || bindOnly ? NULL_OK : NULL_NOT_OK));
5708     }
5709     CONTRACT_END;
5710
5711     if (bindOnly)
5712     {
5713         RETURN  NULL;
5714     }
5715     else
5716     {
5717         LPCSTR psModuleName=NULL;
5718         if (TypeFromToken(kFile) == mdtModuleRef)
5719         {
5720             // This is a moduleRef
5721             IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &psModuleName));
5722         }
5723         else
5724         {
5725            // This is mdtFile
5726            IfFailThrow(GetAssembly()->GetManifestImport()->GetFileProps(kFile,
5727                                       &psModuleName,
5728                                       NULL,
5729                                       NULL,
5730                                       NULL));
5731         }
5732         SString name(SString::Utf8, psModuleName);
5733         EEFileLoadException::Throw(name, COR_E_MULTIMODULEASSEMBLIESDIALLOWED, NULL);
5734     }
5735 }
5736 #endif // !DACCESS_COMPILE
5737
5738 PTR_Module Module::LookupModule(mdToken kFile,BOOL permitResources/*=TRUE*/)
5739 {
5740     CONTRACT(PTR_Module)
5741     {
5742         INSTANCE_CHECK;
5743         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
5744         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
5745         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; 
5746         else { INJECT_FAULT(COMPlusThrowOM()); }
5747         MODE_ANY;
5748         PRECONDITION(TypeFromToken(kFile) == mdtFile
5749                      || TypeFromToken(kFile) == mdtModuleRef);
5750         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
5751         SUPPORTS_DAC;
5752     }
5753     CONTRACT_END;
5754     
5755     if (TypeFromToken(kFile) == mdtModuleRef)
5756     {
5757         LPCSTR moduleName;
5758         IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &moduleName));
5759         mdFile kFileLocal = GetAssembly()->GetManifestFileToken(moduleName);
5760
5761         if (kFileLocal == mdTokenNil)
5762             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
5763
5764         RETURN GetAssembly()->GetManifestModule()->LookupModule(kFileLocal, permitResources);
5765     }
5766
5767     PTR_Module pModule = LookupFile(kFile);
5768     if (pModule == NULL && !IsManifest())
5769     {
5770         // If we didn't find it there, look at the "master rid map" in the manifest file
5771         Assembly *pAssembly = GetAssembly();
5772         mdFile kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile);
5773         if (IsNilToken(kMatch)) {
5774             if (kMatch == mdFileNil)
5775                 pModule = pAssembly->GetManifestModule();
5776             else
5777             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
5778         }
5779         else
5780             pModule = pAssembly->GetManifestModule()->LookupFile(kMatch);
5781     }
5782     RETURN pModule;
5783 }
5784
5785
5786 TypeHandle Module::LookupTypeRef(mdTypeRef token)
5787 {
5788     STATIC_CONTRACT_NOTHROW;
5789     STATIC_CONTRACT_GC_NOTRIGGER;
5790     STATIC_CONTRACT_FORBID_FAULT;
5791     SUPPORTS_DAC;
5792
5793     _ASSERTE(TypeFromToken(token) == mdtTypeRef);
5794
5795     g_IBCLogger.LogRidMapAccess( MakePair( this, token ) );
5796
5797     TypeHandle entry = TypeHandle::FromTAddr(dac_cast<TADDR>(m_TypeRefToMethodTableMap.GetElement(RidFromToken(token))));
5798
5799     if (entry.IsNull())
5800         return TypeHandle();
5801
5802     // Cannot do this in a NOTHROW function.
5803     // Note that this could be called while doing GC from the prestub of
5804     // a method to resolve typerefs in a signature. We cannot THROW
5805     // during GC.
5806
5807     // @PERF: Enable this so that we do not need to touch metadata
5808     // to resolve typerefs
5809
5810 #ifdef FIXUPS_ALL_TYPEREFS 
5811
5812     if (CORCOMPILE_IS_POINTER_TAGGED((SIZE_T) entry.AsPtr()))
5813     {
5814 #ifndef DACCESS_COMPILE 
5815         Module::RestoreTypeHandlePointer(&entry, TRUE);
5816         m_TypeRefToMethodTableMap.SetElement(RidFromToken(token), dac_cast<PTR_TypeRef>(value.AsTAddr()));
5817 #else // DACCESS_COMPILE
5818         DacNotImpl();
5819 #endif // DACCESS_COMPILE
5820     }
5821
5822 #endif // FIXUPS_ALL_TYPEREFS
5823
5824     return entry;
5825 }
5826
5827 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
5828 mdTypeRef Module::LookupTypeRefByMethodTable(MethodTable *pMT)
5829 {
5830     STANDARD_VM_CONTRACT;
5831
5832     HENUMInternalHolder hEnumTypeRefs(GetMDImport());
5833     mdTypeRef token;
5834     hEnumTypeRefs.EnumAllInit(mdtTypeRef);
5835     while (hEnumTypeRefs.EnumNext(&token))
5836     {
5837         TypeHandle thRef = LookupTypeRef(token);
5838         if (thRef.IsNull() || thRef.IsTypeDesc())
5839         {
5840             continue;
5841         }
5842
5843         MethodTable *pMTRef = thRef.AsMethodTable();
5844         if (pMT->HasSameTypeDefAs(pMTRef))
5845         {
5846             _ASSERTE(pMTRef->IsTypicalTypeDefinition());
5847             return token;
5848         }
5849     }
5850
5851 #ifdef FEATURE_READYTORUN_COMPILER
5852     if (IsReadyToRunCompilation())
5853     {
5854         if (pMT->GetClass()->IsEquivalentType())
5855         {
5856             GetSvcLogger()->Log(W("ReadyToRun: Type reference to equivalent type cannot be encoded\n"));
5857             ThrowHR(E_NOTIMPL);
5858         }
5859
5860         // FUTURE: Encoding of new cross-module references for ReadyToRun
5861         // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
5862         // GetSvcLogger()->Log(W("ReadyToRun: Type reference outside of current version bubble cannot be encoded\n"));
5863     }
5864     else
5865 #endif // FEATURE_READYTORUN_COMPILER
5866     {
5867         // FUTURE TODO: Version resilience
5868         _ASSERTE(!"Cross module type reference not found");
5869     }
5870     ThrowHR(E_FAIL);
5871 }
5872
5873 mdMemberRef Module::LookupMemberRefByMethodDesc(MethodDesc *pMD)
5874 {
5875     STANDARD_VM_CONTRACT;
5876
5877     HENUMInternalHolder hEnumMemberRefs(GetMDImport());
5878     mdMemberRef token;
5879     hEnumMemberRefs.EnumAllInit(mdtMemberRef);
5880     while (hEnumMemberRefs.EnumNext(&token))
5881     {
5882         BOOL fIsMethod = FALSE;
5883         TADDR addr = LookupMemberRef(token, &fIsMethod);
5884         if (fIsMethod)
5885         {
5886             MethodDesc *pCurMD = dac_cast<PTR_MethodDesc>(addr);
5887             if (pCurMD == pMD)
5888             {
5889                 return token;
5890             }
5891         }
5892     }
5893
5894     // FUTURE TODO: Version resilience
5895     _ASSERTE(!"Cross module method reference not found");
5896     ThrowHR(E_FAIL);
5897 }
5898 #endif // FEATURE_NATIVE_IMAGE_GENERATION
5899
5900 #ifndef DACCESS_COMPILE 
5901
5902 //
5903 // Increase the size of one of the maps, such that it can handle a RID of at least "rid".
5904 //
5905 // This function must also check that another thread didn't already add a LookupMap capable
5906 // of containing the same RID.
5907 //
5908 PTR_TADDR LookupMapBase::GrowMap(Module * pModule, DWORD rid)
5909 {
5910     CONTRACT(PTR_TADDR)
5911     {
5912         INSTANCE_CHECK;
5913         THROWS;
5914         GC_NOTRIGGER;
5915         MODE_ANY;
5916         INJECT_FAULT(ThrowOutOfMemory(););
5917         POSTCONDITION(CheckPointer(RETVAL));
5918     }
5919     CONTRACT_END;
5920
5921     LookupMapBase *pMap = this;
5922     LookupMapBase *pPrev = NULL;
5923     LookupMapBase *pNewMap = NULL;
5924
5925     // Initial block size
5926     DWORD dwIndex = rid;
5927     DWORD dwBlockSize = 16;
5928
5929     {
5930         CrstHolder ch(pModule->GetLookupTableCrst());
5931         // Check whether we can already handle this RID index
5932         do
5933         {
5934             if (dwIndex < pMap->dwCount)
5935             {
5936                 // Already there - some other thread must have added it
5937                 RETURN pMap->GetIndexPtr(dwIndex);
5938             }
5939
5940             dwBlockSize *= 2;
5941
5942             dwIndex -= pMap->dwCount;
5943
5944             pPrev = pMap;
5945             pMap = pMap->pNext;
5946         } while (pMap != NULL);
5947
5948         _ASSERTE(pPrev != NULL); // should never happen, because there's always at least one map
5949
5950         DWORD dwSizeToAllocate = max(dwIndex + 1, dwBlockSize);
5951
5952         pNewMap = (LookupMapBase *) (void*)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(LookupMapBase)) + S_SIZE_T(dwSizeToAllocate)*S_SIZE_T(sizeof(TADDR)));
5953
5954         // Note: Memory allocated on loader heap is zero filled
5955         // memset(pNewMap, 0, sizeof(LookupMap) + dwSizeToAllocate*sizeof(void*));
5956
5957         pNewMap->pNext          = NULL;
5958         pNewMap->dwCount        = dwSizeToAllocate;
5959
5960         pNewMap->pTable         = dac_cast<ArrayDPTR(TADDR)>(pNewMap + 1);
5961
5962         // Link ourselves in
5963         VolatileStore<LookupMapBase*>(&(pPrev->pNext), pNewMap);
5964     }
5965
5966     RETURN pNewMap->GetIndexPtr(dwIndex);
5967 }
5968
5969 #endif // DACCESS_COMPILE
5970
5971 PTR_TADDR LookupMapBase::GetElementPtr(DWORD rid)
5972 {
5973     CONTRACTL
5974     {
5975         INSTANCE_CHECK;
5976         NOTHROW;
5977         GC_NOTRIGGER;
5978         MODE_ANY;
5979         SO_TOLERANT;
5980         SUPPORTS_DAC;
5981     }
5982     CONTRACTL_END;
5983
5984     LookupMapBase * pMap = this;
5985
5986 #ifdef FEATURE_PREJIT 
5987     if (pMap->dwNumHotItems > 0)
5988     {
5989 #ifdef _DEBUG_IMPL 
5990         static  DWORD counter = 0;
5991         counter++;
5992         if (counter >= pMap->dwNumHotItems)
5993         {
5994             CheckConsistentHotItemList();
5995             counter = 0;
5996         }
5997 #endif // _DEBUG_IMPL
5998
5999         PTR_TADDR pHotItemValue = pMap->FindHotItemValuePtr(rid);
6000         if (pHotItemValue)
6001         {
6002             return pHotItemValue;
6003         }
6004     }
6005 #endif // FEATURE_PREJIT
6006
6007     DWORD dwIndex = rid;
6008     do
6009     {
6010         if (dwIndex < pMap->dwCount)
6011         {
6012             return pMap->GetIndexPtr(dwIndex);
6013         }
6014
6015         dwIndex -= pMap->dwCount;
6016         pMap = pMap->pNext;
6017     } while (pMap != NULL);
6018
6019     return NULL;
6020 }
6021
6022
6023 #ifdef FEATURE_PREJIT 
6024
6025 // This method can only be called on a compressed map (MapIsCompressed() == true). Compressed rid maps store
6026 // the array of values as packed deltas (each value is based on the accumulated of all the previous entries).
6027 // So this method takes the bit stream of compressed data we're navigating and the value of the last entry
6028 // retrieved allowing us to calculate the full value of the next entry. Note that the values passed in and out
6029 // here aren't the final values the top-level caller sees. In order to avoid having to touch the compressed
6030 // data on image base relocations we actually store a form of RVA (though relative to the map base rather than
6031 // the module base).
6032 INT32 LookupMapBase::GetNextCompressedEntry(BitStreamReader *pTableStream, INT32 iLastValue)
6033 {
6034     CONTRACTL
6035     {
6036         INSTANCE_CHECK;
6037         NOTHROW;
6038         GC_NOTRIGGER;
6039         MODE_ANY;
6040         SO_TOLERANT;
6041         SUPPORTS_DAC;
6042         PRECONDITION(MapIsCompressed());
6043     }
6044     CONTRACTL_END;
6045
6046     // The next kLookupMapLengthBits bits in the stream are an index into a per-map table that tells us the
6047     // length of the encoded delta.
6048     DWORD dwValueLength = rgEncodingLengths[pTableStream->Read(kLookupMapLengthBits)];
6049
6050     // Then follows a single bit that indicates whether the delta should be added (1) or subtracted (0) from
6051     // the previous entry value to recover the current entry value.
6052     // Once we've read that bit we read the delta (encoded as an unsigned integer using the number of bits
6053     // that we read from the encoding lengths table above).
6054     if (pTableStream->ReadOneFast())
6055         return iLastValue + (INT32)(pTableStream->Read(dwValueLength));
6056     else
6057         return iLastValue - (INT32)(pTableStream->Read(dwValueLength));
6058 }
6059
6060 // This method can only be called on a compressed map (MapIsCompressed() == true). Retrieves the final value
6061 // (e.g. MethodTable*, MethodDesc* etc. based on map type) given the rid of the entry.
6062 TADDR LookupMapBase::GetValueFromCompressedMap(DWORD rid)
6063 {
6064     CONTRACTL
6065     {
6066         INSTANCE_CHECK;
6067         NOTHROW;
6068         GC_NOTRIGGER;
6069         MODE_ANY;
6070         SO_TOLERANT;
6071         SUPPORTS_DAC;
6072         PRECONDITION(MapIsCompressed());
6073     }
6074     CONTRACTL_END;
6075
6076     // Normally to extract the nth entry in the table we have to linearly parse all (n - 1) preceding entries
6077     // (since entries are stored as the delta from the previous entry). Obviously this can yield exceptionally
6078     // poor performance for the later entries in large tables. So we also build an index of the compressed
6079     // stream. This index has an entry for every kLookupMapIndexStride entries in the compressed table. Each
6080     // index entry contains the full RVA (relative to the map) of the corresponding table entry plus the bit
6081     // offset in the stream from which to start parsing the next entry's data.
6082     // In this fashion we can get to within kLookupMapIndexStride entries of our target entry and then decode
6083     // our way to the final target.
6084
6085     // Ensure that index does not go beyond end of the saved table
6086     if (rid >= dwCount)
6087         return 0;
6088
6089     // Calculate the nearest entry in the index that is lower than our target index in the full table.
6090     DWORD dwIndexEntry = rid / kLookupMapIndexStride;
6091
6092     // Then calculate how many additional entries we'll need to decode from the compressed streams to recover
6093     // the target entry.
6094     DWORD dwSubIndex = rid % kLookupMapIndexStride;
6095
6096     // Open a bit stream reader on the index and skip all the entries prior to the one we're interested in.
6097     BitStreamReader sIndexStream(pIndex);
6098     sIndexStream.Skip(dwIndexEntry * cIndexEntryBits);
6099
6100     // The first kBitsPerRVA of the index entry contain the RVA of the corresponding entry in the compressed
6101     // table. If this is exactly the entry we want (dwSubIndex == 0) then we can use this RVA to recover the
6102     // value the caller wants. Our RVAs are based on the map address rather than the module base (simply
6103     // because we don't record the module base in LookupMapBase). A delta of zero encodes a null value,
6104     // otherwise we simply add the RVA to the our map address to recover the full pointer.
6105     // Note that most LookupMaps are embedded structures (in Module) so we can't directly dac_cast<TADDR> our
6106     // "this" pointer for DAC builds. Instead we have to use the slightly slower (in DAC) but more flexible
6107     // PTR_HOST_INT_TO_TADDR() which copes with interior host pointers.
6108     INT32 iValue = (INT32)sIndexStream.Read(kBitsPerRVA);
6109     if (dwSubIndex == 0)
6110         return iValue ? PTR_HOST_INT_TO_TADDR(this) + iValue : 0;
6111
6112     // Otherwise we must parse one or more entries in the compressed table to accumulate more deltas to the
6113     // base RVA we read above. The remaining portion of the index entry has the bit offset into the compressed
6114     // table at which to begin parsing.
6115     BitStreamReader sTableStream(dac_cast<PTR_CBYTE>(pTable));
6116     sTableStream.Skip(sIndexStream.Read(cIndexEntryBits - kBitsPerRVA));
6117
6118     // Parse all the entries up to our target entry. Each step takes the RVA from the previous cycle (or from
6119     // the index entry we read above) and applies the compressed delta of the next table entry to it.
6120     for (DWORD i = 0; i < dwSubIndex; i++)
6121         iValue = GetNextCompressedEntry(&sTableStream, iValue);
6122
6123     // We have the final RVA so recover the actual pointer from it (a zero RVA encodes a NULL pointer). Note
6124     // the use of PTR_HOST_INT_TO_TADDR() rather than dac_cast<TADDR>, see previous comment on
6125     // PTR_HOST_INT_TO_TADDR for an explanation.
6126     return iValue ? PTR_HOST_INT_TO_TADDR(this) + iValue : 0;
6127 }
6128
6129 PTR_TADDR LookupMapBase::FindHotItemValuePtr(DWORD rid)
6130 {
6131     LIMITED_METHOD_DAC_CONTRACT;
6132
6133     if  (dwNumHotItems < 5)
6134     {
6135         // do simple linear search if there are only a few hot items
6136         for (DWORD i = 0; i < dwNumHotItems; i++)
6137         {
6138             if (hotItemList[i].rid == rid)
6139                 return dac_cast<PTR_TADDR>(
6140                     dac_cast<TADDR>(hotItemList) + i * sizeof(HotItem) + offsetof(HotItem, value));
6141         }
6142     }
6143     else
6144     {
6145         // otherwise do binary search
6146         if (hotItemList[0].rid <= rid && rid <= hotItemList[dwNumHotItems-1].rid)
6147         {
6148             DWORD l = 0;
6149             DWORD r = dwNumHotItems;
6150             while (l + 1 < r)
6151             {
6152                 // loop invariant:
6153                 _ASSERTE(hotItemList[l].rid <= rid && (r >= dwNumHotItems || rid < hotItemList[r].rid));
6154
6155                 DWORD m = (l + r)/2;
6156                 // loop condition implies l < m < r, hence interval shrinks every iteration, hence loop terminates
6157                 _ASSERTE(l < m && m < r);
6158                 if (rid < hotItemList[m].rid)
6159                     r = m;
6160                 else
6161                     l = m;
6162             }
6163             // now we know l + 1 == r && hotItemList[l].rid <= rid < hotItemList[r].rid
6164             // loop invariant:
6165             _ASSERTE(hotItemList[l].rid <= rid && (r >= dwNumHotItems || rid < hotItemList[r].rid));
6166             if (hotItemList[l].rid == rid)
6167                 return dac_cast<PTR_TADDR>(
6168                     dac_cast<TADDR>(hotItemList) + l * sizeof(HotItem) + offsetof(HotItem, value));
6169         }
6170     }
6171     return NULL;
6172 }
6173
6174 #ifdef _DEBUG 
6175 void LookupMapBase::CheckConsistentHotItemList()
6176 {
6177     LIMITED_METHOD_DAC_CONTRACT;
6178
6179     for (DWORD i = 0; i < dwNumHotItems; i++)
6180     {
6181         DWORD rid = hotItemList[i].rid;
6182
6183         PTR_TADDR pHotValue = dac_cast<PTR_TADDR>(
6184             dac_cast<TADDR>(hotItemList) + i * sizeof(HotItem) + offsetof(HotItem, value));
6185         TADDR hotValue = RelativePointer<TADDR>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(pHotValue));
6186
6187         TADDR value;
6188         if (MapIsCompressed())
6189         {
6190             value = GetValueFromCompressedMap(rid);
6191         }
6192         else
6193         {
6194             PTR_TADDR pValue = GetIndexPtr(rid);
6195             value = RelativePointer<TADDR>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(pValue));
6196         }
6197
6198         _ASSERTE(hotValue == value || value == NULL);
6199     }
6200 }
6201 #endif // _DEBUG
6202
6203 #endif // FEATURE_PREJIT
6204
6205 // Get number of RIDs that this table can store
6206 DWORD LookupMapBase::GetSize()
6207 {
6208     CONTRACTL
6209     {
6210         INSTANCE_CHECK;
6211         NOTHROW;
6212         GC_NOTRIGGER;
6213         MODE_ANY;
6214         SUPPORTS_DAC;
6215     }
6216     CONTRACTL_END;
6217
6218     LookupMapBase * pMap = this;
6219     DWORD dwSize = 0;
6220     do
6221     {
6222         dwSize += pMap->dwCount;
6223         pMap = pMap->pNext;
6224     } while (pMap != NULL);
6225
6226     return dwSize;
6227 }
6228
6229 #ifndef DACCESS_COMPILE
6230
6231 #ifdef _DEBUG 
6232 void LookupMapBase::DebugGetRidMapOccupancy(DWORD *pdwOccupied, DWORD *pdwSize)
6233 {
6234     LIMITED_METHOD_CONTRACT;
6235
6236     *pdwOccupied = 0;
6237     *pdwSize     = 0;
6238
6239     LookupMapBase * pMap = this;
6240
6241     // Go through each linked block
6242     for (; pMap != NULL; pMap = pMap->pNext)
6243     {
6244         DWORD dwIterCount = pMap->dwCount;
6245
6246         for (DWORD i = 0; i < dwIterCount; i++)
6247         {
6248 #ifdef FEATURE_PREJIT
6249             if (pMap->MapIsCompressed())
6250             {
6251                 if (pMap->GetValueFromCompressedMap(i))
6252                     (*pdwOccupied)++;
6253             }
6254             else
6255 #endif // FEATURE_PREJIT
6256             if (pMap->pTable[i] != NULL)
6257                 (*pdwOccupied)++;
6258         }
6259
6260         (*pdwSize) += dwIterCount;
6261     }
6262 }
6263
6264 void Module::DebugLogRidMapOccupancy()
6265 {
6266     WRAPPER_NO_CONTRACT;
6267
6268 #define COMPUTE_RID_MAP_OCCUPANCY(var_suffix, map)                                        \
6269     DWORD dwOccupied##var_suffix, dwSize##var_suffix, dwPercent##var_suffix;              \
6270     map.DebugGetRidMapOccupancy(&dwOccupied##var_suffix, &dwSize##var_suffix);            \
6271     dwPercent##var_suffix = dwOccupied##var_suffix ? ((dwOccupied##var_suffix * 100) / dwSize##var_suffix) : 0;
6272
6273     COMPUTE_RID_MAP_OCCUPANCY(1, m_TypeDefToMethodTableMap);
6274     COMPUTE_RID_MAP_OCCUPANCY(2, m_TypeRefToMethodTableMap);
6275     COMPUTE_RID_MAP_OCCUPANCY(3, m_MethodDefToDescMap);
6276     COMPUTE_RID_MAP_OCCUPANCY(4, m_FieldDefToDescMap);
6277     COMPUTE_RID_MAP_OCCUPANCY(5, m_GenericParamToDescMap);
6278     COMPUTE_RID_MAP_OCCUPANCY(6, m_GenericTypeDefToCanonMethodTableMap);
6279     COMPUTE_RID_MAP_OCCUPANCY(7, m_FileReferencesMap);
6280     COMPUTE_RID_MAP_OCCUPANCY(8, m_ManifestModuleReferencesMap);
6281     COMPUTE_RID_MAP_OCCUPANCY(9, m_MethodDefToPropertyInfoMap);
6282
6283     LOG((
6284         LF_EEMEM,
6285         INFO3,
6286         "   Map occupancy:\n"
6287         "      TypeDefToMethodTable map: %4d/%4d (%2d %%)\n"
6288         "      TypeRefToMethodTable map: %4d/%4d (%2d %%)\n"
6289         "      MethodDefToDesc map:  %4d/%4d (%2d %%)\n"
6290         "      FieldDefToDesc map:  %4d/%4d (%2d %%)\n"
6291         "      GenericParamToDesc map:  %4d/%4d (%2d %%)\n"
6292         "      GenericTypeDefToCanonMethodTable map:  %4d/%4d (%2d %%)\n"
6293         "      FileReferences map:  %4d/%4d (%2d %%)\n"
6294         "      AssemblyReferences map:  %4d/%4d (%2d %%)\n"
6295         "      MethodDefToPropInfo map: %4d/%4d (%2d %%)\n"
6296         ,
6297         dwOccupied1, dwSize1, dwPercent1,
6298         dwOccupied2, dwSize2, dwPercent2,
6299         dwOccupied3, dwSize3, dwPercent3,
6300         dwOccupied4, dwSize4, dwPercent4,
6301         dwOccupied5, dwSize5, dwPercent5,
6302         dwOccupied6, dwSize6, dwPercent6,
6303         dwOccupied7, dwSize7, dwPercent7,
6304         dwOccupied8, dwSize8, dwPercent8,
6305         dwOccupied9, dwSize9, dwPercent9
6306     ));
6307
6308 #undef COMPUTE_RID_MAP_OCCUPANCY
6309 }
6310 #endif // _DEBUG
6311
6312 BOOL Module::CanExecuteCode()
6313 {
6314     WRAPPER_NO_CONTRACT;
6315
6316 #ifdef FEATURE_PREJIT 
6317     // In a passive domain, we lock down which assemblies can run code
6318     if (!GetAppDomain()->IsPassiveDomain())
6319         return TRUE;
6320
6321     Assembly * pAssembly = GetAssembly();
6322     PEAssembly * pPEAssembly = pAssembly->GetManifestFile();
6323
6324     // Only mscorlib is allowed to execute code in an ngen passive domain
6325     if (IsCompilationProcess())
6326         return pPEAssembly->IsSystem();
6327
6328     // ExecuteDLLForAttach does not run the managed entry point in 
6329     // a passive domain to avoid loader-lock deadlocks.
6330     // Hence, it is not safe to execute any code from this assembly.
6331     if (pPEAssembly->GetEntryPointToken(INDEBUG(TRUE)) != mdTokenNil)
6332         return FALSE;
6333
6334     // EXEs loaded using LoadAssembly() may not be loaded at their
6335     // preferred base address. If they have any relocs, these may
6336     // not have been fixed up.
6337     if (!pPEAssembly->IsDll() && !pPEAssembly->IsILOnly())
6338         return FALSE;
6339 #endif // FEATURE_PREJIT
6340
6341     return TRUE;
6342 }
6343
6344 //
6345 // FindMethod finds a MethodDesc for a global function methoddef or ref
6346 //
6347
6348 MethodDesc *Module::FindMethodThrowing(mdToken pMethod)
6349 {
6350     CONTRACT (MethodDesc *)
6351     {
6352         INSTANCE_CHECK;
6353         THROWS;
6354         GC_TRIGGERS;
6355         MODE_ANY;
6356         POSTCONDITION(CheckPointer(RETVAL));
6357     }
6358     CONTRACT_END
6359
6360     SigTypeContext typeContext;  /* empty type context: methods will not be generic */
6361     RETURN MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(this, pMethod,
6362                                                                &typeContext,
6363                                                                TRUE, /* strictMetadataChecks */
6364                                                                FALSE /* dont get code shared between generic instantiations */);
6365 }
6366
6367 //
6368 // FindMethod finds a MethodDesc for a global function methoddef or ref
6369 //
6370
6371 MethodDesc *Module::FindMethod(mdToken pMethod)
6372 {
6373     CONTRACT (MethodDesc *) {
6374         INSTANCE_CHECK;
6375         NOTHROW;
6376         GC_TRIGGERS;
6377         MODE_ANY;
6378         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
6379     } CONTRACT_END;
6380
6381     MethodDesc *pMDRet = NULL;
6382
6383     EX_TRY
6384     {
6385         pMDRet = FindMethodThrowing(pMethod);
6386     }
6387     EX_CATCH
6388     {
6389 #ifdef _DEBUG 
6390         CONTRACT_VIOLATION(ThrowsViolation);
6391         char szMethodName [MAX_CLASSNAME_LENGTH];
6392         CEEInfo::findNameOfToken(this, pMethod, szMethodName, COUNTOF (szMethodName));
6393         // This used to be LF_IJW, but changed to LW_INTEROP to reclaim a bit in our log facilities
6394         // IJW itself is not supported in coreclr so this code should never be run.
6395         LOG((LF_INTEROP, LL_INFO10, "Failed to find Method: %s for Vtable Fixup\n", szMethodName));
6396 #endif // _DEBUG
6397     }
6398     EX_END_CATCH(SwallowAllExceptions)
6399
6400     RETURN pMDRet;
6401 }
6402
6403 //
6404 // PopulatePropertyInfoMap precomputes property information during NGen
6405 // that is expensive to look up from metadata at runtime.
6406 //
6407
6408 void Module::PopulatePropertyInfoMap()
6409 {
6410     CONTRACTL
6411     {
6412         INSTANCE_CHECK;
6413         THROWS;
6414         GC_NOTRIGGER;
6415         MODE_ANY;
6416         PRECONDITION(IsCompilationProcess());
6417     }
6418     CONTRACTL_END;
6419
6420     IMDInternalImport* mdImport = GetMDImport();
6421     HENUMInternalHolder   hEnum(mdImport);
6422     hEnum.EnumAllInit(mdtMethodDef);
6423
6424     mdMethodDef md;
6425     while (hEnum.EnumNext(&md))
6426     {
6427         mdProperty prop = 0;
6428         ULONG semantic = 0;
6429         if (mdImport->GetPropertyInfoForMethodDef(md, &prop, NULL, &semantic) == S_OK)
6430         {
6431             // Store the Rid in the lower 24 bits and the semantic in the upper 8
6432             _ASSERTE((semantic & 0xFFFFFF00) == 0);
6433             SIZE_T value = RidFromToken(prop) | (semantic << 24);
6434
6435             // We need to make sure a value of zero indicates an empty LookupMap entry
6436             // Fortunately the semantic will prevent value from being zero
6437             _ASSERTE(value != 0);
6438
6439             m_MethodDefToPropertyInfoMap.AddElement(this, RidFromToken(md), value);
6440         }
6441     }
6442     FastInterlockOr(&m_dwPersistedFlags, COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP);
6443 }
6444
6445 //
6446 // GetPropertyInfoForMethodDef wraps the metadata function of the same name,
6447 // first trying to use the information stored in m_MethodDefToPropertyInfoMap.
6448 //
6449
6450 HRESULT Module::GetPropertyInfoForMethodDef(mdMethodDef md, mdProperty *ppd, LPCSTR *pName, ULONG *pSemantic)
6451 {
6452     CONTRACTL
6453     {
6454         INSTANCE_CHECK;
6455         NOTHROW;
6456         GC_NOTRIGGER;
6457         MODE_ANY;
6458         SO_TOLERANT;
6459     }
6460     CONTRACTL_END;
6461     
6462     HRESULT hr;
6463     
6464     if ((m_dwPersistedFlags & COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP) != 0)
6465     {
6466         SIZE_T value = m_MethodDefToPropertyInfoMap.GetElement(RidFromToken(md));
6467         if (value == 0)
6468         {
6469             _ASSERTE(GetMDImport()->GetPropertyInfoForMethodDef(md, ppd, pName, pSemantic) == S_FALSE);
6470             return S_FALSE;
6471         }
6472         else
6473         {
6474             // Decode the value into semantic and mdProperty as described in PopulatePropertyInfoMap
6475             ULONG semantic = (value & 0xFF000000) >> 24;
6476             mdProperty prop = TokenFromRid(value & 0x00FFFFFF, mdtProperty);
6477
6478 #ifdef _DEBUG
6479             mdProperty dbgPd;
6480             LPCSTR dbgName;
6481             ULONG dbgSemantic;
6482             _ASSERTE(GetMDImport()->GetPropertyInfoForMethodDef(md, &dbgPd, &dbgName, &dbgSemantic) == S_OK);
6483 #endif
6484
6485             if (ppd != NULL)
6486             {
6487                 *ppd = prop;
6488                 _ASSERTE(*ppd == dbgPd);
6489             }
6490             
6491             if (pSemantic != NULL)
6492             {
6493                 *pSemantic = semantic;
6494                 _ASSERTE(*pSemantic == dbgSemantic);
6495             }
6496             
6497             if (pName != NULL)
6498             {
6499                 IfFailRet(GetMDImport()->GetPropertyProps(prop, pName, NULL, NULL, NULL));
6500                 
6501 #ifdef _DEBUG
6502                 HRESULT hr = GetMDImport()->GetPropertyProps(prop, pName, NULL, NULL, NULL);
6503                 _ASSERTE(hr == S_OK);
6504                 _ASSERTE(strcmp(*pName, dbgName) == 0);
6505 #endif
6506             }
6507             
6508             return S_OK;
6509         }
6510     }
6511     
6512     return GetMDImport()->GetPropertyInfoForMethodDef(md, ppd, pName, pSemantic);
6513 }
6514
6515 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
6516 // Fill the m_propertyNameSet hash filter with data that represents every
6517 // property and its name in the module.
6518 void Module::PrecomputeMatchingProperties(DataImage *image)
6519 {
6520     CONTRACTL
6521     {
6522         STANDARD_VM_CHECK;
6523         PRECONDITION(IsCompilationProcess());
6524     }
6525     CONTRACTL_END;
6526
6527     IMDInternalImport* mdImport = GetMDImport();
6528
6529     m_nPropertyNameSet = mdImport->GetCountWithTokenKind(mdtProperty);
6530
6531     if (m_nPropertyNameSet == 0)
6532     {
6533         return;
6534     }
6535     
6536     m_propertyNameSet = new (image->GetHeap()) BYTE[m_nPropertyNameSet];
6537
6538     DWORD nEnumeratedProperties = 0;
6539
6540     HENUMInternalHolder   hEnumTypes(mdImport);
6541     hEnumTypes.EnumAllInit(mdtTypeDef);
6542
6543     // Enumerate all properties of all types
6544     mdTypeDef tkType;
6545     while (hEnumTypes.EnumNext(&tkType))
6546     {
6547         HENUMInternalHolder   hEnumPropertiesForType(mdImport);
6548         hEnumPropertiesForType.EnumInit(mdtProperty, tkType);
6549
6550         mdProperty tkProperty;
6551         while (hEnumPropertiesForType.EnumNext(&tkProperty))
6552         {
6553             LPCSTR name;
6554             HRESULT hr = GetMDImport()->GetPropertyProps(tkProperty, &name, NULL, NULL, NULL);
6555             IfFailThrow(hr);
6556
6557             ++nEnumeratedProperties;
6558
6559             // Use a case-insensitive hash so that we can use this value for
6560             // both case-sensitive and case-insensitive name lookups
6561             SString ssName(SString::Utf8Literal, name);
6562             ULONG nameHashValue = ssName.HashCaseInsensitive();
6563
6564             // Set one bit in m_propertyNameSet per iteration
6565             // This will allow lookup to ensure that the bit from each iteration is set
6566             // and if any are not set, know that the (tkProperty,name) pair is not valid
6567             for (DWORD i = 0; i < NUM_PROPERTY_SET_HASHES; ++i)
6568             {
6569                 DWORD currentHashValue = HashThreeToOne(tkProperty, nameHashValue, i);
6570                 DWORD bitPos = currentHashValue % (m_nPropertyNameSet * 8);
6571                 m_propertyNameSet[bitPos / 8] |= (1 << bitPos % 8);
6572             }
6573         }
6574     }
6575
6576     _ASSERTE(nEnumeratedProperties == m_nPropertyNameSet);
6577 }
6578 #endif // FEATURE_NATIVE_IMAGE_GENERATION
6579
6580 // Check whether the module might possibly have a property with a name with
6581 // the passed hash value without accessing the property's name.  This is done
6582 // by consulting a hash filter populated at NGen time.
6583 BOOL Module::MightContainMatchingProperty(mdProperty tkProperty, ULONG nameHash)
6584 {
6585     CONTRACTL
6586     {
6587         NOTHROW;
6588         GC_NOTRIGGER;
6589         SO_TOLERANT;
6590         MODE_ANY;
6591     }
6592     CONTRACTL_END;
6593
6594     if (m_propertyNameSet)
6595     {
6596         _ASSERTE(HasNativeImage());
6597
6598         // if this property was added after the name set was computed, conservatively
6599         // assume we might have it. This is known to occur in scenarios where a profiler
6600         // injects additional metadata at module load time for an NGEN'ed module. In the
6601         // future other dynamic additions to the module might produce a similar result.
6602         if (RidFromToken(tkProperty) > m_nPropertyNameSet)
6603             return TRUE;
6604
6605         // Check one bit per iteration, failing if any are not set
6606         // We know that all will have been set for any valid (tkProperty,name) pair
6607         for (DWORD i = 0; i < NUM_PROPERTY_SET_HASHES; ++i)
6608         {
6609             DWORD currentHashValue = HashThreeToOne(tkProperty, nameHash, i);
6610             DWORD bitPos = currentHashValue % (m_nPropertyNameSet * 8);
6611             if ((m_propertyNameSet[bitPos / 8] & (1 << bitPos % 8)) == 0)
6612             {
6613                 return FALSE;
6614             }
6615         }
6616     }
6617
6618     return TRUE;
6619 }
6620
6621 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
6622 // Ensure that all elements and flags that we want persisted in the LookupMaps are present
6623 void Module::FinalizeLookupMapsPreSave(DataImage *image)
6624 {
6625     CONTRACTL
6626     {
6627         STANDARD_VM_CHECK;
6628         PRECONDITION(IsCompilationProcess());
6629     }
6630     CONTRACTL_END;
6631
6632     // For each typedef, if it does not need a restore, add the ZAPPED_TYPE_NEEDS_NO_RESTORE flag
6633     {
6634         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
6635
6636         while (typeDefIter.Next())
6637         {
6638             MethodTable * pMT = typeDefIter.GetElement();
6639
6640             if (pMT != NULL && !pMT->NeedsRestore(image))
6641             {
6642                 m_TypeDefToMethodTableMap.AddFlag(RidFromToken(pMT->GetCl()), ZAPPED_TYPE_NEEDS_NO_RESTORE);
6643             }
6644         }
6645     }
6646
6647     // For each canonical instantiation of a generic type def, if it does not need a restore, add the ZAPPED_GENERIC_TYPE_NEEDS_NO_RESTORE flag
6648     {
6649         LookupMap<PTR_MethodTable>::Iterator genericTypeDefIter(&m_GenericTypeDefToCanonMethodTableMap);
6650
6651         while (genericTypeDefIter.Next())
6652         {
6653             MethodTable * pMT = genericTypeDefIter.GetElement();
6654
6655             if (pMT != NULL && !pMT->NeedsRestore(image))
6656             {
6657                 m_GenericTypeDefToCanonMethodTableMap.AddFlag(RidFromToken(pMT->GetCl()), ZAPPED_GENERIC_TYPE_NEEDS_NO_RESTORE);
6658             }
6659         }
6660     }
6661
6662 }
6663 #endif // FEATURE_NATIVE_IMAGE_GENERATION
6664
6665 // Return true if this module has any live (jitted) JMC functions.
6666 // If a module has no jitted JMC functions, then it's as if it's a
6667 // non-user module.
6668 bool Module::HasAnyJMCFunctions()
6669 {
6670     LIMITED_METHOD_CONTRACT;
6671
6672     // If we have any live JMC funcs in us, then we're a JMC module.
6673     // We count JMC functions when we either explicitly toggle their status
6674     // or when we get the code:DebuggerMethodInfo for them (which happens in a jit-complete).
6675     // Since we don't get the jit-completes for ngen modules, we also check the module's
6676     // "default" status. This means we may err on the side of believing we have
6677     // JMC methods.
6678     return ((m_debuggerSpecificData.m_cTotalJMCFuncs > 0) || m_debuggerSpecificData.m_fDefaultJMCStatus);
6679 }
6680
6681 // Alter our module's count of JMC functions.
6682 // Since these may be called on multiple threads (say 2 threads are jitting
6683 // methods within a module), make it thread safe.
6684 void Module::IncJMCFuncCount()
6685 {
6686     LIMITED_METHOD_CONTRACT;
6687
6688     InterlockedIncrement(&m_debuggerSpecificData.m_cTotalJMCFuncs);
6689 }
6690
6691 void Module::DecJMCFuncCount()
6692 {
6693     LIMITED_METHOD_CONTRACT;
6694
6695     InterlockedDecrement(&m_debuggerSpecificData.m_cTotalJMCFuncs);
6696 }
6697
6698 // code:DebuggerMethodInfo are lazily created. Let them lookup what the default is.
6699 bool Module::GetJMCStatus()
6700 {
6701     LIMITED_METHOD_CONTRACT;
6702
6703     return m_debuggerSpecificData.m_fDefaultJMCStatus;
6704 }
6705
6706 // Set the default JMC status of this module.
6707 void Module::SetJMCStatus(bool fStatus)
6708 {
6709     LIMITED_METHOD_CONTRACT;
6710
6711     m_debuggerSpecificData.m_fDefaultJMCStatus = fStatus;
6712 }
6713
6714 // Update the dynamic metadata if needed. Nop for non-dynamic modules
6715 void Module::UpdateDynamicMetadataIfNeeded()
6716 {
6717     CONTRACTL
6718     {
6719         NOTHROW;
6720         GC_TRIGGERS;
6721     }
6722     CONTRACTL_END;
6723
6724     // Only need to serializing metadata for dynamic modules. For non-dynamic modules, metadata is already available.
6725     if (!IsReflection())
6726     {
6727         return;
6728     }
6729
6730     // Since serializing metadata to an auxillary buffer is only needed by the debugger,
6731     // we should only be doing this for modules that the debugger can see. 
6732     if (!IsVisibleToDebugger())
6733     {
6734         return;
6735     }
6736
6737     
6738     HRESULT hr = S_OK;
6739     EX_TRY
6740     {
6741         GetReflectionModule()->CaptureModuleMetaDataToMemory();
6742     }
6743     EX_CATCH_HRESULT(hr);
6744     
6745     // This Metadata buffer is only used for the debugger, so it's a non-fatal exception for regular CLR execution.
6746     // Just swallow it and keep going. However, with the exception of out-of-memory, we do expect it to
6747     // succeed, so assert on failures.
6748     if (hr != E_OUTOFMEMORY)
6749     {
6750         SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
6751     }
6752
6753 }
6754
6755 #ifdef DEBUGGING_SUPPORTED 
6756
6757
6758 #endif // DEBUGGING_SUPPORTED
6759
6760 BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, int flags, BOOL attaching)
6761 {
6762     WRAPPER_NO_CONTRACT;
6763
6764     // We don't notify the debugger about modules that don't contain any code.
6765     if (!IsVisibleToDebugger())
6766         return FALSE;
6767
6768     // Always capture metadata, even if no debugger is attached. If a debugger later attaches, it will use
6769     // this data.
6770     {
6771         Module * pModule = pDomainFile->GetModule();
6772         pModule->UpdateDynamicMetadataIfNeeded();
6773     }
6774
6775
6776     //
6777     // Remaining work is only needed if a debugger is attached
6778     // 
6779     if (!attaching && !pDomain->IsDebuggerAttached())
6780         return FALSE;
6781         
6782
6783     BOOL result = FALSE;
6784
6785     if (flags & ATTACH_MODULE_LOAD)
6786     {
6787         g_pDebugInterface->LoadModule(this,
6788                                       m_file->GetPath(),
6789                                       m_file->GetPath().GetCount(),
6790                                       GetAssembly(), 
6791                                       pDomain, 
6792                                       pDomainFile, 
6793                                       attaching);
6794
6795         result = TRUE;
6796     }
6797
6798     if (flags & ATTACH_CLASS_LOAD)
6799     {
6800         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
6801         while (typeDefIter.Next())
6802         {
6803             MethodTable * pMT = typeDefIter.GetElement();
6804
6805             if (pMT != NULL && pMT->IsRestored())
6806             {
6807                 result = TypeHandle(pMT).NotifyDebuggerLoad(pDomain, attaching) || result;
6808             }
6809         }
6810     }
6811
6812     return result;
6813 }
6814
6815 void Module::NotifyDebuggerUnload(AppDomain *pDomain)
6816 {
6817     LIMITED_METHOD_CONTRACT;
6818
6819     if (!pDomain->IsDebuggerAttached())
6820         return;
6821
6822     // We don't notify the debugger about modules that don't contain any code.
6823     if (!IsVisibleToDebugger())
6824         return;
6825
6826     LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
6827     while (typeDefIter.Next())
6828     {
6829         MethodTable * pMT = typeDefIter.GetElement();
6830
6831         if (pMT != NULL && pMT->IsRestored())
6832         {
6833             TypeHandle(pMT).NotifyDebuggerUnload(pDomain);
6834         }
6835     }
6836
6837     g_pDebugInterface->UnloadModule(this, pDomain);
6838 }
6839
6840
6841
6842 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
6843
6844 // These helpers are used in Module::ExpandAll
6845 // to avoid EX_TRY/EX_CATCH in a loop (uses _alloca and guzzles stack)
6846
6847 static TypeHandle LoadTypeDefOrRefHelper(DataImage * image, Module * pModule, mdToken tk)
6848 {
6849     STANDARD_VM_CONTRACT;
6850
6851     TypeHandle th;
6852
6853     EX_TRY
6854     {
6855         th = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tk,
6856                                               ClassLoader::ThrowIfNotFound,
6857                                               ClassLoader::PermitUninstDefOrRef);
6858     }
6859     EX_CATCH
6860     {
6861         image->GetPreloader()->Error(tk, GET_EXCEPTION());
6862     }
6863     EX_END_CATCH(SwallowAllExceptions)
6864
6865     return th;
6866 }
6867
6868 static TypeHandle LoadTypeSpecHelper(DataImage * image, Module * pModule, mdToken tk, 
6869                                      PCCOR_SIGNATURE pSig, ULONG cSig)
6870 {
6871     STANDARD_VM_CONTRACT;
6872
6873     TypeHandle th;
6874
6875     EX_TRY
6876     {
6877         SigPointer p(pSig, cSig);
6878         SigTypeContext typeContext;
6879         th = p.GetTypeHandleThrowing(pModule, &typeContext);
6880     }
6881     EX_CATCH
6882     {
6883         image->GetPreloader()->Error(tk, GET_EXCEPTION());
6884     }
6885     EX_END_CATCH(SwallowAllExceptions)
6886
6887     return th;
6888 }
6889
6890 static TypeHandle LoadGenericInstantiationHelper(DataImage * image, Module * pModule, mdToken tk, Instantiation inst)
6891 {
6892     STANDARD_VM_CONTRACT;
6893
6894     TypeHandle th;
6895
6896     EX_TRY
6897     {
6898         th = ClassLoader::LoadGenericInstantiationThrowing(pModule, tk, inst);
6899     }
6900     EX_CATCH
6901     {
6902         image->GetPreloader()->Error(tk, GET_EXCEPTION());
6903     }
6904     EX_END_CATCH(SwallowAllExceptions)
6905
6906     return th;
6907 }
6908
6909 static void GetDescFromMemberRefHelper(DataImage * image, Module * pModule, mdToken tk)
6910 {
6911     STANDARD_VM_CONTRACT;
6912
6913     EX_TRY
6914     {
6915         MethodDesc * pMD = NULL;
6916         FieldDesc * pFD = NULL;
6917         TypeHandle th;
6918
6919         // Note: using an empty type context is now OK, because even though the token is a MemberRef
6920         // neither the token nor its parent will directly refer to type variables.
6921         // @TODO GENERICS: want to allow loads of generic methods here but need strict metadata checks on parent
6922         SigTypeContext typeContext;
6923         MemberLoader::GetDescFromMemberRef(pModule, tk, &pMD, &pFD,
6924                 &typeContext,
6925                 FALSE /* strict metadata checks */, &th);
6926     }
6927     EX_CATCH
6928     {
6929         image->GetPreloader()->Error(tk, GET_EXCEPTION());
6930     }
6931     EX_END_CATCH(SwallowAllExceptions)
6932 }
6933
6934 void Module::SetProfileData(CorProfileData * profileData)
6935 {
6936     LIMITED_METHOD_CONTRACT;
6937     m_pProfileData = profileData;
6938 }
6939
6940 CorProfileData * Module::GetProfileData()
6941 {
6942     LIMITED_METHOD_CONTRACT;
6943     return m_pProfileData;
6944 }
6945
6946 mdTypeDef Module::LookupIbcTypeToken(Module *  pExternalModule, mdToken ibcToken, SString* optionalFullNameOut)
6947 {
6948     CONTRACTL
6949     {
6950         THROWS;
6951         GC_TRIGGERS;
6952         MODE_ANY;
6953     }
6954     CONTRACTL_END
6955
6956     _ASSERTE(TypeFromToken(ibcToken) == ibcExternalType);
6957
6958     CorProfileData *  profileData  = this->GetProfileData();
6959
6960     CORBBTPROF_BLOB_TYPE_DEF_ENTRY *  blobTypeDefEntry;
6961     blobTypeDefEntry = profileData->GetBlobExternalTypeDef(ibcToken);
6962
6963     if (blobTypeDefEntry == NULL)
6964         return mdTypeDefNil;
6965
6966     IbcNameHandle  ibcName;
6967     ibcName.szName           = &blobTypeDefEntry->name[0];
6968     ibcName.tkIbcNameSpace   = blobTypeDefEntry->nameSpaceToken;
6969     ibcName.tkIbcNestedClass = blobTypeDefEntry->nestedClassToken;
6970     ibcName.szNamespace      = NULL;
6971     ibcName.tkEnclosingClass = mdTypeDefNil;
6972     
6973     if (!IsNilToken(blobTypeDefEntry->nameSpaceToken))
6974     {
6975         _ASSERTE(IsNilToken(blobTypeDefEntry->nestedClassToken));
6976
6977         idExternalNamespace nameSpaceToken = blobTypeDefEntry->nameSpaceToken;
6978         _ASSERTE(TypeFromToken(nameSpaceToken) == ibcExternalNamespace);
6979
6980         CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY *  blobNamespaceDefEntry;
6981         blobNamespaceDefEntry = profileData->GetBlobExternalNamespaceDef(nameSpaceToken);
6982
6983         if (blobNamespaceDefEntry == NULL)
6984             return mdTypeDefNil;
6985
6986         ibcName.szNamespace = &blobNamespaceDefEntry->name[0];
6987
6988         if (optionalFullNameOut != NULL)
6989         {
6990             optionalFullNameOut->Append(W("["));
6991             optionalFullNameOut->AppendUTF8(pExternalModule->GetSimpleName());
6992             optionalFullNameOut->Append(W("]"));
6993
6994             if ((ibcName.szNamespace != NULL) && ((*ibcName.szNamespace) != W('\0')))
6995             {
6996                 optionalFullNameOut->AppendUTF8(ibcName.szNamespace);
6997                 optionalFullNameOut->Append(W("."));
6998             }
6999             optionalFullNameOut->AppendUTF8(ibcName.szName);
7000         }
7001     }
7002     else if (!IsNilToken(blobTypeDefEntry->nestedClassToken))
7003     {
7004         idExternalType nestedClassToken = blobTypeDefEntry->nestedClassToken;
7005         _ASSERTE(TypeFromToken(nestedClassToken) == ibcExternalType);
7006
7007         ibcName.tkEnclosingClass = LookupIbcTypeToken(pExternalModule, nestedClassToken, optionalFullNameOut);
7008
7009         if (optionalFullNameOut != NULL)
7010         {
7011             optionalFullNameOut->Append(W("+"));
7012             optionalFullNameOut->AppendUTF8(ibcName.szName);
7013         }
7014
7015         if (IsNilToken(ibcName.tkEnclosingClass))
7016             return  mdTypeDefNil;
7017     }
7018
7019     //*****************************************
7020     // look up function for TypeDef
7021     //*****************************************
7022     // STDMETHOD(FindTypeDef)(
7023     //     LPCSTR      szNamespace,            // [IN] Namespace for the TypeDef.
7024     //     LPCSTR      szName,                 // [IN] Name of the TypeDef.
7025     //     mdToken     tkEnclosingClass,       // [IN] TypeRef/TypeDef Token for the enclosing class.
7026     //     mdTypeDef   *ptypedef) PURE;        // [IN] return typedef
7027     
7028     IMDInternalImport *pInternalImport = pExternalModule->GetMDImport();
7029
7030     mdTypeDef mdResult = mdTypeDefNil;
7031
7032     HRESULT hr = pInternalImport->FindTypeDef(ibcName.szNamespace, ibcName.szName, ibcName.tkEnclosingClass, &mdResult);
7033
7034     if(FAILED(hr)) 
7035         mdResult = mdTypeDefNil;
7036
7037     return mdResult;
7038 }
7039
7040 struct IbcCompareContext
7041 {
7042     Module *         pModule;
7043     TypeHandle       enclosingType;
7044     DWORD            cMatch;      // count of methods that had a matching method name
7045     bool             useBestSig;  // if true we should use the BestSig when we don't find an exact match
7046     PCCOR_SIGNATURE  pvBestSig;   // Current Best matching signature
7047     DWORD            cbBestSig;   // 
7048 };
7049
7050 //---------------------------------------------------------------------------------------
7051 // 
7052 // Compare two signatures from the same scope. 
7053 // 
7054 BOOL 
7055 CompareIbcMethodSigs(
7056     PCCOR_SIGNATURE pvCandidateSig, // Candidate signature
7057     DWORD           cbCandidateSig, // 
7058     PCCOR_SIGNATURE pvIbcSignature, // The Ibc signature that we want to match
7059     DWORD           cbIbcSignature, // 
7060     void *          pvContext)      // void pointer to IbcCompareContext
7061 {
7062     CONTRACTL
7063     {
7064         THROWS;
7065         GC_TRIGGERS;
7066         MODE_ANY;
7067     }
7068     CONTRACTL_END
7069     
7070     //
7071     // Same pointer return TRUE
7072     // 
7073     if (pvCandidateSig == pvIbcSignature)
7074     {
7075         _ASSERTE(cbCandidateSig == cbIbcSignature);
7076         return TRUE;
7077     }
7078        
7079     //
7080     // Check for exact match
7081     // 
7082     if (cbCandidateSig == cbIbcSignature)
7083     {
7084         if (memcmp(pvCandidateSig, pvIbcSignature, cbIbcSignature) == 0)
7085         {
7086             return TRUE;
7087         }
7088     }
7089
7090     IbcCompareContext * context = (IbcCompareContext *) pvContext;
7091
7092     //
7093     // No exact match, we will return FALSE and keep looking at other matching method names
7094     // 
7095     // However since the method name was an exact match we will remember this signature,
7096     // so that if it is the best match we can look it up again and return it's methodDef token
7097     // 
7098     if (context->cMatch == 0)
7099     {
7100         context->pvBestSig = pvCandidateSig;
7101         context->cbBestSig = cbCandidateSig;
7102         context->cMatch = 1;
7103         context->useBestSig = true;
7104     }
7105     else
7106     {
7107         context->cMatch++; 
7108
7109         SigTypeContext emptyTypeContext;
7110         SigTypeContext ibcTypeContext =  SigTypeContext(context->enclosingType);
7111         MetaSig ibcSignature (pvIbcSignature, cbIbcSignature, context->pModule, &ibcTypeContext);
7112
7113         MetaSig candidateSig (pvCandidateSig, cbCandidateSig, context->pModule, &emptyTypeContext);
7114         MetaSig bestSignature(context->pvBestSig, context->cbBestSig, context->pModule, &emptyTypeContext);
7115         //
7116         // Is candidateSig a better match than bestSignature?
7117         // 
7118         // First check the calling convention
7119         // 
7120         if (candidateSig.GetCallingConventionInfo() != bestSignature.GetCallingConventionInfo())
7121         {
7122             if (bestSignature.GetCallingConventionInfo() == ibcSignature.GetCallingConventionInfo())
7123                 goto LEAVE_BEST;
7124             if (candidateSig.GetCallingConventionInfo() == ibcSignature.GetCallingConventionInfo())
7125                 goto SELECT_CANDIDATE;
7126             //
7127             // Neither one is a match
7128             // 
7129             goto USE_NEITHER;
7130         }
7131
7132         //
7133         // Next check the number of arguments
7134         // 
7135         if (candidateSig.NumFixedArgs() != bestSignature.NumFixedArgs())
7136         {
7137             //
7138             // Does one of the two have the same number of args?
7139             //
7140             if (bestSignature.NumFixedArgs() == ibcSignature.NumFixedArgs())
7141                 goto LEAVE_BEST;
7142             if (candidateSig.NumFixedArgs() == ibcSignature.NumFixedArgs())
7143                 goto SELECT_CANDIDATE;
7144             //
7145             // Neither one is a match
7146             // 
7147             goto USE_NEITHER;
7148         }
7149         else if (candidateSig.NumFixedArgs() != ibcSignature.NumFixedArgs())
7150         {
7151             //
7152             // Neither one is a match
7153             // 
7154             goto USE_NEITHER;
7155         }
7156
7157         CorElementType  etIbc; 
7158         CorElementType  etCandidate; 
7159         CorElementType  etBest; 
7160         //
7161         // Next get the return element type
7162         // 
7163         // etIbc = ibcSignature.GetReturnProps().PeekElemTypeClosed(ibcSignature.GetSigTypeContext());
7164         IfFailThrow(ibcSignature.GetReturnProps().PeekElemType(&etIbc));
7165         IfFailThrow(candidateSig.GetReturnProps().PeekElemType(&etCandidate));
7166         IfFailThrow(bestSignature.GetReturnProps().PeekElemType(&etBest));
7167         //
7168         // Do they have different return types?
7169         //
7170         if (etCandidate != etBest)
7171         {
7172             if (etBest == etIbc)
7173                 goto LEAVE_BEST;
7174
7175             if (etCandidate == etIbc)
7176                 goto SELECT_CANDIDATE;
7177         }
7178
7179         //
7180         // Now iterate over the method argument types to see which signature
7181         // is the better match
7182         // 
7183         for (DWORD i = 0; (i < ibcSignature.NumFixedArgs()); i++) 
7184         {
7185             ibcSignature.SkipArg();
7186             IfFailThrow(ibcSignature.GetArgProps().PeekElemType(&etIbc));
7187
7188             candidateSig.SkipArg();
7189             IfFailThrow(candidateSig.GetArgProps().PeekElemType(&etCandidate));
7190
7191             bestSignature.SkipArg();
7192             IfFailThrow(bestSignature.GetArgProps().PeekElemType(&etBest));
7193
7194             //
7195             // Do they have different argument types?
7196             //
7197             if (etCandidate != etBest)
7198             {
7199                 if (etBest == etIbc)
7200                     goto LEAVE_BEST;
7201
7202                 if (etCandidate == etIbc)
7203                     goto SELECT_CANDIDATE;
7204             }
7205         } 
7206         // When we fall though to here we did not find any differences
7207         // that we could base a choice on
7208         // 
7209          context->useBestSig = true;
7210
7211 SELECT_CANDIDATE:
7212         context->pvBestSig = pvCandidateSig;
7213         context->cbBestSig = cbCandidateSig;
7214         context->useBestSig = true;
7215         return FALSE;
7216
7217 USE_NEITHER:
7218         context->useBestSig = false;
7219         return FALSE;
7220     }
7221
7222 LEAVE_BEST:
7223     return FALSE;
7224 } // CompareIbcMethodSigs
7225
7226 mdMethodDef Module::LookupIbcMethodToken(TypeHandle enclosingType, mdToken ibcToken, SString* optionalFullNameOut)
7227 {
7228     CONTRACTL
7229     {
7230         THROWS;
7231         GC_TRIGGERS;
7232         MODE_ANY;
7233     }
7234     CONTRACTL_END
7235
7236     _ASSERTE(TypeFromToken(ibcToken) == ibcExternalMethod);
7237
7238     CorProfileData *  profileData  = this->GetProfileData();
7239
7240     CORBBTPROF_BLOB_METHOD_DEF_ENTRY *  blobMethodDefEntry;
7241     blobMethodDefEntry = profileData->GetBlobExternalMethodDef(ibcToken);
7242
7243     if (blobMethodDefEntry == NULL)
7244         return mdMethodDefNil;
7245
7246     idExternalType signatureToken = blobMethodDefEntry->signatureToken;
7247     _ASSERTE(!IsNilToken(signatureToken));
7248     _ASSERTE(TypeFromToken(signatureToken) == ibcExternalSignature);
7249
7250     CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY *  blobSignatureDefEntry;
7251     blobSignatureDefEntry = profileData->GetBlobExternalSignatureDef(signatureToken);
7252
7253     if (blobSignatureDefEntry == NULL)
7254         return mdMethodDefNil;
7255
7256     IbcNameHandle    ibcName;
7257     ibcName.szName                    = &blobMethodDefEntry->name[0];
7258     ibcName.tkIbcNestedClass          = blobMethodDefEntry->nestedClassToken;
7259     ibcName.tkIbcNameSpace            = idExternalNamespaceNil;
7260     ibcName.szNamespace               = NULL;
7261     ibcName.tkEnclosingClass          = mdTypeDefNil;
7262
7263     Module *         pExternalModule  = enclosingType.GetModule();
7264     PCCOR_SIGNATURE  pvSig            = NULL;
7265     ULONG            cbSig            = 0;
7266
7267     _ASSERTE(!IsNilToken(ibcName.tkIbcNestedClass));
7268     _ASSERTE(TypeFromToken(ibcName.tkIbcNestedClass) == ibcExternalType);
7269
7270     ibcName.tkEnclosingClass = LookupIbcTypeToken(pExternalModule, ibcName.tkIbcNestedClass, optionalFullNameOut);
7271        
7272     if (IsNilToken(ibcName.tkEnclosingClass))
7273     {
7274         COMPlusThrow(kTypeLoadException, IDS_IBC_MISSING_EXTERNAL_TYPE);
7275     }
7276
7277     if (optionalFullNameOut != NULL)
7278     {
7279         optionalFullNameOut->Append(W("."));
7280         optionalFullNameOut->AppendUTF8(ibcName.szName);    // MethodName
7281         optionalFullNameOut->Append(W("()"));
7282     }
7283
7284     pvSig = blobSignatureDefEntry->sig;
7285     cbSig = blobSignatureDefEntry->cSig;
7286
7287     //*****************************************
7288     // look up functions for TypeDef
7289     //*****************************************
7290     // STDMETHOD(FindMethodDefUsingCompare)(
7291     //     mdTypeDef   classdef,               // [IN] given typedef
7292     //     LPCSTR      szName,                 // [IN] member name
7293     //     PCCOR_SIGNATURE pvSigBlob,          // [IN] point to a blob value of CLR signature
7294     //     ULONG       cbSigBlob,              // [IN] count of bytes in the signature blob
7295     //     PSIGCOMPARE pSignatureCompare,      // [IN] Routine to compare signatures
7296     //     void*       pSignatureArgs,         // [IN] Additional info to supply the compare function
7297     //     mdMethodDef *pmd) PURE;             // [OUT] matching memberdef
7298     //
7299          
7300     IMDInternalImport *  pInternalImport = pExternalModule->GetMDImport();
7301
7302     IbcCompareContext context;
7303     memset(&context, 0, sizeof(IbcCompareContext));
7304     context.pModule = this;
7305     context.enclosingType = enclosingType;
7306     context.cMatch = 0;
7307     context.useBestSig = false;
7308
7309     mdMethodDef mdResult = mdMethodDefNil;
7310     HRESULT hr = pInternalImport->FindMethodDefUsingCompare(ibcName.tkEnclosingClass, ibcName.szName, 
7311                                                             pvSig, cbSig, 
7312                                                             CompareIbcMethodSigs, (void *) &context,
7313                                                             &mdResult);
7314     if (SUCCEEDED(hr)) 
7315     {
7316         _ASSERTE(mdResult != mdMethodDefNil);
7317     }
7318     else if (context.useBestSig)
7319     {
7320         hr = pInternalImport->FindMethodDefUsingCompare(ibcName.tkEnclosingClass, ibcName.szName, 
7321                                                         context.pvBestSig, context.cbBestSig,
7322                                                         CompareIbcMethodSigs, (void *) &context,
7323                                                         &mdResult);
7324         _ASSERTE(SUCCEEDED(hr));
7325         _ASSERTE(mdResult != mdMethodDefNil);
7326     }
7327     else
7328     {
7329         mdResult = mdMethodDefNil;
7330     }
7331
7332     return mdResult;
7333 }
7334
7335 TypeHandle Module::LoadIBCTypeHelper(DataImage *image, CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry)
7336 {
7337     CONTRACT(TypeHandle)
7338     {
7339         NOTHROW;
7340         GC_TRIGGERS;
7341         MODE_ANY;
7342         INJECT_FAULT(COMPlusThrowOM());
7343         PRECONDITION(CheckPointer(pBlobSigEntry));
7344     }
7345     CONTRACT_END
7346
7347     TypeHandle         loadedType;
7348
7349     PCCOR_SIGNATURE    pSig = pBlobSigEntry->sig;
7350     ULONG              cSig = pBlobSigEntry->cSig;
7351
7352     SigPointer         p(pSig, cSig);
7353
7354     ZapSig::Context    zapSigContext(this, (void *)this, ZapSig::IbcTokens);
7355     ZapSig::Context *  pZapSigContext = &zapSigContext;
7356
7357     EX_TRY
7358     {
7359         // This is what ZapSig::FindTypeHandleFromSignature does...
7360         // 
7361         SigTypeContext typeContext;  // empty type context
7362
7363         loadedType = p.GetTypeHandleThrowing( this,
7364                                               &typeContext,
7365                                               ClassLoader::LoadTypes,
7366                                               CLASS_LOADED,
7367                                               FALSE,
7368                                               NULL,
7369                                               pZapSigContext);
7370 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
7371         g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_1);
7372 #endif
7373     }
7374     EX_CATCH
7375     {
7376         image->GetPreloader()->Error(pBlobSigEntry->blob.token, GET_EXCEPTION());
7377         loadedType = TypeHandle();
7378     }
7379     EX_END_CATCH(SwallowAllExceptions)
7380
7381     RETURN loadedType;
7382 }
7383
7384 //---------------------------------------------------------------------------------------
7385 // 
7386 MethodDesc* Module::LoadIBCMethodHelper(DataImage *image, CORBBTPROF_BLOB_PARAM_SIG_ENTRY * pBlobSigEntry)
7387 {
7388     CONTRACT(MethodDesc*)
7389     {
7390         NOTHROW;
7391         GC_TRIGGERS;
7392         MODE_ANY;
7393         INJECT_FAULT(COMPlusThrowOM());
7394         PRECONDITION(CheckPointer(pBlobSigEntry));
7395     }
7396     CONTRACT_END
7397
7398     MethodDesc* pMethod = NULL;
7399
7400     PCCOR_SIGNATURE    pSig = pBlobSigEntry->sig;
7401     ULONG              cSig = pBlobSigEntry->cSig;
7402
7403     SigPointer p(pSig, cSig);
7404
7405     ZapSig::Context    zapSigContext(this, (void *)this, ZapSig::IbcTokens);
7406     ZapSig::Context *  pZapSigContext = &zapSigContext;
7407
7408     TypeHandle         enclosingType;
7409
7410     //
7411     //  First Decode and Load the enclosing type for this method
7412     //  
7413     EX_TRY
7414     {
7415         // This is what ZapSig::FindTypeHandleFromSignature does...
7416         //
7417         SigTypeContext typeContext;   // empty type context
7418
7419         enclosingType = p.GetTypeHandleThrowing( this,
7420                                   &typeContext,
7421                                   ClassLoader::LoadTypes,
7422                                   CLASS_LOADED,
7423                                   FALSE,
7424                                   NULL,
7425                                   pZapSigContext);
7426         IfFailThrow(p.SkipExactlyOne());
7427 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
7428         g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_2);
7429 #endif
7430     }
7431     EX_CATCH
7432     {
7433         image->GetPreloader()->Error(pBlobSigEntry->blob.token, GET_EXCEPTION());
7434         enclosingType = TypeHandle();
7435     }
7436     EX_END_CATCH(SwallowAllExceptions)
7437
7438     if (enclosingType.IsNull())
7439         return NULL;
7440
7441     //
7442     //  Now Decode and Load the method
7443     //  
7444     EX_TRY
7445     {
7446         MethodTable *pOwnerMT = enclosingType.GetMethodTable();
7447         _ASSERTE(pOwnerMT != NULL);
7448
7449         // decode flags
7450         DWORD methodFlags;
7451         IfFailThrow(p.GetData(&methodFlags));
7452         BOOL isInstantiatingStub = ((methodFlags & ENCODE_METHOD_SIG_InstantiatingStub) == ENCODE_METHOD_SIG_InstantiatingStub);
7453         BOOL isUnboxingStub = ((methodFlags & ENCODE_METHOD_SIG_UnboxingStub) == ENCODE_METHOD_SIG_UnboxingStub);
7454         BOOL fMethodNeedsInstantiation = ((methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) == ENCODE_METHOD_SIG_MethodInstantiation);
7455         BOOL fMethodUsesSlotEncoding = ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == ENCODE_METHOD_SIG_SlotInsteadOfToken);
7456
7457         if ( fMethodUsesSlotEncoding )
7458         {
7459             // get the method desc using slot number
7460             DWORD slot;
7461             IfFailThrow(p.GetData(&slot));
7462
7463             pMethod = pOwnerMT->GetMethodDescForSlot(slot);
7464         }
7465         else  // otherwise we use the normal metadata MethodDef token encoding and we handle ibc tokens.
7466         {
7467             //
7468             // decode method token
7469             //
7470             RID methodRid;
7471             IfFailThrow(p.GetData(&methodRid));
7472
7473             mdMethodDef methodToken; 
7474
7475             //
7476             //  Is our enclosingType from another module?
7477             //  
7478             if (this == enclosingType.GetModule())
7479             {
7480                 //
7481                 // The enclosing type is from our module 
7482                 // The method token is a normal MethodDef token
7483                 // 
7484                 methodToken = TokenFromRid(methodRid, mdtMethodDef);
7485             }
7486             else
7487             {
7488                 //
7489                 // The enclosing type is from an external module 
7490                 // The method token is a ibcExternalMethod token
7491                 //
7492                 idExternalType ibcToken = RidToToken(methodRid, ibcExternalMethod);
7493                 methodToken = this->LookupIbcMethodToken(enclosingType, ibcToken);
7494
7495                 if (IsNilToken(methodToken))
7496                 {
7497                     COMPlusThrow(kTypeLoadException, IDS_IBC_MISSING_EXTERNAL_METHOD);
7498                 }
7499             }
7500
7501             SigTypeContext methodTypeContext( enclosingType );
7502             pMethod = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(
7503                                                   pOwnerMT->GetModule(),
7504                                                   methodToken,
7505                                                   &methodTypeContext,
7506                                                   FALSE,
7507                                                   FALSE );
7508         }
7509
7510         Instantiation inst;
7511
7512         // Instantiate the method if needed, or create a stub to a static method in a generic class.
7513         if (fMethodNeedsInstantiation && pMethod->HasMethodInstantiation())
7514         {
7515             DWORD nargs = pMethod->GetNumGenericMethodArgs();
7516             SIZE_T cbMem;
7517             
7518             if (!ClrSafeInt<SIZE_T>::multiply(nargs, sizeof(TypeHandle), cbMem/* passed by ref */))
7519                 ThrowHR(COR_E_OVERFLOW);
7520             
7521             TypeHandle * pInst = (TypeHandle*) _alloca(cbMem);
7522             SigTypeContext typeContext;   // empty type context
7523
7524             for (DWORD i = 0; i < nargs; i++)
7525             {
7526                 TypeHandle curInst;
7527
7528                 curInst = p.GetTypeHandleThrowing( this,
7529                               &typeContext,
7530                               ClassLoader::LoadTypes,
7531                               CLASS_LOADED,
7532                               FALSE,
7533                               NULL,
7534                               pZapSigContext);
7535
7536                 // curInst will be nullptr when the type fails the versioning bubble check
7537                 if (curInst.IsNull() && IsReadyToRunCompilation())
7538                 {
7539                     COMPlusThrow(kTypeLoadException, IDS_IBC_MISSING_EXTERNAL_TYPE);
7540                 }
7541
7542                 pInst[i] = curInst;
7543                 IfFailThrow(p.SkipExactlyOne());
7544             }
7545
7546             inst = Instantiation(pInst, nargs);
7547         }
7548         else
7549         {
7550             inst = pMethod->LoadMethodInstantiation();
7551         }
7552
7553         // We should now be able to create an instantiation for this generic method
7554
7555         // This must be called even if nargs == 0, in order to create an instantiating
7556         // stub for static methods in generic classees if needed, also for BoxedEntryPointStubs
7557         // in non-generic structs.
7558         const bool allowInstParam = !(isInstantiatingStub || isUnboxingStub);
7559
7560         pMethod = MethodDesc::FindOrCreateAssociatedMethodDesc(pMethod, pOwnerMT,
7561                                                                isUnboxingStub, 
7562                                                                inst, allowInstParam);
7563
7564 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
7565         g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_3);
7566 #endif
7567     }
7568     EX_CATCH
7569     {
7570         // Catch any kTypeLoadException that we may have thrown above
7571         //
7572         image->GetPreloader()->Error(pBlobSigEntry->blob.token, GET_EXCEPTION());
7573         pMethod = NULL;
7574     }
7575     EX_END_CATCH(SwallowAllExceptions)
7576
7577     RETURN pMethod;
7578 } // Module::LoadIBCMethodHelper
7579
7580 #ifdef FEATURE_COMINTEROP
7581 //---------------------------------------------------------------------------------------
7582 // 
7583 // This function is a workaround for missing IBC data in WinRT assemblies and
7584 // not-yet-implemented sharing of IL_STUB(__Canon arg) IL stubs for all interfaces.
7585 //
7586 static void ExpandWindowsRuntimeType(TypeHandle t, DataImage *image)
7587 {
7588     CONTRACTL
7589     {
7590         STANDARD_VM_CHECK;
7591         PRECONDITION(!t.IsNull());
7592     }
7593     CONTRACTL_END
7594
7595     if (t.IsTypeDesc())
7596         return;
7597
7598     // This array contains our poor man's IBC data - instantiations that are known to
7599     // be used by other assemblies.
7600     static const struct
7601     {
7602         LPCUTF8         m_szTypeName;
7603         BinderClassID   m_GenericBinderClassID;
7604     }
7605     rgForcedInstantiations[] = {
7606         { "Windows.UI.Xaml.Data.IGroupInfo", CLASS__IENUMERABLEGENERIC },
7607         { "Windows.UI.Xaml.UIElement",       CLASS__ILISTGENERIC       },
7608         { "Windows.UI.Xaml.Visibility",      CLASS__CLRIREFERENCEIMPL  },
7609         { "Windows.UI.Xaml.VerticalAlignment", CLASS__CLRIREFERENCEIMPL },
7610         { "Windows.UI.Xaml.HorizontalAlignment", CLASS__CLRIREFERENCEIMPL },
7611         // The following instantiations are used by Microsoft.PlayerFramework - http://playerframework.codeplex.com/
7612         { "Windows.UI.Xaml.Media.AudioCategory", CLASS__CLRIREFERENCEIMPL },
7613         { "Windows.UI.Xaml.Media.AudioDeviceType", CLASS__CLRIREFERENCEIMPL },
7614         { "Windows.UI.Xaml.Media.MediaElementState", CLASS__CLRIREFERENCEIMPL },
7615         { "Windows.UI.Xaml.Media.Stereo3DVideoRenderMode", CLASS__CLRIREFERENCEIMPL },
7616         { "Windows.UI.Xaml.Media.Stereo3DVideoPackingMode", CLASS__CLRIREFERENCEIMPL },
7617     };
7618
7619     DefineFullyQualifiedNameForClass();
7620     LPCUTF8 szTypeName = GetFullyQualifiedNameForClass(t.AsMethodTable());
7621
7622     for (SIZE_T i = 0; i < COUNTOF(rgForcedInstantiations); i++)
7623     {
7624         if (strcmp(szTypeName, rgForcedInstantiations[i].m_szTypeName) == 0)
7625         {
7626             EX_TRY
7627             {
7628                 TypeHandle thGenericType = TypeHandle(MscorlibBinder::GetClass(rgForcedInstantiations[i].m_GenericBinderClassID));
7629
7630                 Instantiation inst(&t, 1);
7631                 thGenericType.Instantiate(inst);
7632             }
7633             EX_CATCH
7634             {
7635                 image->GetPreloader()->Error(t.GetCl(), GET_EXCEPTION());
7636             }
7637             EX_END_CATCH(SwallowAllExceptions)
7638         }
7639     }
7640
7641     if (strcmp(szTypeName, "Windows.Foundation.Collections.IObservableVector`1") == 0)
7642     {
7643         EX_TRY
7644         {
7645             TypeHandle thArg = TypeHandle(g_pObjectClass);
7646
7647             Instantiation inst(&thArg, 1);
7648             t.Instantiate(inst);
7649         }
7650         EX_CATCH
7651         {
7652             image->GetPreloader()->Error(t.GetCl(), GET_EXCEPTION());
7653         }
7654         EX_END_CATCH(SwallowAllExceptions)
7655     }
7656 }
7657 #endif // FEATURE_COMINTEROP
7658
7659 //---------------------------------------------------------------------------------------
7660 // 
7661 void Module::ExpandAll(DataImage *image)
7662 {
7663     CONTRACTL
7664     {
7665         STANDARD_VM_CHECK;
7666         PRECONDITION(!IsResource());
7667     }
7668     CONTRACTL_END
7669     
7670     mdToken tk;
7671     DWORD assemblyFlags = GetAssembly()->GetFlags();
7672
7673     //
7674     // Explicitly load the global class.
7675     //
7676
7677     MethodTable *pGlobalMT = GetGlobalMethodTable();
7678
7679     //
7680     // Load all classes.  This also fills out the
7681     // RID maps for the typedefs, method defs,
7682     // and field defs.
7683     //
7684     
7685     IMDInternalImport *pInternalImport = GetMDImport();
7686     {
7687         HENUMInternalHolder hEnum(pInternalImport);
7688         hEnum.EnumTypeDefInit();
7689         
7690         while (pInternalImport->EnumTypeDefNext(&hEnum, &tk))
7691         {
7692 #ifdef FEATURE_COMINTEROP            
7693             // Skip the non-managed WinRT types since they're only used by Javascript and C++
7694             //
7695             // With WinRT files, we want to exclude certain types that cause us problems:
7696             // * Attribute types defined in Windows.Foundation.  The constructor's methodimpl flags
7697             //   specify it is an internal runtime function and gets set as an FCALL when we parse
7698             //   the type
7699             //
7700             if (IsAfContentType_WindowsRuntime(assemblyFlags))
7701             {
7702                 mdToken tkExtends;
7703                 pInternalImport->GetTypeDefProps(tk, NULL, &tkExtends);
7704                 
7705                 if (TypeFromToken(tkExtends) == mdtTypeRef)
7706                 {
7707                     LPCSTR szNameSpace = NULL;
7708                     LPCSTR szName = NULL;
7709                     pInternalImport->GetNameOfTypeRef(tkExtends, &szNameSpace, &szName);
7710                     
7711                     if (!strcmp(szNameSpace, "System") && !_stricmp((szName), "Attribute"))
7712                     {
7713                         continue;
7714                     }
7715                 }
7716             }
7717 #endif // FEATURE_COMINTEROP
7718
7719             TypeHandle t = LoadTypeDefOrRefHelper(image, this, tk);
7720             
7721             if (t.IsNull()) // Skip this type
7722                 continue; 
7723
7724             if (!t.HasInstantiation())
7725             {
7726                 EEClassHashEntry_t *pBucket = NULL;
7727                 HashDatum           data;
7728                 StackSString        ssFullyQualifiedName;
7729                 mdToken             mdEncloser;
7730                 EEClassHashTable   *pTable = GetAvailableClassHash();
7731
7732                 _ASSERTE(pTable != NULL);
7733
7734                 t.GetName(ssFullyQualifiedName);
7735                 
7736                 // Convert to UTF8
7737                 StackScratchBuffer scratch;
7738                 LPCUTF8 szFullyQualifiedName = ssFullyQualifiedName.GetUTF8(scratch);
7739                 
7740                 BOOL isNested = ClassLoader::IsNested(this, tk, &mdEncloser);
7741                 EEClassHashTable::LookupContext sContext;
7742                 pBucket = pTable->GetValue(szFullyQualifiedName, &data, isNested, &sContext);
7743                 
7744                 if (isNested)
7745                 {
7746                     while (pBucket != NULL)
7747                     {
7748                         _ASSERTE (TypeFromToken(tk) == mdtTypeDef);
7749                         BOOL match = GetClassLoader()->CompareNestedEntryWithTypeDef( pInternalImport,
7750                                                                                       mdEncloser,
7751                                                                                       GetAvailableClassHash(),
7752                                                                                       pBucket->GetEncloser());
7753                         if (match)
7754                             break;
7755                         
7756                         pBucket = pTable->FindNextNestedClass(szFullyQualifiedName, &data, &sContext);
7757                     }
7758                 }
7759                 
7760                 // Save the typehandle instead of the token in the hash entry so that ngen'ed images
7761                 // don't have to lookup based on token and update this entry
7762                 if ((pBucket != NULL) && !t.IsNull() && t.IsRestored())
7763                     pBucket->SetData(t.AsPtr());
7764             }
7765             
7766             DWORD nGenericClassParams = t.GetNumGenericArgs();
7767             if (nGenericClassParams != 0)
7768             {
7769                 // For generic types, load the instantiation at Object
7770                 SIZE_T cbMem;
7771                 if (!ClrSafeInt<SIZE_T>::multiply(sizeof(TypeHandle), nGenericClassParams, cbMem/* passed by ref */))
7772                 {
7773                     ThrowHR(COR_E_OVERFLOW);
7774                 }
7775                 CQuickBytes qbGenericClassArgs;
7776                 TypeHandle *genericClassArgs = reinterpret_cast<TypeHandle*>(qbGenericClassArgs.AllocThrows(cbMem));
7777                 for (DWORD i = 0; i < nGenericClassParams; i++)
7778                 {
7779                     genericClassArgs[i] = TypeHandle(g_pCanonMethodTableClass);
7780                 }
7781                 
7782                 TypeHandle thCanonInst = LoadGenericInstantiationHelper(image, this, tk, Instantiation(genericClassArgs, nGenericClassParams));
7783
7784                 // If successful, add the instantiation to the Module's map of generic types instantiated at Object
7785                 if (!thCanonInst.IsNull() && !thCanonInst.IsTypeDesc())
7786                 {
7787                     MethodTable * pCanonMT = thCanonInst.AsMethodTable();
7788                     m_GenericTypeDefToCanonMethodTableMap.AddElement(this, RidFromToken(pCanonMT->GetCl()), pCanonMT);
7789                 }
7790             }
7791
7792 #ifdef FEATURE_COMINTEROP
7793             if (IsAfContentType_WindowsRuntime(assemblyFlags))
7794             {
7795                 ExpandWindowsRuntimeType(t, image);
7796             }
7797 #endif // FEATURE_COMINTEROP
7798         }
7799     }
7800     
7801     //
7802     // Fill out TypeRef RID map
7803     //
7804     
7805     {
7806         HENUMInternalHolder hEnum(pInternalImport);
7807         hEnum.EnumAllInit(mdtTypeRef);
7808         
7809         while (pInternalImport->EnumNext(&hEnum, &tk))
7810         {
7811             mdToken tkResolutionScope = mdTokenNil;
7812             pInternalImport->GetResolutionScopeOfTypeRef(tk, &tkResolutionScope);
7813
7814 #ifdef FEATURE_COMINTEROP            
7815             // WinRT first party files are authored with TypeRefs pointing to TypeDefs in the same module.
7816             // This causes us to load types we do not want to NGen such as custom attributes. We will not
7817             // expand any module local TypeRefs for WinMDs to prevent this.
7818             if(TypeFromToken(tkResolutionScope)==mdtModule && IsAfContentType_WindowsRuntime(assemblyFlags))
7819                 continue;
7820 #endif // FEATURE_COMINTEROP            
7821             TypeHandle t = LoadTypeDefOrRefHelper(image, this, tk);
7822
7823             if (t.IsNull()) // Skip this type
7824                 continue;
7825             
7826 #ifdef FEATURE_COMINTEROP                
7827             if (!g_fNGenWinMDResilient && TypeFromToken(tkResolutionScope) == mdtAssemblyRef)
7828             {
7829                 DWORD dwAssemblyRefFlags;
7830                 IfFailThrow(pInternalImport->GetAssemblyRefProps(tkResolutionScope, NULL, NULL, NULL, NULL, NULL, NULL, &dwAssemblyRefFlags));
7831                 
7832                 if (IsAfContentType_WindowsRuntime(dwAssemblyRefFlags))
7833                 {
7834                     Assembly *pAssembly = t.GetAssembly();
7835                     PEAssembly *pPEAssembly = pAssembly->GetManifestFile();
7836                     AssemblySpec refSpec;
7837                     refSpec.InitializeSpec(tkResolutionScope, pInternalImport);
7838                     LPCSTR psznamespace;
7839                     LPCSTR pszname;
7840                     pInternalImport->GetNameOfTypeRef(tk, &psznamespace, &pszname);
7841                     refSpec.SetWindowsRuntimeType(psznamespace, pszname);
7842                     GetAppDomain()->ToCompilationDomain()->AddDependency(&refSpec,pPEAssembly);
7843                 }
7844             }
7845 #endif // FEATURE_COMINTEROP                
7846         }
7847     }
7848     
7849     //
7850     // Load all type specs
7851     //
7852     
7853     {
7854         HENUMInternalHolder hEnum(pInternalImport);
7855         hEnum.EnumAllInit(mdtTypeSpec);
7856         
7857         while (pInternalImport->EnumNext(&hEnum, &tk))
7858         {
7859             ULONG cSig;
7860             PCCOR_SIGNATURE pSig;
7861             
7862             IfFailThrow(pInternalImport->GetTypeSpecFromToken(tk, &pSig, &cSig));
7863             
7864             // Load all types specs that do not contain variables
7865             if (SigPointer(pSig, cSig).IsPolyType(NULL) == hasNoVars)
7866             {
7867                 LoadTypeSpecHelper(image, this, tk, pSig, cSig);
7868             }
7869         }
7870     }
7871     
7872     //
7873     // Load all the reported parameterized types and methods
7874     //
7875     CorProfileData *  profileData = this->GetProfileData();
7876     CORBBTPROF_BLOB_ENTRY *pBlobEntry = profileData->GetBlobStream();
7877     
7878     if (pBlobEntry != NULL)
7879     {
7880         while (pBlobEntry->TypeIsValid())
7881         {
7882             if (TypeFromToken(pBlobEntry->token) == ibcTypeSpec)
7883             {
7884                 _ASSERTE(pBlobEntry->type == ParamTypeSpec);
7885                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry;
7886
7887                 TypeHandle th = LoadIBCTypeHelper(image, pBlobSigEntry);
7888
7889                 if (!th.IsNull())
7890                 {
7891                     image->GetPreloader()->TriageTypeForZap(th, TRUE);
7892                 }
7893             }
7894             else if (TypeFromToken(pBlobEntry->token) == ibcMethodSpec)
7895             {
7896                 _ASSERTE(pBlobEntry->type == ParamMethodSpec);
7897                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry;
7898                 
7899                 MethodDesc *pMD = LoadIBCMethodHelper(image, pBlobSigEntry);
7900             }
7901             pBlobEntry = pBlobEntry->GetNextEntry();
7902         }
7903         _ASSERTE(pBlobEntry->type == EndOfBlobStream);
7904     }
7905
7906     //
7907     // Record references to all of the hot methods specifiled by MethodProfilingData array
7908     // We call MethodReferencedByCompiledCode to indicate that we plan on compiling this method
7909     //
7910     CORBBTPROF_TOKEN_INFO * pMethodProfilingData = profileData->GetTokenFlagsData(MethodProfilingData);
7911     DWORD                   cMethodProfilingData = profileData->GetTokenFlagsCount(MethodProfilingData);
7912     for (unsigned int i = 0; (i < cMethodProfilingData); i++)
7913     {
7914         mdToken token = pMethodProfilingData[i].token;
7915         DWORD   profilingFlags = pMethodProfilingData[i].flags;
7916
7917         // We call MethodReferencedByCompiledCode only when the profile data indicates that 
7918         // we executed (i.e read) the code for the method
7919         //
7920         if (profilingFlags & (1 << ReadMethodCode))
7921         {
7922             if (TypeFromToken(token) == mdtMethodDef)
7923             {
7924                 MethodDesc *  pMD = LookupMethodDef(token);
7925                 //
7926                 // Record a reference to a hot non-generic method 
7927                 //
7928                 image->GetPreloader()->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pMD);
7929             }
7930             else if (TypeFromToken(token) == ibcMethodSpec)
7931             {
7932                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = profileData->GetBlobSigEntry(token);
7933
7934                 if (pBlobSigEntry != NULL)
7935                 {
7936                     _ASSERTE(pBlobSigEntry->blob.token == token);
7937                     MethodDesc * pMD = LoadIBCMethodHelper(image, pBlobSigEntry);
7938
7939                     if (pMD != NULL)
7940                     {
7941                         // Occasionally a non-instantiated generic method shows up in the IBC data, we should NOT compile it.
7942                         if (!pMD->IsTypicalMethodDefinition())
7943                         {
7944                             //
7945                             // Record a reference to a hot instantiated generic method 
7946                             //
7947                             image->GetPreloader()->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pMD);
7948                         }
7949                     }
7950                 }
7951             }
7952         }
7953     }
7954     
7955     {
7956         //
7957         // Fill out MemberRef RID map and va sig cookies for
7958         // varargs member refs.
7959         //
7960         
7961         HENUMInternalHolder hEnum(pInternalImport);
7962         hEnum.EnumAllInit(mdtMemberRef);
7963         
7964         while (pInternalImport->EnumNext(&hEnum, &tk))
7965         {
7966             mdTypeRef parent;
7967             IfFailThrow(pInternalImport->GetParentOfMemberRef(tk, &parent));
7968
7969 #ifdef FEATURE_COMINTEROP
7970             if (IsAfContentType_WindowsRuntime(assemblyFlags) && TypeFromToken(parent) == mdtTypeRef)
7971             {
7972                 mdToken tkResolutionScope = mdTokenNil;
7973                 pInternalImport->GetResolutionScopeOfTypeRef(parent, &tkResolutionScope);
7974                 // WinRT first party files are authored with TypeRefs pointing to TypeDefs in the same module.
7975                 // This causes us to load types we do not want to NGen such as custom attributes. We will not
7976                 // expand any module local TypeRefs for WinMDs to prevent this.
7977                 if(TypeFromToken(tkResolutionScope)==mdtModule)
7978                     continue;
7979                 
7980                 LPCSTR szNameSpace = NULL;
7981                 LPCSTR szName = NULL;
7982                 if (SUCCEEDED(pInternalImport->GetNameOfTypeRef(parent, &szNameSpace, &szName)))
7983                 {                    
7984                     if (WinMDAdapter::ConvertWellKnownTypeNameFromClrToWinRT(&szNameSpace, &szName))
7985                     {
7986                         //
7987                         // This is a MemberRef from a redirected WinRT type
7988                         // We should skip it as managed view will never see this MemberRef anyway
7989                         // Not skipping this will result MissingMethodExceptions as members in redirected
7990                         // types doesn't exactly match their redirected CLR type counter part
7991                         //
7992                         // Typically we only need to do this for interfaces as we should never see MemberRef
7993                         // from non-interfaces, but here to keep things simple I'm skipping every memberref that
7994                         // belongs to redirected WinRT type
7995                         //
7996                         continue;
7997                     }
7998                 }
7999                 
8000             }
8001 #endif // FEATURE_COMINTEROP
8002
8003             // If the MethodRef has a TypeSpec as a parent (i.e. refers to a method on an array type
8004             // or on a generic class), then it could in turn refer to type variables of
8005             // an unknown class/method. So we don't preresolve any MemberRefs which have TypeSpecs as
8006             // parents.  The RID maps are not filled out for such tokens anyway.
8007             if (TypeFromToken(parent) != mdtTypeSpec)
8008             {
8009                 GetDescFromMemberRefHelper(image, this, tk);
8010             }
8011         }
8012     }
8013     
8014     //
8015     // Fill out binder
8016     //
8017     
8018     if (m_pBinder != NULL)
8019     {
8020         m_pBinder->BindAll();
8021     }
8022
8023 } // Module::ExpandAll
8024
8025 /* static */
8026 void Module::SaveMethodTable(DataImage *    image,
8027                              MethodTable *  pMT,
8028                              DWORD          profilingFlags)
8029 {
8030     STANDARD_VM_CONTRACT;
8031
8032     if (image->IsStored(pMT))
8033         return;
8034
8035     pMT->Save(image, profilingFlags);
8036 }
8037
8038
8039 /* static */
8040 void Module::SaveTypeHandle(DataImage *  image, 
8041                             TypeHandle   t, 
8042                             DWORD        profilingFlags)
8043 {
8044     STANDARD_VM_CONTRACT;
8045
8046     t.CheckRestore();
8047     if (t.IsTypeDesc())
8048     {
8049         TypeDesc *pTD = t.AsTypeDesc();
8050         if (!image->IsStored(pTD))
8051         {
8052             pTD->Save(image);
8053         }
8054     }
8055     else
8056     {
8057         MethodTable *pMT = t.AsMethodTable();
8058         if (pMT != NULL && !image->IsStored(pMT))
8059         {
8060             SaveMethodTable(image, pMT, profilingFlags);
8061             _ASSERTE(image->IsStored(pMT));
8062         }
8063     }
8064 #ifdef _DEBUG 
8065     if (LoggingOn(LF_JIT, LL_INFO100))
8066     {
8067         Module *pPrefModule = Module::GetPreferredZapModuleForTypeHandle(t);
8068         if (image->GetModule() != pPrefModule)
8069         {
8070             StackSString typeName;
8071             t.CheckRestore();
8072             TypeString::AppendTypeDebug(typeName, t);
8073             LOG((LF_ZAP, LL_INFO100, "The type %S was saved outside its preferred module %S\n", typeName.GetUnicode(), pPrefModule->GetPath().GetUnicode()));
8074         }
8075     }
8076 #endif // _DEBUG
8077 }
8078
8079 #ifndef DACCESS_COMPILE
8080
8081 void ModuleCtorInfo::Save(DataImage *image, CorProfileData *profileData)
8082 {
8083     STANDARD_VM_CONTRACT;
8084
8085     if (!numElements)
8086         return;
8087
8088     DWORD i = 0;
8089     DWORD totalBoxedStatics = 0;
8090
8091     // sort the tables so that
8092     // - the hot ppMT entries are at the beginning of the ppMT table
8093     // - the hot cctor entries are at the beginning of the cctorInfoHot table
8094     // - the cold cctor entries are at the end, and we make cctorInfoCold point
8095     //   the first cold entry
8096     //
8097     // the invariant in this loop is:
8098     // items 0...numElementsHot-1 are hot
8099     // items numElementsHot...i-1 are cold
8100     for (i = 0; i < numElements; i++)
8101     {
8102         MethodTable *ppMTTemp = ppMT[i].GetValue();
8103
8104         // Count the number of boxed statics along the way
8105         totalBoxedStatics += ppMTTemp->GetNumBoxedRegularStatics();
8106
8107         bool hot = true; // if there's no profiling data, assume the entries are all hot.
8108         if (profileData->GetTokenFlagsData(TypeProfilingData))
8109         {
8110             if ((profileData->GetTypeProfilingFlagsOfToken(ppMTTemp->GetCl()) & (1 << ReadCCtorInfo)) == 0)
8111                 hot = false;
8112         }
8113         if (hot)
8114         {
8115             // swap ppMT[i] and ppMT[numElementsHot] to maintain the loop invariant
8116             ppMT[i].SetValue(ppMT[numElementsHot].GetValue());
8117             ppMT[numElementsHot].SetValue(ppMTTemp);
8118
8119             numElementsHot++;
8120         }
8121     }
8122
8123     numHotHashes = numElementsHot ? RoundUpToPower2((numElementsHot * sizeof(PTR_MethodTable)) / CACHE_LINE_SIZE) : 0;
8124     numColdHashes = (numElements - numElementsHot) ? RoundUpToPower2(((numElements - numElementsHot) * 
8125                                                                     sizeof(PTR_MethodTable)) / CACHE_LINE_SIZE) : 0;
8126
8127     LOG((LF_ZAP, LL_INFO10, "ModuleCtorInfo::numHotHashes:  0x%4x\n", numHotHashes));
8128     if (numColdHashes != 0)
8129     {
8130         LOG((LF_ZAP, LL_INFO10, "ModuleCtorInfo::numColdHashes: 0x%4x\n", numColdHashes));
8131     }
8132
8133     // The "plus one" is so we can store the offset to the end of the array at the end of
8134     // the hashoffsets arrays, enabling faster lookups.
8135     hotHashOffsets = new DWORD[numHotHashes + 1];
8136     coldHashOffsets = new DWORD[numColdHashes + 1];
8137
8138     DWORD *hashArray = new DWORD[numElements];
8139
8140     for (i = 0; i < numElementsHot; i++)
8141     {
8142         hashArray[i] = GenerateHash(ppMT[i].GetValue(), HOT);
8143     }
8144     for (i = numElementsHot; i < numElements; i++)
8145     {
8146         hashArray[i] = GenerateHash(ppMT[i].GetValue(), COLD);
8147     }
8148
8149     // Sort the two arrays by hash values to create regions with the same hash values.
8150     ClassCtorInfoEntryArraySort cctorInfoHotSort(hashArray, ppMT, numElementsHot);
8151     ClassCtorInfoEntryArraySort cctorInfoColdSort(hashArray + numElementsHot, ppMT + numElementsHot, 
8152                                                     numElements - numElementsHot);
8153     cctorInfoHotSort.Sort();
8154     cctorInfoColdSort.Sort();
8155
8156     // Generate the indices that index into the correct "hash region" in the hot part of the ppMT array, and store 
8157     // them in the hotHashOffests arrays.
8158     DWORD curHash = 0;
8159     i = 0;
8160     while (i < numElementsHot)
8161     {
8162         if (curHash < hashArray[i])
8163         {
8164             hotHashOffsets[curHash++] = i;
8165         }
8166         else if (curHash == hashArray[i])
8167         {
8168             hotHashOffsets[curHash++] = i++;
8169         }
8170         else 
8171         {
8172             i++;
8173         }
8174     }
8175     while (curHash <= numHotHashes)
8176     {
8177         hotHashOffsets[curHash++] = numElementsHot;
8178     }
8179
8180     // Generate the indices that index into the correct "hash region" in the hot part of the ppMT array, and store 
8181     // them in the coldHashOffsets arrays.
8182     curHash = 0;
8183     i = numElementsHot;
8184     while (i < numElements)
8185     {
8186         if (curHash < hashArray[i])
8187         {
8188             coldHashOffsets[curHash++] = i;
8189         }
8190         else if (curHash == hashArray[i])
8191         {
8192             coldHashOffsets[curHash++] = i++;
8193         }
8194         else i++;
8195     }
8196     while (curHash <= numColdHashes)
8197     {
8198         coldHashOffsets[curHash++] = numElements;
8199     }
8200
8201     delete[] hashArray;
8202
8203
8204     cctorInfoHot    = new ClassCtorInfoEntry[numElements];
8205
8206     // make cctorInfoCold point to the first cold element
8207     cctorInfoCold   = cctorInfoHot + numElementsHot;
8208
8209     ppHotGCStaticsMTs   = (totalBoxedStatics != 0) ? new RelativeFixupPointer<PTR_MethodTable>[totalBoxedStatics] : NULL;
8210     numHotGCStaticsMTs  = totalBoxedStatics;
8211
8212     DWORD iGCStaticMT = 0;
8213
8214     for (i = 0; i < numElements; i++)
8215     {
8216         if (numElements == numElementsHot)
8217         {
8218             numHotGCStaticsMTs  = iGCStaticMT;
8219             numColdGCStaticsMTs = (totalBoxedStatics - iGCStaticMT);
8220
8221             // make ppColdGCStaticsMTs point to the first cold element
8222             ppColdGCStaticsMTs = ppHotGCStaticsMTs + numHotGCStaticsMTs;
8223         }
8224
8225         MethodTable* pMT = ppMT[i].GetValue();
8226         ClassCtorInfoEntry* pEntry = &cctorInfoHot[i];
8227
8228         WORD numBoxedStatics = pMT->GetNumBoxedRegularStatics();
8229         pEntry->numBoxedStatics = numBoxedStatics;
8230         pEntry->hasFixedAddressVTStatics = !!pMT->HasFixedAddressVTStatics();
8231
8232         FieldDesc *pField = pMT->HasGenericsStaticsInfo() ? 
8233             pMT->GetGenericsStaticFieldDescs() : (pMT->GetApproxFieldDescListRaw() + pMT->GetNumIntroducedInstanceFields());
8234         FieldDesc *pFieldEnd = pField + pMT->GetNumStaticFields();
8235
8236         pEntry->firstBoxedStaticOffset = (DWORD)-1;
8237         pEntry->firstBoxedStaticMTIndex = (DWORD)-1;
8238
8239         DWORD numFoundBoxedStatics = 0;
8240         while (pField < pFieldEnd)
8241         {
8242             _ASSERTE(pField->IsStatic());
8243
8244             if (!pField->IsSpecialStatic() && pField->IsByValue())
8245             {
8246                 if (pEntry->firstBoxedStaticOffset == (DWORD)-1)
8247                 {
8248                     pEntry->firstBoxedStaticOffset = pField->GetOffset();
8249                     pEntry->firstBoxedStaticMTIndex = iGCStaticMT;
8250                 }
8251                 _ASSERTE(pField->GetOffset() - pEntry->firstBoxedStaticOffset 
8252                     == (iGCStaticMT - pEntry->firstBoxedStaticMTIndex) * sizeof(MethodTable*));
8253
8254                 TypeHandle th = pField->GetFieldTypeHandleThrowing();
8255                 ppHotGCStaticsMTs[iGCStaticMT++].SetValueMaybeNull(th.GetMethodTable());
8256
8257                 numFoundBoxedStatics++;
8258             }
8259             pField++;
8260         }
8261         _ASSERTE(numBoxedStatics == numFoundBoxedStatics);
8262     }
8263     _ASSERTE(iGCStaticMT == totalBoxedStatics);
8264
8265     if (numElementsHot > 0)
8266     {
8267         image->StoreStructure(cctorInfoHot,
8268                                 sizeof(ClassCtorInfoEntry) * numElementsHot,
8269                                 DataImage::ITEM_MODULE_CCTOR_INFO_HOT);
8270
8271         image->StoreStructure(hotHashOffsets,
8272                                 sizeof(DWORD) * (numHotHashes + 1),
8273                                 DataImage::ITEM_MODULE_CCTOR_INFO_HOT);
8274     }
8275
8276     if (numElements > 0)
8277         image->StoreStructure(ppMT,
8278                                 sizeof(RelativePointer<MethodTable *>) * numElements,
8279                                 DataImage::ITEM_MODULE_CCTOR_INFO_HOT);
8280
8281     if (numElements > numElementsHot)
8282     {
8283         image->StoreStructure(cctorInfoCold,
8284                                 sizeof(ClassCtorInfoEntry) * (numElements - numElementsHot),
8285                                 DataImage::ITEM_MODULE_CCTOR_INFO_COLD);
8286
8287         image->StoreStructure(coldHashOffsets,
8288                                 sizeof(DWORD) * (numColdHashes + 1),
8289                                 DataImage::ITEM_MODULE_CCTOR_INFO_COLD);
8290     }
8291
8292     if ( numHotGCStaticsMTs )
8293     {
8294         // Save the mt templates
8295         image->StoreStructure( ppHotGCStaticsMTs, numHotGCStaticsMTs * sizeof(RelativeFixupPointer<MethodTable*>),
8296                                 DataImage::ITEM_GC_STATIC_HANDLES_HOT);
8297     }
8298     else
8299     {
8300         ppHotGCStaticsMTs = NULL;
8301     }
8302
8303     if ( numColdGCStaticsMTs )
8304     {
8305         // Save the hot mt templates
8306         image->StoreStructure( ppColdGCStaticsMTs, numColdGCStaticsMTs * sizeof(RelativeFixupPointer<MethodTable*>),
8307                                 DataImage::ITEM_GC_STATIC_HANDLES_COLD);
8308     }
8309     else
8310     {
8311         ppColdGCStaticsMTs = NULL;
8312     }
8313 }
8314
8315 #endif // !DACCESS_COMPILE
8316
8317 bool Module::AreAllClassesFullyLoaded()
8318 {
8319     STANDARD_VM_CONTRACT;
8320
8321     // Adjust for unused space
8322     IMDInternalImport *pImport = GetMDImport();
8323
8324     HENUMInternalHolder hEnum(pImport);
8325     hEnum.EnumAllInit(mdtTypeDef);
8326
8327     mdTypeDef token;
8328     while (pImport->EnumNext(&hEnum, &token))
8329     {
8330         _ASSERTE(TypeFromToken(token) == mdtTypeDef);
8331
8332         // Special care has to been taken with COR_GLOBAL_PARENT_TOKEN, as the class
8333         // may not be needed, (but we have to distinguish between not needed and threw error).
8334         if (token == COR_GLOBAL_PARENT_TOKEN &&
8335             !NeedsGlobalMethodTable())
8336         {
8337             // No EEClass for this token if there was no need for a global method table
8338             continue;
8339         }
8340
8341         TypeHandle th = LookupTypeDef(token);
8342         if (th.IsNull())
8343             return false;
8344
8345         if (!th.AsMethodTable()->IsFullyLoaded())
8346             return false;
8347     }
8348
8349     return true;
8350 }
8351
8352 void Module::PrepareTypesForSave(DataImage *image)
8353 {
8354     STANDARD_VM_CONTRACT;
8355
8356     //
8357     // Prepare typedefs
8358     //
8359     {
8360         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
8361         while (typeDefIter.Next())
8362         {
8363             MethodTable * pMT = typeDefIter.GetElement();
8364
8365             if (pMT == NULL || !pMT->IsFullyLoaded())
8366                 continue;
8367
8368
8369         }
8370     }
8371
8372     //
8373     // Prepare typespecs
8374     //
8375     {
8376         // Create a local copy in case the new elements are added to the hashtable during population
8377         InlineSArray<TypeHandle, 20> pTypes;
8378
8379         // Make sure the iterator is destroyed before there is a chance of loading new types
8380         {
8381             EETypeHashTable::Iterator it(m_pAvailableParamTypes);
8382             EETypeHashEntry *pEntry;
8383             while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
8384             {
8385                 TypeHandle t = pEntry->GetTypeHandle();
8386
8387                 if (t.IsTypeDesc())
8388                     continue;
8389
8390                 if (!image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(t.AsPtr())))
8391                     continue;
8392
8393                 pTypes.Append(t);
8394             }
8395         }
8396
8397     }
8398
8399     image->GetPreloader()->TriageForZap(FALSE, FALSE);
8400 }
8401
8402 static const char* const MethodTableRestoreReasonDescription[TotalMethodTables + 1] =
8403 {
8404     #undef RESTORE_REASON_FUNC
8405     #define RESTORE_REASON_FUNC(s) #s,
8406
8407     METHODTABLE_RESTORE_REASON()
8408
8409     #undef RESTORE_REASON
8410
8411     "TotalMethodTablesEvaluated"
8412 };
8413
8414
8415 // MethodDescByMethodTableTraits could be a local class in Module::Save(), but g++ doesn't like
8416 // instantiating templates with private classes.
8417 class MethodDescByMethodTableTraits : public NoRemoveSHashTraits< DefaultSHashTraits<MethodDesc *> >
8418 {
8419 public:
8420     typedef MethodTable * key_t;
8421     static MethodDesc * Null() { return NULL; }
8422     static bool IsNull(MethodDesc * pMD) { return pMD == NULL; }
8423     static MethodTable * GetKey(MethodDesc * pMD) { return pMD->GetMethodTable_NoLogging(); }
8424     static count_t Hash(MethodTable * pMT) { LIMITED_METHOD_CONTRACT; return (count_t) (UINT_PTR) pMT->GetTypeDefRid_NoLogging(); }
8425     static BOOL Equals(MethodTable * pMT1, MethodTable * pMT2)
8426     {
8427         return pMT1 == pMT2;
8428     }
8429 };
8430
8431 void Module::Save(DataImage *image)
8432 {
8433     STANDARD_VM_CONTRACT;
8434
8435     // Precompute type specific auxiliary information saved into NGen image
8436     // Note that this operation can load new types.
8437     PrepareTypesForSave(image);
8438
8439     // Cache values of all persisted flags computed from custom attributes
8440     IsNoStringInterning();
8441     IsRuntimeWrapExceptions();
8442     IsPreV4Assembly();
8443
8444     HasDefaultDllImportSearchPathsAttribute();
8445
8446     // Precompute property information to avoid runtime metadata lookup
8447     PopulatePropertyInfoMap();
8448
8449     // Any any elements and compute values of any LookupMap flags that were not available previously
8450     FinalizeLookupMapsPreSave(image);
8451
8452     //
8453     // Save the module
8454     //
8455
8456     ZapStoredStructure * pModuleNode = image->StoreStructure(this, sizeof(Module),
8457                                     DataImage::ITEM_MODULE);
8458
8459     m_pNGenLayoutInfo = (NGenLayoutInfo *)(void *)image->GetModule()->GetLoaderAllocator()->
8460         GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(NGenLayoutInfo)));
8461     image->StoreStructure(m_pNGenLayoutInfo, sizeof(NGenLayoutInfo), DataImage::ITEM_BINDER_ITEMS);
8462
8463     //
8464     // If we are NGening, we don't need to keep a list of va
8465     // sig cookies, as we already have a complete set (of course we do
8466     // have to persist the cookies themselves, though.
8467     //
8468
8469     //
8470     // Initialize maps of child data structures.  Note that each tables's blocks are
8471     // concantentated to a single block in the process.
8472     //
8473     CorProfileData * profileData = GetProfileData();
8474
8475     // ngen the neutral resources culture
8476     if(GetNeutralResourcesLanguage(&m_pszCultureName, &m_CultureNameLength, &m_FallbackLocation, TRUE)) {
8477         image->StoreStructure((void *) m_pszCultureName,
8478                                         (ULONG)(m_CultureNameLength + 1),
8479                                         DataImage::ITEM_BINDER_ITEMS,
8480                                         1);
8481     }
8482
8483
8484     m_TypeRefToMethodTableMap.Save(image, DataImage::ITEM_TYPEREF_MAP, profileData, mdtTypeRef);
8485     image->BindPointer(&m_TypeRefToMethodTableMap, pModuleNode, offsetof(Module, m_TypeRefToMethodTableMap));
8486
8487     if(m_pMemberRefToDescHashTable)
8488         m_pMemberRefToDescHashTable->Save(image, profileData);
8489
8490     m_TypeDefToMethodTableMap.Save(image, DataImage::ITEM_TYPEDEF_MAP, profileData, mdtTypeDef);
8491     image->BindPointer(&m_TypeDefToMethodTableMap, pModuleNode, offsetof(Module, m_TypeDefToMethodTableMap));
8492
8493     m_MethodDefToDescMap.Save(image, DataImage::ITEM_METHODDEF_MAP, profileData, mdtMethodDef);
8494     image->BindPointer(&m_MethodDefToDescMap, pModuleNode, offsetof(Module, m_MethodDefToDescMap));
8495
8496     m_FieldDefToDescMap.Save(image, DataImage::ITEM_FIELDDEF_MAP, profileData, mdtFieldDef);
8497     image->BindPointer(&m_FieldDefToDescMap, pModuleNode, offsetof(Module, m_FieldDefToDescMap));
8498
8499     m_GenericParamToDescMap.Save(image, DataImage::ITEM_GENERICPARAM_MAP, profileData, mdtGenericParam);
8500     image->BindPointer(&m_GenericParamToDescMap, pModuleNode, offsetof(Module, m_GenericParamToDescMap));
8501
8502     m_GenericTypeDefToCanonMethodTableMap.Save(image, DataImage::ITEM_GENERICTYPEDEF_MAP, profileData, mdtTypeDef);
8503     image->BindPointer(&m_GenericTypeDefToCanonMethodTableMap, pModuleNode, offsetof(Module, m_GenericTypeDefToCanonMethodTableMap));
8504
8505     if (m_pAvailableClasses)
8506         m_pAvailableClasses->Save(image, profileData);
8507
8508     //
8509     // Also save the parent maps; the contents will
8510     // need to be rewritten, but we can allocate the
8511     // space in the image.
8512     //
8513
8514     // these items have no hot list and no attribution
8515     m_FileReferencesMap.Save(image, DataImage::ITEM_FILEREF_MAP, profileData, 0);
8516     image->BindPointer(&m_FileReferencesMap, pModuleNode, offsetof(Module, m_FileReferencesMap));
8517
8518     m_ManifestModuleReferencesMap.Save(image, DataImage::ITEM_ASSEMREF_MAP, profileData, 0);
8519     image->BindPointer(&m_ManifestModuleReferencesMap, pModuleNode, offsetof(Module, m_ManifestModuleReferencesMap));
8520
8521     m_MethodDefToPropertyInfoMap.Save(image, DataImage::ITEM_PROPERTYINFO_MAP, profileData, 0, TRUE /*fCopyValues*/);
8522     image->BindPointer(&m_MethodDefToPropertyInfoMap, pModuleNode, offsetof(Module, m_MethodDefToPropertyInfoMap));
8523
8524     if (m_pBinder != NULL)
8525         m_pBinder->Save(image);
8526
8527     if (profileData)
8528     {
8529         // Store types.
8530
8531         // Saving hot things first is a very good thing, because we place items
8532         // in the order they are saved and things that have hot items are also
8533         // more likely to have their other structures touched, hence these should
8534         // also be placed together, at least if we don't have any further information to go on.
8535         // Note we place particular hot items with more care in the Arrange phase.
8536         //
8537         CORBBTPROF_TOKEN_INFO * pTypeProfilingData = profileData->GetTokenFlagsData(TypeProfilingData);
8538         DWORD                   cTypeProfilingData = profileData->GetTokenFlagsCount(TypeProfilingData);
8539
8540         for (unsigned int i = 0; i < cTypeProfilingData; i++)
8541         {
8542             CORBBTPROF_TOKEN_INFO *entry = &pTypeProfilingData[i];
8543             mdToken token = entry->token;
8544             DWORD   flags = entry->flags;
8545 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
8546             g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_4);
8547 #endif
8548
8549             if ((flags & (1 << ReadMethodTable)) == 0)
8550                 continue;
8551
8552             if (TypeFromToken(token) == mdtTypeDef)
8553             {
8554                 MethodTable *pMT = LookupTypeDef(token).GetMethodTable();
8555                 if (pMT && pMT->IsFullyLoaded())
8556                 {
8557                     SaveMethodTable(image, pMT, flags);
8558                 }
8559             }
8560             else  if (TypeFromToken(token) == ibcTypeSpec)
8561             {
8562                 CORBBTPROF_BLOB_ENTRY *pBlobEntry = profileData->GetBlobStream();
8563                 if (pBlobEntry)
8564                 {
8565                     while (pBlobEntry->TypeIsValid())
8566                     {
8567                         if (TypeFromToken(pBlobEntry->token) == ibcTypeSpec)
8568                         {
8569                             _ASSERTE(pBlobEntry->type == ParamTypeSpec);
8570                             
8571                             if (pBlobEntry->token == token)
8572                             {
8573                                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry;
8574                                 TypeHandle th = LoadIBCTypeHelper(image, pBlobSigEntry);
8575                                 
8576                                 if (!th.IsNull())
8577                                 {
8578                                     // When we have stale IBC data the type could have been rejected from this image.
8579                                     if (image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(th.AsPtr())))
8580                                     {
8581                                         SaveTypeHandle(image, th, flags);
8582                                     }
8583                                 }
8584                             }
8585                         }
8586                         pBlobEntry = pBlobEntry->GetNextEntry();
8587                     }
8588                     _ASSERTE(pBlobEntry->type == EndOfBlobStream);
8589                 }
8590             }
8591         }
8592
8593         if (m_pAvailableParamTypes != NULL)
8594         {
8595             // If we have V1 IBC data then we save the hot
8596             //  out-of-module generic instantiations here
8597
8598             CORBBTPROF_TOKEN_INFO * tokens_begin = profileData->GetTokenFlagsData(GenericTypeProfilingData);
8599             CORBBTPROF_TOKEN_INFO * tokens_end = tokens_begin + profileData->GetTokenFlagsCount(GenericTypeProfilingData);
8600
8601             if (tokens_begin != tokens_end)
8602             {
8603                 SArray<CORBBTPROF_TOKEN_INFO> tokens(tokens_begin, tokens_end);
8604                 tokens_begin = &tokens[0];
8605                 tokens_end = tokens_begin + tokens.GetCount();
8606
8607                 util::sort(tokens_begin, tokens_end);
8608
8609                 // enumerate AvailableParamTypes map and find all hot generic instantiations
8610                 EETypeHashTable::Iterator it(m_pAvailableParamTypes);
8611                 EETypeHashEntry *pEntry;
8612                 while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
8613                 {
8614                     TypeHandle t = pEntry->GetTypeHandle();
8615 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
8616                     g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_5);
8617 #endif
8618                     
8619                     if (t.HasInstantiation())
8620                     {
8621                         SString tokenName;
8622                         t.GetName(tokenName);
8623                         unsigned cur_token = tokenName.Hash() & 0xffff;
8624
8625                         CORBBTPROF_TOKEN_INFO * found = util::lower_bound(tokens_begin, tokens_end, CORBBTPROF_TOKEN_INFO(cur_token));
8626                         if (found != tokens_end && found->token == cur_token && (found->flags & (1 << ReadMethodTable)))
8627                         {
8628                             // When we have stale IBC data the type could have been rejected from this image.
8629                             if (image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(t.AsPtr())))
8630                                 SaveTypeHandle(image, t, found->flags);
8631                         }
8632                     }
8633                 }
8634             }
8635         }
8636     }
8637
8638     //
8639     // Now save any types in the TypeDefToMethodTableMap map
8640
8641     {
8642         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
8643
8644         while (typeDefIter.Next())
8645         {
8646             MethodTable * pMT = typeDefIter.GetElement();
8647
8648             if (pMT != NULL && 
8649                 !image->IsStored(pMT) && pMT->IsFullyLoaded())
8650             {
8651                 image->BeginAssociatingStoredObjectsWithMethodTable(pMT);
8652                 SaveMethodTable(image, pMT, 0);
8653                 image->EndAssociatingStoredObjectsWithMethodTable();
8654             }
8655         }
8656     }
8657
8658     //
8659     // Now save any TypeDescs in m_GenericParamToDescMap map
8660
8661     {
8662         LookupMap<PTR_TypeVarTypeDesc>::Iterator genericParamIter(&m_GenericParamToDescMap);
8663
8664         while (genericParamIter.Next())
8665         {
8666             TypeVarTypeDesc *pTD = genericParamIter.GetElement();
8667
8668             if (pTD != NULL)
8669             {
8670                 pTD->Save(image);
8671             }
8672         }
8673     }
8674
8675 #ifdef _DEBUG
8676     SealGenericTypesAndMethods();
8677 #endif
8678
8679     //
8680     // Now save any  types in the AvailableParamTypes map
8681     //
8682     if (m_pAvailableParamTypes != NULL)
8683     {
8684         EETypeHashTable::Iterator it(m_pAvailableParamTypes);
8685         EETypeHashEntry *pEntry;
8686         while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
8687         {
8688             TypeHandle t = pEntry->GetTypeHandle();
8689
8690             if (image->GetPreloader()->IsTypeInTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE(t.AsPtr())))
8691             {
8692                 if (t.GetCanonicalMethodTable() != NULL)
8693                 {
8694                     image->BeginAssociatingStoredObjectsWithMethodTable(t.GetCanonicalMethodTable());
8695                     SaveTypeHandle(image, t, 0);
8696                     image->EndAssociatingStoredObjectsWithMethodTable();
8697                 }
8698                 else
8699                 {
8700                     SaveTypeHandle(image, t, 0);
8701                 }
8702             }
8703         }
8704     }
8705
8706     //
8707     // Now save any methods in the InstMethodHashTable
8708     // 
8709     if (m_pInstMethodHashTable != NULL)
8710     {
8711         //
8712         // Find all MethodDescs that we are going to save, and hash them with MethodTable as the key
8713         //
8714
8715         typedef SHash<MethodDescByMethodTableTraits> MethodDescByMethodTableHash;
8716
8717         MethodDescByMethodTableHash methodDescs;
8718
8719         InstMethodHashTable::Iterator it(m_pInstMethodHashTable);
8720         InstMethodHashEntry *pEntry;
8721         while (m_pInstMethodHashTable->FindNext(&it, &pEntry))
8722         {
8723             MethodDesc *pMD = pEntry->GetMethod();
8724
8725             _ASSERTE(!pMD->IsTightlyBoundToMethodTable());
8726
8727             if (!image->IsStored(pMD) &&
8728                 image->GetPreloader()->IsMethodInTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE(pMD)))
8729             {
8730                 methodDescs.Add(pMD);
8731             }
8732         }
8733
8734         //
8735         // Save all MethodDescs on the same MethodTable using one chunk builder
8736         //
8737
8738         for (MethodDescByMethodTableHash::Iterator i1 = methodDescs.Begin(), end1 = methodDescs.End(); i1 != end1; i1++)
8739         {
8740             MethodDesc * pMD = *(i1);
8741             if (image->IsStored(pMD))
8742                 continue;
8743
8744             MethodTable * pMT = pMD->GetMethodTable();
8745
8746             MethodDesc::SaveChunk methodDescSaveChunk(image);
8747
8748             for (MethodDescByMethodTableHash::KeyIterator i2 = methodDescs.Begin(pMT), end2 = methodDescs.End(pMT); i2 != end2; i2++)
8749             {
8750                 _ASSERTE(!image->IsStored(*i2));
8751                 methodDescSaveChunk.Append(*i2);
8752             }
8753
8754             methodDescSaveChunk.Save();
8755         }
8756     }
8757
8758     // Now save the tables themselves
8759     if (m_pAvailableParamTypes != NULL)
8760     {
8761         m_pAvailableParamTypes->Save(image, this, profileData);
8762     }
8763
8764     if (m_pInstMethodHashTable != NULL)
8765     {
8766         m_pInstMethodHashTable->Save(image, profileData);
8767     }
8768
8769     {
8770         MethodTable * pStubMT = GetILStubCache()->GetStubMethodTable();
8771         if (pStubMT != NULL)
8772         {
8773             SaveMethodTable(image, pStubMT, 0);
8774         }
8775     }
8776
8777     if (m_pStubMethodHashTable != NULL)
8778     {
8779         m_pStubMethodHashTable->Save(image, profileData);
8780     }
8781
8782 #ifdef FEATURE_COMINTEROP
8783     // the type saving operations above had the side effect of populating m_pGuidToTypeHash
8784     if (m_pGuidToTypeHash != NULL)
8785     {
8786         m_pGuidToTypeHash->Save(image, profileData);
8787     }
8788 #endif // FEATURE_COMINTEROP
8789
8790     // Compute and save the property name set
8791     PrecomputeMatchingProperties(image);
8792     image->StoreStructure(m_propertyNameSet,
8793                           m_nPropertyNameSet * sizeof(BYTE),
8794                           DataImage::ITEM_PROPERTY_NAME_SET);
8795
8796
8797     // Sort the list of RVA statics in an ascending order wrt the RVA
8798     // and save them.
8799     image->SaveRvaStructure();
8800
8801     // Save static data
8802     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Saving module static data\n"));
8803
8804     // We have this scenario where ngen will fail to load some classes but will generate
8805     // a valid exe, or it will choose not to save some loaded classes due to some error
8806     // conditions, where statics will be committed at runtime for the classes that ngen
8807     // wasn't able to load or save. So we can't cut down the static block size blindly if we've
8808     // failed to load or save any class. We don't think this scenario deserves complicated code
8809     // paths to get the extra working set perf (you would be pulling in the jitter if
8810     // you need any of these classes), So we are basically simplifying this down, if we failed
8811     // to load or save any class we won't compress the statics block and will persist the original
8812     // estimation. 
8813
8814     // All classes were loaded and saved, cut down the block
8815     if (AreAllClassesFullyLoaded())
8816     {
8817         // Set a mark indicating we had all our classes loaded
8818         m_pRegularStaticOffsets = (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED;
8819         m_pThreadStaticOffsets = (PTR_DWORD) NGEN_STATICS_ALLCLASSES_WERE_LOADED;
8820     }
8821     else
8822     {
8823         // Since not all of the classes loaded we want to zero the pointers to the offset tables so they'll be
8824         // recalculated at runtime. But we can't do that here since we might try to reload some of the failed
8825         // types during the arrange phase (as the result of trying to parse profiling data). So we'll defer
8826         // zero'ing anything until the fixup phase.
8827
8828         // Not all classes were stored, revert to uncompressed maps to support run-time changes
8829         m_TypeDefToMethodTableMap.ConvertSavedMapToUncompressed(image, DataImage::ITEM_TYPEDEF_MAP);
8830         m_MethodDefToDescMap.ConvertSavedMapToUncompressed(image, DataImage::ITEM_METHODDEF_MAP);
8831     }
8832
8833     m_ModuleCtorInfo.Save(image, profileData);
8834     image->BindPointer(&m_ModuleCtorInfo, pModuleNode, offsetof(Module, m_ModuleCtorInfo));
8835
8836     if (m_pDynamicStaticsInfo)
8837     {
8838         image->StoreStructure(m_pDynamicStaticsInfo, m_maxDynamicEntries*sizeof(DynamicStaticsInfo),
8839                                           DataImage::ITEM_DYNAMIC_STATICS_INFO_TABLE);
8840     }
8841
8842     InlineTrackingMap *inlineTrackingMap = image->GetInlineTrackingMap();
8843     if (inlineTrackingMap) 
8844     {
8845         m_pPersistentInlineTrackingMapNGen = new (image->GetHeap()) PersistentInlineTrackingMapNGen(this);
8846         m_pPersistentInlineTrackingMapNGen->Save(image, inlineTrackingMap);
8847     }
8848
8849     if (m_pNgenStats && g_CorCompileVerboseLevel >= CORCOMPILE_STATS)
8850     {
8851         GetSvcLogger()->Printf ("%-35s: %s\n", "MethodTable Restore Reason", "Count");
8852         DWORD dwTotal = 0;
8853         for (int i=0; i<TotalMethodTables; i++)
8854         {
8855             GetSvcLogger()->Printf ("%-35s: %d\n", MethodTableRestoreReasonDescription[i], m_pNgenStats->MethodTableRestoreNumReasons[i]);
8856             dwTotal += m_pNgenStats->MethodTableRestoreNumReasons[i];
8857         }
8858         GetSvcLogger()->Printf ("%-35s: %d\n", "TotalMethodTablesNeedRestore", dwTotal);
8859         GetSvcLogger()->Printf ("%-35s: %d\n", MethodTableRestoreReasonDescription[TotalMethodTables], m_pNgenStats->MethodTableRestoreNumReasons[TotalMethodTables]);
8860     }
8861 }
8862
8863
8864 #ifdef _DEBUG
8865 //
8866 // We call these methods to seal the
8867 // lists: m_pAvailableClasses and m_pAvailableParamTypes 
8868 // 
8869 void Module::SealGenericTypesAndMethods()
8870 {
8871     LIMITED_METHOD_CONTRACT;
8872     // Enforce that after this point in ngen that no more types or methods will be loaded.
8873     //
8874     // We increment the seal count here and only decrement it after we have completed the ngen image
8875     //
8876     if (m_pAvailableParamTypes != NULL)
8877     {
8878         m_pAvailableParamTypes->Seal();
8879     }
8880     if (m_pInstMethodHashTable != NULL)
8881     {
8882         m_pInstMethodHashTable->Seal();
8883     }
8884 }
8885 //
8886 // We call these methods to unseal the
8887 // lists: m_pAvailableClasses and m_pAvailableParamTypes 
8888 // 
8889 void Module::UnsealGenericTypesAndMethods()
8890 {
8891     LIMITED_METHOD_CONTRACT;
8892     // Allow us to create generic types and methods again
8893     // 
8894     // We only decrement it after we have completed the ngen image
8895     //
8896     if (m_pAvailableParamTypes != NULL)
8897     {
8898         m_pAvailableParamTypes->Unseal();
8899     }
8900     if (m_pInstMethodHashTable != NULL)
8901     {
8902         m_pInstMethodHashTable->Unseal();
8903     }
8904 }
8905 #endif
8906
8907
8908 void Module::PrepopulateDictionaries(DataImage *image, BOOL nonExpansive)
8909 {
8910     STANDARD_VM_CONTRACT;
8911
8912     // Prepopulating the dictionaries for instantiated types
8913     // is in theory an iteraive process, i.e. filling in
8914     // a dictionary slot may result in a class load of a new type whose
8915     // dictionary may itself need to be prepopulated.  The type expressions
8916     // involved can get larger, so there's no a-priori reason to expect this
8917     // process to terminate.
8918     //
8919     // Given a starting set of instantiated types, several strategies are
8920     // thus possible - no prepopulation (call this PP0), or
8921     // prepopulate only the dictionaries of the types that are in the initial
8922     // set (call this PP1), or do two iterations (call this PP2) etc. etc.
8923     // Whichever strategy we choose we can always afford to do
8924     // one round of prepopulation where we populate slots
8925     // whose corresponding resulting method/types are already loaded.
8926     // Call this PPn+PP-FINAL.
8927     //
8928     // Below we implement PP1+PP-FINAL for instantiated types and PP0+PP-FINAL
8929     // for instantiations of generic methods.  We use PP1 because most collection
8930     // classes (List, Dictionary etc.) only require one pass of prepopulation in order
8931     // to fully prepopulate the dictionary.
8932
8933     // Do PP1 for instantiated types... Do one iteration where we force type loading...
8934     // Because this phase may cause new entries to appear in the hash table we
8935     // copy the array of types to the stack before we do anything else.
8936     if (!nonExpansive && CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Prepopulate1))
8937     {
8938         if (m_pAvailableParamTypes != NULL)
8939         {
8940             // Create a local copy in case the new elements are added to the hashtable during population
8941             InlineSArray<TypeHandle, 20> pTypes;
8942
8943             EETypeHashTable::Iterator it(m_pAvailableParamTypes);
8944             EETypeHashEntry *pEntry;
8945             while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
8946             {
8947                 TypeHandle th = pEntry->GetTypeHandle();
8948                 if (th.IsTypeDesc())
8949                     continue;
8950
8951                 // Don't do prepopulation for open types - they shouldn't really have dictionaries anyway.
8952                 MethodTable * pMT = th.AsMethodTable();
8953                 if (pMT->ContainsGenericVariables())
8954                     continue;
8955
8956                 // Only do PP1 on things that land in their preferred Zap module.
8957                 // Forcing the load of dictionary entries in the case where we are
8958                 // speculatively saving a copy of an instantiation outside its preferred
8959                 // zap module is too expensive for the common collection class cases.
8960                 ///
8961                 // Invalid generic instantiations will not be fully loaded.
8962                 // We want to ignore them as touching them will re-raise the TypeLoadException
8963                 if (pMT->IsFullyLoaded() && image->GetModule() == GetPreferredZapModuleForMethodTable(pMT))
8964                 {
8965                     pTypes.Append(th);
8966                 }
8967             }
8968             it.Reset();
8969
8970             for(COUNT_T i = 0; i < pTypes.GetCount(); i ++)
8971             {
8972                 TypeHandle th = pTypes[i];
8973                 _ASSERTE(image->GetModule() == GetPreferredZapModuleForTypeHandle(th) );
8974                 _ASSERTE(!th.IsTypeDesc() && !th.ContainsGenericVariables());
8975                 th.AsMethodTable()->PrepopulateDictionary(image, FALSE /* not nonExpansive, i.e. can load types */);
8976             }
8977         }
8978     }
8979
8980     // PP-FINAL for instantiated types.
8981     // This is the final stage where we hardbind any remaining entries that map
8982     // to results that have already been loaded...
8983     // Thus we set the "nonExpansive" flag on PrepopulateDictionary
8984     // below, which may in turn greatly limit the amount of prepopulating we do
8985     // (partly because it's quite difficult to determine if some potential entries
8986     // in the dictionary are already loaded)
8987
8988     if (m_pAvailableParamTypes != NULL)
8989     {
8990         INDEBUG(DWORD nTypes = m_pAvailableParamTypes->GetCount());
8991
8992         EETypeHashTable::Iterator it(m_pAvailableParamTypes);
8993         EETypeHashEntry *pEntry;
8994         while (m_pAvailableParamTypes->FindNext(&it, &pEntry))
8995         {
8996             TypeHandle th = pEntry->GetTypeHandle();
8997             if (th.IsTypeDesc())
8998                 continue;
8999
9000             MethodTable * pMT = th.AsMethodTable();
9001             if (pMT->ContainsGenericVariables())
9002                 continue;
9003
9004             pMT->PrepopulateDictionary(image, TRUE /* nonExpansive */);
9005         }
9006
9007         // No new instantiations should be added by nonExpansive prepopulation
9008         _ASSERTE(nTypes == m_pAvailableParamTypes->GetCount());
9009     }
9010
9011     // PP-FINAL for instantiations of generic methods.
9012     if (m_pInstMethodHashTable != NULL)
9013     {
9014         INDEBUG(DWORD nMethods = m_pInstMethodHashTable->GetCount());
9015
9016         InstMethodHashTable::Iterator it(m_pInstMethodHashTable);
9017         InstMethodHashEntry *pEntry;
9018         while (m_pInstMethodHashTable->FindNext(&it, &pEntry))
9019         {
9020             MethodDesc *pMD = pEntry->GetMethod();
9021             if (!pMD->ContainsGenericVariables())
9022             {
9023                 pMD->PrepopulateDictionary(image, TRUE /* nonExpansive */);
9024             }
9025         }
9026
9027         // No new instantiations should be added by nonExpansive prepopulation
9028         _ASSERTE(nMethods == m_pInstMethodHashTable->GetCount());
9029     }
9030 }
9031
9032 void Module::PlaceType(DataImage *image, TypeHandle th, DWORD profilingFlags)
9033 {
9034     STANDARD_VM_CONTRACT;
9035
9036     if (th.IsNull())
9037         return;
9038
9039     MethodTable *pMT = th.GetMethodTable();
9040
9041     if (pMT && pMT->GetLoaderModule() == this)
9042     {
9043         EEClass *pClass = pMT->GetClass();
9044
9045         if (profilingFlags & (1 << WriteMethodTableWriteableData))
9046         {
9047             image->PlaceStructureForAddress(pMT->GetWriteableData(),CORCOMPILE_SECTION_WRITE);
9048         }
9049
9050         if (profilingFlags & (1 << ReadMethodTable))
9051         {
9052             CorCompileSection section = CORCOMPILE_SECTION_READONLY_HOT;
9053             if (pMT->IsWriteable())
9054                 section = CORCOMPILE_SECTION_HOT_WRITEABLE;
9055             image->PlaceStructureForAddress(pMT, section);
9056
9057             if (pMT->HasInterfaceMap())
9058                 image->PlaceInternedStructureForAddress(pMT->GetInterfaceMap(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
9059
9060             MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
9061             while (it.Next())
9062             {
9063                 image->PlaceInternedStructureForAddress(it.GetIndirectionSlot(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
9064             }
9065
9066             image->PlaceStructureForAddress(pMT->GetWriteableData(), CORCOMPILE_SECTION_HOT);
9067         }
9068
9069         if (profilingFlags & (1 << ReadNonVirtualSlots))
9070         {
9071             if (pMT->HasNonVirtualSlotsArray())
9072                 image->PlaceStructureForAddress(pMT->GetNonVirtualSlotsArray(), CORCOMPILE_SECTION_READONLY_HOT);
9073         }
9074
9075         if (profilingFlags & (1 << ReadDispatchMap) && pMT->HasDispatchMapSlot())
9076         {
9077             image->PlaceInternedStructureForAddress(pMT->GetDispatchMap(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
9078         }
9079
9080         if (profilingFlags & (1 << WriteEEClass))
9081         {
9082             image->PlaceStructureForAddress(pClass, CORCOMPILE_SECTION_WRITE);
9083
9084             if (pClass->HasOptionalFields())
9085                 image->PlaceStructureForAddress(pClass->GetOptionalFields(), CORCOMPILE_SECTION_WRITE);
9086         }
9087
9088         else if (profilingFlags & (1 << ReadEEClass))
9089         {
9090             image->PlaceStructureForAddress(pClass, CORCOMPILE_SECTION_HOT);
9091
9092             if (pClass->HasOptionalFields())
9093                 image->PlaceStructureForAddress(pClass->GetOptionalFields(), CORCOMPILE_SECTION_HOT);
9094
9095             if (pClass->GetVarianceInfo() != NULL)
9096                 image->PlaceInternedStructureForAddress(pClass->GetVarianceInfo(), CORCOMPILE_SECTION_READONLY_WARM, CORCOMPILE_SECTION_READONLY_WARM);
9097
9098 #ifdef FEATURE_COMINTEROP
9099             if (pClass->GetSparseCOMInteropVTableMap() != NULL)
9100             {
9101                 image->PlaceStructureForAddress(pClass->GetSparseCOMInteropVTableMap(), CORCOMPILE_SECTION_WARM);
9102                 image->PlaceInternedStructureForAddress(pClass->GetSparseCOMInteropVTableMap()->GetMapList(), CORCOMPILE_SECTION_READONLY_WARM, CORCOMPILE_SECTION_READONLY_WARM);
9103             }
9104 #endif
9105         }
9106
9107         if (profilingFlags & (1 << ReadFieldDescs))
9108         {
9109             image->PlaceStructureForAddress(pMT->GetApproxFieldDescListRaw(), CORCOMPILE_SECTION_READONLY_HOT);
9110         }
9111
9112         if (profilingFlags != 0)
9113         {
9114             if (pMT->HasPerInstInfo())
9115             {
9116                 DPTR(MethodTable::PerInstInfoElem_t) pPerInstInfo = pMT->GetPerInstInfo();
9117
9118                 BOOL fIsEagerBound = pMT->CanEagerBindToParentDictionaries(image, NULL);
9119
9120                 if (fIsEagerBound)
9121                 {
9122                     if (MethodTable::PerInstInfoElem_t::isRelative)
9123                     {
9124                         image->PlaceStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_HOT);
9125                     }
9126                     else
9127                     {
9128                         image->PlaceInternedStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
9129                     }
9130                 }
9131                 else
9132                 {
9133                     image->PlaceStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_WRITE);
9134                 }
9135             }
9136
9137             Dictionary * pDictionary = pMT->GetDictionary();
9138             if (pDictionary != NULL)
9139             {
9140                 BOOL fIsWriteable;
9141
9142                 if (!pMT->IsCanonicalMethodTable())
9143                 {
9144                     // CanEagerBindToMethodTable would not work for targeted patching here. The dictionary
9145                     // layout is sensitive to compilation order that can be changed by TP compatible changes.
9146                     BOOL canSaveSlots = (image->GetModule() == pMT->GetCanonicalMethodTable()->GetLoaderModule());
9147
9148                     fIsWriteable = pDictionary->IsWriteable(image, canSaveSlots,
9149                                            pMT->GetNumGenericArgs(),
9150                                            pMT->GetModule(),
9151                                            pClass->GetDictionaryLayout());
9152                 }
9153                 else
9154                 {
9155                     fIsWriteable = FALSE;
9156                 }
9157
9158                 if (fIsWriteable)
9159                 {
9160                     image->PlaceStructureForAddress(pDictionary, CORCOMPILE_SECTION_HOT_WRITEABLE);
9161                     image->PlaceStructureForAddress(pClass->GetDictionaryLayout(), CORCOMPILE_SECTION_WARM);
9162                 }
9163                 else
9164                 {
9165                     image->PlaceInternedStructureForAddress(pDictionary, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
9166                 }
9167             }
9168         }
9169
9170         if (profilingFlags & (1 << ReadFieldMarshalers))
9171         {
9172             if (pClass->HasLayout() && pClass->GetLayoutInfo()->GetNumCTMFields() > 0)
9173             {
9174                 image->PlaceStructureForAddress((void *)pClass->GetLayoutInfo()->GetFieldMarshalers(), CORCOMPILE_SECTION_HOT);
9175             }
9176         }
9177     }
9178     if (th.IsTypeDesc())
9179     {
9180         if (profilingFlags & (1 << WriteTypeDesc))
9181             image->PlaceStructureForAddress(th.AsTypeDesc(), CORCOMPILE_SECTION_WRITE);
9182         else if  (profilingFlags & (1 << ReadTypeDesc))
9183             image->PlaceStructureForAddress(th.AsTypeDesc(), CORCOMPILE_SECTION_HOT);
9184         else
9185             image->PlaceStructureForAddress(th.AsTypeDesc(), CORCOMPILE_SECTION_WARM);
9186     }
9187 }
9188
9189 void Module::PlaceMethod(DataImage *image, MethodDesc *pMD, DWORD profilingFlags)
9190 {
9191     STANDARD_VM_CONTRACT;
9192
9193     if (pMD == NULL)
9194         return;
9195
9196     if (pMD->GetLoaderModule() != this)
9197         return;
9198
9199     if (profilingFlags & (1 << ReadMethodCode))
9200     {
9201         if (pMD->IsNDirect())
9202         {
9203             NDirectMethodDesc *pNMD = (NDirectMethodDesc *)pMD;
9204             image->PlaceStructureForAddress((void*) pNMD->GetWriteableData(), CORCOMPILE_SECTION_WRITE);
9205             
9206 #ifdef HAS_NDIRECT_IMPORT_PRECODE
9207             // The NDirect import thunk glue is used only if no marshaling is required
9208             if (!pNMD->MarshalingRequired())
9209             {
9210                 image->PlaceStructureForAddress((void*) pNMD->GetNDirectImportThunkGlue(), CORCOMPILE_SECTION_METHOD_PRECODE_HOT);
9211             }
9212 #endif // HAS_NDIRECT_IMPORT_PRECODE
9213
9214             // Late bound NDirect methods require their LibName at startup.
9215             if (!pNMD->IsQCall())
9216             {
9217                 image->PlaceStructureForAddress((void*) pNMD->GetLibName(), CORCOMPILE_SECTION_READONLY_HOT);
9218                 image->PlaceStructureForAddress((void*) pNMD->GetEntrypointName(), CORCOMPILE_SECTION_READONLY_HOT);
9219             }
9220         }
9221
9222 #ifdef FEATURE_COMINTEROP
9223         if (pMD->IsComPlusCall())
9224         {
9225             ComPlusCallMethodDesc *pCMD = (ComPlusCallMethodDesc *)pMD;
9226
9227             // If the ComPlusCallMethodDesc was actually used for interop, its ComPlusCallInfo should be hot.
9228             image->PlaceStructureForAddress((void*) pCMD->m_pComPlusCallInfo, CORCOMPILE_SECTION_HOT);
9229        }
9230 #endif // FEATURE_COMINTEROP
9231
9232         // Stubs-as-IL have writeable signatures sometimes, so can't place them
9233         // into read-only section. We should not get here for stubs-as-il anyway,
9234         // but we will filter them out just to be sure.
9235         if (pMD->HasStoredSig() && !pMD->IsILStub())
9236         {
9237             StoredSigMethodDesc *pSMD = (StoredSigMethodDesc*) pMD;
9238
9239             if (pSMD->HasStoredMethodSig())
9240             {
9241                 image->PlaceInternedStructureForAddress((void*) pSMD->GetStoredMethodSig(), CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
9242             }
9243         }
9244     }
9245
9246     // We store the entire hot chunk in the SECTION_WRITE section
9247     if (profilingFlags & (1 << WriteMethodDesc))
9248     {
9249         image->PlaceStructureForAddress(pMD, CORCOMPILE_SECTION_WRITE);
9250     }
9251
9252
9253     if (profilingFlags & (1 << WriteMethodPrecode))
9254     {
9255         Precode* pPrecode = pMD->GetSavedPrecodeOrNull(image);
9256         // protect against stale IBC data
9257         if (pPrecode != NULL)
9258         {
9259             CorCompileSection section = CORCOMPILE_SECTION_METHOD_PRECODE_WRITE;
9260             if (pPrecode->IsPrebound(image))
9261                 section = CORCOMPILE_SECTION_METHOD_PRECODE_HOT;
9262             // Note: This is going to place the entire PRECODE_FIXUP chunk if we have one
9263             image->PlaceStructureForAddress(pPrecode, section);
9264         }
9265     }
9266     else if (profilingFlags & (1 << ReadMethodPrecode))
9267     {
9268         Precode* pPrecode = pMD->GetSavedPrecodeOrNull(image);
9269         // protect against stale IBC data
9270         if (pPrecode != NULL)
9271         {
9272             // Note: This is going to place the entire PRECODE_FIXUP chunk if we have one
9273             image->PlaceStructureForAddress(pPrecode, CORCOMPILE_SECTION_METHOD_PRECODE_HOT);
9274         }
9275     }
9276 }
9277
9278 void Module::Arrange(DataImage *image)
9279 {
9280     STANDARD_VM_CONTRACT;
9281
9282     // We collect IBC logging profiling data and use that to guide the layout of the image.
9283     image->PlaceStructureForAddress(this, CORCOMPILE_SECTION_MODULE);
9284
9285     // The stub method table is shared by all IL stubs in the module, so place it into the hot section
9286     MethodTable * pStubMT = GetILStubCache()->GetStubMethodTable();
9287     if (pStubMT != NULL)
9288         PlaceType(image, pStubMT, ReadMethodTable);
9289
9290     CorProfileData * profileData = GetProfileData();
9291     if (profileData)
9292     {
9293         //
9294         // Place hot type structues in the order specifiled by TypeProfilingData array
9295         //
9296         CORBBTPROF_TOKEN_INFO * pTypeProfilingData = profileData->GetTokenFlagsData(TypeProfilingData);
9297         DWORD                   cTypeProfilingData = profileData->GetTokenFlagsCount(TypeProfilingData);
9298         for (unsigned int i = 0; (i < cTypeProfilingData); i++)
9299         {
9300             CORBBTPROF_TOKEN_INFO * entry = &pTypeProfilingData[i];
9301             mdToken                 token = entry->token;
9302             DWORD                   flags = entry->flags;
9303 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
9304             g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_6);
9305 #endif
9306
9307             if (TypeFromToken(token) == mdtTypeDef)
9308             {
9309                 TypeHandle th = LookupTypeDef(token);
9310                 //
9311                 // Place a hot normal type and it's data
9312                 //
9313                 PlaceType(image, th, flags);
9314             }
9315             else if (TypeFromToken(token) == ibcTypeSpec)
9316             {
9317                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = profileData->GetBlobSigEntry(token);
9318                 
9319                 if (pBlobSigEntry == NULL)
9320                 {
9321                     //
9322                     // Print an error message for the type load failure
9323                     // 
9324                     StackSString msg(W("Did not find definition for type token "));
9325
9326                     char buff[16];
9327                     sprintf_s(buff, COUNTOF(buff), "%08x", token); 
9328                     StackSString szToken(SString::Ascii, &buff[0]);
9329                     msg += szToken;
9330                     msg += W(" in profile data.\n");
9331
9332                     GetSvcLogger()->Log(msg, LogLevel_Info);
9333                 }
9334                 else // (pBlobSigEntry  != NULL)
9335                 {
9336                     _ASSERTE(pBlobSigEntry->blob.token == token);
9337                     //
9338                     // decode generic type signature
9339                     //
9340                     TypeHandle th = LoadIBCTypeHelper(image, pBlobSigEntry);
9341
9342                     //
9343                     // Place a hot instantiated type and it's data
9344                     //
9345                     PlaceType(image, th, flags);
9346                 }
9347             }
9348             else if (TypeFromToken(token) == mdtFieldDef)
9349             {
9350                 FieldDesc *pFD = LookupFieldDef(token);
9351                 if (pFD && pFD->IsRVA())
9352                 {
9353                     if (entry->flags & (1 << RVAFieldData))
9354                     {
9355                         BYTE *pRVAData = (BYTE*) pFD->GetStaticAddressHandle(NULL);
9356                         //
9357                         // Place a hot RVA static field
9358                         //
9359                         image->PlaceStructureForAddress(pRVAData, CORCOMPILE_SECTION_RVA_STATICS_HOT);
9360                     }
9361                 }
9362             }
9363         }
9364
9365         //
9366         // Place hot methods and method data in the order specifiled by MethodProfilingData array
9367         //
9368         CORBBTPROF_TOKEN_INFO * pMethodProfilingData = profileData->GetTokenFlagsData(MethodProfilingData);
9369         DWORD                   cMethodProfilingData = profileData->GetTokenFlagsCount(MethodProfilingData);
9370         for (unsigned int i = 0; (i < cMethodProfilingData); i++)
9371         {
9372             mdToken token          = pMethodProfilingData[i].token;
9373             DWORD   profilingFlags = pMethodProfilingData[i].flags;
9374 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
9375             g_pConfig->DebugCheckAndForceIBCFailure(EEConfig::CallSite_7);
9376 #endif
9377
9378             if (TypeFromToken(token) == mdtMethodDef)
9379             {
9380                 MethodDesc *  pMD = LookupMethodDef(token);
9381                 //
9382                 // Place a hot normal method and it's data
9383                 //
9384                 PlaceMethod(image, pMD, profilingFlags);
9385             }
9386             else if (TypeFromToken(token) == ibcMethodSpec)
9387             {
9388                 CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = profileData->GetBlobSigEntry(token);
9389                 
9390                 if (pBlobSigEntry == NULL)
9391                 {
9392                     //
9393                     // Print an error message for the type load failure
9394                     // 
9395                     StackSString msg(W("Did not find definition for method token "));
9396
9397                     char buff[16];
9398                     sprintf_s(buff, COUNTOF(buff), "%08x", token); 
9399                     StackSString szToken(SString::Ascii, &buff[0]);
9400                     msg += szToken;
9401                     msg += W(" in profile data.\n");
9402
9403                     GetSvcLogger()->Log(msg, LogLevel_Info);
9404                 }
9405                 else // (pBlobSigEntry  != NULL)
9406                 {
9407                     _ASSERTE(pBlobSigEntry->blob.token == token);
9408                     MethodDesc * pMD = LoadIBCMethodHelper(image, pBlobSigEntry);
9409                     
9410                     if (pMD != NULL)
9411                     {
9412                         //
9413                         // Place a hot instantiated method and it's data
9414                         //
9415                         PlaceMethod(image, pMD, profilingFlags);
9416                     }
9417                 }
9418             }
9419         }
9420     }
9421
9422     // Now place all remaining items
9423     image->PlaceRemainingStructures();
9424 }
9425
9426 void ModuleCtorInfo::Fixup(DataImage *image)
9427 {
9428     STANDARD_VM_CONTRACT;
9429
9430     if (numElementsHot > 0)
9431     {
9432         image->FixupPointerField(this, offsetof(ModuleCtorInfo, cctorInfoHot));
9433         image->FixupPointerField(this, offsetof(ModuleCtorInfo, hotHashOffsets));
9434     }
9435     else
9436     {
9437         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, cctorInfoHot));
9438         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, hotHashOffsets));
9439     }
9440
9441     _ASSERTE(numElements > numElementsHot || numElements == numElementsHot);
9442     if (numElements > numElementsHot)
9443     {
9444         image->FixupPointerField(this, offsetof(ModuleCtorInfo, cctorInfoCold));
9445         image->FixupPointerField(this, offsetof(ModuleCtorInfo, coldHashOffsets));
9446     }
9447     else
9448     {
9449         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, cctorInfoCold));
9450         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, coldHashOffsets));
9451     }
9452
9453     if (numElements > 0)
9454     {
9455         image->FixupPointerField(this, offsetof(ModuleCtorInfo, ppMT));
9456
9457         for (DWORD i=0; i<numElements; i++)
9458         {
9459             image->FixupRelativePointerField(ppMT, i * sizeof(ppMT[0]));
9460         }
9461     }
9462     else
9463     {
9464         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, ppMT));
9465     }
9466     
9467     if (numHotGCStaticsMTs > 0)
9468     {
9469         image->FixupPointerField(this, offsetof(ModuleCtorInfo, ppHotGCStaticsMTs));
9470
9471         image->BeginRegion(CORINFO_REGION_HOT);
9472         for (DWORD i=0; i < numHotGCStaticsMTs; i++)
9473         {
9474             image->FixupMethodTablePointer(ppHotGCStaticsMTs, &ppHotGCStaticsMTs[i]);
9475         }
9476         image->EndRegion(CORINFO_REGION_HOT);
9477     }
9478     else
9479     {
9480         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, ppHotGCStaticsMTs));
9481     }
9482
9483     if (numColdGCStaticsMTs > 0)
9484     {
9485         image->FixupPointerField(this, offsetof(ModuleCtorInfo, ppColdGCStaticsMTs));
9486
9487         image->BeginRegion(CORINFO_REGION_COLD);
9488         for (DWORD i=0; i < numColdGCStaticsMTs; i++)
9489         {
9490             image->FixupMethodTablePointer(ppColdGCStaticsMTs, &ppColdGCStaticsMTs[i]);
9491         }
9492         image->EndRegion(CORINFO_REGION_COLD);
9493     }
9494     else
9495     {
9496         image->ZeroPointerField(this, offsetof(ModuleCtorInfo, ppColdGCStaticsMTs));
9497     }
9498 }
9499
9500 #ifdef _PREFAST_
9501 #pragma warning(push)
9502 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
9503 #endif
9504 void Module::Fixup(DataImage *image)
9505 {
9506     STANDARD_VM_CONTRACT;
9507
9508     // Propagate all changes to the image copy
9509     memcpy(image->GetImagePointer(this), (void*)this, sizeof(Module));
9510
9511     //
9512     // Zero out VTable
9513     //
9514
9515     image->ZeroPointerField(this, 0);
9516
9517     image->FixupPointerField(this, offsetof(Module, m_pNGenLayoutInfo));
9518
9519     image->ZeroField(this, offsetof(Module, m_pSimpleName), sizeof(m_pSimpleName));
9520
9521     image->ZeroField(this, offsetof(Module, m_file), sizeof(m_file));
9522
9523     image->FixupPointerField(this, offsetof(Module, m_pDllMain));
9524
9525     image->ZeroField(this, offsetof(Module, m_dwTransientFlags), sizeof(m_dwTransientFlags));
9526
9527     image->ZeroField(this, offsetof(Module, m_pVASigCookieBlock), sizeof(m_pVASigCookieBlock));
9528     image->ZeroField(this, offsetof(Module, m_pAssembly), sizeof(m_pAssembly));
9529     image->ZeroField(this, offsetof(Module, m_moduleRef), sizeof(m_moduleRef));
9530
9531     image->ZeroField(this, offsetof(Module, m_Crst), sizeof(m_Crst));
9532     image->ZeroField(this, offsetof(Module, m_FixupCrst), sizeof(m_FixupCrst));
9533
9534     image->ZeroField(this, offsetof(Module, m_pProfilingBlobTable), sizeof(m_pProfilingBlobTable));
9535     image->ZeroField(this, offsetof(Module, m_pProfileData), sizeof(m_pProfileData));
9536
9537     image->ZeroPointerField(this, offsetof(Module, m_pNgenStats));
9538
9539     // fixup the pointer for NeutralResourcesLanguage, if we have it cached
9540     if(!!(m_dwPersistedFlags & NEUTRAL_RESOURCES_LANGUAGE_IS_CACHED)) {
9541         image->FixupPointerField(this, offsetof(Module, m_pszCultureName));
9542     }
9543
9544     // Fixup the property name set
9545     image->FixupPointerField(this, offsetof(Module, m_propertyNameSet));
9546
9547     //
9548     // Fixup the method table
9549     //
9550
9551     image->ZeroField(this, offsetof(Module, m_pISymUnmanagedReader), sizeof(m_pISymUnmanagedReader));
9552     image->ZeroField(this, offsetof(Module, m_ISymUnmanagedReaderCrst), sizeof(m_ISymUnmanagedReaderCrst));
9553
9554     // Clear active dependencies - they will be refilled at load time
9555     image->ZeroField(this, offsetof(Module, m_activeDependencies), sizeof(m_activeDependencies));
9556     new (image->GetImagePointer(this, offsetof(Module, m_unconditionalDependencies))) SynchronizedBitMask();
9557     image->ZeroField(this, offsetof(Module, m_unconditionalDependencies) + offsetof(SynchronizedBitMask, m_bitMaskLock) + offsetof(SimpleRWLock,m_spinCount), sizeof(m_unconditionalDependencies.m_bitMaskLock.m_spinCount));
9558     image->ZeroField(this, offsetof(Module, m_dwNumberOfActivations), sizeof(m_dwNumberOfActivations));
9559
9560     image->ZeroField(this, offsetof(Module, m_LookupTableCrst), sizeof(m_LookupTableCrst));
9561
9562     m_TypeDefToMethodTableMap.Fixup(image);
9563     m_TypeRefToMethodTableMap.Fixup(image, FALSE);
9564     m_MethodDefToDescMap.Fixup(image);
9565     m_FieldDefToDescMap.Fixup(image);
9566     if(m_pMemberRefToDescHashTable != NULL)
9567     {
9568         image->FixupPointerField(this, offsetof(Module, m_pMemberRefToDescHashTable));
9569         m_pMemberRefToDescHashTable->Fixup(image);
9570     }
9571     m_GenericParamToDescMap.Fixup(image);
9572     m_GenericTypeDefToCanonMethodTableMap.Fixup(image);
9573     m_FileReferencesMap.Fixup(image, FALSE);
9574     m_ManifestModuleReferencesMap.Fixup(image, FALSE);
9575     m_MethodDefToPropertyInfoMap.Fixup(image, FALSE);
9576
9577     image->ZeroPointerField(this, offsetof(Module, m_pILStubCache));
9578
9579     if (m_pAvailableClasses != NULL) {
9580         image->FixupPointerField(this, offsetof(Module, m_pAvailableClasses));
9581         m_pAvailableClasses->Fixup(image);
9582     }
9583
9584     image->ZeroField(this, offsetof(Module, m_pAvailableClassesCaseIns), sizeof(m_pAvailableClassesCaseIns));
9585     image->ZeroField(this, offsetof(Module, m_InstMethodHashTableCrst), sizeof(m_InstMethodHashTableCrst));
9586
9587     image->BeginRegion(CORINFO_REGION_COLD);
9588
9589     if (m_pAvailableParamTypes) {
9590         image->FixupPointerField(this, offsetof(Module, m_pAvailableParamTypes));
9591         m_pAvailableParamTypes->Fixup(image);
9592     }
9593
9594     if (m_pInstMethodHashTable) {
9595         image->FixupPointerField(this, offsetof(Module, m_pInstMethodHashTable));
9596         m_pInstMethodHashTable->Fixup(image);
9597     }
9598
9599     {
9600         MethodTable * pStubMT = GetILStubCache()->GetStubMethodTable();
9601         if (pStubMT != NULL)
9602             pStubMT->Fixup(image);
9603     }
9604
9605     if (m_pStubMethodHashTable) {
9606         image->FixupPointerField(this, offsetof(Module, m_pStubMethodHashTable));
9607         m_pStubMethodHashTable->Fixup(image);
9608     }
9609
9610 #ifdef FEATURE_COMINTEROP
9611     if (m_pGuidToTypeHash) {
9612         image->FixupPointerField(this, offsetof(Module, m_pGuidToTypeHash));
9613         m_pGuidToTypeHash->Fixup(image);
9614     }
9615 #endif // FEATURE_COMINTEROP
9616
9617     image->EndRegion(CORINFO_REGION_COLD);
9618
9619 #ifdef _DEBUG
9620     //
9621     // Unseal the generic tables:
9622     //
9623     // - We need to run managed code to serialize the Security attributes of the ngen image
9624     //   and we are now using generic types in the Security/Reflection code.
9625     // - Compilation of other modules of multimodule assemblies may add more types
9626     //   to the generic tables.
9627     //
9628     UnsealGenericTypesAndMethods();
9629 #endif
9630
9631     m_ModuleCtorInfo.Fixup(image);
9632
9633     //
9634     // Fixup binder
9635     //
9636
9637     if (m_pBinder != NULL)
9638     {
9639         image->FixupPointerField(this, offsetof(Module, m_pBinder));
9640         m_pBinder->Fixup(image);
9641     }
9642
9643
9644     //
9645     // Fixup classes
9646     //
9647
9648     {
9649         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
9650
9651         image->BeginRegion(CORINFO_REGION_COLD);
9652         while (typeDefIter.Next())
9653         {
9654             MethodTable * t = typeDefIter.GetElement();
9655             if (image->IsStored(t))
9656                 t->Fixup(image);
9657         }
9658         image->EndRegion(CORINFO_REGION_COLD);
9659     }
9660
9661     {
9662         LookupMap<PTR_TypeRef>::Iterator typeRefIter(&m_TypeRefToMethodTableMap);
9663         DWORD rid = 0;
9664
9665         image->BeginRegion(CORINFO_REGION_HOT);
9666         while (typeRefIter.Next())
9667         {
9668             TADDR flags;
9669             TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(typeRefIter.GetElementAndFlags(&flags)));
9670             
9671             if (!th.IsNull())
9672             {
9673                 if (th.GetLoaderModule() != this || image->IsStored(th.AsPtr()))
9674                 {
9675                     PTR_TADDR hotItemValuePtr = m_TypeRefToMethodTableMap.FindHotItemValuePtr(rid);
9676                     BOOL fSet = FALSE;
9677                    
9678                     if (image->CanEagerBindToTypeHandle(th))
9679                     {
9680                         if (image->CanHardBindToZapModule(th.GetLoaderModule()))
9681                         {
9682                             PVOID pTarget = th.IsTypeDesc() ? th.AsTypeDesc() : th.AsPtr();
9683                             SSIZE_T offset = th.IsTypeDesc() ? 2 : 0;
9684
9685                             _ASSERTE((flags & offset) == 0);
9686
9687                             image->FixupField(m_TypeRefToMethodTableMap.pTable, rid * sizeof(TADDR), 
9688                                 pTarget, flags | offset, IMAGE_REL_BASED_RelativePointer);
9689
9690                             // In case this item is also in the hot item subtable, fix it up there as well
9691                             if (hotItemValuePtr != NULL)
9692                             {
9693                                 image->FixupField(m_TypeRefToMethodTableMap.hotItemList, 
9694                                     (BYTE *)hotItemValuePtr - (BYTE *)m_TypeRefToMethodTableMap.hotItemList,
9695                                     pTarget, flags | offset, IMAGE_REL_BASED_RelativePointer);
9696                             }
9697                             fSet = TRUE;
9698                         }
9699                         else
9700                         // Create the indirection only if the entry is hot or we do have indirection cell already
9701                         if (hotItemValuePtr != NULL || image->GetExistingTypeHandleImport(th) != NULL)
9702                         {
9703                             _ASSERTE((flags & FIXUP_POINTER_INDIRECTION) == 0);
9704
9705                             ZapNode * pImport = image->GetTypeHandleImport(th);
9706                             image->FixupFieldToNode(m_TypeRefToMethodTableMap.pTable, rid * sizeof(TADDR), 
9707                                 pImport, flags | FIXUP_POINTER_INDIRECTION, IMAGE_REL_BASED_RelativePointer);
9708                             if (hotItemValuePtr != NULL)
9709                             {
9710                                 image->FixupFieldToNode(m_TypeRefToMethodTableMap.hotItemList, 
9711                                     (BYTE *)hotItemValuePtr - (BYTE *)m_TypeRefToMethodTableMap.hotItemList, 
9712                                     pImport, flags | FIXUP_POINTER_INDIRECTION, IMAGE_REL_BASED_RelativePointer);
9713                             }
9714                             fSet = TRUE;
9715                         }
9716                     }
9717
9718                     if (!fSet)
9719                     {
9720                         image->ZeroPointerField(m_TypeRefToMethodTableMap.pTable, rid * sizeof(TADDR));
9721                         // In case this item is also in the hot item subtable, fix it up there as well
9722                         if (hotItemValuePtr != NULL)
9723                         {
9724                             image->ZeroPointerField(m_TypeRefToMethodTableMap.hotItemList,
9725                                 (BYTE *)hotItemValuePtr - (BYTE *)m_TypeRefToMethodTableMap.hotItemList);
9726                         }
9727                     }
9728                 }
9729             }
9730             
9731             rid++;
9732         }
9733         image->EndRegion(CORINFO_REGION_HOT);
9734     }
9735
9736     {
9737         LookupMap<PTR_TypeVarTypeDesc>::Iterator genericParamIter(&m_GenericParamToDescMap);
9738
9739         while (genericParamIter.Next())
9740         {
9741             TypeVarTypeDesc * pTypeDesc = genericParamIter.GetElement();
9742
9743             if (pTypeDesc != NULL)
9744             {
9745                 _ASSERTE(image->IsStored(pTypeDesc));
9746                 pTypeDesc->Fixup(image);
9747             }
9748         }
9749     }
9750
9751     //
9752     // Fixup the assembly reference map table
9753     //
9754
9755     {
9756         LookupMap<PTR_Module>::Iterator manifestModuleIter(&m_ManifestModuleReferencesMap);
9757         DWORD rid = 0;
9758
9759         while (manifestModuleIter.Next())
9760         {
9761             TADDR flags;
9762             Module * pModule = manifestModuleIter.GetElementAndFlags(&flags);
9763
9764             if (pModule != NULL)
9765             {
9766                 if (image->CanEagerBindToModule(pModule))
9767                 {
9768                     if (image->CanHardBindToZapModule(pModule))
9769                     {
9770                         image->FixupField(m_ManifestModuleReferencesMap.pTable, rid * sizeof(TADDR),
9771                             pModule, flags, IMAGE_REL_BASED_RelativePointer);
9772                     }
9773                     else
9774                     {
9775                         image->ZeroPointerField(m_ManifestModuleReferencesMap.pTable, rid * sizeof(TADDR));
9776                     }
9777                 }
9778                 else
9779                 {
9780                     image->ZeroPointerField(m_ManifestModuleReferencesMap.pTable, rid * sizeof(TADDR));
9781                 }
9782             }
9783
9784             rid++;
9785         }
9786     }
9787
9788     //
9789     // Zero out file references table.
9790     //
9791     image->ZeroField(m_FileReferencesMap.pTable, 0,
9792                      m_FileReferencesMap.GetSize() * sizeof(void*));
9793
9794
9795     image->ZeroField(this, offsetof(Module, m_debuggerSpecificData), sizeof(m_debuggerSpecificData));
9796
9797     image->ZeroField(this, offsetof(Module, m_AssemblyRefByNameCount), sizeof(m_AssemblyRefByNameCount));
9798     image->ZeroPointerField(this, offsetof(Module, m_AssemblyRefByNameTable));
9799
9800     image->ZeroPointerField(this,offsetof(Module, m_NativeMetadataAssemblyRefMap));
9801     
9802     //
9803     // Fixup statics
9804     //
9805     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: fixing up module static data\n"));
9806
9807     image->ZeroPointerField(this, offsetof(Module, m_ModuleID));
9808     image->ZeroField(this, offsetof(Module, m_ModuleIndex), sizeof(m_ModuleIndex));
9809
9810     image->FixupPointerField(this, offsetof(Module, m_pDynamicStaticsInfo));
9811
9812     DynamicStaticsInfo* pDSI = m_pDynamicStaticsInfo;
9813     for (DWORD i = 0; i < m_cDynamicEntries; i++, pDSI++)
9814     {
9815         if (pDSI->pEnclosingMT->GetLoaderModule() == this &&
9816             // CEEPreloader::TriageTypeForZap() could have rejected this type
9817             image->IsStored(pDSI->pEnclosingMT))
9818         {
9819             image->FixupPointerField(m_pDynamicStaticsInfo, (BYTE *)&pDSI->pEnclosingMT - (BYTE *)m_pDynamicStaticsInfo);
9820         }
9821         else
9822         {
9823             // Some other (mutually-recursive) dependency must have loaded
9824             // a generic instantiation whose static were pumped into the
9825             // assembly being ngenned.
9826             image->ZeroPointerField(m_pDynamicStaticsInfo, (BYTE *)&pDSI->pEnclosingMT - (BYTE *)m_pDynamicStaticsInfo);
9827         }
9828     }
9829
9830     // If we failed to load some types we need to reset the pointers to the static offset tables so they'll be
9831     // rebuilt at runtime.
9832     if (m_pRegularStaticOffsets != (PTR_DWORD)NGEN_STATICS_ALLCLASSES_WERE_LOADED)
9833     {
9834         _ASSERTE(m_pThreadStaticOffsets != (PTR_DWORD)NGEN_STATICS_ALLCLASSES_WERE_LOADED);
9835         image->ZeroPointerField(this, offsetof(Module, m_pRegularStaticOffsets));
9836         image->ZeroPointerField(this, offsetof(Module, m_pThreadStaticOffsets));
9837     }
9838
9839     // Fix up inlining data
9840     if(m_pPersistentInlineTrackingMapNGen)
9841     {
9842         image->FixupPointerField(this, offsetof(Module, m_pPersistentInlineTrackingMapNGen));
9843         m_pPersistentInlineTrackingMapNGen->Fixup(image);
9844     } 
9845     else
9846     {
9847         image->ZeroPointerField(this, offsetof(Module, m_pPersistentInlineTrackingMapNGen));
9848     }
9849
9850     SetIsModuleSaved();
9851 }
9852 #ifdef _PREFAST_
9853 #pragma warning(pop)
9854 #endif
9855
9856 #endif // FEATURE_NATIVE_IMAGE_GENERATION
9857
9858 #ifdef FEATURE_PREJIT
9859 //
9860 // Is "address" a data-structure in the native image?
9861 //
9862
9863 BOOL Module::IsPersistedObject(void *address)
9864 {
9865     CONTRACTL
9866     {
9867         INSTANCE_CHECK;
9868         NOTHROW;
9869         GC_NOTRIGGER;
9870         MODE_ANY;
9871         FORBID_FAULT;
9872     }
9873     CONTRACTL_END;
9874
9875     if (!HasNativeImage())
9876         return FALSE;
9877
9878     PEImageLayout *pLayout = GetNativeImage();
9879     _ASSERTE(pLayout->IsMapped());
9880
9881     return (address >= pLayout->GetBase()
9882             && address < (BYTE*)pLayout->GetBase() + pLayout->GetVirtualSize());
9883 }
9884
9885 Module *Module::GetModuleFromIndex(DWORD ix)
9886 {
9887     CONTRACT(Module*)
9888     {
9889         INSTANCE_CHECK;
9890         THROWS;
9891         GC_TRIGGERS;
9892         MODE_ANY;
9893         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
9894     }
9895     CONTRACT_END;
9896
9897     if (HasNativeImage())
9898     {
9899         PRECONDITION(GetNativeImage()->CheckNativeImportFromIndex(ix));
9900         CORCOMPILE_IMPORT_TABLE_ENTRY *p = GetNativeImage()->GetNativeImportFromIndex(ix);
9901         RETURN ZapSig::DecodeModuleFromIndexes(this, p->wAssemblyRid, p->wModuleRid);
9902     }
9903     else
9904     {
9905         mdAssemblyRef mdAssemblyRefToken = TokenFromRid(ix, mdtAssemblyRef);
9906         Assembly *pAssembly = this->LookupAssemblyRef(mdAssemblyRefToken);
9907         if (pAssembly)
9908         {
9909             RETURN pAssembly->GetManifestModule();
9910         }
9911         else
9912         {
9913             // GetModuleFromIndex failed
9914             RETURN NULL;
9915         }
9916     }
9917 }
9918 #endif // FEATURE_PREJIT
9919
9920 #endif // !DACCESS_COMPILE
9921
9922 #ifdef FEATURE_PREJIT
9923
9924 Module *Module::GetModuleFromIndexIfLoaded(DWORD ix)
9925 {
9926     CONTRACT(Module*)
9927     {
9928         INSTANCE_CHECK;
9929         NOTHROW;
9930         GC_NOTRIGGER;
9931         MODE_ANY;
9932         PRECONDITION(HasNativeImage());
9933         PRECONDITION(GetNativeImage()->CheckNativeImportFromIndex(ix));
9934         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
9935     }
9936     CONTRACT_END;
9937
9938 #ifndef DACCESS_COMPILE 
9939     CORCOMPILE_IMPORT_TABLE_ENTRY *p = GetNativeImage()->GetNativeImportFromIndex(ix);
9940
9941     RETURN ZapSig::DecodeModuleFromIndexesIfLoaded(this, p->wAssemblyRid, p->wModuleRid);
9942 #else // DACCESS_COMPILE
9943     DacNotImpl();
9944     RETURN NULL;
9945 #endif // DACCESS_COMPILE
9946 }
9947
9948 #ifndef DACCESS_COMPILE 
9949
9950 BYTE *Module::GetNativeFixupBlobData(RVA rva)
9951 {
9952     CONTRACT(BYTE *)
9953     {
9954         INSTANCE_CHECK;
9955         NOTHROW;
9956         GC_NOTRIGGER;
9957         MODE_ANY;
9958         SO_TOLERANT;
9959         POSTCONDITION(CheckPointer(RETVAL));
9960     }
9961     CONTRACT_END;
9962
9963     RETURN (BYTE *) GetNativeOrReadyToRunImage()->GetRvaData(rva);
9964 }
9965
9966 IMDInternalImport *Module::GetNativeAssemblyImport(BOOL loadAllowed)
9967 {
9968     CONTRACT(IMDInternalImport *)
9969     {
9970         INSTANCE_CHECK;
9971         if (loadAllowed) GC_TRIGGERS;                    else GC_NOTRIGGER;
9972         if (loadAllowed) THROWS;                         else NOTHROW;
9973         if (loadAllowed) INJECT_FAULT(COMPlusThrowOM()); else FORBID_FAULT;
9974         MODE_ANY;
9975         PRECONDITION(HasNativeImage());
9976         POSTCONDITION(CheckPointer(RETVAL));
9977     }
9978     CONTRACT_END;
9979
9980     RETURN GetFile()->GetPersistentNativeImage()->GetNativeMDImport(loadAllowed);
9981 }
9982
9983
9984 /*static*/
9985 void Module::RestoreMethodTablePointerRaw(MethodTable ** ppMT,
9986                                           Module *pContainingModule,
9987                                           ClassLoadLevel level)
9988 {
9989     CONTRACTL
9990     {
9991         THROWS;
9992         GC_TRIGGERS;
9993         MODE_ANY;
9994     }
9995     CONTRACTL_END;
9996
9997     // Ensure that the compiler won't fetch the value twice
9998     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppMT);
9999
10000 #ifdef _DEBUG
10001     if (pContainingModule != NULL)
10002     {
10003         Module * dbg_pZapModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMT));
10004         _ASSERTE((dbg_pZapModule == NULL) || (pContainingModule == dbg_pZapModule));
10005     }
10006 #endif //_DEBUG
10007
10008     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
10009     {
10010 #ifdef _WIN64 
10011         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
10012 #endif
10013
10014         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
10015
10016         if (pContainingModule == NULL)
10017             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMT));
10018         PREFIX_ASSUME(pContainingModule != NULL);
10019
10020         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_TYPE_HANDLE);
10021
10022         Module * pInfoModule;
10023         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
10024
10025         TypeHandle  th          = ZapSig::DecodeType(pContainingModule,
10026                                                              pInfoModule,
10027                                                              pBlobData,
10028                                                              level);
10029         *EnsureWritablePages(ppMT) = th.AsMethodTable();
10030     }
10031     else if (*ppMT)
10032     {
10033         ClassLoader::EnsureLoaded(*ppMT, level);
10034     }
10035 }
10036
10037 /*static*/
10038 void Module::RestoreMethodTablePointer(FixupPointer<PTR_MethodTable> * ppMT,
10039                                        Module *pContainingModule,
10040                                        ClassLoadLevel level)
10041 {
10042     CONTRACTL
10043     {
10044         THROWS;
10045         GC_TRIGGERS;
10046         MODE_ANY;
10047     }
10048     CONTRACTL_END;
10049
10050     if (ppMT->IsNull())
10051         return;
10052
10053     if (ppMT->IsTagged())
10054     {
10055         RestoreMethodTablePointerRaw(ppMT->GetValuePtr(), pContainingModule, level);
10056     }
10057     else
10058     {
10059         ClassLoader::EnsureLoaded(ppMT->GetValue(), level);
10060     }
10061 }
10062
10063 /*static*/
10064 void Module::RestoreMethodTablePointer(RelativeFixupPointer<PTR_MethodTable> * ppMT,
10065                                        Module *pContainingModule,
10066                                        ClassLoadLevel level)
10067 {
10068     CONTRACTL
10069     {
10070         THROWS;
10071         GC_TRIGGERS;
10072         MODE_ANY;
10073     }
10074     CONTRACTL_END;
10075
10076     if (ppMT->IsNull())
10077         return;
10078
10079     if (ppMT->IsTagged((TADDR)ppMT))
10080     {
10081         RestoreMethodTablePointerRaw(ppMT->GetValuePtr(), pContainingModule, level);
10082     }
10083     else
10084     {
10085         ClassLoader::EnsureLoaded(ppMT->GetValue(), level);
10086     }
10087 }
10088
10089 #endif // !DACCESS_COMPILE
10090
10091 BOOL Module::IsZappedCode(PCODE code)
10092 {
10093     CONTRACTL
10094     {
10095         NOTHROW;
10096         GC_NOTRIGGER;
10097         SO_TOLERANT;
10098         SUPPORTS_DAC;
10099     }
10100     CONTRACTL_END;
10101
10102     if (!HasNativeImage())
10103         return FALSE;
10104
10105     PEImageLayout *pNativeImage = GetNativeImage();
10106
10107     UINT32 cCode = 0;
10108     PCODE pCodeSection;
10109
10110     pCodeSection = pNativeImage->GetNativeHotCode(&cCode);
10111     if ((pCodeSection <= code) && (code < pCodeSection + cCode))
10112     {
10113         return TRUE;
10114     }
10115
10116     pCodeSection = pNativeImage->GetNativeCode(&cCode);
10117     if ((pCodeSection <= code) && (code < pCodeSection + cCode))
10118     {
10119         return TRUE;
10120     }
10121
10122     return FALSE;
10123 }
10124
10125 BOOL Module::IsZappedPrecode(PCODE code)
10126 {
10127     CONTRACTL
10128     {
10129         NOTHROW;
10130         GC_NOTRIGGER;
10131         SUPPORTS_DAC;
10132         SO_TOLERANT;
10133     }
10134     CONTRACTL_END;
10135
10136     if (m_pNGenLayoutInfo == NULL)
10137         return FALSE;
10138
10139     for (SIZE_T i = 0; i < COUNTOF(m_pNGenLayoutInfo->m_Precodes); i++)
10140     {
10141         if (m_pNGenLayoutInfo->m_Precodes[i].IsInRange(code))
10142             return TRUE;
10143     }
10144
10145     return FALSE;
10146 }
10147
10148 PCCOR_SIGNATURE Module::GetEncodedSig(RVA fixupRva, Module **ppDefiningModule)
10149 {
10150     CONTRACT(PCCOR_SIGNATURE)
10151     {
10152         INSTANCE_CHECK;
10153         THROWS;
10154         GC_TRIGGERS;
10155         MODE_ANY;
10156         SO_INTOLERANT;
10157         POSTCONDITION(CheckPointer(RETVAL));
10158         SUPPORTS_DAC;
10159     }
10160     CONTRACT_END;
10161
10162 #ifndef DACCESS_COMPILE 
10163     PCCOR_SIGNATURE pBuffer = GetNativeFixupBlobData(fixupRva);
10164
10165     BYTE kind = *pBuffer++;
10166
10167     *ppDefiningModule = (kind & ENCODE_MODULE_OVERRIDE) ? GetModuleFromIndex(CorSigUncompressData(pBuffer)) : this;
10168
10169     RETURN pBuffer;
10170 #else
10171     RETURN NULL;
10172 #endif // DACCESS_COMPILE
10173 }
10174
10175 PCCOR_SIGNATURE Module::GetEncodedSigIfLoaded(RVA fixupRva, Module **ppDefiningModule)
10176 {
10177     CONTRACT(PCCOR_SIGNATURE)
10178     {
10179         INSTANCE_CHECK;
10180         NOTHROW;
10181         GC_NOTRIGGER;
10182         MODE_ANY;
10183         SO_INTOLERANT;
10184         POSTCONDITION(CheckPointer(RETVAL));
10185         SUPPORTS_DAC;
10186     }
10187     CONTRACT_END;
10188
10189 #ifndef DACCESS_COMPILE 
10190     PCCOR_SIGNATURE pBuffer = GetNativeFixupBlobData(fixupRva);
10191
10192     BYTE kind = *pBuffer++;
10193
10194     *ppDefiningModule = (kind & ENCODE_MODULE_OVERRIDE) ? GetModuleFromIndexIfLoaded(CorSigUncompressData(pBuffer)) : this;
10195
10196     RETURN pBuffer;
10197 #else
10198     *ppDefiningModule = NULL;
10199     RETURN NULL;
10200 #endif // DACCESS_COMPILE
10201 }
10202
10203 /*static*/
10204 PTR_Module Module::RestoreModulePointerIfLoaded(DPTR(RelativeFixupPointer<PTR_Module>) ppModule, Module *pContainingModule)
10205 {
10206     CONTRACTL
10207     {
10208         NOTHROW;
10209         GC_NOTRIGGER;
10210         MODE_ANY;
10211         FORBID_FAULT;
10212         SUPPORTS_DAC;
10213     }
10214     CONTRACTL_END;
10215
10216     if (!ppModule->IsTagged(dac_cast<TADDR>(ppModule)))
10217         return ppModule->GetValue(dac_cast<TADDR>(ppModule));
10218
10219 #ifndef DACCESS_COMPILE 
10220     PTR_Module * ppValue = ppModule->GetValuePtr();
10221
10222     // Ensure that the compiler won't fetch the value twice
10223     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue);
10224
10225     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
10226     {
10227
10228 #ifdef _WIN64 
10229         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
10230 #endif
10231
10232         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
10233
10234         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_MODULE_HANDLE);
10235
10236         Module * pInfoModule;
10237         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSigIfLoaded(fixupRva, &pInfoModule);
10238
10239         if (pInfoModule)
10240         {
10241             if (EnsureWritablePagesNoThrow(ppValue, sizeof(*ppValue)))
10242                 *ppValue = pInfoModule;
10243         }
10244         return pInfoModule;
10245     }
10246     else
10247     {
10248         return PTR_Module(fixup);
10249     }
10250 #else
10251     DacNotImpl();
10252     return NULL;
10253 #endif
10254 }
10255
10256 #ifndef DACCESS_COMPILE 
10257
10258 /*static*/
10259 void Module::RestoreModulePointer(RelativeFixupPointer<PTR_Module> * ppModule, Module *pContainingModule)
10260 {
10261     CONTRACTL
10262     {
10263         THROWS;
10264         GC_TRIGGERS;
10265         MODE_ANY;
10266         INJECT_FAULT(COMPlusThrowOM());
10267     }
10268     CONTRACTL_END;
10269
10270     if (!ppModule->IsTagged((TADDR)ppModule))
10271         return;
10272
10273     PTR_Module * ppValue = ppModule->GetValuePtr();
10274
10275     // Ensure that the compiler won't fetch the value twice
10276     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue);
10277
10278     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
10279     {
10280 #ifdef _WIN64 
10281         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
10282 #endif
10283
10284         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
10285
10286         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_MODULE_HANDLE);
10287
10288         Module * pInfoModule;
10289         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
10290
10291         *EnsureWritablePages(ppValue) = pInfoModule;
10292     }
10293 }
10294
10295 /*static*/
10296 void Module::RestoreTypeHandlePointerRaw(TypeHandle *pHandle, Module* pContainingModule, ClassLoadLevel level)
10297 {
10298     CONTRACTL
10299     {
10300         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
10301         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
10302         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else {INJECT_FAULT(COMPlusThrowOM(););}
10303         MODE_ANY;
10304     }
10305     CONTRACTL_END;
10306
10307 #ifdef _DEBUG
10308     if (pContainingModule != NULL)
10309     {
10310         Module * dbg_pZapModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pHandle));
10311         _ASSERTE((dbg_pZapModule == NULL) || (pContainingModule == dbg_pZapModule));
10312     }
10313 #endif //_DEBUG
10314
10315     TADDR fixup;
10316
10317     if (IS_ALIGNED(pHandle, sizeof(TypeHandle)))
10318     {
10319         // Ensure that the compiler won't fetch the value twice
10320         fixup = VolatileLoadWithoutBarrier((TADDR *)pHandle);
10321     }
10322     else
10323     {
10324         // This is necessary to handle in-place fixups (see by FixupTypeHandlePointerInplace)
10325         // in stubs-as-il signatures.
10326
10327         //
10328         // protect this unaligned read with the Module Crst for the rare case that 
10329         // the TypeHandle to fixup is in a signature and unaligned.
10330         //
10331         if (NULL == pContainingModule)
10332         {
10333             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pHandle));
10334         }
10335         CrstHolder ch(&pContainingModule->m_Crst);
10336         fixup = *(TADDR UNALIGNED *)pHandle;
10337     }
10338
10339     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
10340     {
10341 #ifdef _WIN64 
10342         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
10343 #endif
10344
10345         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
10346
10347         if (NULL == pContainingModule)
10348         {
10349             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pHandle));
10350         }
10351         PREFIX_ASSUME(pContainingModule != NULL);
10352
10353         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_TYPE_HANDLE);
10354
10355         Module * pInfoModule;
10356         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
10357
10358         TypeHandle thResolved = ZapSig::DecodeType(pContainingModule,
10359                                                            pInfoModule,
10360                                                            pBlobData,
10361                                                            level);
10362         EnsureWritablePages(pHandle);
10363         if (IS_ALIGNED(pHandle, sizeof(TypeHandle)))
10364         {
10365             *pHandle = thResolved;
10366         }
10367         else
10368         {
10369             //
10370             // protect this unaligned write with the Module Crst for the rare case that 
10371             // the TypeHandle to fixup is in a signature and unaligned.
10372             //
10373             CrstHolder ch(&pContainingModule->m_Crst);
10374             *(TypeHandle UNALIGNED *)pHandle = thResolved;
10375         }
10376     }
10377     else if (fixup != NULL)
10378     {
10379         ClassLoader::EnsureLoaded(TypeHandle::FromTAddr(fixup), level);
10380     }
10381 }
10382
10383 /*static*/
10384 void Module::RestoreTypeHandlePointer(FixupPointer<TypeHandle> * pHandle,
10385                                       Module *pContainingModule,
10386                                       ClassLoadLevel level)
10387 {
10388     CONTRACTL
10389     {
10390         THROWS;
10391         GC_TRIGGERS;
10392         MODE_ANY;
10393     }
10394     CONTRACTL_END;
10395
10396     if (pHandle->IsNull())
10397         return;
10398
10399     if (pHandle->IsTagged())
10400     {
10401         RestoreTypeHandlePointerRaw(pHandle->GetValuePtr(), pContainingModule, level);
10402     }
10403     else
10404     {
10405         ClassLoader::EnsureLoaded(pHandle->GetValue(), level);
10406     }
10407 }
10408
10409 /*static*/
10410 void Module::RestoreTypeHandlePointer(RelativeFixupPointer<TypeHandle> * pHandle,
10411                                       Module *pContainingModule,
10412                                       ClassLoadLevel level)
10413 {
10414     CONTRACTL
10415     {
10416         THROWS;
10417         GC_TRIGGERS;
10418         MODE_ANY;
10419     }
10420     CONTRACTL_END;
10421
10422     if (pHandle->IsNull())
10423         return;
10424
10425     if (pHandle->IsTagged((TADDR)pHandle))
10426     {
10427         RestoreTypeHandlePointerRaw(pHandle->GetValuePtr(), pContainingModule, level);
10428     }
10429     else
10430     {
10431         ClassLoader::EnsureLoaded(pHandle->GetValue((TADDR)pHandle), level);
10432     }
10433 }
10434
10435 /*static*/
10436 void Module::RestoreMethodDescPointerRaw(PTR_MethodDesc * ppMD, Module *pContainingModule, ClassLoadLevel level)
10437 {
10438     CONTRACTL
10439     {
10440         THROWS;
10441         GC_TRIGGERS;
10442         MODE_ANY;
10443     }
10444     CONTRACTL_END;
10445
10446     // Ensure that the compiler won't fetch the value twice
10447     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppMD);
10448
10449 #ifdef _DEBUG
10450     if (pContainingModule != NULL)
10451     {
10452         Module * dbg_pZapModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMD));
10453         _ASSERTE((dbg_pZapModule == NULL) || (pContainingModule == dbg_pZapModule));
10454     }
10455 #endif //_DEBUG
10456
10457     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
10458     {
10459         GCX_PREEMP();
10460
10461 #ifdef _WIN64 
10462         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
10463 #endif
10464
10465         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
10466
10467         if (pContainingModule == NULL)
10468             pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(ppMD));
10469         PREFIX_ASSUME(pContainingModule != NULL);
10470
10471         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_METHOD_HANDLE);
10472
10473         Module * pInfoModule;
10474         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
10475
10476         *EnsureWritablePages(ppMD) =  ZapSig::DecodeMethod(pContainingModule,
10477                                               pInfoModule,
10478                                               pBlobData);
10479     }
10480     else if (*ppMD) {
10481         (*ppMD)->CheckRestore(level);
10482     }
10483 }
10484
10485 /*static*/
10486 void Module::RestoreMethodDescPointer(FixupPointer<PTR_MethodDesc> * ppMD,
10487                                       Module *pContainingModule,
10488                                       ClassLoadLevel level)
10489 {
10490     CONTRACTL
10491     {
10492         THROWS;
10493         GC_TRIGGERS;
10494         MODE_ANY;
10495     }
10496     CONTRACTL_END;
10497
10498     if (ppMD->IsNull())
10499         return;
10500
10501     if (ppMD->IsTagged())
10502     {
10503         RestoreMethodDescPointerRaw(ppMD->GetValuePtr(), pContainingModule, level);
10504     }
10505     else
10506     {
10507         ppMD->GetValue()->CheckRestore(level);
10508     }
10509 }
10510
10511 /*static*/
10512 void Module::RestoreMethodDescPointer(RelativeFixupPointer<PTR_MethodDesc> * ppMD,
10513                                       Module *pContainingModule,
10514                                       ClassLoadLevel level)
10515 {
10516     CONTRACTL
10517     {
10518         THROWS;
10519         GC_TRIGGERS;
10520         MODE_ANY;
10521     }
10522     CONTRACTL_END;
10523
10524     if (ppMD->IsNull())
10525         return;
10526
10527     if (ppMD->IsTagged((TADDR)ppMD))
10528     {
10529         RestoreMethodDescPointerRaw(ppMD->GetValuePtr(), pContainingModule, level);
10530     }
10531     else
10532     {
10533         ppMD->GetValue((TADDR)ppMD)->CheckRestore(level);
10534     }
10535 }
10536
10537 /*static*/
10538 void Module::RestoreFieldDescPointer(RelativeFixupPointer<PTR_FieldDesc> * ppFD)
10539 {
10540     CONTRACTL
10541     {
10542         THROWS;
10543         GC_TRIGGERS;
10544         MODE_ANY;
10545     }
10546     CONTRACTL_END;
10547
10548     if (!ppFD->IsTagged())
10549         return;
10550
10551     PTR_FieldDesc * ppValue = ppFD->GetValuePtr();
10552
10553     // Ensure that the compiler won't fetch the value twice
10554     TADDR fixup = VolatileLoadWithoutBarrier((TADDR *)ppValue);
10555
10556     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
10557     {
10558 #ifdef _WIN64 
10559         CONSISTENCY_CHECK((CORCOMPILE_UNTAG_TOKEN(fixup)>>32) == 0);
10560 #endif
10561
10562         Module * pContainingModule = ExecutionManager::FindZapModule((TADDR)ppValue);
10563         PREFIX_ASSUME(pContainingModule != NULL);
10564
10565         RVA fixupRva = (RVA) CORCOMPILE_UNTAG_TOKEN(fixup);
10566
10567         _ASSERTE((*pContainingModule->GetNativeFixupBlobData(fixupRva) & ~ENCODE_MODULE_OVERRIDE) == ENCODE_FIELD_HANDLE);
10568
10569         Module * pInfoModule;
10570         PCCOR_SIGNATURE pBlobData = pContainingModule->GetEncodedSig(fixupRva, &pInfoModule);
10571
10572         *EnsureWritablePages(ppValue) =  ZapSig::DecodeField(pContainingModule,
10573                                                 pInfoModule,
10574                                                 pBlobData);
10575     }
10576 }
10577
10578
10579 //-----------------------------------------------------------------------------
10580
10581 #if 0 
10582
10583         This diagram illustrates the layout of fixups in the ngen image.
10584         This is the case where function foo2 has a class-restore fixup
10585         for class C1 in b.dll.
10586
10587                                   zapBase+curTableVA+rva /         FixupList (see Fixup Encoding below)
10588                                   m_pFixupBlobs
10589                                                             +-------------------+
10590                   pEntry->VA +--------------------+         |     non-NULL      | foo1
10591                              |Handles             |         +-------------------+
10592 ZapHeader.ImportTable        |                    |         |     non-NULL      |
10593                              |                    |         +-------------------+
10594    +------------+            +--------------------+         |     non-NULL      |
10595    |a.dll       |            |Class cctors        |<---+    +-------------------+
10596    |            |            |                    |     \   |         0         |
10597    |            |     p->VA/ |                    |<---+ \  +===================+
10598    |            |      blobs +--------------------+     \ +-------non-NULL      | foo2
10599    +------------+            |Class restore       |      \  +-------------------+
10600    |b.dll       |            |                    |       +-------non-NULL      |
10601    |            |            |                    |         +-------------------+
10602    |  token_C1  |<--------------blob(=>fixedUp/0) |<--pBlob--------index        |
10603    |            | \          |                    |         +-------------------+
10604    |            |  \         +--------------------+         |     non-NULL      |
10605    |            |   \        |                    |         +-------------------+
10606    |            |    \       |        .           |         |         0         |
10607    |            |     \      |        .           |         +===================+
10608    +------------+      \     |        .           |         |         0         | foo3
10609                         \    |                    |         +===================+
10610                          \   +--------------------+         |     non-NULL      | foo4
10611                           \  |Various fixups that |         +-------------------+
10612                            \ |need too happen     |         |         0         |
10613                             \|                    |         +===================+
10614                              |(CorCompileTokenTable)
10615                              |                    |
10616                pEntryEnd->VA +--------------------+
10617
10618
10619
10620 #endif // 0
10621
10622 //-----------------------------------------------------------------------------
10623
10624 BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
10625 {
10626     CONTRACTL
10627     {
10628         STANDARD_VM_CHECK;
10629         PRECONDITION(CheckPointer(fixupCell));
10630     }
10631     CONTRACTL_END;
10632
10633     // Ensure that the compiler won't fetch the value twice
10634     SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell);
10635
10636     if (pSection->Signatures != NULL)
10637     {
10638         if (fixup == NULL)
10639         {
10640             PTR_DWORD pSignatures = dac_cast<PTR_DWORD>(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures));
10641
10642             if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell))
10643                 return FALSE;
10644
10645             _ASSERTE(*fixupCell != NULL);
10646         }
10647     }
10648     else
10649     {
10650         if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
10651         {
10652             // Fixup has not been fixed up yet
10653             if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell))
10654                 return FALSE;
10655
10656             _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection));
10657         }
10658         else
10659         {
10660             //
10661             // Handle tables are special. We may need to restore static handle or previous 
10662             // attempts to load handle could have been partial.
10663             //
10664             if (pSection->Type == CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE)
10665             {
10666                 TypeHandle::FromPtr((void *)fixup).CheckRestore();
10667             }
10668             else
10669             if (pSection->Type == CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE)
10670             {
10671                 ((MethodDesc *)(fixup))->CheckRestore();
10672             }
10673         }
10674     }
10675
10676     return TRUE;
10677 }
10678
10679 //-----------------------------------------------------------------------------
10680
10681 void Module::RunEagerFixups()
10682 {
10683     STANDARD_VM_CONTRACT;
10684
10685     COUNT_T nSections;
10686     PTR_CORCOMPILE_IMPORT_SECTION pSections = GetImportSections(&nSections);
10687
10688     if (nSections == 0)
10689         return;
10690
10691 #ifdef _DEBUG
10692     // Loading types during eager fixup is not a tested scenario. Make bugs out of any attempts to do so in a
10693     // debug build. Use holder to recover properly in case of exception.
10694     class ForbidTypeLoadHolder
10695     {
10696     public:
10697         ForbidTypeLoadHolder()
10698         {
10699             BEGIN_FORBID_TYPELOAD();
10700         }
10701
10702         ~ForbidTypeLoadHolder()
10703         {
10704             END_FORBID_TYPELOAD();
10705         }
10706     }
10707     forbidTypeLoad;
10708 #endif
10709
10710     // TODO: Verify that eager fixup dependency graphs can contain no cycles
10711     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
10712
10713     PEImageLayout *pNativeImage = GetNativeOrReadyToRunImage();
10714
10715     for (COUNT_T iSection = 0; iSection < nSections; iSection++)
10716     {
10717         PTR_CORCOMPILE_IMPORT_SECTION pSection = pSections + iSection;
10718
10719         if ((pSection->Flags & CORCOMPILE_IMPORT_FLAGS_EAGER) == 0)
10720             continue;
10721
10722         COUNT_T tableSize;
10723         TADDR tableBase = pNativeImage->GetDirectoryData(&pSection->Section, &tableSize);
10724
10725         if (pSection->Signatures != NULL)
10726         {
10727             PTR_DWORD pSignatures = dac_cast<PTR_DWORD>(pNativeImage->GetRvaData(pSection->Signatures));
10728
10729             for (SIZE_T * fixupCell = (SIZE_T *)tableBase; fixupCell < (SIZE_T *)(tableBase + tableSize); fixupCell++)
10730             {
10731                 SIZE_T fixupIndex = fixupCell - (SIZE_T *)tableBase;
10732                 if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell))
10733                 {
10734                     _ASSERTE(!"LoadDynamicInfoEntry failed");
10735                     ThrowHR(COR_E_BADIMAGEFORMAT);
10736                 }
10737                 _ASSERTE(*fixupCell != NULL);
10738             }
10739         }
10740         else
10741         {
10742             for (SIZE_T * fixupCell = (SIZE_T *)tableBase; fixupCell < (SIZE_T *)(tableBase + tableSize); fixupCell++)
10743             {
10744                 // Ensure that the compiler won't fetch the value twice
10745                 SIZE_T fixup = VolatileLoadWithoutBarrier(fixupCell);
10746
10747                 // This method may execute multiple times in multi-domain scenarios. Check that the fixup has not been 
10748                 // fixed up yet.
10749                 if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
10750                 {
10751                     if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell))
10752                     {
10753                         _ASSERTE(!"LoadDynamicInfoEntry failed");
10754                         ThrowHR(COR_E_BADIMAGEFORMAT);
10755                     }
10756                     _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection));
10757                 }
10758             }
10759         }
10760     }
10761 }
10762
10763 void Module::LoadTokenTables()
10764 {
10765     CONTRACTL
10766     {
10767         INSTANCE_CHECK;
10768         THROWS;
10769         GC_TRIGGERS;
10770         MODE_ANY;
10771         PRECONDITION(HasNativeImage());
10772     }
10773     CONTRACTL_END;
10774
10775 #ifndef CROSSGEN_COMPILE
10776     if (NingenEnabled())
10777         return;
10778
10779     CORCOMPILE_EE_INFO_TABLE *pEEInfo = GetNativeImage()->GetNativeEEInfoTable();
10780     PREFIX_ASSUME(pEEInfo != NULL);
10781
10782     pEEInfo->inlinedCallFrameVptr = InlinedCallFrame::GetMethodFrameVPtr();
10783     pEEInfo->addrOfCaptureThreadGlobal = (LONG *)&g_TrapReturningThreads;
10784
10785     //CoreClr doesn't always have the debugger loaded
10786     //patch up the ngen image to point to this address so that the JIT bypasses JMC if there is no debugger
10787     static DWORD g_dummyJMCFlag = 0;
10788     pEEInfo->addrOfJMCFlag = g_pDebugInterface ? g_pDebugInterface->GetJMCFlagAddr(this) : &g_dummyJMCFlag;
10789    
10790     pEEInfo->gsCookie = GetProcessGSCookie();
10791
10792     if (!IsSystem())
10793     {
10794         pEEInfo->emptyString = (CORINFO_Object **)StringObject::GetEmptyStringRefPtr();
10795     }
10796
10797     pEEInfo->threadTlsIndex = TLS_OUT_OF_INDEXES;
10798     pEEInfo->rvaStaticTlsIndex = NULL;
10799 #endif // CROSSGEN_COMPILE
10800 }
10801
10802 #endif // !DACCESS_COMPILE
10803
10804 // Returns the RVA to the compressed debug information blob for the given method
10805
10806 CORCOMPILE_DEBUG_ENTRY Module::GetMethodDebugInfoOffset(MethodDesc *pMD)
10807 {
10808     CONTRACT(CORCOMPILE_DEBUG_ENTRY)
10809     {
10810         INSTANCE_CHECK;
10811         PRECONDITION(HasNativeImage());
10812         PRECONDITION(CheckPointer(pMD) && pMD->IsPreImplemented());
10813         POSTCONDITION(GetNativeImage()->CheckRva(RETVAL, NULL_OK));
10814         NOTHROW;
10815         GC_NOTRIGGER;
10816         MODE_ANY;
10817         SUPPORTS_DAC;
10818     }
10819     CONTRACT_END;
10820
10821     if (!GetNativeImage()->HasNativeDebugMap() || pMD->IsRuntimeSupplied())
10822         RETURN 0;
10823
10824     COUNT_T size;
10825     PTR_CORCOMPILE_DEBUG_RID_ENTRY ridTable = 
10826         dac_cast<PTR_CORCOMPILE_DEBUG_RID_ENTRY>(GetNativeImage()->GetNativeDebugMap(&size));
10827
10828     COUNT_T count = size / sizeof(CORCOMPILE_DEBUG_RID_ENTRY);
10829     // The size should be odd for better hashing
10830     _ASSERTE((count & 1) != 0);
10831
10832     CORCOMPILE_DEBUG_RID_ENTRY ridEntry = ridTable[GetDebugRidEntryHash(pMD->GetMemberDef()) % count];
10833
10834     // Do we have multiple code corresponding to the same RID
10835     if (!IsMultipleLabelledEntries(ridEntry))
10836     {
10837         RETURN(ridEntry);
10838     }
10839
10840     PTR_CORCOMPILE_DEBUG_LABELLED_ENTRY pLabelledEntry =
10841         PTR_CORCOMPILE_DEBUG_LABELLED_ENTRY
10842         (GetNativeImage()->GetRvaData(ridEntry &
10843                                       ~CORCOMPILE_DEBUG_MULTIPLE_ENTRIES));
10844
10845     DWORD codeRVA = GetNativeImage()->
10846         GetDataRva((const TADDR)pMD->GetNativeCode());
10847 #if defined(_TARGET_ARM_)
10848     // Since the Thumb Bit is set on ARM, the RVA calculated above will have it set as well
10849     // and will result in the failure of checks in the loop below. Hence, mask off the
10850     // bit before proceeding ahead.
10851     codeRVA = ThumbCodeToDataPointer<DWORD, DWORD>(codeRVA);
10852 #endif // _TARGET_ARM_
10853
10854     for (;;)
10855     {
10856         if (pLabelledEntry->nativeCodeRVA == codeRVA)
10857         {
10858             RETURN (pLabelledEntry->debugInfoOffset & ~CORCOMPILE_DEBUG_MULTIPLE_ENTRIES);
10859         }
10860
10861         if (!IsMultipleLabelledEntries(pLabelledEntry->debugInfoOffset))
10862         {
10863             break;
10864         }
10865
10866         pLabelledEntry++;
10867     }
10868
10869     _ASSERTE(!"Debug info not found - corrupted ngen image?");
10870     RETURN (0);
10871 }
10872
10873 PTR_BYTE Module::GetNativeDebugInfo(MethodDesc * pMD)
10874 {
10875     CONTRACTL
10876     {
10877         INSTANCE_CHECK;
10878         PRECONDITION(HasNativeImage());
10879         PRECONDITION(CheckPointer(pMD));
10880         PRECONDITION(pMD->GetZapModule() == this);
10881         THROWS;
10882         GC_NOTRIGGER;
10883         MODE_ANY;
10884         SUPPORTS_DAC;
10885     }
10886     CONTRACTL_END;
10887
10888     CORCOMPILE_DEBUG_ENTRY debugInfoOffset = GetMethodDebugInfoOffset(pMD);
10889
10890     if (debugInfoOffset == 0)
10891         return NULL;
10892
10893     return dac_cast<PTR_BYTE>(GetNativeImage()->GetRvaData(debugInfoOffset));
10894 }
10895 #endif //FEATURE_PREJIT
10896
10897
10898
10899 #ifndef DACCESS_COMPILE 
10900
10901 #ifdef FEATURE_PREJIT 
10902 //
10903 // Profile data management
10904 //
10905
10906 ICorJitInfo::ProfileBuffer * Module::AllocateProfileBuffer(mdToken _token, DWORD _count, DWORD _ILSize)
10907 {
10908     CONTRACT (ICorJitInfo::ProfileBuffer*)
10909     {
10910         INSTANCE_CHECK;
10911         THROWS;
10912         GC_NOTRIGGER;
10913         MODE_ANY;
10914         INJECT_FAULT(CONTRACT_RETURN NULL;);
10915         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
10916     }
10917     CONTRACT_END;
10918
10919     assert(_ILSize != 0);
10920
10921     DWORD   listSize   = sizeof(CORCOMPILE_METHOD_PROFILE_LIST);
10922     DWORD   headerSize = sizeof(CORBBTPROF_METHOD_HEADER);
10923     DWORD   blockSize  = _count * sizeof(CORBBTPROF_BLOCK_DATA);
10924     DWORD   totalSize  = listSize + headerSize + blockSize;
10925
10926     BYTE *  memory     = (BYTE *) (void *) this->m_pAssembly->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(totalSize));
10927
10928     CORCOMPILE_METHOD_PROFILE_LIST * methodProfileList = (CORCOMPILE_METHOD_PROFILE_LIST *) (memory + 0);
10929     CORBBTPROF_METHOD_HEADER *       methodProfileData = (CORBBTPROF_METHOD_HEADER *)       (memory + listSize);
10930     
10931     // Note: Memory allocated on the LowFrequencyHeap is zero filled
10932
10933     methodProfileData->size          = headerSize + blockSize;
10934     methodProfileData->method.token  = _token;
10935     methodProfileData->method.ILSize = _ILSize;
10936     methodProfileData->method.cBlock = _count;
10937
10938     assert(methodProfileData->size == methodProfileData->Size());
10939
10940     // Link it to the per module list of profile data buffers
10941
10942     methodProfileList->next = m_methodProfileList;
10943     m_methodProfileList     = methodProfileList;
10944
10945     RETURN ((ICorJitInfo::ProfileBuffer *) &methodProfileData->method.block[0]);
10946 }
10947
10948 HANDLE Module::OpenMethodProfileDataLogFile(GUID mvid)
10949 {
10950     CONTRACTL
10951     {
10952         INSTANCE_CHECK;
10953         THROWS;
10954         GC_NOTRIGGER;
10955         MODE_ANY;
10956     }
10957     CONTRACTL_END;
10958
10959     HANDLE profileDataFile = INVALID_HANDLE_VALUE;
10960
10961     SString path;
10962     LPCWSTR assemblyPath = m_file->GetPath();
10963     LPCWSTR ibcDir = g_pConfig->GetZapBBInstrDir();     // should we put the ibc data into a particular directory?
10964     if (ibcDir == 0) {
10965         path.Set(assemblyPath);                         // no, then put it beside the IL dll
10966     }
10967     else {
10968         LPCWSTR assemblyFileName = wcsrchr(assemblyPath, '\\'); 
10969         if (assemblyFileName)
10970             assemblyFileName++;                         // skip past the \ char
10971         else 
10972             assemblyFileName = assemblyPath;
10973
10974         path.Set(ibcDir);                               // yes, put it in the directory, named with the assembly name.
10975         path.Append('\\');
10976         path.Append(assemblyFileName);
10977     }
10978
10979     SString::Iterator ext = path.End();                 // remove the extension
10980     if (path.FindBack(ext, '.'))
10981         path.Truncate(ext);
10982     path.Append(W(".ibc"));               // replace with .ibc extension
10983
10984     profileDataFile = WszCreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
10985                                     OPEN_ALWAYS,
10986                                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
10987                                     NULL);
10988
10989     if (profileDataFile == INVALID_HANDLE_VALUE) COMPlusThrowWin32();
10990
10991     DWORD count;
10992     CORBBTPROF_FILE_HEADER fileHeader;
10993
10994     SetFilePointer(profileDataFile, 0, NULL, FILE_BEGIN);
10995     BOOL result = ReadFile(profileDataFile, &fileHeader, sizeof(fileHeader), &count, NULL);
10996     if (result                                                    &&
10997         (count                 == sizeof(fileHeader))             &&
10998         (fileHeader.HeaderSize == sizeof(CORBBTPROF_FILE_HEADER)) &&
10999         (fileHeader.Magic      == CORBBTPROF_MAGIC)               &&
11000         (fileHeader.Version    == CORBBTPROF_CURRENT_VERSION)     &&
11001         (fileHeader.MVID       == mvid))
11002     {
11003         //
11004         // The existing file was from the same assembly version - just append to it.
11005         //
11006
11007         SetFilePointer(profileDataFile, 0, NULL, FILE_END);
11008     }
11009     else
11010     {
11011         //
11012         // Either this is a new file, or it's from a previous version.  Replace the contents.
11013         //
11014
11015         SetFilePointer(profileDataFile, 0, NULL, FILE_BEGIN);
11016     }
11017
11018     return profileDataFile;
11019 }
11020
11021 // Note that this method cleans up the profile buffers, so it's crucial that
11022 // no managed code in the module is allowed to run once this method has
11023 // been called!
11024
11025 class ProfileMap
11026 {
11027 public:
11028     SIZE_T getCurrentOffset() {WRAPPER_NO_CONTRACT; return buffer.Size();}
11029
11030     void * getOffsetPtr(SIZE_T offset)
11031     {
11032         LIMITED_METHOD_CONTRACT;
11033         _ASSERTE(offset <= buffer.Size());
11034         return ((void *) (((char *) buffer.Ptr()) + offset));
11035     }
11036
11037     void *Allocate(SIZE_T size)
11038     {
11039         CONTRACT(void *)
11040         {
11041             INSTANCE_CHECK;
11042             THROWS;
11043             GC_NOTRIGGER;
11044             MODE_ANY;
11045             INJECT_FAULT(CONTRACT_RETURN NULL;);
11046             POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
11047         }
11048         CONTRACT_END;
11049
11050         SIZE_T oldSize = buffer.Size();
11051         buffer.ReSizeThrows(oldSize + size);
11052         RETURN getOffsetPtr(oldSize);
11053     }
11054
11055 private:
11056     CQuickBytes buffer;
11057 };
11058
11059 class ProfileEmitter
11060 {
11061 public:
11062
11063     ProfileEmitter()
11064     {
11065         LIMITED_METHOD_CONTRACT;
11066         pSectionList = NULL;
11067     }
11068
11069     ~ProfileEmitter()
11070     {
11071         WRAPPER_NO_CONTRACT;
11072         while (pSectionList)
11073         {
11074             SectionList *temp = pSectionList->next;
11075             delete pSectionList;
11076             pSectionList = temp;
11077         }
11078     }
11079
11080     ProfileMap *EmitNewSection(SectionFormat format)
11081     {
11082         WRAPPER_NO_CONTRACT;
11083         SectionList *s = new SectionList();
11084
11085         s->format    = format;
11086         s->next      = pSectionList;
11087         pSectionList = s;
11088
11089         return &s->profileMap;
11090     }
11091
11092     //
11093     // Serialize the profile sections into pMap
11094     //
11095
11096     void Serialize(ProfileMap *profileMap, GUID mvid)
11097     {
11098         CONTRACTL
11099         {
11100             INSTANCE_CHECK;
11101             THROWS;
11102             GC_NOTRIGGER;
11103             MODE_ANY;
11104             INJECT_FAULT(COMPlusThrowOM());
11105         }
11106         CONTRACTL_END;
11107
11108         //
11109         // Allocate the file header
11110         //
11111         {
11112             CORBBTPROF_FILE_HEADER *fileHeader;
11113             fileHeader = (CORBBTPROF_FILE_HEADER *) profileMap->Allocate(sizeof(CORBBTPROF_FILE_HEADER));
11114             
11115             fileHeader->HeaderSize = sizeof(CORBBTPROF_FILE_HEADER);
11116             fileHeader->Magic      = CORBBTPROF_MAGIC;
11117             fileHeader->Version    = CORBBTPROF_CURRENT_VERSION;
11118             fileHeader->MVID       = mvid;
11119         }
11120
11121         //
11122         // Count the number of sections
11123         //
11124         ULONG32 numSections = 0;
11125         for (SectionList *p = pSectionList; p; p = p->next)
11126         {
11127             numSections++;
11128         }
11129
11130         //
11131         // Allocate the section table
11132         //
11133         SIZE_T tableEntryOffset;
11134         {
11135             CORBBTPROF_SECTION_TABLE_HEADER *tableHeader;
11136             tableHeader = (CORBBTPROF_SECTION_TABLE_HEADER *)
11137                 profileMap->Allocate(sizeof(CORBBTPROF_SECTION_TABLE_HEADER));
11138
11139             tableHeader->NumEntries = numSections;
11140             tableEntryOffset = profileMap->getCurrentOffset();
11141             
11142             CORBBTPROF_SECTION_TABLE_ENTRY *tableEntry;
11143             tableEntry = (CORBBTPROF_SECTION_TABLE_ENTRY *)
11144                 profileMap->Allocate(sizeof(CORBBTPROF_SECTION_TABLE_ENTRY) * numSections);
11145         }
11146
11147         //
11148         // Allocate the data sections
11149         //
11150         {
11151             ULONG secCount = 0;
11152             for (SectionList *pSec = pSectionList; pSec; pSec = pSec->next, secCount++)
11153             {
11154                 SIZE_T offset = profileMap->getCurrentOffset();
11155                 assert((offset & 0x3) == 0);
11156                 
11157                 SIZE_T actualSize  = pSec->profileMap.getCurrentOffset();
11158                 SIZE_T alignUpSize = AlignUp(actualSize, sizeof(DWORD));
11159                 
11160                 profileMap->Allocate(alignUpSize);
11161                 
11162                 memcpy(profileMap->getOffsetPtr(offset), pSec->profileMap.getOffsetPtr(0), actualSize);
11163                 if (alignUpSize > actualSize)
11164                 {
11165                     memset(((BYTE*)profileMap->getOffsetPtr(offset))+actualSize, 0, (alignUpSize - actualSize)); 
11166                 }
11167                 
11168                 CORBBTPROF_SECTION_TABLE_ENTRY *tableEntry;
11169                 tableEntry = (CORBBTPROF_SECTION_TABLE_ENTRY *) profileMap->getOffsetPtr(tableEntryOffset);
11170                 tableEntry += secCount;
11171                 tableEntry->FormatID    = pSec->format;
11172                 tableEntry->Data.Offset = offset;
11173                 tableEntry->Data.Size   = alignUpSize;
11174             }
11175         }
11176
11177         //
11178         // Allocate the end token marker
11179         //
11180         {
11181             ULONG *endToken;
11182             endToken = (ULONG *) profileMap->Allocate(sizeof(ULONG));
11183             
11184             *endToken = CORBBTPROF_END_TOKEN;
11185         }
11186     }
11187
11188 private:
11189     struct SectionList
11190     {
11191         SectionFormat format;
11192         ProfileMap    profileMap;
11193         SectionList   *next;
11194     };
11195     SectionList *  pSectionList;
11196 };
11197
11198
11199 /*static*/ idTypeSpec          TypeSpecBlobEntry::s_lastTypeSpecToken                   = idTypeSpecNil;
11200 /*static*/ idMethodSpec        MethodSpecBlobEntry::s_lastMethodSpecToken               = idMethodSpecNil;
11201 /*static*/ idExternalNamespace ExternalNamespaceBlobEntry::s_lastExternalNamespaceToken = idExternalNamespaceNil;
11202 /*static*/ idExternalType      ExternalTypeBlobEntry::s_lastExternalTypeToken           = idExternalTypeNil;
11203 /*static*/ idExternalSignature ExternalSignatureBlobEntry::s_lastExternalSignatureToken = idExternalSignatureNil;
11204 /*static*/ idExternalMethod    ExternalMethodBlobEntry::s_lastExternalMethodToken       = idExternalMethodNil;
11205
11206
11207 inline static size_t HashCombine(size_t h1, size_t h2)
11208 {
11209     LIMITED_METHOD_CONTRACT;
11210
11211     size_t result = (h1 * 129) ^ h2;
11212     return result;
11213 }
11214
11215 bool        TypeSpecBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
11216 {
11217     WRAPPER_NO_CONTRACT;
11218
11219     if (this->kind() != other->kind())
11220         return false;
11221
11222     const TypeSpecBlobEntry *  other2 = static_cast<const TypeSpecBlobEntry *>(other);
11223
11224     if (this->cbSig() != other2->cbSig())
11225         return false;
11226
11227     PCCOR_SIGNATURE  p1 = this->pSig();
11228     PCCOR_SIGNATURE  p2 = other2->pSig();
11229     
11230     for (DWORD i=0; (i < this->cbSig()); i++)
11231         if (p1[i] != p2[i])
11232             return false;
11233
11234     return true;
11235 }
11236
11237 size_t     TypeSpecBlobEntry::Hash() const
11238 {
11239     WRAPPER_NO_CONTRACT;
11240
11241     size_t hashValue = HashInit();
11242
11243     PCCOR_SIGNATURE  p1 = pSig();
11244     for (DWORD i=0; (i < cbSig()); i++)
11245         hashValue = HashCombine(hashValue, p1[i]);
11246
11247     return hashValue;
11248 }
11249
11250 TypeSpecBlobEntry::TypeSpecBlobEntry(DWORD _cbSig, PCCOR_SIGNATURE _pSig)
11251 {
11252     CONTRACTL
11253     {
11254         NOTHROW;
11255         GC_NOTRIGGER;
11256         PRECONDITION(_cbSig > 0);
11257         PRECONDITION(CheckPointer(_pSig));
11258     }
11259     CONTRACTL_END;
11260
11261     m_token  = idTypeSpecNil;
11262     m_flags  = 0;
11263     m_cbSig  = 0;
11264
11265     COR_SIGNATURE * pNewSig = (COR_SIGNATURE *) new (nothrow) BYTE[_cbSig];
11266     if (pNewSig != NULL)
11267     {
11268         m_flags  = 0;
11269         m_cbSig  = _cbSig;
11270         memcpy(pNewSig, _pSig, _cbSig);
11271     }
11272     m_pSig = const_cast<PCCOR_SIGNATURE>(pNewSig);
11273 }
11274
11275 /* static */ const TypeSpecBlobEntry *  TypeSpecBlobEntry::FindOrAdd(PTR_Module      pModule, 
11276                                                                      DWORD           _cbSig, 
11277                                                                      PCCOR_SIGNATURE _pSig)
11278 {
11279     CONTRACTL
11280     {
11281         NOTHROW;
11282         GC_NOTRIGGER;
11283     }
11284     CONTRACTL_END;
11285
11286     if ((_cbSig == 0) || (_pSig == NULL))
11287         return NULL;
11288
11289     TypeSpecBlobEntry sEntry(_cbSig, _pSig);
11290
11291     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
11292     if (pEntry == NULL)
11293     {
11294         //
11295         // Not Found, add a new type spec profiling blob entry
11296         // 
11297         TypeSpecBlobEntry * newEntry = new (nothrow) TypeSpecBlobEntry(_cbSig, _pSig);
11298         if (newEntry == NULL)
11299             return NULL;
11300
11301         newEntry->newToken();                 // Assign a new ibc type spec token
11302         CONTRACT_VIOLATION(ThrowsViolation);
11303         pModule->GetProfilingBlobTable()->Add(newEntry);
11304         pEntry = newEntry;
11305     }
11306
11307     //
11308     // Return the type spec entry that we found or the new one that we just created
11309     // 
11310     _ASSERTE(pEntry->kind() == ParamTypeSpec);
11311     return static_cast<const TypeSpecBlobEntry *>(pEntry);
11312 }
11313
11314 bool        MethodSpecBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
11315 {
11316     WRAPPER_NO_CONTRACT;
11317
11318     if (this->kind() != other->kind())
11319         return false;
11320
11321     const MethodSpecBlobEntry *  other2 = static_cast<const MethodSpecBlobEntry *>(other);
11322
11323     if (this->cbSig() != other2->cbSig())
11324         return false;
11325
11326     PCCOR_SIGNATURE  p1 = this->pSig();
11327     PCCOR_SIGNATURE  p2 = other2->pSig();
11328     
11329     for (DWORD i=0; (i < this->cbSig()); i++)
11330         if (p1[i] != p2[i])
11331             return false;
11332
11333     return true;
11334 }
11335
11336 size_t     MethodSpecBlobEntry::Hash() const
11337 {
11338     WRAPPER_NO_CONTRACT;
11339
11340     size_t hashValue = HashInit();
11341
11342     PCCOR_SIGNATURE  p1 = pSig();
11343     for (DWORD i=0; (i < cbSig()); i++)
11344         hashValue = HashCombine(hashValue, p1[i]);
11345
11346     return hashValue;
11347 }
11348
11349 MethodSpecBlobEntry::MethodSpecBlobEntry(DWORD _cbSig, PCCOR_SIGNATURE _pSig)
11350 {
11351     CONTRACTL
11352     {
11353         NOTHROW;
11354         GC_NOTRIGGER;
11355         PRECONDITION(_cbSig > 0);
11356         PRECONDITION(CheckPointer(_pSig));
11357     }
11358     CONTRACTL_END;
11359
11360     m_token  = idMethodSpecNil;
11361     m_flags  = 0;
11362     m_cbSig  = 0;
11363
11364     COR_SIGNATURE * pNewSig = (COR_SIGNATURE *) new (nothrow) BYTE[_cbSig];
11365     if (pNewSig != NULL)
11366     {
11367         m_flags  = 0;
11368         m_cbSig  = _cbSig;
11369         memcpy(pNewSig, _pSig, _cbSig);
11370     }
11371     m_pSig = const_cast<PCCOR_SIGNATURE>(pNewSig);
11372 }
11373
11374 /* static */ const MethodSpecBlobEntry *  MethodSpecBlobEntry::FindOrAdd(PTR_Module      pModule, 
11375                                                                          DWORD           _cbSig, 
11376                                                                          PCCOR_SIGNATURE _pSig)
11377 {
11378     CONTRACTL
11379     {
11380         NOTHROW;
11381         GC_NOTRIGGER;
11382     }
11383     CONTRACTL_END;
11384
11385     if ((_cbSig == 0) || (_pSig == NULL))
11386         return NULL;
11387
11388     MethodSpecBlobEntry sEntry(_cbSig, _pSig);
11389
11390     const ProfilingBlobEntry * pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
11391     if (pEntry == NULL)
11392     {
11393         //
11394         // Not Found, add a new method spec profiling blob entry
11395         // 
11396         MethodSpecBlobEntry * newEntry = new (nothrow) MethodSpecBlobEntry(_cbSig, _pSig);
11397         if (newEntry == NULL)
11398             return NULL;
11399
11400         newEntry->newToken();                 // Assign a new ibc method spec token
11401         CONTRACT_VIOLATION(ThrowsViolation);
11402         pModule->GetProfilingBlobTable()->Add(newEntry);
11403         pEntry = newEntry;
11404     }
11405
11406     //
11407     // Return the method spec entry that we found or the new one that we just created
11408     // 
11409     _ASSERTE(pEntry->kind() == ParamMethodSpec);
11410     return static_cast<const MethodSpecBlobEntry *>(pEntry);
11411 }
11412
11413 bool        ExternalNamespaceBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
11414 {
11415     WRAPPER_NO_CONTRACT;
11416
11417     if (this->kind() != other->kind())
11418         return false;
11419
11420     const ExternalNamespaceBlobEntry *  other2 = static_cast<const ExternalNamespaceBlobEntry *>(other);
11421
11422     if (this->cbName() != other2->cbName())
11423         return false;
11424
11425     LPCSTR p1 = this->pName();
11426     LPCSTR p2 = other2->pName();
11427     
11428     for (DWORD i=0; (i < this->cbName()); i++)
11429         if (p1[i] != p2[i])
11430             return false;
11431
11432     return true;
11433 }
11434
11435 size_t     ExternalNamespaceBlobEntry::Hash() const
11436 {
11437     WRAPPER_NO_CONTRACT;
11438
11439     size_t hashValue = HashInit();
11440
11441     LPCSTR p1 = pName();
11442     for (DWORD i=0; (i < cbName()); i++)
11443         hashValue = HashCombine(hashValue, p1[i]);
11444
11445     return hashValue;
11446 }
11447
11448 ExternalNamespaceBlobEntry::ExternalNamespaceBlobEntry(LPCSTR _pName)
11449 {
11450    CONTRACTL
11451     {
11452         NOTHROW;
11453         GC_NOTRIGGER;
11454         PRECONDITION(CheckPointer(_pName));
11455     }
11456     CONTRACTL_END;
11457
11458     m_token  = idExternalNamespaceNil;
11459     m_cbName = 0;
11460     m_pName  = NULL;
11461
11462     DWORD _cbName = (DWORD) strlen(_pName) + 1;
11463     LPSTR * pName = (LPSTR *) new (nothrow) CHAR[_cbName];
11464     if (pName != NULL)
11465     {
11466         m_cbName = _cbName;
11467         memcpy(pName, _pName, _cbName);
11468         m_pName  = (LPCSTR) pName;
11469     }
11470 }
11471
11472 /* static */ const ExternalNamespaceBlobEntry *  ExternalNamespaceBlobEntry::FindOrAdd(PTR_Module pModule, LPCSTR _pName)
11473 {
11474    CONTRACTL
11475     {
11476         NOTHROW;
11477         GC_NOTRIGGER;
11478     }
11479     CONTRACTL_END;
11480
11481     if ((_pName == NULL) || (::strlen(_pName) == 0))
11482         return NULL;
11483
11484     ExternalNamespaceBlobEntry sEntry(_pName);
11485
11486     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
11487     if (pEntry == NULL)
11488     {
11489         //
11490         // Not Found, add a new external namespace blob entry
11491         // 
11492         ExternalNamespaceBlobEntry * newEntry = new (nothrow) ExternalNamespaceBlobEntry(_pName);
11493         if (newEntry == NULL)
11494             return NULL;
11495
11496         newEntry->newToken();                 // Assign a new ibc external namespace token
11497         CONTRACT_VIOLATION(ThrowsViolation);
11498         pModule->GetProfilingBlobTable()->Add(newEntry);
11499         pEntry = newEntry;
11500     }
11501
11502     //
11503     // Return the external namespace entry that we found or the new one that we just created
11504     // 
11505     _ASSERTE(pEntry->kind() == ExternalNamespaceDef);
11506     return static_cast<const ExternalNamespaceBlobEntry *>(pEntry);
11507 }
11508
11509 bool        ExternalTypeBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
11510 {
11511     WRAPPER_NO_CONTRACT;
11512
11513     if (this->kind() != other->kind())
11514         return false;
11515
11516     const ExternalTypeBlobEntry *  other2 = static_cast<const ExternalTypeBlobEntry *>(other);
11517
11518     if (this->assemblyRef() != other2->assemblyRef())
11519         return false;
11520
11521     if (this->nestedClass() != other2->nestedClass())
11522         return false;
11523
11524     if (this->nameSpace() != other2->nameSpace())
11525         return false;
11526
11527     if (this->cbName() != other2->cbName())
11528         return false;
11529
11530     LPCSTR p1 = this->pName();
11531     LPCSTR p2 = other2->pName();
11532     
11533     for (DWORD i=0; (i < this->cbName()); i++)
11534         if (p1[i] != p2[i])
11535             return false;
11536
11537     return true;
11538 }
11539
11540 size_t     ExternalTypeBlobEntry::Hash() const
11541 {
11542     WRAPPER_NO_CONTRACT;
11543
11544     size_t hashValue = HashInit();
11545
11546     hashValue = HashCombine(hashValue, assemblyRef());
11547     hashValue = HashCombine(hashValue, nestedClass());
11548     hashValue = HashCombine(hashValue, nameSpace());
11549
11550     LPCSTR p1 = pName();
11551     
11552     for (DWORD i=0; (i < cbName()); i++)
11553         hashValue = HashCombine(hashValue, p1[i]);
11554
11555     return hashValue;
11556 }
11557
11558 ExternalTypeBlobEntry::ExternalTypeBlobEntry(mdToken _assemblyRef, 
11559                                              mdToken _nestedClass,
11560                                              mdToken _nameSpace, 
11561                                              LPCSTR  _pName)
11562 {
11563    CONTRACTL
11564     {
11565         NOTHROW;
11566         GC_NOTRIGGER;
11567         PRECONDITION(CheckPointer(_pName));
11568     }
11569     CONTRACTL_END;
11570
11571     m_token  = idExternalTypeNil;
11572     m_assemblyRef = mdAssemblyRefNil; 
11573     m_nestedClass = idExternalTypeNil; 
11574     m_nameSpace   = idExternalNamespaceNil; 
11575     m_cbName = 0;
11576     m_pName  = NULL;
11577
11578     DWORD _cbName = (DWORD) strlen(_pName) + 1;
11579     LPSTR * pName = (LPSTR *) new (nothrow) CHAR[_cbName];
11580     if (pName != NULL)
11581     {
11582         m_assemblyRef = _assemblyRef;
11583         m_nestedClass = _nestedClass;
11584         m_nameSpace   = _nameSpace;
11585         m_cbName      = _cbName;
11586         memcpy(pName, _pName, _cbName);
11587         m_pName       = (LPCSTR) pName;
11588     }
11589 }
11590
11591 /* static */ const ExternalTypeBlobEntry *  ExternalTypeBlobEntry::FindOrAdd(PTR_Module pModule, 
11592                                                                              mdToken    _assemblyRef, 
11593                                                                              mdToken    _nestedClass,
11594                                                                              mdToken    _nameSpace, 
11595                                                                              LPCSTR     _pName)
11596 {
11597    CONTRACTL
11598     {
11599         NOTHROW;
11600         GC_NOTRIGGER;
11601     }
11602     CONTRACTL_END;
11603
11604     if ((_pName == NULL) || (::strlen(_pName) == 0))
11605         return NULL;
11606
11607     ExternalTypeBlobEntry sEntry(_assemblyRef, _nestedClass, _nameSpace, _pName);
11608
11609     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
11610     if (pEntry == NULL)
11611     {
11612         //
11613         // Not Found, add a new external type blob entry
11614         // 
11615         ExternalTypeBlobEntry *  newEntry = new (nothrow) ExternalTypeBlobEntry(_assemblyRef, _nestedClass, _nameSpace, _pName);
11616         if (newEntry == NULL)
11617             return NULL;
11618
11619         newEntry->newToken();                 // Assign a new ibc external type token
11620         CONTRACT_VIOLATION(ThrowsViolation);
11621         pModule->GetProfilingBlobTable()->Add(newEntry);
11622         pEntry = newEntry;
11623     }
11624
11625     //
11626     // Return the external type entry that we found or the new one that we just created
11627     // 
11628     _ASSERTE(pEntry->kind() == ExternalTypeDef);
11629     return static_cast<const ExternalTypeBlobEntry *>(pEntry);
11630 }
11631
11632 bool        ExternalSignatureBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
11633 {
11634     WRAPPER_NO_CONTRACT;
11635
11636     if (this->kind() != other->kind())
11637         return false;
11638
11639     const ExternalSignatureBlobEntry *  other2 = static_cast<const ExternalSignatureBlobEntry *>(other);
11640
11641     if (this->cbSig() != other2->cbSig())
11642         return false;
11643
11644     PCCOR_SIGNATURE  p1 = this->pSig();
11645     PCCOR_SIGNATURE  p2 = other2->pSig();
11646     
11647     for (DWORD i=0; (i < this->cbSig()); i++)
11648         if (p1[i] != p2[i])
11649             return false;
11650
11651     return true;
11652 }
11653
11654 size_t     ExternalSignatureBlobEntry::Hash() const
11655 {
11656     WRAPPER_NO_CONTRACT;
11657
11658     size_t hashValue = HashInit();
11659
11660     hashValue = HashCombine(hashValue, cbSig());
11661
11662     PCCOR_SIGNATURE  p1 = pSig();
11663     
11664     for (DWORD i=0; (i < cbSig()); i++)
11665         hashValue = HashCombine(hashValue, p1[i]);
11666
11667     return hashValue;
11668 }
11669
11670 ExternalSignatureBlobEntry::ExternalSignatureBlobEntry(DWORD _cbSig, PCCOR_SIGNATURE _pSig)
11671 {
11672     CONTRACTL
11673     {
11674         NOTHROW;
11675         GC_NOTRIGGER;
11676         PRECONDITION(_cbSig > 0);
11677         PRECONDITION(CheckPointer(_pSig));
11678     }
11679     CONTRACTL_END;
11680
11681     m_token  = idExternalSignatureNil;
11682     m_cbSig  = 0;
11683
11684     COR_SIGNATURE *  pNewSig = (COR_SIGNATURE *) new (nothrow) BYTE[_cbSig];
11685     if (pNewSig != NULL)
11686     {
11687         m_cbSig  = _cbSig;
11688         memcpy(pNewSig, _pSig, _cbSig);
11689     }
11690     m_pSig = const_cast<PCCOR_SIGNATURE>(pNewSig);
11691 }
11692
11693 /* static */ const ExternalSignatureBlobEntry *  ExternalSignatureBlobEntry::FindOrAdd(PTR_Module      pModule, 
11694                                                                                        DWORD           _cbSig, 
11695                                                                                        PCCOR_SIGNATURE _pSig)
11696 {
11697     CONTRACTL
11698     {
11699         NOTHROW;
11700         GC_NOTRIGGER;
11701     }
11702     CONTRACTL_END;
11703
11704     if ((_cbSig == 0) || (_pSig == NULL))
11705         return NULL;
11706
11707     ExternalSignatureBlobEntry sEntry(_cbSig, _pSig);
11708
11709     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
11710     if (pEntry == NULL)
11711     {
11712         //
11713         // Not Found, add a new external signature blob entry
11714         // 
11715         ExternalSignatureBlobEntry * newEntry = new (nothrow) ExternalSignatureBlobEntry(_cbSig, _pSig);
11716         if (newEntry == NULL)
11717             return NULL;
11718
11719         newEntry->newToken();                 // Assign a new ibc external signature token
11720         CONTRACT_VIOLATION(ThrowsViolation);
11721         pModule->GetProfilingBlobTable()->Add(newEntry);
11722         pEntry = newEntry;
11723     }
11724
11725     //
11726     // Return the external signature entry that we found or the new one that we just created
11727     // 
11728     _ASSERTE(pEntry->kind() == ExternalSignatureDef);
11729     return static_cast<const ExternalSignatureBlobEntry *>(pEntry);
11730 }
11731
11732 bool        ExternalMethodBlobEntry::IsEqual(const ProfilingBlobEntry *  other) const
11733 {
11734     WRAPPER_NO_CONTRACT;
11735
11736     if (this->kind() != other->kind())
11737         return false;
11738
11739     const ExternalMethodBlobEntry *  other2 = static_cast<const ExternalMethodBlobEntry *>(other);
11740
11741     if (this->nestedClass() != other2->nestedClass())
11742         return false;
11743
11744     if (this->signature() != other2->signature())
11745         return false;
11746
11747     if (this->cbName() != other2->cbName())
11748         return false;
11749
11750     LPCSTR p1 = this->pName();
11751     LPCSTR p2 = other2->pName();
11752     
11753     for (DWORD i=0; (i < this->cbName()); i++)
11754         if (p1[i] != p2[i])
11755             return false;
11756
11757     return true;
11758 }
11759
11760 size_t     ExternalMethodBlobEntry::Hash() const
11761 {
11762     WRAPPER_NO_CONTRACT;
11763
11764     size_t hashValue = HashInit();
11765
11766     hashValue = HashCombine(hashValue, nestedClass());
11767     hashValue = HashCombine(hashValue, signature());
11768
11769     LPCSTR p1 = pName();
11770     
11771     for (DWORD i=0; (i < cbName()); i++)
11772         hashValue = HashCombine(hashValue, p1[i]);
11773
11774     return hashValue;
11775 }
11776
11777 ExternalMethodBlobEntry::ExternalMethodBlobEntry(mdToken _nestedClass, 
11778                                                  mdToken _signature, 
11779                                                  LPCSTR  _pName)
11780 {
11781     CONTRACTL
11782     {
11783         NOTHROW;
11784         GC_NOTRIGGER;
11785         PRECONDITION(CheckPointer(_pName));
11786     }
11787     CONTRACTL_END;
11788
11789     m_token       = idExternalMethodNil;
11790     m_nestedClass = idExternalTypeNil; 
11791     m_signature   = idExternalSignatureNil; 
11792     m_cbName      = 0;
11793
11794     DWORD _cbName = (DWORD) strlen(_pName) + 1;
11795     LPSTR * pName = (LPSTR *) new (nothrow) CHAR[_cbName];
11796     if (pName != NULL)
11797         {
11798         m_nestedClass = _nestedClass;
11799         m_signature   = _signature;
11800         m_cbName      = _cbName;
11801         memcpy(pName, _pName, _cbName);
11802         m_pName       = (LPSTR) pName;
11803     }
11804         }
11805
11806 /* static */ const ExternalMethodBlobEntry *  ExternalMethodBlobEntry::FindOrAdd(
11807                                                              PTR_Module pModule, 
11808                                                              mdToken    _nestedClass, 
11809                                                              mdToken    _signature, 
11810                                                              LPCSTR     _pName)
11811 {
11812     CONTRACTL
11813         {
11814         NOTHROW;
11815         GC_NOTRIGGER;
11816         PRECONDITION(CheckPointer(_pName));
11817         }
11818     CONTRACTL_END;
11819
11820     if ((_pName == NULL) || (::strlen(_pName) == 0))
11821         return NULL;
11822
11823     ExternalMethodBlobEntry sEntry(_nestedClass, _signature, _pName);
11824
11825     const ProfilingBlobEntry *  pEntry = pModule->GetProfilingBlobTable()->Lookup(&sEntry);
11826     if (pEntry == NULL)
11827     {
11828         //
11829         // Not Found, add a new external type blob entry
11830         // 
11831         ExternalMethodBlobEntry *  newEntry;
11832         newEntry = new (nothrow) ExternalMethodBlobEntry(_nestedClass, _signature, _pName);
11833         if (newEntry == NULL)
11834             return NULL;
11835
11836         newEntry->newToken();                 // Assign a new ibc external method token
11837         CONTRACT_VIOLATION(ThrowsViolation);
11838         pModule->GetProfilingBlobTable()->Add(newEntry);
11839         pEntry = newEntry;
11840     }
11841
11842     //
11843     // Return the external method entry that we found or the new one that we just created
11844     // 
11845     _ASSERTE(pEntry->kind() == ExternalMethodDef);
11846     return static_cast<const ExternalMethodBlobEntry *>(pEntry);
11847 }
11848
11849
11850 static bool GetBasename(LPCWSTR _src, __out_ecount(dstlen) __out_z LPWSTR _dst, int dstlen)
11851 {
11852     LIMITED_METHOD_CONTRACT;
11853     LPCWSTR src = _src;
11854     LPWSTR  dst = _dst;
11855
11856     if ((src == NULL) || (dstlen <= 0))
11857         return false;
11858
11859     bool   inQuotes = false;
11860     LPWSTR dstLast = dst + (dstlen - 1);
11861     while (dst < dstLast)
11862     {
11863         WCHAR wch = *src++;
11864         if (wch == W('"'))
11865         {
11866             inQuotes = !inQuotes;
11867             continue;
11868         }
11869
11870         if (wch == 0)
11871             break;
11872
11873         *dst++ = wch;
11874
11875         if (!inQuotes)
11876         {
11877             if ((wch == W('\\')) || (wch == W(':')))
11878             {
11879                 dst = _dst;
11880             }
11881             else if (wch == W(' '))
11882             {
11883                 dst--;
11884                 break;
11885             }
11886         }
11887     }
11888     *dst++ = 0;
11889     return true;
11890 }
11891
11892 static void ProfileDataAllocateScenarioInfo(ProfileEmitter * pEmitter, LPCSTR scopeName, GUID* pMvid)
11893 {
11894     CONTRACTL
11895     {
11896         THROWS;
11897         GC_NOTRIGGER;
11898         MODE_ANY;
11899         INJECT_FAULT(COMPlusThrowOM());
11900     }
11901     CONTRACTL_END;
11902
11903     ProfileMap *profileMap = pEmitter->EmitNewSection(ScenarioInfo);
11904
11905     //
11906     // Allocate and initialize the scenario info section
11907     //
11908     {
11909         CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *siHeader;
11910         siHeader = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) profileMap->Allocate(sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER));
11911         
11912         siHeader->NumScenarios = 1;
11913         siHeader->TotalNumRuns = 1;
11914     }
11915
11916     //
11917     // Allocate and initialize the scenario header section
11918     //
11919     {
11920         LPCWSTR  pCmdLine    = GetCommandLineW();
11921         S_SIZE_T cCmdLine = S_SIZE_T(wcslen(pCmdLine));
11922         cCmdLine += 1;
11923         if (cCmdLine.IsOverflow())
11924         {
11925             ThrowHR(COR_E_OVERFLOW);
11926         }
11927         
11928         LPCWSTR  pSystemInfo = W("<machine,OS>");
11929         S_SIZE_T cSystemInfo = S_SIZE_T(wcslen(pSystemInfo));
11930         cSystemInfo += 1;
11931         if (cSystemInfo.IsOverflow())
11932         {
11933             ThrowHR(COR_E_OVERFLOW);
11934         }
11935         
11936         FILETIME runTime, unused1, unused2, unused3;
11937         GetProcessTimes(GetCurrentProcess(), &runTime, &unused1, &unused2, &unused3);
11938         
11939         WCHAR    scenarioName[256];
11940         GetBasename(pCmdLine, &scenarioName[0], 256);
11941         
11942         LPCWSTR  pName      = &scenarioName[0];
11943         S_SIZE_T cName      = S_SIZE_T(wcslen(pName));
11944         cName += 1;
11945         if (cName.IsOverflow())
11946         {
11947             ThrowHR(COR_E_OVERFLOW);
11948         }
11949
11950         S_SIZE_T sizeHeader = S_SIZE_T(sizeof(CORBBTPROF_SCENARIO_HEADER));
11951         sizeHeader += cName * S_SIZE_T(sizeof(WCHAR));
11952         if (sizeHeader.IsOverflow())
11953         {
11954             ThrowHR(COR_E_OVERFLOW);
11955         }
11956         
11957         S_SIZE_T sizeRun    = S_SIZE_T(sizeof(CORBBTPROF_SCENARIO_RUN));
11958         sizeRun += cCmdLine * S_SIZE_T(sizeof(WCHAR));
11959         sizeRun += cSystemInfo * S_SIZE_T(sizeof(WCHAR));
11960         if (sizeRun.IsOverflow())
11961         {
11962             ThrowHR(COR_E_OVERFLOW);
11963         }
11964         
11965         //
11966         // Allocate the Scenario Header struct
11967         // 
11968         SIZE_T sHeaderOffset;
11969         {
11970             CORBBTPROF_SCENARIO_HEADER *sHeader;
11971             S_SIZE_T sHeaderSize = sizeHeader + sizeRun;
11972             if (sHeaderSize.IsOverflow())
11973             {
11974                 ThrowHR(COR_E_OVERFLOW);
11975             }
11976             
11977             sHeaderOffset = profileMap->getCurrentOffset();
11978             sHeader = (CORBBTPROF_SCENARIO_HEADER *) profileMap->Allocate(sizeHeader.Value());
11979             
11980             sHeader->size              = sHeaderSize.Value();
11981             sHeader->scenario.ordinal  = 1;
11982             sHeader->scenario.mask     = 1;
11983             sHeader->scenario.priority = 0;
11984             sHeader->scenario.numRuns  = 1;
11985             sHeader->scenario.cName    = cName.Value();
11986             wcscpy_s(sHeader->scenario.name, cName.Value(), pName);
11987         }
11988
11989         //
11990         // Allocate the Scenario Run struct
11991         // 
11992         {
11993             CORBBTPROF_SCENARIO_RUN *sRun;
11994             sRun = (CORBBTPROF_SCENARIO_RUN *)  profileMap->Allocate(sizeRun.Value());
11995             
11996             sRun->runTime     = runTime;
11997             sRun->mvid        = *pMvid;
11998             sRun->cCmdLine    = cCmdLine.Value();
11999             sRun->cSystemInfo = cSystemInfo.Value();
12000             wcscpy_s(sRun->cmdLine, cCmdLine.Value(), pCmdLine);
12001             wcscpy_s(sRun->cmdLine+cCmdLine.Value(), cSystemInfo.Value(), pSystemInfo);
12002         }
12003 #ifdef _DEBUG
12004         {
12005             CORBBTPROF_SCENARIO_HEADER * sHeader;
12006             sHeader = (CORBBTPROF_SCENARIO_HEADER *) profileMap->getOffsetPtr(sHeaderOffset);
12007             assert(sHeader->size == sHeader->Size());
12008         }
12009 #endif
12010     }
12011 }
12012
12013 static void ProfileDataAllocateMethodBlockCounts(ProfileEmitter * pEmitter, CORCOMPILE_METHOD_PROFILE_LIST * pMethodProfileListHead)
12014 {
12015     CONTRACTL
12016     {
12017         THROWS;
12018         GC_NOTRIGGER;
12019         MODE_ANY;
12020         INJECT_FAULT(COMPlusThrowOM());
12021     }
12022     CONTRACTL_END;
12023
12024     ProfileMap *profileMap = pEmitter->EmitNewSection(MethodBlockCounts);
12025     
12026     //
12027     // Allocate and initialize the method block count section
12028     //
12029     SIZE_T mbcHeaderOffset;
12030     {
12031         CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader;
12032         mbcHeaderOffset = profileMap->getCurrentOffset();
12033         mbcHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *)
12034             profileMap->Allocate(sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER));
12035         mbcHeader->NumMethods = 0;  // This gets filled in later
12036     }
12037
12038     ULONG numMethods = 0;   // We count the number of methods that were executed
12039
12040     for (CORCOMPILE_METHOD_PROFILE_LIST * methodProfileList = pMethodProfileListHead;
12041          methodProfileList;
12042          methodProfileList = methodProfileList->next)
12043     {
12044         CORBBTPROF_METHOD_HEADER * pInfo = methodProfileList->GetInfo();
12045         
12046         assert(pInfo->size == pInfo->Size());
12047         
12048         //
12049         // We set methodWasExecuted based upon the ExecutionCount of the very first block
12050         // 
12051         bool methodWasExecuted = (pInfo->method.block[0].ExecutionCount > 0);
12052         
12053         //
12054         // If the method was not executed then we don't need to output this methods block counts
12055         //
12056         SIZE_T methodHeaderOffset;
12057         if (methodWasExecuted)
12058         {
12059             DWORD profileDataSize = pInfo->size;
12060             methodHeaderOffset = profileMap->getCurrentOffset();
12061             CORBBTPROF_METHOD_HEADER *methodHeader = (CORBBTPROF_METHOD_HEADER *) profileMap->Allocate(profileDataSize);
12062             memcpy(methodHeader, pInfo, profileDataSize);
12063             numMethods++;
12064         }
12065         
12066         // Reset all of the basic block counts to zero
12067         for (ULONG i=0; (i <  pInfo->method.cBlock); i++ )
12068         {
12069             //
12070             // If methodWasExecuted is false then every block's ExecutionCount should also be zero
12071             //
12072             _ASSERTE(methodWasExecuted  || (pInfo->method.block[i].ExecutionCount == 0));
12073             
12074             pInfo->method.block[i].ExecutionCount = 0;
12075         }
12076     }
12077     
12078     {
12079         CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader;
12080         // We have to refetch the mbcHeader as calls to Allocate will resize and thus move the mbcHeader
12081         mbcHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *) profileMap->getOffsetPtr(mbcHeaderOffset);
12082         mbcHeader->NumMethods = numMethods;
12083     }
12084 }
12085
12086 /*static*/ void Module::ProfileDataAllocateTokenLists(ProfileEmitter * pEmitter, Module::TokenProfileData* pTokenProfileData)
12087 {
12088     CONTRACTL
12089     {
12090         THROWS;
12091         GC_NOTRIGGER;
12092         MODE_ANY;
12093         INJECT_FAULT(COMPlusThrowOM());
12094     }
12095     CONTRACTL_END;
12096
12097     //
12098     // Allocate and initialize the token list sections
12099     //
12100     if (pTokenProfileData)
12101     {
12102         for (int format = 0; format < (int)SectionFormatCount; format++)
12103         {
12104             CQuickArray<CORBBTPROF_TOKEN_INFO> *pTokenArray = &(pTokenProfileData->m_formats[format].tokenArray);
12105             
12106             if (pTokenArray->Size() != 0)
12107             {
12108                 ProfileMap *  profileMap = pEmitter->EmitNewSection((SectionFormat) format);
12109                 
12110                 CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header;
12111                 header = (CORBBTPROF_TOKEN_LIST_SECTION_HEADER *)
12112                     profileMap->Allocate(sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER) +
12113                                          pTokenArray->Size() * sizeof(CORBBTPROF_TOKEN_INFO));
12114                 
12115                 header->NumTokens = pTokenArray->Size();
12116                 memcpy( (header + 1), &((*pTokenArray)[0]), pTokenArray->Size() * sizeof(CORBBTPROF_TOKEN_INFO));
12117                 
12118                 // Reset the collected tokens
12119                 for (unsigned i = 0; i < CORBBTPROF_TOKEN_MAX_NUM_FLAGS; i++)
12120                 {
12121                     pTokenProfileData->m_formats[format].tokenBitmaps[i].Reset();
12122                 }
12123                 pTokenProfileData->m_formats[format].tokenArray.ReSizeNoThrow(0);
12124             }
12125         }
12126     }
12127 }
12128
12129 static void ProfileDataAllocateTokenDefinitions(ProfileEmitter * pEmitter, Module * pModule)
12130 {
12131     CONTRACTL
12132     {
12133         THROWS;
12134         GC_NOTRIGGER;
12135         MODE_ANY;
12136         INJECT_FAULT(COMPlusThrowOM());
12137     }
12138     CONTRACTL_END;
12139
12140     //
12141     // Allocate and initialize the ibc token definition section (aka the Blob stream)
12142     //
12143     ProfileMap *  profileMap = pEmitter->EmitNewSection(BlobStream);
12144
12145     // Compute the size of the metadata section:
12146     // It is the sum of all of the Metadata Profile pool entries
12147     //  plus the sum of all of the Param signature entries
12148     //
12149     size_t totalSize = 0;
12150
12151     for (ProfilingBlobTable::Iterator cur = pModule->GetProfilingBlobTable()->Begin(),
12152                                       end = pModule->GetProfilingBlobTable()->End(); 
12153          (cur != end); 
12154          cur++)
12155     {
12156         const ProfilingBlobEntry * pEntry = *cur;
12157         size_t blobElementSize = pEntry->varSize();
12158         switch (pEntry->kind()) {
12159         case ParamTypeSpec:
12160         case ParamMethodSpec:
12161             blobElementSize += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
12162             break;
12163
12164         case ExternalNamespaceDef:
12165             blobElementSize += sizeof(CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY);
12166             break;
12167
12168         case ExternalTypeDef:
12169             blobElementSize += sizeof(CORBBTPROF_BLOB_TYPE_DEF_ENTRY);
12170             break;
12171
12172         case ExternalSignatureDef:
12173             blobElementSize += sizeof(CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY);
12174             break;
12175
12176         case ExternalMethodDef:
12177             blobElementSize += sizeof(CORBBTPROF_BLOB_METHOD_DEF_ENTRY);
12178             break;
12179
12180         default:
12181             _ASSERTE(!"Unexpected blob type");
12182             break;
12183         }
12184         totalSize += blobElementSize;
12185     }
12186
12187     profileMap->Allocate(totalSize);
12188
12189     size_t currentPos = 0;
12190
12191     // Traverse each element and record it
12192     size_t blobElementSize = 0;
12193     for (ProfilingBlobTable::Iterator cur = pModule->GetProfilingBlobTable()->Begin(),
12194                                       end = pModule->GetProfilingBlobTable()->End(); 
12195          (cur != end); 
12196          cur++, currentPos += blobElementSize)
12197     {
12198         const ProfilingBlobEntry * pEntry = *cur;
12199         blobElementSize = pEntry->varSize();
12200         void *profileData = profileMap->getOffsetPtr(currentPos);
12201
12202         switch (pEntry->kind()) {
12203         case ParamTypeSpec:
12204         {
12205             CORBBTPROF_BLOB_PARAM_SIG_ENTRY *  bProfileData      = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) profileData;
12206             const TypeSpecBlobEntry *          typeSpecBlobEntry = static_cast<const TypeSpecBlobEntry *>(pEntry);
12207
12208             blobElementSize         += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
12209             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
12210             bProfileData->blob.type  = typeSpecBlobEntry->kind();
12211             bProfileData->blob.token = typeSpecBlobEntry->token();
12212             _ASSERTE(typeSpecBlobEntry->cbSig() > 0);
12213             bProfileData->cSig       = typeSpecBlobEntry->cbSig();
12214             memcpy(&bProfileData->sig[0], typeSpecBlobEntry->pSig(), typeSpecBlobEntry->cbSig());
12215             break;
12216         }
12217
12218         case ParamMethodSpec:
12219         {
12220             CORBBTPROF_BLOB_PARAM_SIG_ENTRY *  bProfileData        = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) profileData;
12221             const MethodSpecBlobEntry *        methodSpecBlobEntry = static_cast<const MethodSpecBlobEntry *>(pEntry);
12222
12223             blobElementSize         += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY);
12224             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
12225             bProfileData->blob.type  = methodSpecBlobEntry->kind();
12226             bProfileData->blob.token = methodSpecBlobEntry->token();
12227             _ASSERTE(methodSpecBlobEntry->cbSig() > 0);
12228             bProfileData->cSig       = methodSpecBlobEntry->cbSig();
12229             memcpy(&bProfileData->sig[0], methodSpecBlobEntry->pSig(), methodSpecBlobEntry->cbSig());
12230             break;
12231         }
12232
12233         case ExternalNamespaceDef:
12234         {
12235             CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY *  bProfileData        = (CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY*) profileData;
12236             const ExternalNamespaceBlobEntry *     namespaceBlobEntry  = static_cast<const ExternalNamespaceBlobEntry *>(pEntry);
12237
12238             blobElementSize         += sizeof(CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY);
12239             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
12240             bProfileData->blob.type  = namespaceBlobEntry->kind();
12241             bProfileData->blob.token = namespaceBlobEntry->token();
12242             _ASSERTE(namespaceBlobEntry->cbName() > 0);
12243             bProfileData->cName      = namespaceBlobEntry->cbName();
12244             memcpy(&bProfileData->name[0], namespaceBlobEntry->pName(), namespaceBlobEntry->cbName());
12245             break;
12246         }
12247             
12248         case ExternalTypeDef:
12249         {
12250             CORBBTPROF_BLOB_TYPE_DEF_ENTRY *       bProfileData        = (CORBBTPROF_BLOB_TYPE_DEF_ENTRY*) profileData;
12251             const ExternalTypeBlobEntry *          typeBlobEntry       = static_cast<const ExternalTypeBlobEntry *>(pEntry);
12252
12253             blobElementSize         += sizeof(CORBBTPROF_BLOB_TYPE_DEF_ENTRY);
12254             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
12255             bProfileData->blob.type  = typeBlobEntry->kind();
12256             bProfileData->blob.token = typeBlobEntry->token();
12257             bProfileData->assemblyRefToken = typeBlobEntry->assemblyRef();
12258             bProfileData->nestedClassToken = typeBlobEntry->nestedClass();
12259             bProfileData->nameSpaceToken   = typeBlobEntry->nameSpace();
12260             _ASSERTE(typeBlobEntry->cbName() > 0);
12261             bProfileData->cName            = typeBlobEntry->cbName();
12262             memcpy(&bProfileData->name[0], typeBlobEntry->pName(), typeBlobEntry->cbName());
12263             break;
12264         }
12265             
12266         case ExternalSignatureDef:
12267         {
12268             CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY *  bProfileData        = (CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY*) profileData;
12269             const ExternalSignatureBlobEntry *     signatureBlobEntry  = static_cast<const ExternalSignatureBlobEntry *>(pEntry);
12270
12271             blobElementSize         += sizeof(CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY);
12272             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
12273             bProfileData->blob.type  = signatureBlobEntry->kind();
12274             bProfileData->blob.token = signatureBlobEntry->token();
12275             _ASSERTE(signatureBlobEntry->cbSig() > 0);
12276             bProfileData->cSig       = signatureBlobEntry->cbSig();
12277             memcpy(&bProfileData->sig[0], signatureBlobEntry->pSig(), signatureBlobEntry->cbSig());
12278             break;
12279         }
12280
12281         case ExternalMethodDef:
12282         {
12283             CORBBTPROF_BLOB_METHOD_DEF_ENTRY *     bProfileData        = (CORBBTPROF_BLOB_METHOD_DEF_ENTRY*) profileData;
12284             const ExternalMethodBlobEntry *        methodBlobEntry     = static_cast<const ExternalMethodBlobEntry *>(pEntry);
12285
12286             blobElementSize         += sizeof(CORBBTPROF_BLOB_METHOD_DEF_ENTRY);
12287             bProfileData->blob.size  = static_cast<DWORD>(blobElementSize);
12288             bProfileData->blob.type  = methodBlobEntry->kind();
12289             bProfileData->blob.token = methodBlobEntry->token();
12290             bProfileData->nestedClassToken = methodBlobEntry->nestedClass();
12291             bProfileData->signatureToken   = methodBlobEntry->signature();
12292             _ASSERTE(methodBlobEntry->cbName() > 0);
12293             bProfileData->cName            = methodBlobEntry->cbName();
12294             memcpy(&bProfileData->name[0], methodBlobEntry->pName(), methodBlobEntry->cbName());
12295             break;
12296         }
12297
12298         default:
12299             _ASSERTE(!"Unexpected blob type");
12300             break;
12301         }
12302     }
12303     
12304     _ASSERTE(currentPos == totalSize);
12305     
12306     // Emit a terminating entry with type EndOfBlobStream to mark the end
12307     DWORD mdElementSize = sizeof(CORBBTPROF_BLOB_ENTRY);
12308     void *profileData = profileMap->Allocate(mdElementSize);
12309     memset(profileData, 0, mdElementSize);
12310     
12311     CORBBTPROF_BLOB_ENTRY* mdProfileData = (CORBBTPROF_BLOB_ENTRY*) profileData;
12312     mdProfileData->type = EndOfBlobStream;
12313     mdProfileData->size = sizeof(CORBBTPROF_BLOB_ENTRY);
12314 }
12315
12316 // Responsible for writing out the profile data if the COMPlus_BBInstr 
12317 // environment variable is set.  This is called when the module is unloaded
12318 // (usually at shutdown).
12319 HRESULT Module::WriteMethodProfileDataLogFile(bool cleanup)
12320 {
12321     CONTRACTL
12322     {
12323         INSTANCE_CHECK;
12324         NOTHROW;
12325         GC_TRIGGERS;
12326         MODE_ANY;
12327         INJECT_FAULT(return E_OUTOFMEMORY;);
12328     }
12329     CONTRACTL_END;
12330
12331     HRESULT hr = S_OK;
12332
12333     if (IsResource())
12334         return S_OK;
12335
12336     EX_TRY
12337     {
12338         if (GetAssembly()->IsInstrumented() && (m_pProfilingBlobTable != NULL) && (m_tokenProfileData != NULL))
12339         {
12340             ProfileEmitter * pEmitter = new ProfileEmitter();
12341
12342             // Get this ahead of time - metadata access may be logged, which will
12343             // take the m_tokenProfileData->crst, which we take a couple lines below
12344             LPCSTR pszName;
12345             GUID mvid;
12346             IfFailThrow(GetMDImport()->GetScopeProps(&pszName, &mvid));
12347             
12348             CrstHolder ch(&m_tokenProfileData->crst);
12349             
12350             //
12351             // Create the scenario info section
12352             //
12353             ProfileDataAllocateScenarioInfo(pEmitter, pszName, &mvid);
12354
12355             //
12356             // Create the method block count section
12357             // 
12358             ProfileDataAllocateMethodBlockCounts(pEmitter, m_methodProfileList);
12359
12360             //
12361             // Create the token list sections
12362             // 
12363             ProfileDataAllocateTokenLists(pEmitter, m_tokenProfileData);
12364
12365             //
12366             // Create the ibc token definition section (aka the Blob stream)
12367             // 
12368             ProfileDataAllocateTokenDefinitions(pEmitter, this);
12369   
12370             //
12371             // Now store the profile data in the ibc file
12372             //
12373             ProfileMap profileImage;
12374             pEmitter->Serialize(&profileImage, mvid);
12375
12376             HandleHolder profileDataFile(OpenMethodProfileDataLogFile(mvid));
12377
12378             ULONG count;
12379             BOOL result = WriteFile(profileDataFile, profileImage.getOffsetPtr(0), profileImage.getCurrentOffset(), &count, NULL);
12380             if (!result || (count != profileImage.getCurrentOffset()))
12381             {
12382                 DWORD lasterror = GetLastError();
12383                 _ASSERTE(!"Error writing ibc profile data to file");
12384                 hr = HRESULT_FROM_WIN32(lasterror);
12385             }
12386         }
12387
12388         if (cleanup)
12389         {
12390             DeleteProfilingData();
12391         }
12392     }
12393     EX_CATCH
12394     {
12395         hr = E_FAIL;
12396     }
12397     EX_END_CATCH(SwallowAllExceptions)
12398
12399     return hr;
12400 }
12401
12402
12403 /* static */
12404 void Module::WriteAllModuleProfileData(bool cleanup)
12405 {
12406     CONTRACTL
12407     {
12408         NOTHROW;
12409         GC_TRIGGERS;
12410         MODE_ANY;
12411     }
12412     CONTRACTL_END;
12413
12414     // Iterate over all the app domains; for each one iterator over its
12415     // assemblies; for each one iterate over its modules.
12416     EX_TRY
12417     {
12418         AppDomainIterator appDomainIterator(FALSE);
12419         while(appDomainIterator.Next())
12420         {
12421             AppDomain * appDomain = appDomainIterator.GetDomain();
12422             AppDomain::AssemblyIterator assemblyIterator = appDomain->IterateAssembliesEx(
12423                 (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution));
12424             CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
12425
12426             while (assemblyIterator.Next(pDomainAssembly.This()))
12427             {
12428                 DomainModuleIterator i = pDomainAssembly->IterateModules(kModIterIncludeLoaded);
12429                 while (i.Next())
12430                 {
12431                     /*hr=*/i.GetModule()->WriteMethodProfileDataLogFile(cleanup);
12432                 }
12433             }
12434         }
12435     }
12436     EX_CATCH
12437     { }
12438     EX_END_CATCH(SwallowAllExceptions);
12439 }
12440
12441 PTR_ProfilingBlobTable Module::GetProfilingBlobTable()
12442 {
12443     LIMITED_METHOD_CONTRACT;
12444     return m_pProfilingBlobTable;
12445 }
12446
12447 void Module::CreateProfilingData()
12448 {
12449     TokenProfileData *tpd = TokenProfileData::CreateNoThrow();
12450     
12451     PVOID pv = InterlockedCompareExchangeT(&m_tokenProfileData, tpd, NULL);
12452     if (pv != NULL)
12453     {
12454         delete tpd;
12455     }
12456     
12457     PTR_ProfilingBlobTable ppbt = new (nothrow) ProfilingBlobTable();
12458
12459     if (ppbt != NULL)
12460     {
12461         pv = InterlockedCompareExchangeT(&m_pProfilingBlobTable, ppbt, NULL);
12462         if (pv != NULL)
12463         {
12464             delete ppbt;
12465         }
12466     }
12467 }
12468
12469 void Module::DeleteProfilingData()
12470 {
12471     if (m_pProfilingBlobTable != NULL)
12472     {
12473         for (ProfilingBlobTable::Iterator cur = m_pProfilingBlobTable->Begin(),
12474                                           end = m_pProfilingBlobTable->End(); 
12475              (cur != end); 
12476              cur++)
12477         {
12478             const ProfilingBlobEntry *  pCurrentEntry = *cur;
12479             delete pCurrentEntry;
12480         }
12481         delete m_pProfilingBlobTable;
12482         m_pProfilingBlobTable = NULL;
12483     }
12484
12485     if (m_tokenProfileData != NULL)
12486     {
12487         delete m_tokenProfileData;
12488         m_tokenProfileData = NULL;
12489     }
12490     
12491     // the metadataProfileData is free'ed in destructor of the corresponding MetaDataTracker
12492 }
12493 #endif //FEATURE_PREJIT
12494
12495
12496
12497 #ifdef FEATURE_PREJIT
12498 /* static */
12499 Module::TokenProfileData *Module::TokenProfileData::CreateNoThrow(void)
12500 {
12501     STATIC_CONTRACT_NOTHROW;
12502
12503     TokenProfileData *tpd = NULL;
12504
12505     EX_TRY
12506     {
12507         //
12508         // This constructor calls crst.Init(), which may throw.  So putting (nothrow) doesn't
12509         // do what we would want it to.  Thus I wrap it here in a TRY/CATCH and revert to NULL
12510         // if it fails.
12511         //
12512         tpd = new TokenProfileData();
12513     }
12514     EX_CATCH
12515     {
12516         tpd = NULL;
12517     }
12518     EX_END_CATCH(SwallowAllExceptions);
12519
12520     return tpd;
12521 }
12522
12523 #endif // FEATURE_PREJIT
12524
12525 #endif // !DACCESS_COMPILE
12526
12527 #ifndef DACCESS_COMPILE
12528 void Module::SetBeingUnloaded()
12529 {
12530     LIMITED_METHOD_CONTRACT;
12531     FastInterlockOr((ULONG*)&m_dwTransientFlags, IS_BEING_UNLOADED);
12532 }
12533 #endif
12534
12535 #ifdef FEATURE_PREJIT 
12536 void Module::LogTokenAccess(mdToken token, SectionFormat format, ULONG flagnum)
12537 {
12538     CONTRACTL
12539     {
12540         INSTANCE_CHECK;
12541         NOTHROW;
12542         GC_NOTRIGGER;
12543         MODE_ANY;
12544         PRECONDITION(g_IBCLogger.InstrEnabled());
12545         PRECONDITION(flagnum < CORBBTPROF_TOKEN_MAX_NUM_FLAGS);
12546     }
12547     CONTRACTL_END;
12548
12549 #ifndef DACCESS_COMPILE 
12550
12551     //
12552     // If we are in ngen instrumentation mode, then we should record this token.
12553     //
12554
12555     if (!m_nativeImageProfiling)
12556         return;
12557
12558     if (flagnum >= CORBBTPROF_TOKEN_MAX_NUM_FLAGS)
12559     {
12560         return;
12561     }
12562
12563     mdToken rid = RidFromToken(token);
12564     CorTokenType  tkType  = (CorTokenType) TypeFromToken(token);
12565     SectionFormat tkKind  = (SectionFormat) (tkType >> 24);
12566
12567     if ((rid == 0) && (tkKind < (SectionFormat) TBL_COUNT))
12568         return;
12569
12570     FAULT_NOT_FATAL();
12571
12572     _ASSERTE(TypeProfilingData   == FirstTokenFlagSection + TBL_TypeDef);
12573     _ASSERTE(MethodProfilingData == FirstTokenFlagSection + TBL_Method);
12574     _ASSERTE(SectionFormatCount  >= FirstTokenFlagSection + TBL_COUNT + 4);
12575
12576     if (!m_tokenProfileData)
12577     {
12578         CreateProfilingData();
12579     }
12580
12581     if (!m_tokenProfileData)
12582     {
12583         return;
12584     }
12585
12586     if (tkKind == (SectionFormat) (ibcTypeSpec >> 24))
12587         tkKind = IbcTypeSpecSection;
12588     else if (tkKind == (SectionFormat) (ibcMethodSpec >> 24))
12589         tkKind = IbcMethodSpecSection;
12590
12591     _ASSERTE(tkKind >= 0);
12592     _ASSERTE(tkKind < SectionFormatCount);
12593     if (tkKind < 0 || tkKind >= SectionFormatCount)
12594     {
12595         return;
12596     }
12597     
12598     CQuickArray<CORBBTPROF_TOKEN_INFO> * pTokenArray  = &m_tokenProfileData->m_formats[format].tokenArray;
12599     RidBitmap *                          pTokenBitmap = &m_tokenProfileData->m_formats[tkKind].tokenBitmaps[flagnum];
12600
12601     // Have we seen this token with this flag already?
12602     if (pTokenBitmap->IsTokenInBitmap(token))
12603     {
12604         return;
12605     }
12606
12607     // Insert the token to the bitmap
12608     if (FAILED(pTokenBitmap->InsertToken(token)))
12609     {
12610         return;
12611     }
12612
12613     ULONG flag = 1 << flagnum;
12614
12615     // [ToDo] Fix: this is a sequential search and can be very slow
12616     for (unsigned int i = 0; i < pTokenArray->Size(); i++)
12617     {
12618         if ((*pTokenArray)[i].token == token)
12619         {
12620             _ASSERTE(! ((*pTokenArray)[i].flags & flag));
12621             (*pTokenArray)[i].flags |= flag;
12622             return;
12623         }
12624     }
12625
12626     if (FAILED(pTokenArray->ReSizeNoThrow(pTokenArray->Size() + 1)))
12627     {
12628         return;
12629     }
12630
12631     (*pTokenArray)[pTokenArray->Size() - 1].token = token;
12632     (*pTokenArray)[pTokenArray->Size() - 1].flags = flag;
12633     (*pTokenArray)[pTokenArray->Size() - 1].scenarios = 0;
12634
12635 #endif // !DACCESS_COMPILE
12636 }
12637
12638 void Module::LogTokenAccess(mdToken token, ULONG flagNum)
12639 {
12640     WRAPPER_NO_CONTRACT;
12641     SectionFormat format = (SectionFormat)((TypeFromToken(token)>>24) + FirstTokenFlagSection);
12642     if (FirstTokenFlagSection <= format && format < SectionFormatCount)
12643     {
12644         LogTokenAccess(token, format, flagNum);
12645     }
12646 }
12647 #endif // FEATURE_PREJIT
12648
12649 #ifndef DACCESS_COMPILE
12650 #ifdef FEATURE_PREJIT
12651
12652 //
12653 // Encoding callbacks
12654 //
12655
12656 /*static*/ DWORD Module::EncodeModuleHelper(void * pModuleContext, Module *pReferencedModule)
12657 {
12658     Module* pReferencingModule = (Module *) pModuleContext;
12659     _ASSERTE(pReferencingModule != pReferencedModule);
12660
12661     Assembly *pReferencingAssembly = pReferencingModule->GetAssembly();
12662     Assembly *pReferencedAssembly  = pReferencedModule->GetAssembly();
12663
12664     _ASSERTE(pReferencingAssembly != pReferencedAssembly);
12665
12666     if (pReferencedAssembly == pReferencingAssembly)
12667     {
12668         return 0;
12669     }
12670
12671     mdAssemblyRef token = pReferencingModule->FindAssemblyRef(pReferencedAssembly);
12672
12673     if (IsNilToken(token))
12674     {
12675         return ENCODE_MODULE_FAILED;
12676     }
12677
12678     return RidFromToken(token);
12679 }
12680
12681 /*static*/ void Module::TokenDefinitionHelper(void* pModuleContext, Module *pReferencedModule, DWORD index, mdToken* pToken)
12682 {
12683     LIMITED_METHOD_CONTRACT;
12684     HRESULT              hr;
12685     Module *             pReferencingModule = (Module *) pModuleContext;
12686     mdAssemblyRef        mdAssemblyRef      = TokenFromRid(index, mdtAssemblyRef);
12687     IMDInternalImport *  pImport            = pReferencedModule->GetMDImport();
12688     LPCUTF8              szName             = NULL;
12689     
12690     if (TypeFromToken(*pToken) == mdtTypeDef)
12691     {
12692         //
12693         // Compute nested type (if any)
12694         // 
12695         mdTypeDef mdEnclosingType = idExternalTypeNil;
12696         hr = pImport->GetNestedClassProps(*pToken, &mdEnclosingType);
12697         // If there's not enclosing type, then hr=CLDB_E_RECORD_NOTFOUND and mdEnclosingType is unchanged
12698         _ASSERTE((hr == S_OK) || (hr == CLDB_E_RECORD_NOTFOUND));
12699         
12700         if (!IsNilToken(mdEnclosingType))
12701         {
12702             _ASSERT(TypeFromToken(mdEnclosingType) ==  mdtTypeDef);
12703             TokenDefinitionHelper(pModuleContext, pReferencedModule, index, &mdEnclosingType);
12704         }
12705         _ASSERT(TypeFromToken(mdEnclosingType) == ibcExternalType);
12706         
12707         //
12708         // Compute type name and namespace.
12709         //
12710         LPCUTF8 szNamespace = NULL;
12711         hr = pImport->GetNameOfTypeDef(*pToken, &szName, &szNamespace);
12712         _ASSERTE(hr == S_OK);
12713         
12714         //
12715         // Transform namespace string into ibc external namespace token
12716         // 
12717         idExternalNamespace idNamespace = idExternalNamespaceNil;
12718         if (szNamespace != NULL)
12719         {
12720             const ExternalNamespaceBlobEntry *  pNamespaceEntry;
12721             pNamespaceEntry = ExternalNamespaceBlobEntry::FindOrAdd(pReferencingModule, szNamespace);
12722             if (pNamespaceEntry != NULL)
12723             {
12724                 idNamespace = pNamespaceEntry->token();
12725             }
12726         }
12727         _ASSERTE(TypeFromToken(idNamespace) == ibcExternalNamespace);
12728
12729         //
12730         // Transform type name into ibc external type token
12731         // 
12732         idExternalType idType = idExternalTypeNil;
12733         _ASSERTE(szName != NULL);
12734         const ExternalTypeBlobEntry *  pTypeEntry = NULL;
12735         pTypeEntry = ExternalTypeBlobEntry::FindOrAdd(pReferencingModule, 
12736                                                       mdAssemblyRef, 
12737                                                       mdEnclosingType,
12738                                                       idNamespace, 
12739                                                       szName);
12740         if (pTypeEntry != NULL)
12741         {
12742             idType = pTypeEntry->token();
12743         }
12744         _ASSERTE(TypeFromToken(idType) == ibcExternalType);
12745
12746         *pToken = idType;   // Remap pToken to our idExternalType token 
12747     }
12748     else if (TypeFromToken(*pToken) == mdtMethodDef)
12749     {
12750         //
12751         // Compute nested type (if any)
12752         // 
12753         mdTypeDef mdEnclosingType = idExternalTypeNil;
12754         hr = pImport->GetParentToken(*pToken, &mdEnclosingType);
12755         _ASSERTE(!FAILED(hr));
12756
12757         if (!IsNilToken(mdEnclosingType))
12758         {
12759             _ASSERT(TypeFromToken(mdEnclosingType) ==  mdtTypeDef);
12760             TokenDefinitionHelper(pModuleContext, pReferencedModule, index, &mdEnclosingType);
12761         }
12762         _ASSERT(TypeFromToken(mdEnclosingType) == ibcExternalType);
12763
12764         //
12765         // Compute the method name and signature
12766         // 
12767         PCCOR_SIGNATURE pSig = NULL;
12768         DWORD           cbSig = 0;
12769         hr = pImport->GetNameAndSigOfMethodDef(*pToken, &pSig, &cbSig, &szName);
12770         _ASSERTE(hr == S_OK);
12771         
12772         //
12773         // Transform signature into ibc external signature token
12774         // 
12775         idExternalSignature idSignature = idExternalSignatureNil;
12776         if (pSig != NULL)
12777         {
12778             const ExternalSignatureBlobEntry *  pSignatureEntry;
12779             pSignatureEntry = ExternalSignatureBlobEntry::FindOrAdd(pReferencingModule, cbSig, pSig);
12780             if (pSignatureEntry != NULL)
12781             {
12782                 idSignature = pSignatureEntry->token();
12783             }
12784         }
12785         _ASSERTE(TypeFromToken(idSignature) == ibcExternalSignature);
12786
12787         //
12788         // Transform method name into ibc external method token
12789         // 
12790         idExternalMethod idMethod = idExternalMethodNil;
12791         _ASSERTE(szName != NULL);
12792         const ExternalMethodBlobEntry *  pMethodEntry = NULL;
12793         pMethodEntry = ExternalMethodBlobEntry::FindOrAdd(pReferencingModule, 
12794                                                           mdEnclosingType,
12795                                                           idSignature, 
12796                                                           szName);
12797         if (pMethodEntry != NULL)
12798         {
12799             idMethod = pMethodEntry->token();
12800         }
12801         _ASSERTE(TypeFromToken(idMethod) == ibcExternalMethod);
12802
12803         *pToken = idMethod;   // Remap pToken to our idMethodSpec token 
12804     }
12805     else
12806     {
12807         _ASSERTE(!"Unexpected token type");
12808     }
12809 }
12810
12811 idTypeSpec Module::LogInstantiatedType(TypeHandle typeHnd, ULONG flagNum)
12812 {
12813     CONTRACT(idTypeSpec)
12814     {
12815         NOTHROW;
12816         GC_NOTRIGGER;
12817         MODE_ANY;
12818         PRECONDITION(g_IBCLogger.InstrEnabled());
12819         PRECONDITION(!typeHnd.HasUnrestoredTypeKey());
12820         // We want to report the type only in its own loader module as a type's
12821         // MethodTable can only live in its own loader module.
12822         // We can relax this if we allow a (duplicate) MethodTable to live
12823         // in any module (which might be needed for ngen of generics)
12824 #ifdef FEATURE_PREJIT
12825         // All callsites already do this...
12826         // PRECONDITION(this == GetPreferredZapModuleForTypeHandle(typeHnd));
12827 #endif
12828     }
12829     CONTRACT_END;
12830
12831     idTypeSpec result = idTypeSpecNil;
12832
12833     if (m_nativeImageProfiling)
12834     {
12835         CONTRACT_VIOLATION(ThrowsViolation|FaultViolation|GCViolation);
12836
12837         SigBuilder sigBuilder;
12838
12839         ZapSig zapSig(this, this, ZapSig::IbcTokens, 
12840                         Module::EncodeModuleHelper, Module::TokenDefinitionHelper);
12841         BOOL fSuccess = zapSig.GetSignatureForTypeHandle(typeHnd, &sigBuilder);
12842
12843         // a return value of 0 indicates a failure to create the signature
12844         if (fSuccess)
12845         {
12846             DWORD cbSig;
12847             PCCOR_SIGNATURE pSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cbSig);
12848
12849             ULONG flag = (1 << flagNum);
12850             TypeSpecBlobEntry *  pEntry = const_cast<TypeSpecBlobEntry *>(TypeSpecBlobEntry::FindOrAdd(this, cbSig, pSig));
12851             if (pEntry != NULL)
12852             {
12853                 // Update the flags with any new bits
12854                 pEntry->orFlag(flag);
12855                 result = pEntry->token();
12856             }
12857         }
12858     }
12859     _ASSERTE(TypeFromToken(result) == ibcTypeSpec);
12860
12861     RETURN result;
12862 }
12863
12864 idMethodSpec Module::LogInstantiatedMethod(const MethodDesc * md, ULONG flagNum)
12865 {
12866     CONTRACT(idMethodSpec)
12867     {
12868         NOTHROW;
12869         GC_NOTRIGGER;
12870         MODE_ANY;
12871         PRECONDITION( md != NULL );
12872     }
12873     CONTRACT_END;
12874
12875     idMethodSpec result = idMethodSpecNil;
12876
12877     if (m_nativeImageProfiling)
12878     {
12879         CONTRACT_VIOLATION(ThrowsViolation|FaultViolation|GCViolation);
12880
12881         // get data
12882         SigBuilder sigBuilder;
12883
12884         BOOL fSuccess;
12885         fSuccess = ZapSig::EncodeMethod(const_cast<MethodDesc *>(md), this, &sigBuilder,
12886                                       (LPVOID) this,
12887                        (ENCODEMODULE_CALLBACK) Module::EncodeModuleHelper,
12888                         (DEFINETOKEN_CALLBACK) Module::TokenDefinitionHelper);
12889
12890         if (fSuccess)
12891         {
12892             DWORD dataSize;
12893             BYTE * pBlob = (BYTE *)sigBuilder.GetSignature(&dataSize);
12894
12895             ULONG flag = (1 << flagNum);
12896             MethodSpecBlobEntry *  pEntry = const_cast<MethodSpecBlobEntry *>(MethodSpecBlobEntry::FindOrAdd(this, dataSize, pBlob));
12897             if (pEntry != NULL)
12898             {
12899                 // Update the flags with any new bits
12900                 pEntry->orFlag(flag);
12901                 result = pEntry->token();
12902             }
12903         }
12904     }
12905
12906     _ASSERTE(TypeFromToken(result) == ibcMethodSpec);
12907     RETURN result;
12908 }
12909 #endif // DACCESS_COMPILE
12910 #endif //FEATURE_PREJIT
12911
12912 #ifndef DACCESS_COMPILE
12913
12914 #ifndef CROSSGEN_COMPILE
12915 // ===========================================================================
12916 // ReflectionModule
12917 // ===========================================================================
12918
12919 /* static */
12920 ReflectionModule *ReflectionModule::Create(Assembly *pAssembly, PEFile *pFile, AllocMemTracker *pamTracker, LPCWSTR szName, BOOL fIsTransient)
12921 {
12922     CONTRACT(ReflectionModule *)
12923     {
12924         STANDARD_VM_CHECK;
12925         PRECONDITION(CheckPointer(pAssembly));
12926         PRECONDITION(CheckPointer(pFile));
12927         PRECONDITION(pFile->IsDynamic());
12928         POSTCONDITION(CheckPointer(RETVAL));
12929     }
12930     CONTRACT_END;
12931
12932     // Hoist CONTRACT into separate routine because of EX incompatibility
12933
12934     mdFile token;
12935     _ASSERTE(pFile->IsAssembly());
12936     token = mdFileNil;
12937
12938     // Initial memory block for Modules must be zero-initialized (to make it harder
12939     // to introduce Destruct crashes arising from OOM's during initialization.)
12940
12941     void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(ReflectionModule))));
12942     ReflectionModuleHolder pModule(new (pMemory) ReflectionModule(pAssembly, token, pFile));
12943
12944     pModule->DoInit(pamTracker, szName);
12945
12946     // Set this at module creation time. The m_fIsTransient field should never change during the lifetime of this ReflectionModule.
12947     pModule->SetIsTransient(fIsTransient ? true : false);
12948
12949     RETURN pModule.Extract();
12950 }
12951
12952
12953 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
12954 //
12955 // The constructor phase initializes just enough so that Destruct() can be safely called.
12956 // It cannot throw or fail.
12957 //
12958 ReflectionModule::ReflectionModule(Assembly *pAssembly, mdFile token, PEFile *pFile)
12959   : Module(pAssembly, token, pFile)
12960 {
12961     CONTRACTL
12962     {
12963         NOTHROW;
12964         GC_TRIGGERS;
12965         FORBID_FAULT;
12966     }
12967     CONTRACTL_END
12968
12969     m_pInMemoryWriter = NULL;
12970     m_sdataSection = NULL;
12971     m_pISymUnmanagedWriter = NULL;
12972     m_pCreatingAssembly = NULL;
12973     m_pCeeFileGen = NULL;
12974     m_pDynamicMetadata = NULL;
12975     m_fSuppressMetadataCapture = false;
12976     m_fIsTransient = false;
12977 }
12978
12979 HRESULT STDMETHODCALLTYPE CreateICeeGen(REFIID riid, void **pCeeGen);
12980
12981 // Module initialization occurs in two phases: the constructor phase and the Initialize phase.
12982 //
12983 // The Initialize() phase completes the initialization after the constructor has run.
12984 // It can throw exceptions but whether it throws or succeeds, it must leave the Module
12985 // in a state where Destruct() can be safely called.
12986 //
12987 void ReflectionModule::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
12988 {
12989     CONTRACTL
12990     {
12991         INSTANCE_CHECK;
12992         STANDARD_VM_CHECK;
12993         PRECONDITION(szName != NULL);
12994     }
12995     CONTRACTL_END;
12996
12997     Module::Initialize(pamTracker);
12998
12999     IfFailThrow(CreateICeeGen(IID_ICeeGen, (void **)&m_pCeeFileGen));
13000
13001     // Collectible modules should try to limit the growth of their associate IL section, as common scenarios for collectible
13002     // modules include single type modules
13003     if (IsCollectible())
13004     {
13005         ReleaseHolder<ICeeGenInternal> pCeeGenInternal(NULL);
13006         IfFailThrow(m_pCeeFileGen->QueryInterface(IID_ICeeGenInternal, (void **)&pCeeGenInternal));
13007         IfFailThrow(pCeeGenInternal->SetInitialGrowth(CEE_FILE_GEN_GROWTH_COLLECTIBLE));
13008     }
13009
13010     m_pInMemoryWriter = new RefClassWriter();
13011
13012     IfFailThrow(m_pInMemoryWriter->Init(GetCeeGen(), GetEmitter(), szName));
13013
13014     m_CrstLeafLock.Init(CrstLeafLock);
13015 }
13016
13017 void ReflectionModule::Destruct()
13018 {
13019     CONTRACTL
13020     {
13021         NOTHROW;
13022         GC_TRIGGERS;
13023         MODE_PREEMPTIVE;
13024     }
13025     CONTRACTL_END;
13026
13027     delete m_pInMemoryWriter;
13028
13029     if (m_pISymUnmanagedWriter)
13030     {
13031         m_pISymUnmanagedWriter->Close();
13032         m_pISymUnmanagedWriter->Release();
13033         m_pISymUnmanagedWriter = NULL;
13034     }
13035
13036     if (m_pCeeFileGen)
13037         m_pCeeFileGen->Release();
13038
13039     Module::Destruct();
13040
13041     delete m_pDynamicMetadata;
13042     m_pDynamicMetadata = NULL;
13043
13044     m_CrstLeafLock.Destroy();
13045 }
13046
13047 // Returns true iff metadata capturing is suppressed.
13048 // 
13049 // Notes:
13050 //   This is during the window after code:ReflectionModule.SuppressMetadataCapture and before 
13051 //   code:ReflectionModule.ResumeMetadataCapture.
13052 //   
13053 //   If metadata updates are suppressed, then class-load notifications should be suppressed too.
13054 bool ReflectionModule::IsMetadataCaptureSuppressed()
13055 {
13056     return m_fSuppressMetadataCapture;
13057 }
13058 // 
13059 // Holder of changed value of MDUpdateMode via IMDInternalEmit::SetMDUpdateMode.
13060 // Returns back the original value on release.
13061 // 
13062 class MDUpdateModeHolder
13063 {
13064 public:
13065     MDUpdateModeHolder()
13066     {
13067         m_pInternalEmitter = NULL;
13068         m_OriginalMDUpdateMode = ULONG_MAX;
13069     }
13070     ~MDUpdateModeHolder()
13071     {
13072         WRAPPER_NO_CONTRACT;
13073         (void)Release();
13074     }
13075     HRESULT SetMDUpdateMode(IMetaDataEmit *pEmitter, ULONG updateMode)
13076     {
13077         LIMITED_METHOD_CONTRACT;
13078         HRESULT hr = S_OK;
13079         
13080         _ASSERTE(updateMode != ULONG_MAX);
13081         
13082         IfFailRet(pEmitter->QueryInterface(IID_IMDInternalEmit, (void **)&m_pInternalEmitter));
13083         _ASSERTE(m_pInternalEmitter != NULL);
13084         
13085         IfFailRet(m_pInternalEmitter->SetMDUpdateMode(updateMode, &m_OriginalMDUpdateMode));
13086         _ASSERTE(m_OriginalMDUpdateMode != ULONG_MAX);
13087         
13088         return hr;
13089     }
13090     HRESULT Release(ULONG expectedPreviousUpdateMode = ULONG_MAX)
13091     {
13092         HRESULT hr = S_OK;
13093         
13094         if (m_OriginalMDUpdateMode != ULONG_MAX)
13095         {
13096             _ASSERTE(m_pInternalEmitter != NULL);
13097             ULONG previousUpdateMode;
13098             // Ignore the error when releasing
13099             hr = m_pInternalEmitter->SetMDUpdateMode(m_OriginalMDUpdateMode, &previousUpdateMode);
13100             m_OriginalMDUpdateMode = ULONG_MAX;
13101             
13102             if (expectedPreviousUpdateMode != ULONG_MAX)
13103             {
13104                 if ((hr == S_OK) && (expectedPreviousUpdateMode != previousUpdateMode))
13105                 {
13106                     hr = S_FALSE;
13107                 }
13108             }
13109         }
13110         if (m_pInternalEmitter != NULL)
13111         {
13112             (void)m_pInternalEmitter->Release();
13113             m_pInternalEmitter = NULL;
13114         }
13115         return hr;
13116     }
13117     ULONG GetOriginalMDUpdateMode()
13118     {
13119         WRAPPER_NO_CONTRACT;
13120         _ASSERTE(m_OriginalMDUpdateMode != LONG_MAX);
13121         return m_OriginalMDUpdateMode;
13122     }
13123 private:
13124     IMDInternalEmit *m_pInternalEmitter;
13125     ULONG            m_OriginalMDUpdateMode;
13126 };
13127
13128 // Called in live paths to fetch metadata for dynamic modules. This makes the metadata available to the
13129 // debugger from out-of-process.
13130 // 
13131 // Notes:
13132 //    This buffer can be retrieved by the debugger via code:ReflectionModule.GetDynamicMetadataBuffer 
13133 //    
13134 //    Threading:
13135 //    - Callers must ensure nobody else is adding to the metadata.
13136 //    - This function still takes its own locks to cooperate with the Debugger's out-of-process access.
13137 //      The debugger can slip this thread outside the locks to ensure the data is consistent.
13138 //    
13139 //    This does not raise a debug notification to invalidate the metadata. Reasoning is that this only
13140 //    happens in two cases:
13141 //    1) manifest module is updated with the name of a new dynamic module. 
13142 //    2) on each class load, in which case we already send a debug event. In this case, we already send a
13143 //    class-load notification, so sending a separate "metadata-refresh" would make the eventing twice as
13144 //    chatty. Class-load events are high-volume and events are slow.
13145 //    Thus we can avoid the chatiness by ensuring the debugger knows that Class-load also means "refresh
13146 //    metadata".
13147 //    
13148 void ReflectionModule::CaptureModuleMetaDataToMemory()
13149 {
13150     CONTRACTL
13151     {
13152         THROWS;
13153         GC_TRIGGERS;
13154     }
13155     CONTRACTL_END;
13156
13157     // If we've suppresed metadata capture, then skip this. We'll recapture when we enable it. This allows
13158     // for batching up capture.
13159     // If a debugger is attached, then the CLR will still send ClassLoad notifications for dynamic modules,
13160     // which mean we still need to keep the metadata available. This is the same as Whidbey.
13161     // An alternative (and better) design would be to suppress ClassLoad notifications too, but then we'd
13162     // need some way of sending a "catchup" notification to the debugger after we re-enable notifications. 
13163     if (IsMetadataCaptureSuppressed() && !CORDebuggerAttached())
13164     {
13165         return;
13166     }
13167
13168     // Do not release the emitter. This is a weak reference.
13169     IMetaDataEmit *pEmitter = this->GetEmitter();
13170     _ASSERTE(pEmitter != NULL);
13171
13172     HRESULT hr;
13173     
13174     MDUpdateModeHolder hMDUpdateMode;
13175     IfFailThrow(hMDUpdateMode.SetMDUpdateMode(pEmitter, MDUpdateExtension));
13176     _ASSERTE(hMDUpdateMode.GetOriginalMDUpdateMode() == MDUpdateFull);
13177     
13178     DWORD numBytes;
13179     hr = pEmitter->GetSaveSize(cssQuick, &numBytes);
13180     IfFailThrow(hr);
13181
13182     // Operate on local data, and then persist it into the module once we know it's valid.
13183     NewHolder<SBuffer> pBuffer(new SBuffer());
13184     _ASSERTE(pBuffer != NULL); // allocation would throw first
13185
13186     // ReflectionModule is still in a consistent state, and now we're just operating on local data to
13187     // assemble the new metadata buffer. If this fails, then worst case is that metadata does not include
13188     // recently generated classes.
13189     
13190     // Caller ensures serialization that guarantees that the metadata doesn't grow underneath us.
13191     BYTE * pRawData = pBuffer->OpenRawBuffer(numBytes);
13192     hr = pEmitter->SaveToMemory(pRawData, numBytes);
13193     pBuffer->CloseRawBuffer();
13194
13195     IfFailThrow(hr);
13196     
13197     // Now that we're successful, transfer ownership back into the module.
13198     {
13199         CrstHolder ch(&m_CrstLeafLock);
13200
13201         delete m_pDynamicMetadata;
13202         
13203         m_pDynamicMetadata = pBuffer.Extract();
13204     }
13205
13206     // 
13207     
13208     hr = hMDUpdateMode.Release(MDUpdateExtension);
13209     // Will be S_FALSE if someone changed the MDUpdateMode (from MDUpdateExtension) meanwhile
13210     _ASSERTE(hr == S_OK);
13211 }
13212
13213 // Suppress the eager metadata serialization.
13214 // 
13215 // Notes:
13216 //    This casues code:ReflectionModule.CaptureModuleMetaDataToMemory to be a nop.
13217 //    This is not nestable.
13218 //    This exists purely for performance reasons. 
13219 //    
13220 //    Don't call this directly. Use a SuppressMetadataCaptureHolder holder to ensure it's 
13221 //    balanced with code:ReflectionModule.ResumeMetadataCapture
13222 //    
13223 //    Types generating while eager metadata-capture is suppressed should not actually be executed until
13224 //    after metadata capture is restored.
13225 void ReflectionModule::SuppressMetadataCapture()
13226 {
13227     LIMITED_METHOD_CONTRACT;
13228     // If this fires, then you probably missed a call to ResumeMetadataCapture.
13229     CONSISTENCY_CHECK_MSG(!m_fSuppressMetadataCapture, "SuppressMetadataCapture is not nestable");
13230     m_fSuppressMetadataCapture = true;
13231 }
13232
13233 // Resumes eager metadata serialization.
13234 // 
13235 // Notes:
13236 //    This casues code:ReflectionModule.CaptureModuleMetaDataToMemory to resume eagerly serializing metadata.
13237 //    This must be called after code:ReflectionModule.SuppressMetadataCapture.
13238 //    
13239 void ReflectionModule::ResumeMetadataCapture()
13240 {
13241     WRAPPER_NO_CONTRACT;
13242     _ASSERTE(m_fSuppressMetadataCapture);
13243     m_fSuppressMetadataCapture = false;
13244     
13245     CaptureModuleMetaDataToMemory();
13246 }
13247
13248 void ReflectionModule::ReleaseILData()
13249 {
13250     WRAPPER_NO_CONTRACT;
13251
13252     if (m_pISymUnmanagedWriter)
13253     {
13254         m_pISymUnmanagedWriter->Release();
13255         m_pISymUnmanagedWriter = NULL;
13256     }
13257
13258     Module::ReleaseILData();
13259 }
13260 #endif // !CROSSGEN_COMPILE
13261
13262 #endif // !DACCESS_COMPILE
13263
13264 #ifdef DACCESS_COMPILE
13265 // Accessor to expose m_pDynamicMetadata to debugger.
13266 // 
13267 // Returns:
13268 //    Pointer to SBuffer  containing metadata buffer. May be null.
13269 //    
13270 // Notes:
13271 //    Only used by the debugger, so only accessible via DAC.
13272 //    The buffer is updated via code:ReflectionModule.CaptureModuleMetaDataToMemory
13273 PTR_SBuffer ReflectionModule::GetDynamicMetadataBuffer() const
13274 {
13275     SUPPORTS_DAC;
13276
13277     // If we ask for metadata, but have been suppressing capture, then we're out of date.
13278     // However, the debugger may be debugging already baked types in the module and so may need the metadata
13279     // for that. So we return what we do have. 
13280     // 
13281     // Debugger will get the next metadata update:
13282     // 1) with the next load class
13283     // 2) or if this is right after the last class, see code:ReflectionModule.CaptureModuleMetaDataToMemory
13284
13285     return m_pDynamicMetadata; 
13286 }
13287 #endif
13288
13289 TADDR ReflectionModule::GetIL(RVA il) // virtual
13290 {
13291 #ifndef DACCESS_COMPILE 
13292     WRAPPER_NO_CONTRACT;
13293
13294     BYTE* pByte = NULL;
13295     m_pCeeFileGen->GetMethodBuffer(il, &pByte);
13296     return TADDR(pByte);
13297 #else // DACCESS_COMPILE
13298     SUPPORTS_DAC;
13299     DacNotImpl();
13300     return NULL;
13301 #endif // DACCESS_COMPILE
13302 }
13303
13304 PTR_VOID ReflectionModule::GetRvaField(RVA field, BOOL fZapped) // virtual
13305 {
13306     _ASSERTE(!fZapped);
13307 #ifndef DACCESS_COMPILE 
13308     WRAPPER_NO_CONTRACT;
13309     // This function should be call only if the target is a field or a field with RVA.
13310     PTR_BYTE pByte = NULL;
13311     m_pCeeFileGen->ComputePointer(m_sdataSection, field, &pByte);
13312     return dac_cast<PTR_VOID>(pByte);
13313 #else // DACCESS_COMPILE
13314     SUPPORTS_DAC;
13315     DacNotImpl();
13316     return NULL;
13317 #endif // DACCESS_COMPILE
13318 }
13319
13320 #ifndef DACCESS_COMPILE 
13321
13322 // ===========================================================================
13323 // VASigCookies
13324 // ===========================================================================
13325
13326 //==========================================================================
13327 // Enregisters a VASig.
13328 //==========================================================================
13329 VASigCookie *Module::GetVASigCookie(Signature vaSignature)
13330 {
13331     CONTRACT(VASigCookie*)
13332     {
13333         INSTANCE_CHECK;
13334         THROWS;
13335         GC_TRIGGERS;
13336         MODE_ANY;
13337         POSTCONDITION(CheckPointer(RETVAL));
13338         INJECT_FAULT(COMPlusThrowOM());
13339     }
13340     CONTRACT_END;
13341
13342     VASigCookieBlock *pBlock;
13343     VASigCookie      *pCookie;
13344
13345     pCookie = NULL;
13346
13347     // First, see if we already enregistered this sig.
13348     // Note that we're outside the lock here, so be a bit careful with our logic
13349     for (pBlock = m_pVASigCookieBlock; pBlock != NULL; pBlock = pBlock->m_Next)
13350     {
13351         for (UINT i = 0; i < pBlock->m_numcookies; i++)
13352         {
13353             if (pBlock->m_cookies[i].signature.GetRawSig() == vaSignature.GetRawSig())
13354             {
13355                 pCookie = &(pBlock->m_cookies[i]);
13356                 break;
13357             }
13358         }
13359     }
13360
13361     if (!pCookie)
13362     {
13363         // If not, time to make a new one.
13364
13365         // Compute the size of args first, outside of the lock.
13366
13367         // @TODO GENERICS: We may be calling a varargs method from a 
13368         // generic type/method. Using an empty context will make such a 
13369         // case cause an unexpected exception. To make this work, 
13370         // we need to create a specialized signature for every instantiation
13371         SigTypeContext typeContext;
13372
13373         MetaSig metasig(vaSignature, this, &typeContext);
13374         ArgIterator argit(&metasig);
13375
13376         // Upper estimate of the vararg size
13377         DWORD sizeOfArgs = argit.SizeOfArgStack();
13378
13379         // enable gc before taking lock
13380         {
13381             CrstHolder ch(&m_Crst);
13382
13383             // Note that we were possibly racing to create the cookie, and another thread
13384             // may have already created it.  We could put another check
13385             // here, but it's probably not worth the effort, so we'll just take an
13386             // occasional duplicate cookie instead.
13387
13388             // Is the first block in the list full?
13389             if (m_pVASigCookieBlock && m_pVASigCookieBlock->m_numcookies
13390                 < VASigCookieBlock::kVASigCookieBlockSize)
13391             {
13392                 // Nope, reserve a new slot in the existing block.
13393                 pCookie = &(m_pVASigCookieBlock->m_cookies[m_pVASigCookieBlock->m_numcookies]);
13394             }
13395             else
13396             {
13397                 // Yes, create a new block.
13398                 VASigCookieBlock *pNewBlock = new VASigCookieBlock();
13399
13400                 pNewBlock->m_Next = m_pVASigCookieBlock;
13401                 pNewBlock->m_numcookies = 0;
13402                 m_pVASigCookieBlock = pNewBlock;
13403                 pCookie = &(pNewBlock->m_cookies[0]);
13404             }
13405
13406             // Now, fill in the new cookie (assuming we had enough memory to create one.)
13407             pCookie->pModule = this;
13408             pCookie->pNDirectILStub = NULL;
13409             pCookie->sizeOfArgs = sizeOfArgs;
13410             pCookie->signature = vaSignature;
13411
13412             // Finally, now that it's safe for asynchronous readers to see it,
13413             // update the count.
13414             m_pVASigCookieBlock->m_numcookies++;
13415         }
13416     }
13417
13418     RETURN pCookie;
13419 }
13420
13421 // ===========================================================================
13422 // LookupMap
13423 // ===========================================================================
13424 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
13425
13426 int __cdecl LookupMapBase::HotItem::Cmp(const void* a_, const void* b_)
13427 {
13428     LIMITED_METHOD_CONTRACT;
13429     const HotItem *a = (const HotItem *)a_;
13430     const HotItem *b = (const HotItem *)b_;
13431
13432     if (a->rid < b->rid)
13433         return -1;
13434     else if (a->rid > b->rid)
13435         return 1;
13436     else
13437         return 0;
13438 }
13439
13440 void LookupMapBase::CreateHotItemList(DataImage *image, CorProfileData *profileData, int table, BOOL fSkipNullEntries /*= FALSE*/)
13441 {
13442     STANDARD_VM_CONTRACT;
13443     _ASSERTE(!MapIsCompressed());
13444
13445     if (profileData)
13446     {
13447         DWORD numInTokenList = profileData->GetHotTokens(table, 1<<RidMap, 1<<RidMap, NULL, 0);
13448         
13449         if (numInTokenList > 0)
13450         {
13451             HotItem *itemList = (HotItem*)(void*)image->GetModule()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(HotItem)) * S_SIZE_T(numInTokenList));
13452             mdToken *tokenList = (mdToken*)(void*)image->GetModule()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(mdToken)) * S_SIZE_T(numInTokenList));
13453
13454             profileData->GetHotTokens(table, 1<<RidMap, 1<<RidMap, tokenList, numInTokenList);
13455             DWORD numItems = 0;
13456             for (DWORD i = 0; i < numInTokenList; i++)
13457             {
13458                 DWORD rid = RidFromToken(tokenList[i]);
13459                 TADDR value = RelativePointer<TADDR>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(GetElementPtr(RidFromToken(tokenList[i]))));
13460                 if (!fSkipNullEntries || value != NULL)
13461                 {
13462                     itemList[numItems].rid = rid;
13463                     itemList[numItems].value = value;
13464                     ++numItems;
13465                 }
13466             }
13467
13468             if (numItems > 0)
13469             {
13470                 qsort(itemList,          // start of array
13471                       numItems,          // array size in elements
13472                       sizeof(HotItem),      // element size in bytes
13473                       HotItem::Cmp);        // comparer function
13474
13475                 // Eliminate any duplicates in the list. Due to the qsort, they must be adjacent now.
13476                 // We do this by walking the array and copying entries that are not duplicates of the previous one.
13477                 // We can start the loop at +1, because 0 is not a duplicate of the previous entry, and does not
13478                 // need to be copied either.
13479                 DWORD j = 1;
13480                 for (DWORD i = 1; i < numItems; i++)
13481                 {
13482                     if (itemList[i].rid != itemList[i-1].rid)
13483                     {
13484                         itemList[j].rid   = itemList[i].rid;
13485                         itemList[j].value = itemList[i].value;
13486                         j++;
13487                     }
13488                 }
13489                 _ASSERTE(j <= numItems);
13490                 numItems = j;
13491
13492                 // We have treated the values as normal TADDRs to let qsort move them around freely.
13493                 // Fix them up to be the relative pointers now.
13494                 for (DWORD ii = 0; ii < numItems; ii++)
13495                 {
13496                     if (itemList[ii].value != NULL)
13497                     {
13498                         RelativePointer<TADDR> *pRelPtr = (RelativePointer<TADDR> *)&itemList[ii].value;
13499                         pRelPtr->SetValueMaybeNull(itemList[ii].value);
13500                     }
13501                 }
13502
13503                 if (itemList != NULL)
13504                     image->StoreStructure(itemList, sizeof(HotItem)*numItems,
13505                                           DataImage::ITEM_RID_MAP_HOT);
13506
13507                 hotItemList = itemList;
13508                 dwNumHotItems = numItems;
13509             }
13510         }
13511     }
13512 }
13513
13514 void LookupMapBase::Save(DataImage *image, DataImage::ItemKind kind, CorProfileData *profileData, int table, BOOL fCopyValues /*= FALSE*/)
13515 {
13516     STANDARD_VM_CONTRACT;
13517
13518     // the table index that comes in is a token mask, the upper 8 bits are the table type for the tokens, that's all we want
13519     table >>= 24;
13520
13521     dwNumHotItems = 0;
13522     hotItemList = NULL;
13523
13524     if (table != 0)
13525     {
13526         // Because we use the same IBC encoding to record a touch to the m_GenericTypeDefToCanonMethodTableMap as
13527         // to the m_TypeDefToMethodTableMap, the hot items we get in both will be the union of the touches.  This limitation
13528         // in the IBC infrastructure does not hurt us much because touching an entry for a generic type in one map often if
13529         // not always implies touching the corresponding entry in the other.  But when saving the GENERICTYPEDEF_MAP it
13530         // does mean that we need to be prepared to see "hot" items whose data is NULL in this map (specifically, the non-
13531         // generic types).  We don't want the hot list to be unnecessarily big with these entries, so tell CreateHotItemList to
13532         // skip them.
13533         BOOL fSkipNullEntries = (kind == DataImage::ITEM_GENERICTYPEDEF_MAP);
13534         CreateHotItemList(image, profileData, table, fSkipNullEntries);
13535     }
13536
13537     // Determine whether we want to compress this lookup map (to improve density of cold pages in the map on
13538     // hot item cache misses). We only enable this optimization for the TypeDefToMethodTable, the 
13539     // GenericTypeDefToCanonMethodTable, and the MethodDefToDesc maps since (a) they're the largest and 
13540     // as a result reap the most space savings and (b) these maps are fully populated in an ngen image and immutable 
13541     // at runtime, something that's important when dealing with a compressed version of the table.
13542     if (kind == DataImage::ITEM_TYPEDEF_MAP || kind == DataImage::ITEM_GENERICTYPEDEF_MAP || kind == DataImage::ITEM_METHODDEF_MAP)
13543     {
13544         // The bulk of the compression work is done in the later stages of ngen image generation (since it
13545         // relies on knowing the final RVAs of each value stored in the table). So we create a specialzed
13546         // ZapNode that knows how to perform the compression for us.
13547         image->StoreCompressedLayoutMap(this, DataImage::ITEM_COMPRESSED_MAP);
13548
13549         // We need to know we decided to compress during the Fixup stage but the table kind is not available
13550         // there. So we use the cIndexEntryBits field as a flag (this will be initialized to zero and is only
13551         // set to a meaningful value near the end of ngen image generation, during the compression of the
13552         // table itself).
13553         cIndexEntryBits = 1;
13554
13555         // The ZapNode we allocated above takes care of all the rest of the processing for this map, so we're
13556         // done here.
13557         return;
13558     }
13559
13560     SaveUncompressedMap(image, kind, fCopyValues);
13561 }
13562
13563 void LookupMapBase::SaveUncompressedMap(DataImage *image, DataImage::ItemKind kind, BOOL fCopyValues /*= FALSE*/)
13564 {
13565     STANDARD_VM_CONTRACT;
13566
13567     // We should only be calling this once per map
13568     _ASSERTE(!image->IsStored(pTable));
13569
13570     //
13571     // We will only store one (big) node instead of the full list,
13572     // and make the one node large enough to fit all the RIDs
13573     //
13574
13575     ZapStoredStructure * pTableNode = image->StoreStructure(NULL, GetSize() * sizeof(TADDR), kind);
13576
13577     LookupMapBase *map = this;
13578     DWORD offsetIntoCombo = 0;
13579     while (map != NULL)
13580     {
13581         DWORD len = map->dwCount * sizeof(void*);
13582
13583         if (fCopyValues)
13584             image->CopyDataToOffset(pTableNode, offsetIntoCombo, map->pTable, len);
13585
13586         image->BindPointer(map->pTable,pTableNode,offsetIntoCombo);
13587         offsetIntoCombo += len;
13588         map = map->pNext;
13589     }
13590 }
13591
13592 void LookupMapBase::ConvertSavedMapToUncompressed(DataImage *image, DataImage::ItemKind kind)
13593 {
13594     STANDARD_VM_CONTRACT;
13595
13596     // Check whether we decided to compress this map (see Save() above).
13597     if (cIndexEntryBits == 0)
13598         return;
13599
13600     cIndexEntryBits = 0;
13601     SaveUncompressedMap(image, kind);
13602 }
13603
13604 void LookupMapBase::Fixup(DataImage *image, BOOL fFixupEntries /*=TRUE*/)
13605 {
13606     STANDARD_VM_CONTRACT;
13607
13608     if (hotItemList != NULL)
13609         image->FixupPointerField(this, offsetof(LookupMapBase, hotItemList));
13610
13611     // Find the biggest RID supported by the entire list of LookupMaps.
13612     // We will only store one LookupMap node instead of the full list,
13613     // and make it big enough to fit all RIDs.
13614     *(DWORD *)image->GetImagePointer(this, offsetof(LookupMapBase, dwCount)) = GetSize();
13615
13616     // Persist the supportedFlags that this particular instance was created with.
13617     *(TADDR *)image->GetImagePointer(this, offsetof(LookupMapBase, supportedFlags)) = supportedFlags;
13618
13619     image->ZeroPointerField(this, offsetof(LookupMapBase, pNext));
13620
13621     // Check whether we've decided to compress this map (see Save() above).
13622     if (cIndexEntryBits == 1)
13623     {
13624         // In the compressed case most of the Fixup logic is performed by the specialized ZapNode we allocated
13625         // during Save(). But we still have to record fixups for any hot items we've cached (these aren't
13626         // compressed).
13627         for (DWORD i = 0; i < dwNumHotItems; i++)
13628         {
13629             TADDR *pHotValueLoc = &hotItemList[i].value;
13630             TADDR pHotValue = RelativePointer<TADDR>::GetValueMaybeNullAtPtr((TADDR)pHotValueLoc);
13631             TADDR flags = pHotValue & supportedFlags;
13632             pHotValue -= flags;
13633
13634             if (image->IsStored((PVOID)pHotValue))
13635             {
13636                 image->FixupField(hotItemList,
13637                                   (BYTE *)pHotValueLoc - (BYTE *)hotItemList,
13638                                   (PVOID)pHotValue, flags, IMAGE_REL_BASED_RelativePointer);
13639             }
13640             else
13641             {
13642                 image->ZeroPointerField(hotItemList, (BYTE *)pHotValueLoc - (BYTE *)hotItemList);
13643             }
13644         }
13645
13646         // The ZapNode will handle everything else so we're done.
13647         return;
13648     }
13649
13650     // Note that the caller is responsible for calling FixupPointerField()
13651     // or zeroing out the contents of pTable as appropriate
13652     image->FixupPointerField(this, offsetof(LookupMapBase, pTable));
13653
13654     if (fFixupEntries)
13655     {
13656         LookupMap<PVOID>::Iterator iter((LookupMap<PVOID> *)this);
13657         DWORD rid = 0;
13658
13659         while (iter.Next())
13660         {
13661             TADDR flags;
13662             PVOID p = iter.GetElementAndFlags(&flags);
13663             PTR_TADDR hotItemValuePtr = FindHotItemValuePtr(rid);
13664
13665             if (image->IsStored(p))
13666             {
13667                 image->FixupField(pTable, rid * sizeof(TADDR),
13668                     p, flags, IMAGE_REL_BASED_RelativePointer);
13669
13670                 // In case this item is also in the hot item subtable, fix it up there as well
13671                 if (hotItemValuePtr != NULL)
13672                     image->FixupField(hotItemList,
13673                         (BYTE *)hotItemValuePtr - (BYTE *)hotItemList,
13674                         p, flags, IMAGE_REL_BASED_RelativePointer);
13675             }
13676             else
13677             {
13678                 image->ZeroPointerField(pTable, rid * sizeof(TADDR));
13679                 // In case this item is also in the hot item subtable, zero it there as well
13680                 if (hotItemValuePtr != NULL)
13681                     image->ZeroPointerField(hotItemList, 
13682                         (BYTE *)hotItemValuePtr - (BYTE *)hotItemList);
13683             }
13684
13685             rid++;
13686         }
13687     }
13688 }
13689 #endif // FEATURE_NATIVE_IMAGE_GENERATION
13690
13691 #endif // !DACCESS_COMPILE
13692
13693 #ifdef DACCESS_COMPILE 
13694
13695 void
13696 LookupMapBase::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
13697                              bool enumThis)
13698 {
13699     CONTRACTL
13700     {
13701         INSTANCE_CHECK;
13702         NOTHROW;
13703         GC_NOTRIGGER;
13704         MODE_ANY;
13705         FORBID_FAULT;
13706         SUPPORTS_DAC;
13707     }
13708     CONTRACTL_END;
13709
13710     if (enumThis)
13711     {
13712         DacEnumHostDPtrMem(this);
13713     }
13714     if (pTable.IsValid())
13715     {
13716 #ifdef FEATURE_PREJIT
13717         if (MapIsCompressed())
13718         {
13719             // Compressed maps have tables whose size cannot be calculated cheaply. Plus they have an
13720             // additional index blob.
13721             DacEnumMemoryRegion(dac_cast<TADDR>(pTable),
13722                                 cbTable);
13723             DacEnumMemoryRegion(dac_cast<TADDR>(pIndex),
13724                                 cbIndex);
13725         }
13726         else
13727 #endif // FEATURE_PREJIT
13728             DacEnumMemoryRegion(dac_cast<TADDR>(pTable),
13729                                 dwCount * sizeof(TADDR));
13730     }
13731 #ifdef FEATURE_PREJIT 
13732     if (dwNumHotItems && hotItemList.IsValid())
13733     {
13734         DacEnumMemoryRegion(dac_cast<TADDR>(hotItemList),
13735                             dwNumHotItems * sizeof(HotItem));
13736     }
13737 #endif // FEATURE_PREJIT
13738 }
13739
13740
13741 /* static */
13742 void
13743 LookupMapBase::ListEnumMemoryRegions(CLRDataEnumMemoryFlags flags)
13744 {
13745     CONTRACTL
13746     {
13747         NOTHROW;
13748         GC_NOTRIGGER;
13749         MODE_ANY;
13750         FORBID_FAULT;
13751         SUPPORTS_DAC;
13752     }
13753     CONTRACTL_END;
13754
13755     LookupMapBase * headMap = this;
13756     bool enumHead = false;
13757     while (headMap)
13758     {
13759         headMap->EnumMemoryRegions(flags, enumHead);
13760
13761         if (!headMap->pNext.IsValid())
13762         {
13763             break;
13764         }
13765
13766         headMap = headMap->pNext;
13767         enumHead = true;
13768     }
13769 }
13770
13771 #endif // DACCESS_COMPILE
13772
13773
13774 // Optimization intended for Module::EnsureActive only
13775 #include <optsmallperfcritical.h>
13776
13777 #ifndef DACCESS_COMPILE
13778 VOID Module::EnsureActive()
13779 {
13780     CONTRACTL
13781     {
13782         THROWS;
13783         GC_TRIGGERS;
13784         MODE_ANY;
13785     }
13786     CONTRACTL_END;
13787     GetDomainFile()->EnsureActive();
13788 }
13789 #endif // DACCESS_COMPILE
13790
13791 #include <optdefault.h>
13792
13793
13794 #ifndef DACCESS_COMPILE
13795
13796 VOID Module::EnsureAllocated()
13797 {
13798     CONTRACTL
13799     {
13800         THROWS;
13801         GC_TRIGGERS;
13802         MODE_ANY;
13803     }
13804     CONTRACTL_END;
13805
13806     GetDomainFile()->EnsureAllocated();
13807 }
13808
13809 VOID Module::EnsureLibraryLoaded()
13810 {
13811     STANDARD_VM_CONTRACT;
13812     GetDomainFile()->EnsureLibraryLoaded();
13813 }
13814 #endif // !DACCESS_COMPILE
13815
13816 CHECK Module::CheckActivated()
13817 {
13818     CONTRACTL
13819     {
13820         NOTHROW;
13821         GC_NOTRIGGER;
13822         MODE_ANY;
13823     }
13824     CONTRACTL_END;
13825
13826 #ifndef DACCESS_COMPILE 
13827     DomainFile *pDomainFile = FindDomainFile(GetAppDomain());
13828     CHECK(pDomainFile != NULL);
13829     PREFIX_ASSUME(pDomainFile != NULL);
13830     CHECK(pDomainFile->CheckActivated());
13831 #endif
13832     CHECK_OK;
13833 }
13834
13835 #ifdef DACCESS_COMPILE 
13836
13837 void
13838 ModuleCtorInfo::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
13839 {
13840     SUPPORTS_DAC;
13841
13842     // This class is contained so do not enumerate 'this'.
13843     DacEnumMemoryRegion(dac_cast<TADDR>(ppMT), numElements *
13844                         sizeof(RelativePointer<MethodTable *>));
13845     DacEnumMemoryRegion(dac_cast<TADDR>(cctorInfoHot), numElementsHot *
13846                         sizeof(ClassCtorInfoEntry));
13847     DacEnumMemoryRegion(dac_cast<TADDR>(cctorInfoCold),
13848                         (numElements - numElementsHot) *
13849                         sizeof(ClassCtorInfoEntry));
13850     DacEnumMemoryRegion(dac_cast<TADDR>(hotHashOffsets), numHotHashes *
13851                         sizeof(DWORD));
13852     DacEnumMemoryRegion(dac_cast<TADDR>(coldHashOffsets), numColdHashes *
13853                         sizeof(DWORD));
13854 }
13855
13856 void Module::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
13857                                bool enumThis)
13858 {
13859     CONTRACTL
13860     {
13861         INSTANCE_CHECK;
13862         NOTHROW;
13863         GC_NOTRIGGER;
13864         MODE_ANY;
13865         FORBID_FAULT;
13866         SUPPORTS_DAC;
13867     }
13868     CONTRACTL_END;
13869
13870     if (enumThis)
13871     {
13872         DAC_ENUM_VTHIS();
13873         EMEM_OUT(("MEM: %p Module\n", dac_cast<TADDR>(this)));
13874     }
13875
13876     //Save module id data only if it a real pointer, not a tagged sugestion to use ModuleIndex.
13877     if (!Module::IsEncodedModuleIndex(GetModuleID()))
13878     {
13879         if (m_ModuleID.IsValid())
13880         {
13881             m_ModuleID->EnumMemoryRegions(flags);
13882         }
13883     }
13884
13885     // TODO: Enumerate DomainLocalModules?  It's not clear if we need all AppDomains 
13886     // in the multi-domain case (where m_ModuleID has it's low-bit set).
13887     if (m_file.IsValid())
13888     {
13889         m_file->EnumMemoryRegions(flags);
13890     }
13891     if (m_pAssembly.IsValid())
13892     {
13893         m_pAssembly->EnumMemoryRegions(flags);
13894     }
13895
13896     m_TypeRefToMethodTableMap.ListEnumMemoryRegions(flags);
13897     m_TypeDefToMethodTableMap.ListEnumMemoryRegions(flags);
13898
13899     if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE)
13900     {
13901         if (m_pAvailableClasses.IsValid())
13902         {
13903             m_pAvailableClasses->EnumMemoryRegions(flags);
13904         }
13905         if (m_pAvailableParamTypes.IsValid())
13906         {
13907             m_pAvailableParamTypes->EnumMemoryRegions(flags);
13908         }
13909         if (m_pInstMethodHashTable.IsValid())
13910         {
13911             m_pInstMethodHashTable->EnumMemoryRegions(flags);
13912         }
13913         if (m_pAvailableClassesCaseIns.IsValid())
13914         {
13915             m_pAvailableClassesCaseIns->EnumMemoryRegions(flags);
13916         }
13917 #ifdef FEATURE_PREJIT
13918         if (m_pStubMethodHashTable.IsValid())
13919         {
13920             m_pStubMethodHashTable->EnumMemoryRegions(flags);
13921         }
13922 #endif // FEATURE_PREJIT
13923         if (m_pBinder.IsValid())
13924         {
13925             m_pBinder->EnumMemoryRegions(flags);
13926         }
13927         m_ModuleCtorInfo.EnumMemoryRegions(flags);
13928
13929         // Save the LookupMap structures.
13930         m_MethodDefToDescMap.ListEnumMemoryRegions(flags);
13931         m_FieldDefToDescMap.ListEnumMemoryRegions(flags);
13932         m_pMemberRefToDescHashTable->EnumMemoryRegions(flags);
13933         m_GenericParamToDescMap.ListEnumMemoryRegions(flags);
13934         m_GenericTypeDefToCanonMethodTableMap.ListEnumMemoryRegions(flags);
13935         m_FileReferencesMap.ListEnumMemoryRegions(flags);
13936         m_ManifestModuleReferencesMap.ListEnumMemoryRegions(flags);
13937         m_MethodDefToPropertyInfoMap.ListEnumMemoryRegions(flags);
13938
13939         LookupMap<PTR_MethodTable>::Iterator typeDefIter(&m_TypeDefToMethodTableMap);
13940         while (typeDefIter.Next())
13941         {
13942             if (typeDefIter.GetElement())
13943             {
13944                 typeDefIter.GetElement()->EnumMemoryRegions(flags);
13945             }
13946         }
13947
13948         LookupMap<PTR_TypeRef>::Iterator typeRefIter(&m_TypeRefToMethodTableMap);
13949         while (typeRefIter.Next())
13950         {
13951             if (typeRefIter.GetElement())
13952             {
13953                 TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(typeRefIter.GetElement()));
13954                 th.EnumMemoryRegions(flags);
13955             }
13956         }
13957
13958         LookupMap<PTR_MethodDesc>::Iterator methodDefIter(&m_MethodDefToDescMap);
13959         while (methodDefIter.Next())
13960         {
13961             if (methodDefIter.GetElement())
13962             {
13963                 methodDefIter.GetElement()->EnumMemoryRegions(flags);
13964             }
13965         }
13966
13967         LookupMap<PTR_FieldDesc>::Iterator fieldDefIter(&m_FieldDefToDescMap);
13968         while (fieldDefIter.Next())
13969         {
13970             if (fieldDefIter.GetElement())
13971             {
13972                 fieldDefIter.GetElement()->EnumMemoryRegions(flags);
13973             }
13974         }
13975
13976         LookupMap<PTR_TypeVarTypeDesc>::Iterator genericParamIter(&m_GenericParamToDescMap);
13977         while (genericParamIter.Next())
13978         {
13979             if (genericParamIter.GetElement())
13980             {
13981                 genericParamIter.GetElement()->EnumMemoryRegions(flags);
13982             }
13983         }
13984
13985         LookupMap<PTR_MethodTable>::Iterator genericTypeDefIter(&m_GenericTypeDefToCanonMethodTableMap);
13986         while (genericTypeDefIter.Next())
13987         {
13988             if (genericTypeDefIter.GetElement())
13989             {
13990                 genericTypeDefIter.GetElement()->EnumMemoryRegions(flags);
13991             }
13992         }
13993
13994     }   // !CLRDATA_ENUM_MEM_MINI && !CLRDATA_ENUM_MEM_TRIAGE
13995     
13996
13997     LookupMap<PTR_Module>::Iterator fileRefIter(&m_FileReferencesMap);
13998     while (fileRefIter.Next())
13999     {
14000         if (fileRefIter.GetElement())
14001         {
14002             fileRefIter.GetElement()->EnumMemoryRegions(flags, true);
14003         }
14004     }
14005
14006     LookupMap<PTR_Module>::Iterator asmRefIter(&m_ManifestModuleReferencesMap);
14007     while (asmRefIter.Next())
14008     {
14009         if (asmRefIter.GetElement())
14010         {
14011             asmRefIter.GetElement()->GetAssembly()->EnumMemoryRegions(flags);
14012         }
14013     }
14014
14015     ECall::EnumFCallMethods();
14016 }
14017
14018 FieldDesc *Module::LookupFieldDef(mdFieldDef token)
14019 {
14020     WRAPPER_NO_CONTRACT;
14021     _ASSERTE(TypeFromToken(token) == mdtFieldDef);
14022     g_IBCLogger.LogRidMapAccess( MakePair( this, token ) );
14023     return m_FieldDefToDescMap.GetElement(RidFromToken(token));
14024 }
14025
14026 #endif // DACCESS_COMPILE
14027
14028
14029
14030
14031
14032 //-------------------------------------------------------------------------------
14033 // Make best-case effort to obtain an image name for use in an error message.
14034 //
14035 // This routine must expect to be called before the this object is fully loaded.
14036 // It can return an empty if the name isn't available or the object isn't initialized
14037 // enough to get a name, but it mustn't crash.
14038 //-------------------------------------------------------------------------------
14039 LPCWSTR Module::GetPathForErrorMessages()
14040 {
14041     CONTRACTL
14042     {
14043         THROWS;
14044         GC_TRIGGERS;
14045         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
14046     }
14047     CONTRACTL_END
14048
14049     PEFile *pFile = GetFile();
14050     
14051     if (pFile)
14052     {
14053         return pFile->GetPathForErrorMessages();
14054     }
14055     else
14056     {
14057         return W("");
14058     }
14059 }
14060
14061 #if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(CROSS_COMPILE)
14062 void Module::ExpandAll()
14063 {
14064     CONTRACTL
14065     {
14066         THROWS;
14067         GC_TRIGGERS;
14068         MODE_ANY;
14069     }
14070     CONTRACTL_END;
14071
14072     //This is called from inside EEStartupHelper, so it breaks the SO rules.  However, this is debug only
14073     //(and only supported for limited jit testing), so it's ok here.
14074     CONTRACT_VIOLATION(SOToleranceViolation);
14075
14076     //If the EE isn't started yet, it's not safe to jit.  We fail in COM jitting a p/invoke.
14077     if (!g_fEEStarted)
14078         return;
14079     struct Local
14080     {
14081         static void CompileMethodDesc(MethodDesc * pMD)
14082         {
14083             //Must have a method body
14084             if (pMD->HasILHeader()
14085                 //Can't jit open instantiations
14086                 && !pMD->IsGenericMethodDefinition()
14087                 //These are the only methods we can jit
14088                 && (pMD->IsStatic() || pMD->GetNumGenericMethodArgs() == 0
14089                     || pMD->HasClassInstantiation())
14090                 && (pMD->MayHaveNativeCode() && !pMD->IsFCallOrIntrinsic()))
14091             {
14092                 pMD->PrepareInitialCode();
14093             }
14094         }
14095         static void CompileMethodsForMethodTable(MethodTable * pMT)
14096         {
14097             MethodTable::MethodIterator it(pMT);
14098             for (; it.IsValid(); it.Next())
14099             {
14100                 MethodDesc * pMD = it.GetMethodDesc();
14101                 CompileMethodDesc(pMD);
14102             }
14103         }
14104 #if 0
14105         static void CompileMethodsForTypeDef(Module * pModule, mdTypeDef td)
14106         {
14107             TypeHandle th = ClassLoader::LoadTypeDefThrowing(pModule, td, ClassLoader::ThrowIfNotFound,
14108                                                              ClassLoader::PermitUninstDefOrRef);
14109
14110             MethodTable * pMT = th.GetMethodTable();
14111             CompileMethodsForMethodTable(pMT);
14112         }
14113 #endif
14114         static void CompileMethodsForTypeDefRefSpec(Module * pModule, mdToken tok)
14115         {
14116             TypeHandle th;
14117             HRESULT hr = S_OK;
14118
14119             EX_TRY
14120             {
14121                 th = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
14122                     pModule, 
14123                     tok, 
14124                     NULL /*SigTypeContext*/);
14125             }
14126             EX_CATCH
14127             {
14128                 hr = GET_EXCEPTION()->GetHR();
14129             }
14130             EX_END_CATCH(SwallowAllExceptions);
14131
14132             //Only do this for non-generic types and unshared generic types
14133             //(canonical generics and value type generic instantiations).
14134             if (SUCCEEDED(hr) && !th.IsTypeDesc()
14135                             && th.AsMethodTable()->IsCanonicalMethodTable())
14136             {
14137                 CompileMethodsForMethodTable(th.AsMethodTable());
14138             }
14139         }
14140         static void CompileMethodsForMethodDefRefSpec(Module * pModule, mdToken tok)
14141         {
14142             HRESULT hr = S_OK;
14143             EX_TRY
14144             {
14145                 MethodDesc * pMD =
14146                     MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule, tok,
14147                                                                         /*SigTypeContext*/NULL,
14148                                                                         TRUE, TRUE);
14149                 CompileMethodDesc(pMD);
14150             }
14151             EX_CATCH
14152             {
14153                 hr = GET_EXCEPTION()->GetHR();
14154                 //@telesto what should we do with this HR?  the Silverlight code doesn't seem
14155                 //to do anything...but that doesn't seem safe...
14156             }
14157             EX_END_CATCH(SwallowAllExceptions);
14158         }
14159     };
14160     //Jit all methods eagerly
14161
14162     IMDInternalImport * pMDI = GetMDImport();
14163     HENUMTypeDefInternalHolder hEnum(pMDI);
14164     mdTypeDef td;
14165     hEnum.EnumTypeDefInit();
14166
14167     //verify global methods
14168     if (GetGlobalMethodTable())
14169     {
14170         //jit everything in the MT.
14171         Local::CompileMethodsForTypeDefRefSpec(this, COR_GLOBAL_PARENT_TOKEN);
14172     }
14173     while (pMDI->EnumTypeDefNext(&hEnum, &td))
14174     {
14175         //jit everything
14176         Local::CompileMethodsForTypeDefRefSpec(this, td);
14177     }
14178
14179     //Get the type refs.  They're always awesome.
14180     HENUMInternalHolder hEnumTypeRefs(pMDI);
14181     mdToken tr;
14182
14183     hEnumTypeRefs.EnumAllInit(mdtTypeRef);
14184     while (hEnumTypeRefs.EnumNext(&tr))
14185     {
14186         Local::CompileMethodsForTypeDefRefSpec(this, tr);
14187     }
14188
14189     //make sure to get the type specs
14190     HENUMInternalHolder hEnumTypeSpecs(pMDI);
14191     mdToken ts;
14192
14193     hEnumTypeSpecs.EnumAllInit(mdtTypeSpec);
14194     while (hEnumTypeSpecs.EnumNext(&ts))
14195     {
14196         Local::CompileMethodsForTypeDefRefSpec(this, ts);
14197     }
14198
14199
14200     //And now for the interesting generic methods
14201     HENUMInternalHolder hEnumMethodSpecs(pMDI);
14202     mdToken ms;
14203
14204     hEnumMethodSpecs.EnumAllInit(mdtMethodSpec);
14205     while (hEnumMethodSpecs.EnumNext(&ms))
14206     {
14207         Local::CompileMethodsForMethodDefRefSpec(this, ms);
14208     }
14209 }
14210 #endif //_DEBUG && !DACCESS_COMPILE && !CROSS_COMPILE
14211
14212 //-------------------------------------------------------------------------------
14213
14214 // Verify consistency of asmconstants.h
14215
14216 // Wrap all C_ASSERT's in asmconstants.h with a class definition.  Many of the
14217 // fields referenced below are private, and this class is a friend of the
14218 // enclosing type.  (A C_ASSERT isn't a compiler intrinsic, just a magic
14219 // typedef that produces a compiler error when the condition is false.)
14220 #include "clrvarargs.h" /* for VARARG C_ASSERTs in asmconstants.h */
14221 class CheckAsmOffsets
14222 {
14223 #ifndef CROSSBITNESS_COMPILE
14224 #define ASMCONSTANTS_C_ASSERT(cond) static_assert(cond, #cond);
14225 #include "asmconstants.h"
14226 #endif // CROSSBITNESS_COMPILE
14227 };
14228
14229 //-------------------------------------------------------------------------------
14230
14231 #ifndef DACCESS_COMPILE
14232
14233 void Module::CreateAssemblyRefByNameTable(AllocMemTracker *pamTracker)
14234 {
14235     CONTRACTL
14236     {
14237         THROWS;
14238         GC_NOTRIGGER;
14239         INJECT_FAULT(COMPlusThrowOM(););
14240     }
14241     CONTRACTL_END
14242
14243     LoaderHeap *        pHeap       = GetLoaderAllocator()->GetLowFrequencyHeap();
14244     IMDInternalImport * pImport     = GetMDImport();
14245
14246     DWORD               dwMaxRid    = pImport->GetCountWithTokenKind(mdtAssemblyRef);
14247     if (dwMaxRid == 0)
14248         return;
14249
14250     S_SIZE_T            dwAllocSize = S_SIZE_T(sizeof(LPWSTR)) * S_SIZE_T(dwMaxRid);
14251     m_AssemblyRefByNameTable = (LPCSTR *) pamTracker->Track( pHeap->AllocMem(dwAllocSize) );
14252
14253     DWORD dwCount = 0;
14254     for (DWORD rid=1; rid <= dwMaxRid; rid++)
14255     {
14256         mdAssemblyRef mdToken = TokenFromRid(rid,mdtAssemblyRef);
14257         LPCSTR        szName;
14258         HRESULT       hr;
14259
14260         hr = pImport->GetAssemblyRefProps(mdToken, NULL, NULL, &szName, NULL, NULL, NULL, NULL);
14261
14262         if (SUCCEEDED(hr))
14263         {
14264             m_AssemblyRefByNameTable[dwCount++] = szName;
14265         }
14266     }
14267     m_AssemblyRefByNameCount = dwCount;
14268 }
14269
14270 bool Module::HasReferenceByName(LPCUTF8 pModuleName)
14271 {
14272     LIMITED_METHOD_CONTRACT;
14273
14274     for (DWORD i=0; i < m_AssemblyRefByNameCount; i++)
14275     {
14276         if (0 == strcmp(pModuleName, m_AssemblyRefByNameTable[i]))
14277             return true;
14278     }
14279
14280     return false;
14281 }
14282 #endif
14283
14284 #ifdef _MSC_VER
14285 #pragma warning(pop)
14286 #endif // _MSC_VER: warning C4244
14287
14288 #if defined(_DEBUG) && !defined(DACCESS_COMPILE)
14289 NOINLINE void NgenForceFailure_AV()
14290 {
14291     LIMITED_METHOD_CONTRACT;
14292     static int* alwaysNull = 0;
14293     *alwaysNull = 0;
14294 }
14295
14296 NOINLINE void NgenForceFailure_TypeLoadException()
14297 {
14298     WRAPPER_NO_CONTRACT;
14299     ::ThrowTypeLoadException("ForceIBC", "Failure", W("Assembly"), NULL, IDS_CLASSLOAD_BADFORMAT);       
14300 }
14301
14302 void EEConfig::DebugCheckAndForceIBCFailure(BitForMask bitForMask)
14303 {
14304     CONTRACTL
14305     {
14306         THROWS;
14307         GC_NOTRIGGER;
14308         MODE_ANY;
14309     }
14310     CONTRACTL_END;
14311     static DWORD s_ibcCheckCount = 0;
14312
14313     // Both of these must be set to non-zero values for us to force a failure
14314     // 
14315     if ((NgenForceFailureCount() == 0) || (NgenForceFailureKind() == 0))
14316         return;
14317
14318     // The bitForMask value must also beset in the FailureMask
14319     // 
14320     if ((((DWORD) bitForMask) & NgenForceFailureMask()) == 0)
14321         return;
14322
14323     s_ibcCheckCount++;
14324     if (s_ibcCheckCount < NgenForceFailureCount())
14325         return;
14326
14327     // We force one failure every NgenForceFailureCount()
14328     // 
14329     s_ibcCheckCount = 0;
14330     switch (NgenForceFailureKind())
14331     {
14332     case 1:
14333         NgenForceFailure_TypeLoadException();
14334         break;
14335     case 2:
14336         NgenForceFailure_AV();
14337         break;
14338     }
14339 }
14340 #endif // defined(_DEBUG) && !defined(DACCESS_COMPILE)
14341